diff --git a/LICENSE b/LICENSE index 2796620..2e83cda 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,9 @@ -LibTomCrypt is public domain. As should all quality software be. - -All of the software was either written by or donated to Tom St Denis for the purposes -of this project. The only exception is the SAFER.C source which has no known -license status (assumed copyrighted) which is why SAFER,C is shipped as disabled. - -Tom St Denis \ No newline at end of file +LibTomCrypt is public domain. As should all quality software be. + +All of the software was either written by or donated to Tom St Denis for the purposes +of this project. The only exception is the SAFER.C source which has no known +license status (assumed copyrighted) which is why SAFER,C is shipped as disabled. + +Tom St Denis + + diff --git a/PLAN b/PLAN new file mode 100644 index 0000000..71ebc1a --- /dev/null +++ b/PLAN @@ -0,0 +1,38 @@ +The following functions are marked for removal and/or behavioural change by v1.00 of LibTomCrypt + +1. RSA Support + + rsa_pad, rsa_signpad, rsa_depad, rsa_signdepad, rsa_import, rsa_export + +They will be replaced with PKCS #1 compliant OAEP/PSS padding function as early as v0.96 + +2. DSA Support + + dsa_import, dsa_export + +Will be replaced with suitable DSS [what is the standard?] compliant formats. Planned for v0.96 + +3. Key Ring Support + + (all) + +The entire API will be dropped as early as v0.96. It was just an experiment and nobody uses it anyways. + +4. Test Harness + + demos/test.c + +The test harness is well overdue for a makeover. Planned for as early as v0.97 + + +Put things in order... + +v0.96 -- removed keyring.c and gf.c + -- removed LTC RSA padding + -- DSS support [whatever this entails] + -- Bug fixes/updates to the PKCS/DSS support, should be stable in this release + +v0.97 -- Re-written test harness + -- More demos in the manual and demos/ directory + +... future??? diff --git a/aes.c b/aes.c index f78ea45..342948d 100644 --- a/aes.c +++ b/aes.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -183,28 +183,28 @@ int rijndael_setup(const unsigned char *key, int keylen, int rounds, symmetric_k #ifdef SMALL_CODE temp = rrk[0]; rk[0] = - Td0[255 & Te4[byte(temp, 3)]] ^ - Td1[255 & Te4[byte(temp, 2)]] ^ - Td2[255 & Te4[byte(temp, 1)]] ^ - Td3[255 & Te4[byte(temp, 0)]]; + Td0(255 & Te4[byte(temp, 3)]) ^ + Td1(255 & Te4[byte(temp, 2)]) ^ + Td2(255 & Te4[byte(temp, 1)]) ^ + Td3(255 & Te4[byte(temp, 0)]); temp = rrk[1]; rk[1] = - Td0[255 & Te4[byte(temp, 3)]] ^ - Td1[255 & Te4[byte(temp, 2)]] ^ - Td2[255 & Te4[byte(temp, 1)]] ^ - Td3[255 & Te4[byte(temp, 0)]]; + Td0(255 & Te4[byte(temp, 3)]) ^ + Td1(255 & Te4[byte(temp, 2)]) ^ + Td2(255 & Te4[byte(temp, 1)]) ^ + Td3(255 & Te4[byte(temp, 0)]); temp = rrk[2]; rk[2] = - Td0[255 & Te4[byte(temp, 3)]] ^ - Td1[255 & Te4[byte(temp, 2)]] ^ - Td2[255 & Te4[byte(temp, 1)]] ^ - Td3[255 & Te4[byte(temp, 0)]]; + Td0(255 & Te4[byte(temp, 3)]) ^ + Td1(255 & Te4[byte(temp, 2)]) ^ + Td2(255 & Te4[byte(temp, 1)]) ^ + Td3(255 & Te4[byte(temp, 0)]); temp = rrk[3]; rk[3] = - Td0[255 & Te4[byte(temp, 3)]] ^ - Td1[255 & Te4[byte(temp, 2)]] ^ - Td2[255 & Te4[byte(temp, 1)]] ^ - Td3[255 & Te4[byte(temp, 0)]]; + Td0(255 & Te4[byte(temp, 3)]) ^ + Td1(255 & Te4[byte(temp, 2)]) ^ + Td2(255 & Te4[byte(temp, 1)]) ^ + Td3(255 & Te4[byte(temp, 0)]); #else temp = rrk[0]; rk[0] = @@ -276,28 +276,28 @@ void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_ r = Nr >> 1; for (;;) { t0 = - Te0[byte(s0, 3)] ^ - Te1[byte(s1, 2)] ^ - Te2[byte(s2, 1)] ^ - Te3[byte(s3, 0)] ^ + Te0(byte(s0, 3)) ^ + Te1(byte(s1, 2)) ^ + Te2(byte(s2, 1)) ^ + Te3(byte(s3, 0)) ^ rk[4]; t1 = - Te0[byte(s1, 3)] ^ - Te1[byte(s2, 2)] ^ - Te2[byte(s3, 1)] ^ - Te3[byte(s0, 0)] ^ + Te0(byte(s1, 3)) ^ + Te1(byte(s2, 2)) ^ + Te2(byte(s3, 1)) ^ + Te3(byte(s0, 0)) ^ rk[5]; t2 = - Te0[byte(s2, 3)] ^ - Te1[byte(s3, 2)] ^ - Te2[byte(s0, 1)] ^ - Te3[byte(s1, 0)] ^ + Te0(byte(s2, 3)) ^ + Te1(byte(s3, 2)) ^ + Te2(byte(s0, 1)) ^ + Te3(byte(s1, 0)) ^ rk[6]; t3 = - Te0[byte(s3, 3)] ^ - Te1[byte(s0, 2)] ^ - Te2[byte(s1, 1)] ^ - Te3[byte(s2, 0)] ^ + Te0(byte(s3, 3)) ^ + Te1(byte(s0, 2)) ^ + Te2(byte(s1, 1)) ^ + Te3(byte(s2, 0)) ^ rk[7]; rk += 8; @@ -306,28 +306,28 @@ void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_ } s0 = - Te0[byte(t0, 3)] ^ - Te1[byte(t1, 2)] ^ - Te2[byte(t2, 1)] ^ - Te3[byte(t3, 0)] ^ + Te0(byte(t0, 3)) ^ + Te1(byte(t1, 2)) ^ + Te2(byte(t2, 1)) ^ + Te3(byte(t3, 0)) ^ rk[0]; s1 = - Te0[byte(t1, 3)] ^ - Te1[byte(t2, 2)] ^ - Te2[byte(t3, 1)] ^ - Te3[byte(t0, 0)] ^ + Te0(byte(t1, 3)) ^ + Te1(byte(t2, 2)) ^ + Te2(byte(t3, 1)) ^ + Te3(byte(t0, 0)) ^ rk[1]; s2 = - Te0[byte(t2, 3)] ^ - Te1[byte(t3, 2)] ^ - Te2[byte(t0, 1)] ^ - Te3[byte(t1, 0)] ^ + Te0(byte(t2, 3)) ^ + Te1(byte(t3, 2)) ^ + Te2(byte(t0, 1)) ^ + Te3(byte(t1, 0)) ^ rk[2]; s3 = - Te0[byte(t3, 3)] ^ - Te1[byte(t0, 2)] ^ - Te2[byte(t1, 1)] ^ - Te3[byte(t2, 0)] ^ + Te0(byte(t3, 3)) ^ + Te1(byte(t0, 2)) ^ + Te2(byte(t1, 1)) ^ + Te3(byte(t2, 0)) ^ rk[3]; } /* @@ -404,28 +404,28 @@ void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_ for (;;) { t0 = - Td0[byte(s0, 3)] ^ - Td1[byte(s3, 2)] ^ - Td2[byte(s2, 1)] ^ - Td3[byte(s1, 0)] ^ + Td0(byte(s0, 3)) ^ + Td1(byte(s3, 2)) ^ + Td2(byte(s2, 1)) ^ + Td3(byte(s1, 0)) ^ rk[4]; t1 = - Td0[byte(s1, 3)] ^ - Td1[byte(s0, 2)] ^ - Td2[byte(s3, 1)] ^ - Td3[byte(s2, 0)] ^ + Td0(byte(s1, 3)) ^ + Td1(byte(s0, 2)) ^ + Td2(byte(s3, 1)) ^ + Td3(byte(s2, 0)) ^ rk[5]; t2 = - Td0[byte(s2, 3)] ^ - Td1[byte(s1, 2)] ^ - Td2[byte(s0, 1)] ^ - Td3[byte(s3, 0)] ^ + Td0(byte(s2, 3)) ^ + Td1(byte(s1, 2)) ^ + Td2(byte(s0, 1)) ^ + Td3(byte(s3, 0)) ^ rk[6]; t3 = - Td0[byte(s3, 3)] ^ - Td1[byte(s2, 2)] ^ - Td2[byte(s1, 1)] ^ - Td3[byte(s0, 0)] ^ + Td0(byte(s3, 3)) ^ + Td1(byte(s2, 2)) ^ + Td2(byte(s1, 1)) ^ + Td3(byte(s0, 0)) ^ rk[7]; rk += 8; @@ -435,28 +435,28 @@ void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_ s0 = - Td0[byte(t0, 3)] ^ - Td1[byte(t3, 2)] ^ - Td2[byte(t2, 1)] ^ - Td3[byte(t1, 0)] ^ + Td0(byte(t0, 3)) ^ + Td1(byte(t3, 2)) ^ + Td2(byte(t2, 1)) ^ + Td3(byte(t1, 0)) ^ rk[0]; s1 = - Td0[byte(t1, 3)] ^ - Td1[byte(t0, 2)] ^ - Td2[byte(t3, 1)] ^ - Td3[byte(t2, 0)] ^ + Td0(byte(t1, 3)) ^ + Td1(byte(t0, 2)) ^ + Td2(byte(t3, 1)) ^ + Td3(byte(t2, 0)) ^ rk[1]; s2 = - Td0[byte(t2, 3)] ^ - Td1[byte(t1, 2)] ^ - Td2[byte(t0, 1)] ^ - Td3[byte(t3, 0)] ^ + Td0(byte(t2, 3)) ^ + Td1(byte(t1, 2)) ^ + Td2(byte(t0, 1)) ^ + Td3(byte(t3, 0)) ^ rk[2]; s3 = - Td0[byte(t3, 3)] ^ - Td1[byte(t2, 2)] ^ - Td2[byte(t1, 1)] ^ - Td3[byte(t0, 0)] ^ + Td0(byte(t3, 3)) ^ + Td1(byte(t2, 2)) ^ + Td2(byte(t1, 1)) ^ + Td3(byte(t0, 0)) ^ rk[3]; } diff --git a/aes_tab.c b/aes_tab.c index 4541515..a93c746 100644 --- a/aes_tab.c +++ b/aes_tab.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -23,7 +23,7 @@ Td3[x] = Si[x].[09, 0d, 0b, 0e]; Td4[x] = Si[x].[01, 01, 01, 01]; */ -static const ulong32 Te0[256] = { +static const ulong32 TE0[256] = { 0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL, 0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL, 0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL, @@ -89,205 +89,7 @@ static const ulong32 Te0[256] = { 0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL, 0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL, }; -static const ulong32 Te1[256] = { - 0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL, - 0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL, - 0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL, - 0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL, - 0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL, - 0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL, - 0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL, - 0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL, - 0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL, - 0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL, - 0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL, - 0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL, - 0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL, - 0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL, - 0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL, - 0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL, - 0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL, - 0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL, - 0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL, - 0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL, - 0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL, - 0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL, - 0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL, - 0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL, - 0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL, - 0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL, - 0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL, - 0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL, - 0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL, - 0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL, - 0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL, - 0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL, - 0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL, - 0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL, - 0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL, - 0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL, - 0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL, - 0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL, - 0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL, - 0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL, - 0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL, - 0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL, - 0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL, - 0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL, - 0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL, - 0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL, - 0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL, - 0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL, - 0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL, - 0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL, - 0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL, - 0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL, - 0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL, - 0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL, - 0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL, - 0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL, - 0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL, - 0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL, - 0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL, - 0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL, - 0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL, - 0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL, - 0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL, - 0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL, -}; -static const ulong32 Te2[256] = { - 0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL, - 0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL, - 0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL, - 0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL, - 0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL, - 0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL, - 0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL, - 0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL, - 0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL, - 0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL, - 0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL, - 0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL, - 0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL, - 0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL, - 0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL, - 0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL, - 0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL, - 0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL, - 0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL, - 0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL, - 0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL, - 0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL, - 0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL, - 0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL, - 0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL, - 0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL, - 0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL, - 0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL, - 0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL, - 0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL, - 0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL, - 0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL, - 0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL, - 0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL, - 0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL, - 0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL, - 0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL, - 0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL, - 0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL, - 0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL, - 0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL, - 0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL, - 0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL, - 0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL, - 0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL, - 0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL, - 0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL, - 0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL, - 0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL, - 0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL, - 0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL, - 0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL, - 0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL, - 0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL, - 0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL, - 0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL, - 0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL, - 0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL, - 0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL, - 0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL, - 0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL, - 0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL, - 0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL, - 0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL, -}; -static const ulong32 Te3[256] = { - 0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL, - 0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL, - 0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL, - 0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL, - 0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL, - 0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL, - 0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL, - 0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL, - 0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL, - 0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL, - 0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL, - 0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL, - 0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL, - 0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL, - 0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL, - 0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL, - 0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL, - 0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL, - 0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL, - 0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL, - 0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL, - 0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL, - 0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL, - 0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL, - 0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL, - 0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL, - 0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL, - 0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL, - 0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL, - 0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL, - 0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL, - 0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL, - 0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL, - 0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL, - 0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL, - 0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL, - 0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL, - 0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL, - 0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL, - 0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL, - 0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL, - 0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL, - 0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL, - 0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL, - 0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL, - 0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL, - 0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL, - 0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL, - 0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL, - 0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL, - 0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL, - 0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL, - 0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL, - 0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL, - 0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL, - 0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL, - 0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL, - 0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL, - 0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL, - 0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL, - 0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL, - 0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL, - 0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL, - 0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL, -}; static const ulong32 Te4[256] = { 0x63636363UL, 0x7c7c7c7cUL, 0x77777777UL, 0x7b7b7b7bUL, 0xf2f2f2f2UL, 0x6b6b6b6bUL, 0x6f6f6f6fUL, 0xc5c5c5c5UL, @@ -355,8 +157,152 @@ static const ulong32 Te4[256] = { 0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL, }; +static const ulong32 TD0[256] = { + 0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL, + 0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL, + 0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL, + 0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL, + 0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL, + 0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL, + 0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL, + 0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL, + 0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL, + 0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL, + 0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL, + 0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL, + 0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL, + 0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL, + 0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL, + 0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL, + 0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL, + 0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL, + 0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL, + 0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL, + 0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL, + 0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL, + 0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL, + 0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL, + 0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL, + 0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL, + 0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL, + 0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL, + 0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL, + 0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL, + 0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL, + 0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL, + 0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL, + 0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL, + 0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL, + 0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL, + 0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL, + 0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL, + 0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL, + 0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL, + 0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL, + 0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL, + 0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL, + 0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL, + 0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL, + 0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL, + 0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL, + 0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL, + 0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL, + 0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL, + 0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL, + 0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL, + 0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL, + 0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL, + 0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL, + 0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL, + 0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL, + 0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL, + 0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL, + 0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL, + 0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL, + 0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL, + 0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL, + 0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL, +}; + +static const ulong32 Td4[256] = { + 0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL, + 0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL, + 0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL, + 0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL, + 0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL, + 0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL, + 0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL, + 0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL, + 0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL, + 0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL, + 0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL, + 0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL, + 0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL, + 0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL, + 0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL, + 0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL, + 0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL, + 0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL, + 0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL, + 0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL, + 0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL, + 0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL, + 0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL, + 0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL, + 0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL, + 0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL, + 0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL, + 0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL, + 0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL, + 0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL, + 0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL, + 0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL, + 0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL, + 0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL, + 0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL, + 0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL, + 0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL, + 0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL, + 0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL, + 0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL, + 0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL, + 0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL, + 0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL, + 0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL, + 0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL, + 0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL, + 0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL, + 0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL, + 0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL, + 0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL, + 0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL, + 0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL, + 0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL, + 0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL, + 0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL, + 0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL, + 0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL, + 0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL, + 0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL, + 0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL, + 0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL, + 0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL, + 0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL, + 0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL, +}; + #ifdef SMALL_CODE +#define Te0(x) TE0[x] +#define Te1(x) ROR(TE0[x], 8) +#define Te2(x) ROR(TE0[x], 16) +#define Te3(x) ROR(TE0[x], 24) + +#define Td0(x) TD0[x] +#define Td1(x) ROR(TD0[x], 8) +#define Td2(x) ROR(TD0[x], 16) +#define Td3(x) ROR(TD0[x], 24) + #define Te4_0 0x000000FF & Te4 #define Te4_1 0x0000FF00 & Te4 #define Te4_2 0x00FF0000 & Te4 @@ -364,6 +310,216 @@ static const ulong32 Te4[256] = { #else +#define Te0(x) TE0[x] +#define Te1(x) TE1[x] +#define Te2(x) TE2[x] +#define Te3(x) TE3[x] + +#define Td0(x) TD0[x] +#define Td1(x) TD1[x] +#define Td2(x) TD2[x] +#define Td3(x) TD3[x] + +static const ulong32 TE1[256] = { + 0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL, + 0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL, + 0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL, + 0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL, + 0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL, + 0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL, + 0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL, + 0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL, + 0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL, + 0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL, + 0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL, + 0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL, + 0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL, + 0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL, + 0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL, + 0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL, + 0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL, + 0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL, + 0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL, + 0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL, + 0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL, + 0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL, + 0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL, + 0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL, + 0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL, + 0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL, + 0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL, + 0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL, + 0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL, + 0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL, + 0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL, + 0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL, + 0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL, + 0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL, + 0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL, + 0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL, + 0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL, + 0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL, + 0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL, + 0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL, + 0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL, + 0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL, + 0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL, + 0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL, + 0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL, + 0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL, + 0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL, + 0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL, + 0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL, + 0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL, + 0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL, + 0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL, + 0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL, + 0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL, + 0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL, + 0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL, + 0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL, + 0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL, + 0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL, + 0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL, + 0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL, + 0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL, + 0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL, + 0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL, +}; +static const ulong32 TE2[256] = { + 0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL, + 0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL, + 0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL, + 0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL, + 0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL, + 0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL, + 0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL, + 0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL, + 0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL, + 0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL, + 0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL, + 0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL, + 0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL, + 0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL, + 0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL, + 0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL, + 0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL, + 0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL, + 0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL, + 0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL, + 0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL, + 0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL, + 0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL, + 0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL, + 0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL, + 0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL, + 0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL, + 0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL, + 0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL, + 0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL, + 0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL, + 0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL, + 0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL, + 0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL, + 0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL, + 0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL, + 0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL, + 0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL, + 0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL, + 0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL, + 0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL, + 0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL, + 0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL, + 0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL, + 0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL, + 0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL, + 0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL, + 0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL, + 0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL, + 0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL, + 0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL, + 0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL, + 0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL, + 0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL, + 0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL, + 0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL, + 0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL, + 0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL, + 0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL, + 0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL, + 0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL, + 0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL, + 0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL, + 0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL, +}; +static const ulong32 TE3[256] = { + + 0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL, + 0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL, + 0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL, + 0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL, + 0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL, + 0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL, + 0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL, + 0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL, + 0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL, + 0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL, + 0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL, + 0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL, + 0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL, + 0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL, + 0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL, + 0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL, + 0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL, + 0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL, + 0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL, + 0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL, + 0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL, + 0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL, + 0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL, + 0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL, + 0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL, + 0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL, + 0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL, + 0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL, + 0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL, + 0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL, + 0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL, + 0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL, + 0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL, + 0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL, + 0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL, + 0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL, + 0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL, + 0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL, + 0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL, + 0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL, + 0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL, + 0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL, + 0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL, + 0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL, + 0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL, + 0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL, + 0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL, + 0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL, + 0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL, + 0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL, + 0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL, + 0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL, + 0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL, + 0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL, + 0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL, + 0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL, + 0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL, + 0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL, + 0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL, + 0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL, + 0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL, + 0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL, + 0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL, + 0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL, +}; + static const ulong32 Te4_0[] = { 0x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, 0x0000006bUL, 0x0000006fUL, 0x000000c5UL, 0x00000030UL, 0x00000001UL, 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, 0x00000076UL, @@ -504,75 +660,7 @@ static const ulong32 Te4_3[] = { 0x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL }; -#endif - -static const ulong32 Td0[256] = { - 0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL, - 0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL, - 0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL, - 0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL, - 0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL, - 0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL, - 0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL, - 0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL, - 0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL, - 0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL, - 0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL, - 0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL, - 0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL, - 0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL, - 0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL, - 0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL, - 0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL, - 0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL, - 0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL, - 0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL, - 0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL, - 0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL, - 0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL, - 0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL, - 0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL, - 0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL, - 0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL, - 0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL, - 0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL, - 0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL, - 0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL, - 0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL, - 0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL, - 0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL, - 0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL, - 0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL, - 0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL, - 0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL, - 0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL, - 0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL, - 0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL, - 0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL, - 0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL, - 0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL, - 0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL, - 0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL, - 0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL, - 0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL, - 0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL, - 0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL, - 0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL, - 0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL, - 0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL, - 0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL, - 0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL, - 0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL, - 0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL, - 0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL, - 0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL, - 0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL, - 0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL, - 0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL, - 0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL, - 0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL, -}; -static const ulong32 Td1[256] = { +static const ulong32 TD1[256] = { 0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL, 0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL, 0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL, @@ -638,7 +726,7 @@ static const ulong32 Td1[256] = { 0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL, 0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL, }; -static const ulong32 Td2[256] = { +static const ulong32 TD2[256] = { 0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL, 0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL, 0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL, @@ -659,7 +747,6 @@ static const ulong32 Td2[256] = { 0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL, 0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL, 0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL, - 0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL, 0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL, 0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL, @@ -705,7 +792,7 @@ static const ulong32 Td2[256] = { 0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL, 0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL, }; -static const ulong32 Td3[256] = { +static const ulong32 TD3[256] = { 0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL, 0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL, 0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL, @@ -771,79 +858,7 @@ static const ulong32 Td3[256] = { 0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL, 0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL, }; -static const ulong32 Td4[256] = { - 0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL, - 0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL, - 0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL, - 0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL, - 0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL, - 0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL, - 0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL, - 0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL, - 0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL, - 0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL, - 0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL, - 0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL, - 0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL, - 0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL, - 0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL, - 0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL, - 0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL, - 0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL, - 0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL, - 0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL, - 0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL, - 0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL, - 0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL, - 0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL, - 0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL, - 0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL, - 0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL, - 0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL, - 0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL, - 0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL, - 0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL, - 0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL, - 0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL, - 0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL, - 0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL, - 0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL, - 0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL, - 0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL, - 0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL, - 0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL, - 0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL, - 0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL, - 0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL, - 0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL, - 0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL, - 0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL, - 0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL, - 0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL, - 0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL, - 0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL, - 0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL, - 0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL, - 0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL, - 0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL, - 0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL, - 0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL, - 0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL, - 0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL, - 0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL, - 0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL, - 0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL, - 0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL, - 0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL, - 0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL, -}; -static const ulong32 rcon[] = { - 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, - 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, - 0x1B000000UL, 0x36000000UL, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ -}; -#ifndef SMALL_CODE static const ulong32 Tks0[] = { 0x00000000UL, 0x0e090d0bUL, 0x1c121a16UL, 0x121b171dUL, 0x3824342cUL, 0x362d3927UL, 0x24362e3aUL, 0x2a3f2331UL, 0x70486858UL, 0x7e416553UL, 0x6c5a724eUL, 0x62537f45UL, 0x486c5c74UL, 0x4665517fUL, 0x547e4662UL, 0x5a774b69UL, @@ -983,5 +998,11 @@ static const ulong32 Tks3[] = { 0x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL, 0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL, 0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL }; -#endif +#endif /* SMALL CODE */ + +static const ulong32 rcon[] = { + 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, + 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, + 0x1B000000UL, 0x36000000UL, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; diff --git a/base64.c b/base64.c index 37796f8..f2421fe 100644 --- a/base64.c +++ b/base64.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/blowfish.c b/blowfish.c index 3a07b97..229ba88 100644 --- a/blowfish.c +++ b/blowfish.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/mem.c b/burn_stack.c similarity index 75% rename from mem.c rename to burn_stack.c index 7dc6ee6..17b1391 100644 --- a/mem.c +++ b/burn_stack.c @@ -4,20 +4,12 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ #include "mycrypt.h" -void zeromem(void *dst, size_t len) -{ - unsigned char *mem = (unsigned char *)dst; - _ARGCHK(dst != NULL); - while (len-- > 0) - *mem++ = 0; -} - void burn_stack(unsigned long len) { unsigned char buf[32]; diff --git a/cast5.c b/cast5.c index 60dbc3b..45a8433 100644 --- a/cast5.c +++ b/cast5.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/cbc.c b/cbc.c deleted file mode 100644 index 5f72f0f..0000000 --- a/cbc.c +++ /dev/null @@ -1,121 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * gurantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org - */ -#include "mycrypt.h" - -#ifdef CBC - -int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key, - int keylen, int num_rounds, symmetric_CBC *cbc) -{ - int x, err; - - _ARGCHK(IV != NULL); - _ARGCHK(key != NULL); - _ARGCHK(cbc != NULL); - - /* bad param? */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - /* setup cipher */ - if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cbc->key)) != CRYPT_OK) { - return err; - } - - /* copy IV */ - cbc->blocklen = cipher_descriptor[cipher].block_length; - cbc->cipher = cipher; - for (x = 0; x < cbc->blocklen; x++) { - cbc->IV[x] = IV[x]; - } - return CRYPT_OK; -} - -int cbc_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_CBC *cbc) -{ - int x, err; - unsigned char tmp[MAXBLOCKSIZE]; - - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - _ARGCHK(cbc != NULL); - - if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { - return err; - } - - /* is blocklen valid? */ - if (cbc->blocklen < 0 || cbc->blocklen > (int)sizeof(cbc->IV)) { - return CRYPT_INVALID_ARG; - } - - /* xor IV against plaintext */ - for (x = 0; x < cbc->blocklen; x++) { - tmp[x] = pt[x] ^ cbc->IV[x]; - } - - /* encrypt */ - cipher_descriptor[cbc->cipher].ecb_encrypt(tmp, ct, &cbc->key); - - /* store IV [ciphertext] for a future block */ - for (x = 0; x < cbc->blocklen; x++) { - cbc->IV[x] = ct[x]; - } - - #ifdef CLEAN_STACK - zeromem(tmp, sizeof(tmp)); - #endif - return CRYPT_OK; -} - -int cbc_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_CBC *cbc) -{ - int x, err; - unsigned char tmp[MAXBLOCKSIZE], tmp2[MAXBLOCKSIZE]; - - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - _ARGCHK(cbc != NULL); - - /* decrypt the block from ct into tmp */ - if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { - return err; - } - cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key); - - /* is blocklen valid? */ - if (cbc->blocklen < 0 || cbc->blocklen > (int)sizeof(cbc->IV)) { - return CRYPT_INVALID_ARG; - } - - /* xor IV against the plaintext of the previous step */ - for (x = 0; x < cbc->blocklen; x++) { - /* copy CT in case ct == pt */ - tmp2[x] = ct[x]; - - /* actually decrypt the byte */ - pt[x] = tmp[x] ^ cbc->IV[x]; - } - - /* replace IV with this current ciphertext */ - for (x = 0; x < cbc->blocklen; x++) { - cbc->IV[x] = tmp2[x]; - } - #ifdef CLEAN_STACK - zeromem(tmp, sizeof(tmp)); - zeromem(tmp2, sizeof(tmp2)); - #endif - return CRYPT_OK; -} - -#endif - diff --git a/cbc_decrypt.c b/cbc_decrypt.c new file mode 100644 index 0000000..add5438 --- /dev/null +++ b/cbc_decrypt.c @@ -0,0 +1,56 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef CBC + +int cbc_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_CBC *cbc) +{ + int x, err; + unsigned char tmp[MAXBLOCKSIZE], tmp2[MAXBLOCKSIZE]; + + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + _ARGCHK(cbc != NULL); + + /* decrypt the block from ct into tmp */ + if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key); + + /* is blocklen valid? */ + if (cbc->blocklen < 0 || cbc->blocklen > (int)sizeof(cbc->IV)) { + return CRYPT_INVALID_ARG; + } + + /* xor IV against the plaintext of the previous step */ + for (x = 0; x < cbc->blocklen; x++) { + /* copy CT in case ct == pt */ + tmp2[x] = ct[x]; + + /* actually decrypt the byte */ + pt[x] = tmp[x] ^ cbc->IV[x]; + } + + /* replace IV with this current ciphertext */ + for (x = 0; x < cbc->blocklen; x++) { + cbc->IV[x] = tmp2[x]; + } + #ifdef CLEAN_STACK + zeromem(tmp, sizeof(tmp)); + zeromem(tmp2, sizeof(tmp2)); + #endif + return CRYPT_OK; +} + +#endif + diff --git a/cbc_encrypt.c b/cbc_encrypt.c new file mode 100644 index 0000000..8db5b5b --- /dev/null +++ b/cbc_encrypt.c @@ -0,0 +1,52 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef CBC + +int cbc_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_CBC *cbc) +{ + int x, err; + unsigned char tmp[MAXBLOCKSIZE]; + + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + _ARGCHK(cbc != NULL); + + if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen valid? */ + if (cbc->blocklen < 0 || cbc->blocklen > (int)sizeof(cbc->IV)) { + return CRYPT_INVALID_ARG; + } + + /* xor IV against plaintext */ + for (x = 0; x < cbc->blocklen; x++) { + tmp[x] = pt[x] ^ cbc->IV[x]; + } + + /* encrypt */ + cipher_descriptor[cbc->cipher].ecb_encrypt(tmp, ct, &cbc->key); + + /* store IV [ciphertext] for a future block */ + for (x = 0; x < cbc->blocklen; x++) { + cbc->IV[x] = ct[x]; + } + + #ifdef CLEAN_STACK + zeromem(tmp, sizeof(tmp)); + #endif + return CRYPT_OK; +} + +#endif diff --git a/cbc_start.c b/cbc_start.c new file mode 100644 index 0000000..f0d5fb6 --- /dev/null +++ b/cbc_start.c @@ -0,0 +1,43 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef CBC + +int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_CBC *cbc) +{ + int x, err; + + _ARGCHK(IV != NULL); + _ARGCHK(key != NULL); + _ARGCHK(cbc != NULL); + + /* bad param? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* setup cipher */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cbc->key)) != CRYPT_OK) { + return err; + } + + /* copy IV */ + cbc->blocklen = cipher_descriptor[cipher].block_length; + cbc->cipher = cipher; + for (x = 0; x < cbc->blocklen; x++) { + cbc->IV[x] = IV[x]; + } + return CRYPT_OK; +} + +#endif diff --git a/cfb.c b/cfb.c deleted file mode 100644 index 398fd38..0000000 --- a/cfb.c +++ /dev/null @@ -1,111 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * gurantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org - */ -#include "mycrypt.h" - -#ifdef CFB - -int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, - int keylen, int num_rounds, symmetric_CFB *cfb) -{ - int x, err; - - _ARGCHK(IV != NULL); - _ARGCHK(key != NULL); - _ARGCHK(cfb != NULL); - - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - - /* copy data */ - cfb->cipher = cipher; - cfb->blocklen = cipher_descriptor[cipher].block_length; - for (x = 0; x < cfb->blocklen; x++) - cfb->IV[x] = IV[x]; - - /* init the cipher */ - if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cfb->key)) != CRYPT_OK) { - return err; - } - - /* encrypt the IV */ - cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->IV, cfb->IV, &cfb->key); - cfb->padlen = 0; - - return CRYPT_OK; -} - -int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb) -{ - int err; - - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - _ARGCHK(cfb != NULL); - - if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) { - return err; - } - - /* is blocklen/padlen valid? */ - if (cfb->blocklen < 0 || cfb->blocklen > (int)sizeof(cfb->IV) || - cfb->padlen < 0 || cfb->padlen > (int)sizeof(cfb->pad)) { - return CRYPT_INVALID_ARG; - } - - while (len-- > 0) { - if (cfb->padlen == cfb->blocklen) { - cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->pad, cfb->IV, &cfb->key); - cfb->padlen = 0; - } - cfb->pad[cfb->padlen] = (*ct = *pt ^ cfb->IV[cfb->padlen]); - ++pt; - ++ct; - ++cfb->padlen; - } - return CRYPT_OK; -} - -int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb) -{ - int err; - - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - _ARGCHK(cfb != NULL); - - if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) { - return err; - } - - /* is blocklen/padlen valid? */ - if (cfb->blocklen < 0 || cfb->blocklen > (int)sizeof(cfb->IV) || - cfb->padlen < 0 || cfb->padlen > (int)sizeof(cfb->pad)) { - return CRYPT_INVALID_ARG; - } - - while (len-- > 0) { - if (cfb->padlen == cfb->blocklen) { - cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->pad, cfb->IV, &cfb->key); - cfb->padlen = 0; - } - cfb->pad[cfb->padlen] = *ct; - *pt = *ct ^ cfb->IV[cfb->padlen]; - ++pt; - ++ct; - ++cfb->padlen; - } - return CRYPT_OK; -} - -#endif - diff --git a/cfb_decrypt.c b/cfb_decrypt.c new file mode 100644 index 0000000..1e1d3c0 --- /dev/null +++ b/cfb_decrypt.c @@ -0,0 +1,48 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef CFB + +int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb) +{ + int err; + + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + _ARGCHK(cfb != NULL); + + if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen/padlen valid? */ + if (cfb->blocklen < 0 || cfb->blocklen > (int)sizeof(cfb->IV) || + cfb->padlen < 0 || cfb->padlen > (int)sizeof(cfb->pad)) { + return CRYPT_INVALID_ARG; + } + + while (len-- > 0) { + if (cfb->padlen == cfb->blocklen) { + cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->pad, cfb->IV, &cfb->key); + cfb->padlen = 0; + } + cfb->pad[cfb->padlen] = *ct; + *pt = *ct ^ cfb->IV[cfb->padlen]; + ++pt; + ++ct; + ++cfb->padlen; + } + return CRYPT_OK; +} + +#endif + diff --git a/cfb_encrypt.c b/cfb_encrypt.c new file mode 100644 index 0000000..8016959 --- /dev/null +++ b/cfb_encrypt.c @@ -0,0 +1,46 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef CFB + +int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb) +{ + int err; + + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + _ARGCHK(cfb != NULL); + + if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen/padlen valid? */ + if (cfb->blocklen < 0 || cfb->blocklen > (int)sizeof(cfb->IV) || + cfb->padlen < 0 || cfb->padlen > (int)sizeof(cfb->pad)) { + return CRYPT_INVALID_ARG; + } + + while (len-- > 0) { + if (cfb->padlen == cfb->blocklen) { + cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->pad, cfb->IV, &cfb->key); + cfb->padlen = 0; + } + cfb->pad[cfb->padlen] = (*ct = *pt ^ cfb->IV[cfb->padlen]); + ++pt; + ++ct; + ++cfb->padlen; + } + return CRYPT_OK; +} + +#endif diff --git a/cfb_start.c b/cfb_start.c new file mode 100644 index 0000000..d471412 --- /dev/null +++ b/cfb_start.c @@ -0,0 +1,47 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef CFB + +int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_CFB *cfb) +{ + int x, err; + + _ARGCHK(IV != NULL); + _ARGCHK(key != NULL); + _ARGCHK(cfb != NULL); + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + + /* copy data */ + cfb->cipher = cipher; + cfb->blocklen = cipher_descriptor[cipher].block_length; + for (x = 0; x < cfb->blocklen; x++) + cfb->IV[x] = IV[x]; + + /* init the cipher */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cfb->key)) != CRYPT_OK) { + return err; + } + + /* encrypt the IV */ + cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->IV, cfb->IV, &cfb->key); + cfb->padlen = 0; + + return CRYPT_OK; +} + +#endif diff --git a/changes b/changes index d47c475..e050ddc 100644 --- a/changes +++ b/changes @@ -1,3 +1,22 @@ +May 12th, 2004 +v0.95 -- Optimized AES and WHIRLPOOL for SMALL_CODE by taking advantage of the fact + the transforms are circulant. AES dropped 5KB and WHIRLPOOL dropped 13KB + using the default build options on the x86. + -- Updated eax so the eax_done() would clear the state [like hmac,pmac,ocb] when + CLEAN_STACK has been defined. + -- added LTC_TEST support to rmd160 + -- updates to mycrypt_pk.h + -- updated rand_prime() to faciliate making RSA composites + -- DSA/RSA now makes composites of the exact size desired. + -- Refactored quite a bit of the code, fewer functions per C file + -- cleaned up the makefiles to organize the objects logically + -- added ICC makefile along with "profiled" targets for both GNU and ICC compilers + -- Marked functions for removal before v1.00 see PLAN for more information + -- GCC 3.4.0 tested and seems to work + -- Added PKCS #5 support + -- Fixed typo in comment header of .C files ;-) + -- Added PKCS #1 OAEP and PSS support. + Feb 20th, 2004 v0.94 -- removed unused variables from ocb.c and fixed it to match known test vectors. -- Added PMAC support, minor changes to OMAC/EAX code [I think....] diff --git a/config.pl b/config.pl deleted file mode 100644 index ef873ad..0000000 --- a/config.pl +++ /dev/null @@ -1,173 +0,0 @@ -#!/usr/bin/perl -# -# Generates a makefile based on user input -# -# Tom St Denis, tomstdenis@yahoo.com, http://tom.iahu.ca - -@settings = ( - "CC,Compiler,gcc", - "AR,Archiver,ar", - "LD,Linker,ld", - "CFLAGS,Optimizations,-Os", - "CFLAGS,Warnings,-Wall -Wsign-compare -W -Wno-unused -Werror", - "CFLAGS,Include Paths,-I./", - "CFLAGS,Other compiler options,", - "CFLAGS,XMALLOC,-DXMALLOC=malloc", - "CFLAGS,XREALLOC,-DXREALLOC=realloc", - "CFLAGS,XCALLOC,-DXCALLOC=calloc", - "CFLAGS,XFREE,-DXFREE=free", - "CFLAGS,XCLOCK,-DXCLOCK=clock", - "CFLAGS,XCLOCKS_PER_SEC,-DXCLOCKS_PER_SEC=CLOCKS_PER_SEC", -); - -@opts = ( - "SMALL_CODE,Use small code where possible (slower code),y", - "NO_FILE,Avoid file I/O calls,n", - "CLEAN_STACK,Clean the stack within functions,n", - "LTC_TEST,Include Test Vector Routines,y", - - "BLOWFISH,Include Blowfish block cipher,y", - "RC2,Include RC2 block cipher,y", - "RC5,Include RC5 block cipher,y", - "RC6,Include RC6 block cipher,y", - "SAFERP,Include Safer+ block cipher,y", - "SAFER,Include Safer-64 block ciphers,n", - "RIJNDAEL,Include Rijndael (AES) block cipher,y", - "XTEA,Include XTEA block cipher,y", - "TWOFISH,Include Twofish block cipher (default: fast),y", - "TWOFISH_SMALL,Use a low ram variant of Twofish (slow cipher+keyschedule!),n", - "TWOFISH_TABLES,Use precomputed tables (fast cipher and faster keychedule but adds ~3.3KB to the size),y", - "TWOFISH_ALL_TABLES,Speed up the key schedule a little (adds ~8KB ontop of TWOFISH_TABLES to the size),n", - "DES,Include DES and 3DES block ciphers,y", - "CAST5,Include CAST5 (aka CAST-128) block cipher,y", - "NOEKEON,Include Noekeon block cipher,y", - "SKIPJACK,Include Skipjack block cipher,y", - - "CFB,Include CFB block mode of operation,y", - "OFB,Include OFB block mode of operation,y", - "ECB,Include ECB block mode of operation,y", - "CBC,Include CBC block mode of operation,y", - "CTR,Include CTR block mode of operation,y", - - "WHIRLPOOL,Include WHIRLPOOL 512-bit one-way hash,y", - "SHA512,Include SHA512 one-way hash,y", - "SHA384,Include SHA384 one-way hash (requires SHA512),y", - "SHA256,Include SHA256 one-way hash,y", - "SHA224,Include SHA224 one-way hash (requires SHA256),y", - "TIGER,Include TIGER one-way hash,y", - "SHA1,Include SHA1 one-way hash,y", - "MD5,Include MD5 one-way hash,y", - "MD4,Include MD4 one-way hash,y", - "MD2,Include MD2 one-way hash,y", - "RIPEMD128,Include RIPEMD-128 one-way hash,y", - "RIPEMD160,Include RIPEMD-160 one-way hash,y", - "HMAC,Include Hash based Message Authentication Support,y", - "OMAC,Include OMAC1 Message Authentication Support,y", - "PMAC,Include PMAC Message Authentication Support,y", - "EAX_MODE,Include EAX Encrypt-and-Authenticate Support,y", - "OCB_MODE,Include OCB Encrypt-and-Authenticate Support,y", - - "BASE64,Include Base64 encoding support,y", - - "YARROW,Include Yarrow PRNG,y", - "SPRNG,Include Secure PRNG base on RNG code,y", - "RC4,Include RC4 PRNG,y", - "DEVRANDOM,Use /dev/random or /dev/urandom if available?,y", - "TRY_URANDOM_FIRST,Try /dev/urandom before /dev/random?,n", - - "MRSA,Include RSA public key support,y", - "MDSA,Include DSA public key support,y", - "MDH,Include Diffie-Hellman (over Z/pZ) public key support,y", - "MECC,Include Eliptic Curve public key crypto support,y", - "KR,Include Keyring support (groups all three PK systems),n", - - "DH768,768-bit DH key support,y", - "DH1024,1024-bit DH key support,y", - "DH1280,1280-bit DH key support,y", - "DH1536,1536-bit DH key support,y", - "DH1792,1792-bit DH key support,y", - "DH2048,2048-bit DH key support,y", - "DH2560,2560-bit DH key support,y", - "DH3072,3072-bit DH key support,y", - "DH4096,4096-bit DH key support,y", - - "ECC160,160-bit ECC key support,y", - "ECC192,192-bit ECC key support,y", - "ECC224,224-bit ECC key support,y", - "ECC256,256-bit ECC key support,y", - "ECC384,384-bit ECC key support,y", - "ECC521,521-bit ECC key support,y", - - "GF,Include GF(2^w) math support (not used internally),n", - - "MPI,Include MPI big integer math support (required by the public key code),y", -); - -# scan for switches and make variables -for (@settings) { - @m = split(",", $_); - print "@m[1]: [@m[2]] "; - $r = <>; $r = @m[2] if ($r eq "\n"); - chomp($r); - @vars{@m[0]} = @vars{@m[0]} . $r . " "; -} - -# scan for build flags -for (@opts) { - @m = split(",", $_); - print "@m[1]: [@m[2]]"; - $r = <>; @vars{'CFLAGS'} = @vars{'CFLAGS'} . "-D" . $m[0] . " " if (($r eq "y\n") || ($r eq "\n" && @m[2] eq "y")); -} - -# write header - -open(OUT,">mycrypt_custom.h"); -print OUT "/* This header is meant to be included before mycrypt.h in projects where\n"; -print OUT " * you don't want to throw all the defines in a makefile. \n"; -print OUT " */\n\n#ifndef MYCRYPT_CUSTOM_H_\n#define MYCRYPT_CUSTOM_H_\n\n#ifdef CRYPT\n\t#error mycrypt_custom.h should be included before mycrypt.h\n#endif\n\n"; - -@m = split(" ", @vars{'CFLAGS'}); -for (@m) { - if ($_ =~ /^-D/) { - $_ =~ s/-D//; - $_ =~ s/=/" "/ge; - print OUT "#define $_\n"; - } -} - -print OUT "\n\n#include \n\n#endif\n\n"; -close OUT; - -print "\n\nmycrypt_custom.h generated.\n"; - -open(OUT,">makefile.out"); -print OUT "#makefile generated with config.pl\n#\n#Tom St Denis (tomstdenis\@yahoo.com, http://tom.iahu.ca) \n\n"; - -# output unique vars first -@vars{'CFLAGS'} =~ s/-D.+ /""/ge; - -for (@settings) { - @m = split(",", $_); - print OUT "@m[0] = @vars{@m[0]}\n" if (@vars{@m[0]} ne "" && @m[0] ne "CFLAGS"); - print OUT "CFLAGS += @vars{@m[0]}\n" if (@vars{@m[0]} ne "" && @m[0] eq "CFLAGS"); - @vars{@m[0]} = ""; -} - -# output objects -print OUT "\ndefault: library\n\n"; -print OUT "OBJECTS = keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o des.o safer_tab.o safer.o saferp.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o mpi.o prime.o twofish.o packet.o hmac.o strings.o rmd128.o rmd160.o skipjack.o omac.o dsa.o eax.o ocb.o pmac.o whirl.o\n\n"; - -# some depends -print OUT "rsa.o: rsa_sys.c\ndh.o: dh_sys.c\necc.o: ecc_sys.c\naes.o: aes.c aes_tab.c\ntwofish.o: twofish.c twofish_tab.c\nsha512.o: sha384.c sha512.c\nsha256.o: sha256.c sha224.c\n\n"; - -# targets -print OUT "library: \$(OBJECTS)\n\t \$(AR) r libtomcrypt.a \$(OBJECTS)\n\t ranlib libtomcrypt.a\n\n"; -print OUT "clean:\n\trm -f \$(OBJECTS) libtomcrypt.a \n\n"; - -close OUT; - -print "makefile.out generated.\n"; - -print "\nNow use makefile.out to build the library, e.g. `make -f makefile.out'\n"; -print "In your project just include mycrypt_custom.h (you don't have to include mycrypt.h \n"; -print "but if you do make sure mycrypt_custom.h appears first) your settings should be intact.\n"; diff --git a/crypt.c b/crypt.c index 99d771d..e94c9cd 100644 --- a/crypt.c +++ b/crypt.c @@ -4,378 +4,11 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ #include "mycrypt.h" -#include - -#define TAB_SIZE 32 - -struct _cipher_descriptor cipher_descriptor[TAB_SIZE] = { -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL } }; - -struct _hash_descriptor hash_descriptor[TAB_SIZE] = { -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, -{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL } }; - -struct _prng_descriptor prng_descriptor[TAB_SIZE] = { -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL }, -{ NULL, NULL, NULL, NULL, NULL } }; - -/* ch1-01-1 */ -#if (ARGTYPE == 0) -void crypt_argchk(char *v, char *s, int d) -{ - fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n", - v, d, s); - (void)raise(SIGABRT); -} -#endif -/* ch1-01-1 */ - -int find_cipher(const char *name) -{ - int x; - _ARGCHK(name != NULL); - for (x = 0; x < TAB_SIZE; x++) { - if (cipher_descriptor[x].name != NULL && !strcmp(cipher_descriptor[x].name, name)) { - return x; - } - } - return -1; -} - -int find_hash(const char *name) -{ - int x; - _ARGCHK(name != NULL); - for (x = 0; x < TAB_SIZE; x++) { - if (hash_descriptor[x].name != NULL && strcmp(hash_descriptor[x].name, name) == 0) { - return x; - } - } - return -1; -} - -int find_prng(const char *name) -{ - int x; - _ARGCHK(name != NULL); - for (x = 0; x < TAB_SIZE; x++) { - if ((prng_descriptor[x].name != NULL) && strcmp(prng_descriptor[x].name, name) == 0) { - return x; - } - } - return -1; -} - -int find_cipher_id(unsigned char ID) -{ - int x; - for (x = 0; x < TAB_SIZE; x++) { - if (cipher_descriptor[x].ID == ID) { - return (cipher_descriptor[x].name == NULL) ? -1 : x; - } - } - return -1; -} - -int find_hash_id(unsigned char ID) -{ - int x; - for (x = 0; x < TAB_SIZE; x++) { - if (hash_descriptor[x].ID == ID) { - return (hash_descriptor[x].name == NULL) ? -1 : x; - } - } - return -1; -} - -/* idea from Wayne Scott */ -int find_cipher_any(const char *name, int blocklen, int keylen) -{ - int x; - - _ARGCHK(name != NULL); - - x = find_cipher(name); - if (x != -1) return x; - - for (x = 0; x < TAB_SIZE; x++) { - if (cipher_descriptor[x].name == NULL) { - continue; - } - if (blocklen <= (int)cipher_descriptor[x].block_length && keylen <= (int)cipher_descriptor[x].max_key_length) { - return x; - } - } - return -1; -} - -/* return first hash with at least [amount over] digestlen bytes of output */ -int find_hash_any(const char *name, int digestlen) -{ - int x, y, z; - _ARGCHK(name != NULL); - - x = find_hash(name); - if (x != -1) return x; - - y = MAXBLOCKSIZE+1; - z = -1; - for (x = 0; x < TAB_SIZE; x++) { - if (hash_descriptor[x].name == NULL) { - continue; - } - if ((int)hash_descriptor[x].hashsize >= digestlen && (int)hash_descriptor[x].hashsize < y) { - z = x; - y = hash_descriptor[x].hashsize; - } - } - return z; -} - - -int register_cipher(const struct _cipher_descriptor *cipher) -{ - int x; - - _ARGCHK(cipher != NULL); - - /* is it already registered? */ - for (x = 0; x < TAB_SIZE; x++) { - if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) { - return x; - } - } - - /* find a blank spot */ - for (x = 0; x < TAB_SIZE; x++) { - if (cipher_descriptor[x].name == NULL) { - memcpy(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor)); - return x; - } - } - - /* no spot */ - return -1; -} - -int unregister_cipher(const struct _cipher_descriptor *cipher) -{ - int x; - - _ARGCHK(cipher != NULL); - - /* is it already registered? */ - for (x = 0; x < TAB_SIZE; x++) { - if (memcmp(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor)) == 0) { - cipher_descriptor[x].name = NULL; - cipher_descriptor[x].ID = 255; - return CRYPT_OK; - } - } - return CRYPT_ERROR; -} - -int register_hash(const struct _hash_descriptor *hash) -{ - int x; - - _ARGCHK(hash != NULL); - - /* is it already registered? */ - for (x = 0; x < TAB_SIZE; x++) { - if (memcmp(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor)) == 0) { - return x; - } - } - - /* find a blank spot */ - for (x = 0; x < TAB_SIZE; x++) { - if (hash_descriptor[x].name == NULL) { - memcpy(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor)); - return x; - } - } - - /* no spot */ - return -1; -} - -int unregister_hash(const struct _hash_descriptor *hash) -{ - int x; - - _ARGCHK(hash != NULL); - - /* is it already registered? */ - for (x = 0; x < TAB_SIZE; x++) { - if (memcmp(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor)) == 0) { - hash_descriptor[x].name = NULL; - return CRYPT_OK; - } - } - return CRYPT_ERROR; -} - -int register_prng(const struct _prng_descriptor *prng) -{ - int x; - - _ARGCHK(prng != NULL); - - /* is it already registered? */ - for (x = 0; x < TAB_SIZE; x++) { - if (memcmp(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor)) == 0) { - return x; - } - } - - /* find a blank spot */ - for (x = 0; x < TAB_SIZE; x++) { - if (prng_descriptor[x].name == NULL) { - memcpy(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor)); - return x; - } - } - - /* no spot */ - return -1; -} - -int unregister_prng(const struct _prng_descriptor *prng) -{ - int x; - - _ARGCHK(prng != NULL); - - /* is it already registered? */ - for (x = 0; x < TAB_SIZE; x++) { - if (memcmp(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor)) != 0) { - prng_descriptor[x].name = NULL; - return CRYPT_OK; - } - } - return CRYPT_ERROR; -} - -int cipher_is_valid(int idx) -{ - if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx].name == NULL) { - return CRYPT_INVALID_CIPHER; - } - return CRYPT_OK; -} - -int hash_is_valid(int idx) -{ - if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) { - return CRYPT_INVALID_HASH; - } - return CRYPT_OK; -} - -int prng_is_valid(int idx) -{ - if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) { - return CRYPT_INVALID_PRNG; - } - return CRYPT_OK; -} const char *crypt_build_settings = "LibTomCrypt " SCRYPT "\n\n" @@ -549,6 +182,9 @@ const char *crypt_build_settings = #if defined(__GNUC__) " GCC compiler detected.\n" #endif +#if defined(INTEL_CC) + " Intel C Compiler detected.\n" +#endif "\nVarious others: " #if defined(GF) @@ -580,9 +216,14 @@ const char *crypt_build_settings = #endif #if defined(LTC_TEST) " LTC_TEST " +#endif +#if defined(PKCS_1) + " PKCS#1 " +#endif +#if defined(PKCS_5) + " PKCS#5 " #endif "\n" - "\n\n\n" ; diff --git a/crypt.pdf b/crypt.pdf index a459ff2..749b9da 100644 Binary files a/crypt.pdf and b/crypt.pdf differ diff --git a/crypt.tex b/crypt.tex index 007b512..14c54ef 100644 --- a/crypt.tex +++ b/crypt.tex @@ -47,7 +47,7 @@ \def\gap{\vspace{0.5ex}} \makeindex \begin{document} -\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.94} +\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.95} \author{Tom St Denis \\ \\ tomstdenis@iahu.ca \\ @@ -108,7 +108,7 @@ number theory and cryptography. \subsection{What the library IS NOT for?} -The library is not designed to be in anyway an implementation of the SSL, PKCS, P1363 or OpenPGP standards. The library +The library is not designed to be in anyway an implementation of the SSL or OpenPGP standards. The library is not designed to be compliant with any known form of API or programming hierarchy. It is not a port of any other library and it is not platform specific (like the MS CSP). So if you're looking to drop in some buzzword compliant crypto library this is not for you. The library has been written from scratch to provide basic functions as @@ -505,21 +505,21 @@ As of this release the current cipher\_descriptors elements are \begin{center} \begin{tabular}{|c|c|c|c|c|c|} \hline Name & Descriptor Name & Block Size & Key Range & Rounds \\ - \hline Blowfish & blowfish\_desc & 8 & 8 ... 56 & 16 \\ + \hline Blowfish & blowfish\_desc & 8 & 8 $\ldots$ 56 & 16 \\ \hline X-Tea & xtea\_desc & 8 & 16 & 32 \\ - \hline RC2 & rc2\_desc & 8 & 8 .. 128 & 16 \\ - \hline RC5-32/12/b & rc5\_desc & 8 & 8 ... 128 & 12 ... 24 \\ - \hline RC6-32/20/b & rc6\_desc & 16 & 8 ... 128 & 20 \\ + \hline RC2 & rc2\_desc & 8 & 8 $\ldots$ 128 & 16 \\ + \hline RC5-32/12/b & rc5\_desc & 8 & 8 $\ldots$ 128 & 12 $\ldots$ 24 \\ + \hline RC6-32/20/b & rc6\_desc & 16 & 8 $\ldots$ 128 & 20 \\ \hline SAFER+ & saferp\_desc &16 & 16, 24, 32 & 8, 12, 16 \\ - \hline Safer K64 & safer\_k64\_desc & 8 & 8 & 6 .. 13 \\ - \hline Safer SK64 & safer\_sk64\_desc & 8 & 8 & 6 .. 13 \\ - \hline Safer K128 & safer\_k128\_desc & 8 & 16 & 6 .. 13 \\ - \hline Safer SK128 & safer\_sk128\_desc & 8 & 16 & 6 .. 13 \\ + \hline Safer K64 & safer\_k64\_desc & 8 & 8 & 6 $\ldots$ 13 \\ + \hline Safer SK64 & safer\_sk64\_desc & 8 & 8 & 6 $\ldots$ 13 \\ + \hline Safer K128 & safer\_k128\_desc & 8 & 16 & 6 $\ldots$ 13 \\ + \hline Safer SK128 & safer\_sk128\_desc & 8 & 16 & 6 $\ldots$ 13 \\ \hline AES & aes\_desc & 16 & 16, 24, 32 & 10, 12, 14 \\ \hline Twofish & twofish\_desc & 16 & 16, 24, 32 & 16 \\ \hline DES & des\_desc & 8 & 7 & 16 \\ \hline 3DES (EDE mode) & des3\_desc & 8 & 21 & 16 \\ - \hline CAST5 (CAST-128) & cast5\_desc & 8 & 5 .. 16 & 12, 16 \\ + \hline CAST5 (CAST-128) & cast5\_desc & 8 & 5 $\ldots$ 16 & 12, 16 \\ \hline Noekeon & noekeon\_desc & 16 & 16 & 16 \\ \hline Skipjack & skipjack\_desc & 8 & 10 & 32 \\ \hline @@ -627,8 +627,7 @@ int main(void) } \end{verbatim} \end{small} -This snippet is a small program that registers only Rijndael only. Note you must register ciphers before -using the PK code since all of the PK code (RSA, DH and ECC) rely heavily on the descriptor tables. +This snippet is a small program that registers only Rijndael only. \section{Symmetric Modes of Operations} \subsection{Background} @@ -890,7 +889,7 @@ int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt); This will encrypt (or decrypt for the latter) a fixed length of data from ``pt'' to ``ct'' (vice versa for the latter). They assume that ``pt'' and ``ct'' are the same size as the block cipher's block size. Note that you cannot call both functions given a single ``ocb'' state. For bi-directional communication you will have to initialize two ``ocb'' -states (with difference nonces). Also ``pt'' and ``ct'' may point to the same location in memory. +states (with different nonces). Also ``pt'' and ``ct'' may point to the same location in memory. When you are finished encrypting the message you call the following function to compute the tag. @@ -1716,8 +1715,175 @@ int main(void) \end{verbatim} \end{small} +\chapter{RSA Public Key Cryptography} +\textbf{Note: } \textit{This chapter on PKCS \#1 RSA will replace the older chapter on RSA (The current chapter nine) in subsequent +releases of the library. Users are encouraged to stop using the LibTomCrypt style padding functions.} + +\section{PKCS \#1 Encryption} + +PKCS \#1 RSA Encryption amounts to OAEP padding of the input message followed by the modular exponentiation. As far as this portion of +the library is concerned we are only dealing with th OAEP padding of the message. + +\subsection{OAEP Encoding} + +\begin{alltt} +int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, int hash_idx, + int prng_idx, prng_state *prng, + unsigned char *out, unsigned long *outlen); +\end{alltt} + +This accepts ``msg'' as input of length ``msglen'' which will be OAEP padded. The ``lparam'' variable is an additional system specific +tag that can be applied to the encoding. This is useful to identify which system encoded the message. If no variance is desired then +``lparam'' can be set to \textbf{NULL}. + +OAEP encoding requires the length of the modulus in bits in order to calculate the size of the output. This is passed as the parameter +``modulus\_bitlen''. ``hash\_idx'' is the index into the hash descriptor table of the hash desired. PKCS \#1 allows any hash to be +used but both the encoder and decoder must use the same hash in order for this to succeed. The size of hash output affects the maximum + sized input message. ``prng\_idx'' and ``prng'' are the random number generator arguments required to randomize the padding process. +The padded message is stored in ``out'' along with the length in ``outlen''. + +If $h$ is the length of the hash and $m$ the length of the modulus (both in octets) then the maximum payload for ``msg'' is +$m - 2h - 2$. For example, with a $1024$--bit RSA key and SHA--1 as the hash the maximum payload is $86$ bytes. + +Note that when the message is padded it still has not been RSA encrypted. You must pass the output of this function to +rsa\_exptmod() to encrypt it. + +\subsection{OAEP Decoding} + +\begin{alltt} +int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, int hash_idx, + unsigned char *out, unsigned long *outlen); +\end{alltt} + +This function decodes an OAEP encoded message and outputs the original message that was passed to the OAEP encoder. ``msg'' is the +output of pkcs\_1\_oaep\_encode() of length ``msglen''. ``lparam'' is the same system variable passed to the OAEP encoder. If it does not +match what was used during encoding this function will not decode the packet. ``modulus\_bitlen'' is the size of the RSA modulus in bits +and must match what was used during encoding. Similarly the ``hash\_idx'' index into the hash descriptor table must match what was used +during encoding. + +If the function succeeds it decodes the OAEP encoded message into ``out'' of length ``outlen''. + +\section{PKCS \#1 Digital Signatures} + +\subsection{PSS Encoding} +PSS encoding is the second half of the PKCS \#1 standard which is padding to be applied to messages that are signed. + +\begin{alltt} +int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, + unsigned long saltlen, int hash_idx, + int prng_idx, prng_state *prng, + unsigned long modulus_bitlen, + unsigned char *out, unsigned long *outlen); +\end{alltt} + +This function assumes the message to be PSS encoded has previously been hashed. The input hash ``msghash'' is of length +``msghashlen''. PSS allows a variable length random salt (it can be zero length) to be introduced in the signature process. +``hash\_idx'' is the index into the hash descriptor table of the hash to use. ``prng\_idx'' and ``prng'' are the random +number generator information required for the salt. + +Similar to OAEP encoding ``modulus\_bitlen'' is the size of the RSA modulus. It limits the size of the salt. If $m$ is the length +of the modulus $h$ the length of the hash output (in octets) then there can be $m - h - 2$ bytes of salt. + +This function does not actually sign the data it merely pads the hash of a message so that it can be processed by rsa\_exptmod(). + +\subsection{PSS Decoding} + +To decode a PSS encoded signature block you have to use the following. + +\begin{alltt} +int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, + const unsigned char *sig, unsigned long siglen, + unsigned long saltlen, int hash_idx, + unsigned long modulus_bitlen, int *res); +\end{alltt} +This will decode the PSS encoded message in ``sig'' of length ``siglen'' and compare it to values in ``msghash'' of length +``msghashlen''. If the block is a valid PSS block and the decoded hash equals the hash supplied ``res'' is set to non--zero. Otherwise, +it is set to zero. The rest of the parameters are as in the PSS encode call. + +It's important to use the same ``saltlen'' and hash for both encoding and decoding as otherwise the procedure will not work. + +\chapter{Password Based Cryptography} +\section{PKCS \#5} +In order to securely handle user passwords for the purposes of creating session keys and chaining IVs the PKCS \#5 was drafted. PKCS \#5 +is made up of two algorithms, Algorithm One and Algorithm Two. Algorithm One is the older fairly limited algorithm which has been implemented +for completeness. Algorithm Two is a bit more modern and more flexible to work with. + +\section{Algorithm One} +Algorithm One accepts as input a password, an 8--byte salt and an iteration counter. The iteration counter is meant to act as delay for +people trying to brute force guess the password. The higher the iteration counter the longer the delay. This algorithm also requires a hash +algorithm and produces an output no longer than the output of the hash. + +\begin{alltt} +int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen) +\end{alltt} +Where ``password'' is the users password. Since the algorithm allows binary passwords you must also specify the length in ``password\_len''. +The ``salt'' is a fixed size 8--byte array which should be random for each user and session. The ``iteration\_count'' is the delay desired +on the password. The ``hash\_idx'' is the index of the hash you wish to use in the descriptor table. + +The output of length upto ``outlen'' is stored in ``out''. If ``outlen'' is initially larger than the size of the hash functions output +it is set to the number of bytes stored. If it is smaller than not all of the hash output is stored in ``out''. + +\section{Algorithm Two} + +Algorithm Two is the recommended algorithm for this task. It allows variable length salts and can produce outputs larger than the +hash functions output. As such it can easily be used to derive session keys for ciphers and MACs as well initial vectors as required +from a single password and invokation of this algorithm. + +\begin{alltt} +int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, unsigned long salt_len, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen) +\end{alltt} +Where ``password'' is the users password. Since the algorithm allows binary passwords you must also specify the length in ``password\_len''. +The ``salt'' is an array of size ``salt\_len''. It should be random for each user and session. The ``iteration\_count'' is the delay desired +on the password. The ``hash\_idx'' is the index of the hash you wish to use in the descriptor table. The output of length upto +``outlen'' is stored in ``out''. + +\begin{alltt} +/* demo to show how to make session state material from a password */ +#include +int main(void) +\{ + unsigned char password[100], salt[100], + cipher_key[16], cipher_iv[16], + mac_key[16], outbuf[48]; + int err, hash_idx; + unsigned long outlen, password_len, salt_len; + + /* register hash and get it's idx .... */ + + /* get users password and make up a salt ... */ + + /* create the material (100 iterations in algorithm) */ + outlen = sizeof(outbuf); + if ((err = pkcs_5_alg2(password, password_len, salt, salt_len, + 100, hash_idx, outbuf, &outlen)) != CRYPT_OK) \{ + /* error handle */ + \} + + /* now extract it */ + memcpy(cipher_key, outbuf, 16); + memcpy(cipher_iv, outbuf+16, 16); + memcpy(mac_key, outbuf+32, 16); + + /* use material (recall to store the salt in the output) */ +\} +\end{alltt} + \chapter{RSA Routines} +\textbf{Note: } \textit{This chapter has been marked for removal. In particular any function that uses the LibTomCrypt style +RSA padding (e.g. rsa\_pad() rsa\_signpad()) will be removed in the v0.96 release cycle. The functions like rsa\_make\_key() and +rsa\_exptmod() will stay but may be slightly modified. } + \section{Background} RSA is a public key algorithm that is based on the inability to find the ``e-th'' root modulo a composite of unknown diff --git a/crypt_argchk.c b/crypt_argchk.c new file mode 100644 index 0000000..3bb73a0 --- /dev/null +++ b/crypt_argchk.c @@ -0,0 +1,21 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" +#include + +#if (ARGTYPE == 0) +void crypt_argchk(char *v, char *s, int d) +{ + fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n", + v, d, s); + (void)raise(SIGABRT); +} +#endif diff --git a/crypt_cipher_descriptor.c b/crypt_cipher_descriptor.c new file mode 100644 index 0000000..fd69d5b --- /dev/null +++ b/crypt_cipher_descriptor.c @@ -0,0 +1,46 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +struct _cipher_descriptor cipher_descriptor[TAB_SIZE] = { +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL } }; + diff --git a/crypt_cipher_is_valid.c b/crypt_cipher_is_valid.c new file mode 100644 index 0000000..8b0c448 --- /dev/null +++ b/crypt_cipher_is_valid.c @@ -0,0 +1,19 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int cipher_is_valid(int idx) +{ + if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx].name == NULL) { + return CRYPT_INVALID_CIPHER; + } + return CRYPT_OK; +} diff --git a/crypt_find_cipher.c b/crypt_find_cipher.c new file mode 100644 index 0000000..0aa88c7 --- /dev/null +++ b/crypt_find_cipher.c @@ -0,0 +1,24 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int find_cipher(const char *name) +{ + int x; + _ARGCHK(name != NULL); + for (x = 0; x < TAB_SIZE; x++) { + if (cipher_descriptor[x].name != NULL && !strcmp(cipher_descriptor[x].name, name)) { + return x; + } + } + return -1; +} + diff --git a/crypt_find_cipher_any.c b/crypt_find_cipher_any.c new file mode 100644 index 0000000..81c33be --- /dev/null +++ b/crypt_find_cipher_any.c @@ -0,0 +1,32 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +/* idea from Wayne Scott */ +int find_cipher_any(const char *name, int blocklen, int keylen) +{ + int x; + + _ARGCHK(name != NULL); + + x = find_cipher(name); + if (x != -1) return x; + + for (x = 0; x < TAB_SIZE; x++) { + if (cipher_descriptor[x].name == NULL) { + continue; + } + if (blocklen <= (int)cipher_descriptor[x].block_length && keylen <= (int)cipher_descriptor[x].max_key_length) { + return x; + } + } + return -1; +} diff --git a/crypt_find_cipher_id.c b/crypt_find_cipher_id.c new file mode 100644 index 0000000..91b19d5 --- /dev/null +++ b/crypt_find_cipher_id.c @@ -0,0 +1,22 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int find_cipher_id(unsigned char ID) +{ + int x; + for (x = 0; x < TAB_SIZE; x++) { + if (cipher_descriptor[x].ID == ID) { + return (cipher_descriptor[x].name == NULL) ? -1 : x; + } + } + return -1; +} diff --git a/crypt_find_hash.c b/crypt_find_hash.c new file mode 100644 index 0000000..1422233 --- /dev/null +++ b/crypt_find_hash.c @@ -0,0 +1,23 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int find_hash(const char *name) +{ + int x; + _ARGCHK(name != NULL); + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x].name != NULL && strcmp(hash_descriptor[x].name, name) == 0) { + return x; + } + } + return -1; +} diff --git a/crypt_find_hash_any.c b/crypt_find_hash_any.c new file mode 100644 index 0000000..5b35252 --- /dev/null +++ b/crypt_find_hash_any.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +/* return first hash with at least [amount over] digestlen bytes of output */ +int find_hash_any(const char *name, int digestlen) +{ + int x, y, z; + _ARGCHK(name != NULL); + + x = find_hash(name); + if (x != -1) return x; + + y = MAXBLOCKSIZE+1; + z = -1; + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x].name == NULL) { + continue; + } + if ((int)hash_descriptor[x].hashsize >= digestlen && (int)hash_descriptor[x].hashsize < y) { + z = x; + y = hash_descriptor[x].hashsize; + } + } + return z; +} diff --git a/crypt_find_hash_id.c b/crypt_find_hash_id.c new file mode 100644 index 0000000..ff04aea --- /dev/null +++ b/crypt_find_hash_id.c @@ -0,0 +1,22 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int find_hash_id(unsigned char ID) +{ + int x; + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x].ID == ID) { + return (hash_descriptor[x].name == NULL) ? -1 : x; + } + } + return -1; +} diff --git a/crypt_find_prng.c b/crypt_find_prng.c new file mode 100644 index 0000000..7fc4e45 --- /dev/null +++ b/crypt_find_prng.c @@ -0,0 +1,24 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int find_prng(const char *name) +{ + int x; + _ARGCHK(name != NULL); + for (x = 0; x < TAB_SIZE; x++) { + if ((prng_descriptor[x].name != NULL) && strcmp(prng_descriptor[x].name, name) == 0) { + return x; + } + } + return -1; +} + diff --git a/crypt_hash_descriptor.c b/crypt_hash_descriptor.c new file mode 100644 index 0000000..7e9f059 --- /dev/null +++ b/crypt_hash_descriptor.c @@ -0,0 +1,45 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +struct _hash_descriptor hash_descriptor[TAB_SIZE] = { +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, +{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL } }; diff --git a/crypt_hash_is_valid.c b/crypt_hash_is_valid.c new file mode 100644 index 0000000..b924e59 --- /dev/null +++ b/crypt_hash_is_valid.c @@ -0,0 +1,19 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int hash_is_valid(int idx) +{ + if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) { + return CRYPT_INVALID_HASH; + } + return CRYPT_OK; +} diff --git a/crypt_prng_descriptor.c b/crypt_prng_descriptor.c new file mode 100644 index 0000000..593516d --- /dev/null +++ b/crypt_prng_descriptor.c @@ -0,0 +1,46 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +struct _prng_descriptor prng_descriptor[TAB_SIZE] = { +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL }, +{ NULL, NULL, NULL, NULL, NULL } }; + diff --git a/crypt_prng_is_valid.c b/crypt_prng_is_valid.c new file mode 100644 index 0000000..cc66bc2 --- /dev/null +++ b/crypt_prng_is_valid.c @@ -0,0 +1,19 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int prng_is_valid(int idx) +{ + if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) { + return CRYPT_INVALID_PRNG; + } + return CRYPT_OK; +} diff --git a/crypt_register_cipher.c b/crypt_register_cipher.c new file mode 100644 index 0000000..5fb0dcb --- /dev/null +++ b/crypt_register_cipher.c @@ -0,0 +1,36 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int register_cipher(const struct _cipher_descriptor *cipher) +{ + int x; + + _ARGCHK(cipher != NULL); + + /* is it already registered? */ + for (x = 0; x < TAB_SIZE; x++) { + if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) { + return x; + } + } + + /* find a blank spot */ + for (x = 0; x < TAB_SIZE; x++) { + if (cipher_descriptor[x].name == NULL) { + memcpy(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor)); + return x; + } + } + + /* no spot */ + return -1; +} diff --git a/crypt_register_hash.c b/crypt_register_hash.c new file mode 100644 index 0000000..7603693 --- /dev/null +++ b/crypt_register_hash.c @@ -0,0 +1,36 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int register_hash(const struct _hash_descriptor *hash) +{ + int x; + + _ARGCHK(hash != NULL); + + /* is it already registered? */ + for (x = 0; x < TAB_SIZE; x++) { + if (memcmp(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor)) == 0) { + return x; + } + } + + /* find a blank spot */ + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x].name == NULL) { + memcpy(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor)); + return x; + } + } + + /* no spot */ + return -1; +} diff --git a/crypt_register_prng.c b/crypt_register_prng.c new file mode 100644 index 0000000..1b14a33 --- /dev/null +++ b/crypt_register_prng.c @@ -0,0 +1,36 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int register_prng(const struct _prng_descriptor *prng) +{ + int x; + + _ARGCHK(prng != NULL); + + /* is it already registered? */ + for (x = 0; x < TAB_SIZE; x++) { + if (memcmp(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor)) == 0) { + return x; + } + } + + /* find a blank spot */ + for (x = 0; x < TAB_SIZE; x++) { + if (prng_descriptor[x].name == NULL) { + memcpy(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor)); + return x; + } + } + + /* no spot */ + return -1; +} diff --git a/crypt_unregister_cipher.c b/crypt_unregister_cipher.c new file mode 100644 index 0000000..6321daf --- /dev/null +++ b/crypt_unregister_cipher.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int unregister_cipher(const struct _cipher_descriptor *cipher) +{ + int x; + + _ARGCHK(cipher != NULL); + + /* is it already registered? */ + for (x = 0; x < TAB_SIZE; x++) { + if (memcmp(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor)) == 0) { + cipher_descriptor[x].name = NULL; + cipher_descriptor[x].ID = 255; + return CRYPT_OK; + } + } + return CRYPT_ERROR; +} diff --git a/crypt_unregister_hash.c b/crypt_unregister_hash.c new file mode 100644 index 0000000..fcdca5f --- /dev/null +++ b/crypt_unregister_hash.c @@ -0,0 +1,27 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int unregister_hash(const struct _hash_descriptor *hash) +{ + int x; + + _ARGCHK(hash != NULL); + + /* is it already registered? */ + for (x = 0; x < TAB_SIZE; x++) { + if (memcmp(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor)) == 0) { + hash_descriptor[x].name = NULL; + return CRYPT_OK; + } + } + return CRYPT_ERROR; +} diff --git a/crypt_unregister_prng.c b/crypt_unregister_prng.c new file mode 100644 index 0000000..c315338 --- /dev/null +++ b/crypt_unregister_prng.c @@ -0,0 +1,27 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int unregister_prng(const struct _prng_descriptor *prng) +{ + int x; + + _ARGCHK(prng != NULL); + + /* is it already registered? */ + for (x = 0; x < TAB_SIZE; x++) { + if (memcmp(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor)) != 0) { + prng_descriptor[x].name = NULL; + return CRYPT_OK; + } + } + return CRYPT_ERROR; +} diff --git a/ctr_decrypt.c b/ctr_decrypt.c new file mode 100644 index 0000000..dce3a39 --- /dev/null +++ b/ctr_decrypt.c @@ -0,0 +1,25 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef CTR + +int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr) +{ + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + _ARGCHK(ctr != NULL); + + return ctr_encrypt(ct, pt, len, ctr); +} + +#endif + diff --git a/ctr.c b/ctr_encrypt.c similarity index 63% rename from ctr.c rename to ctr_encrypt.c index 9d743de..476de38 100644 --- a/ctr.c +++ b/ctr_encrypt.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -12,37 +12,6 @@ #ifdef CTR -int ctr_start(int cipher, const unsigned char *count, const unsigned char *key, int keylen, - int num_rounds, symmetric_CTR *ctr) -{ - int x, err; - - _ARGCHK(count != NULL); - _ARGCHK(key != NULL); - _ARGCHK(ctr != NULL); - - /* bad param? */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - /* setup cipher */ - if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ctr->key)) != CRYPT_OK) { - return err; - } - - /* copy ctr */ - ctr->blocklen = cipher_descriptor[cipher].block_length; - ctr->cipher = cipher; - ctr->padlen = 0; - ctr->mode = 0; - for (x = 0; x < ctr->blocklen; x++) { - ctr->ctr[x] = count[x]; - } - cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key); - return CRYPT_OK; -} - int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr) { int x, err; @@ -92,14 +61,4 @@ int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s return CRYPT_OK; } -int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr) -{ - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - _ARGCHK(ctr != NULL); - - return ctr_encrypt(ct, pt, len, ctr); -} - #endif - diff --git a/ctr_start.c b/ctr_start.c new file mode 100644 index 0000000..f752b65 --- /dev/null +++ b/ctr_start.c @@ -0,0 +1,46 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef CTR + +int ctr_start(int cipher, const unsigned char *count, const unsigned char *key, int keylen, + int num_rounds, symmetric_CTR *ctr) +{ + int x, err; + + _ARGCHK(count != NULL); + _ARGCHK(key != NULL); + _ARGCHK(ctr != NULL); + + /* bad param? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* setup cipher */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ctr->key)) != CRYPT_OK) { + return err; + } + + /* copy ctr */ + ctr->blocklen = cipher_descriptor[cipher].block_length; + ctr->cipher = cipher; + ctr->padlen = 0; + ctr->mode = 0; + for (x = 0; x < ctr->blocklen; x++) { + ctr->ctr[x] = count[x]; + } + cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key); + return CRYPT_OK; +} + +#endif diff --git a/demos/encrypt.c b/demos/encrypt.c index b6b3e5c..5320c21 100644 --- a/demos/encrypt.c +++ b/demos/encrypt.c @@ -11,19 +11,11 @@ int errno; -static const struct _cipher_descriptor *ciphers[] = { - &blowfish_desc, &xtea_desc, &rc5_desc, &rc6_desc, - &saferp_desc, &rijndael_desc, - &twofish_desc, &safer_k64_desc, &safer_sk64_desc, - &safer_k128_desc, &safer_sk128_desc, &rc2_desc, - &des_desc, &des3_desc, &cast5_desc, &skipjack_desc, NULL -}; - int usage(char *name) { int x; - printf("Usage: ./%s [-d](ecrypt) cipher infile outfile\nCiphers:\n", name); + printf("Usage: %s [-d](ecrypt) cipher infile outfile\nCiphers:\n", name); for (x = 0; cipher_descriptor[x].name != NULL; x++) { printf("%s\n",cipher_descriptor[x].name); } @@ -34,12 +26,49 @@ void register_algs(void) { int x; - for (x = 0; ciphers[x] != NULL; x++) { - if (register_cipher(ciphers[x]) == -1) { - printf("Error registering cipher\n"); - exit(-1); - } - } +#ifdef RIJNDAEL + register_cipher (&aes_desc); +#endif +#ifdef BLOWFISH + register_cipher (&blowfish_desc); +#endif +#ifdef XTEA + register_cipher (&xtea_desc); +#endif +#ifdef RC5 + register_cipher (&rc5_desc); +#endif +#ifdef RC6 + register_cipher (&rc6_desc); +#endif +#ifdef SAFERP + register_cipher (&saferp_desc); +#endif +#ifdef TWOFISH + register_cipher (&twofish_desc); +#endif +#ifdef SAFER + register_cipher (&safer_k64_desc); + register_cipher (&safer_sk64_desc); + register_cipher (&safer_k128_desc); + register_cipher (&safer_sk128_desc); +#endif +#ifdef RC2 + register_cipher (&rc2_desc); +#endif +#ifdef DES + register_cipher (&des_desc); + register_cipher (&des3_desc); +#endif +#ifdef CAST5 + register_cipher (&cast5_desc); +#endif +#ifdef NOEKEON + register_cipher (&noekeon_desc); +#endif +#ifdef SKIPJACK + register_cipher (&skipjack_desc); +#endif if (register_hash(&sha256_desc) == -1) { printf("Error registering SHA256\n"); @@ -121,9 +150,9 @@ int main(int argc, char *argv[]) } printf("\nEnter key: "); - fgets(tmpkey,sizeof(tmpkey), stdin); + fgets((char *)tmpkey,sizeof(tmpkey), stdin); outlen = sizeof(key); - if ((errno = hash_memory(hash_idx,tmpkey,strlen(tmpkey),key,&outlen)) != CRYPT_OK) { + if ((errno = hash_memory(hash_idx,tmpkey,strlen((char *)tmpkey),key,&outlen)) != CRYPT_OK) { printf("Error hashing key: %s\n", error_to_string(errno)); exit(-1); } diff --git a/demos/test.c b/demos/test.c index 126e640..6d1df5a 100644 --- a/demos/test.c +++ b/demos/test.c @@ -613,47 +613,50 @@ rsa_test (void) for (z = 1024; z <= limit; z += 512) { t = XCLOCK (); for (tt = 0; tt < 3; tt++) { - if ((errnum = - rsa_make_key (&prng, find_prng ("yarrow"), z / 8, 65537, - &key)) != CRYPT_OK) { - printf ("Error: %s\n", error_to_string (errnum)); - exit (-1); - } - if (tt < 2) - rsa_free (&key); + if ((errnum = rsa_make_key (&prng, find_prng ("yarrow"), z / 8, 65537, &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* check modulus size */ + if (mp_unsigned_bin_size(&key.N) != (int)(z/8)) { + printf("\nRSA key supposed to be %lu bits but was %d bits\n", z, mp_count_bits(&key.N)); + exit(EXIT_FAILURE); + } + + if (tt < 2) { + rsa_free (&key); + } } t = XCLOCK () - t; - printf ("Took %.0f ms to make a %ld-bit RSA key.\n", - 1000.0 * (((double) t / 3.0) / (double) XCLOCKS_PER_SEC), z); + printf ("Took %.0f ms to make a %ld-bit RSA key.\n", 1000.0 * (((double) t / 3.0) / (double) XCLOCKS_PER_SEC), z); /* time encryption */ t = XCLOCK (); for (tt = 0; tt < 20; tt++) { - y = sizeof (in); - if ((errnum = - rsa_exptmod (in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { - printf ("Error: %s\n", error_to_string (errnum)); - exit (-1); - } + y = sizeof (in); + if ((errnum = rsa_exptmod (in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } } t = XCLOCK () - t; printf ("Took %.0f ms to encrypt with a %ld-bit RSA key.\n", - 1000.0 * (((double) t / 20.0) / (double) XCLOCKS_PER_SEC), z); + 1000.0 * (((double) t / 20.0) / (double) XCLOCKS_PER_SEC), z); /* time decryption */ t = XCLOCK (); for (tt = 0; tt < 20; tt++) { - x = sizeof (out); - if ((errnum = - rsa_exptmod (out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { - printf ("Error: %s\n", error_to_string (errnum)); - exit (-1); - } + x = sizeof (out); + if ((errnum = rsa_exptmod (out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } } t = XCLOCK () - t; printf ("Took %.0f ms to decrypt with a %ld-bit RSA key.\n", - 1000.0 * (((double) t / 20.0) / (double) XCLOCKS_PER_SEC), z); + 1000.0 * (((double) t / 20.0) / (double) XCLOCKS_PER_SEC), z); rsa_free (&key); } } @@ -970,12 +973,12 @@ dh_tests (void) printf ("Error: %s\n", error_to_string (errnum)); exit (-1); } - if (dh_verify_hash (buf[1], x, buf[0], 16, &stat, &usera)) { + if ((errnum = dh_verify_hash (buf[1], x, buf[0], 16, &stat, &usera)) != CRYPT_OK) { printf ("Error: %s\n", error_to_string (errnum)); exit (-1); } buf[0][0] ^= 1; - if (dh_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera)) { + if ((errnum = dh_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera)) != CRYPT_OK) { printf ("Error: %s\n", error_to_string (errnum)); exit (-1); } @@ -1272,7 +1275,7 @@ test_prime (void) /* make a 1024 bit prime */ mp_init (&a); - rand_prime (&a, 128, &prng, find_prng ("yarrow")); + rand_prime (&a, 128*8, &prng, find_prng ("yarrow")); /* dump it */ mp_todecimal (&a, buf); @@ -1809,8 +1812,87 @@ void dsa_tests(void) dsa_free(&key); } +#ifdef PKCS_1 +void pkcs1_test(void) +{ + unsigned char buf[3][128]; + int err, res1, res2, res3, prng_idx, hash_idx; + unsigned long x, y, l1, l2, l3, i1, i2; + /* get hash/prng */ + hash_idx = find_hash("sha1"); + prng_idx = find_prng("yarrow"); + /* do many tests */ + for (x = 0; x < 10000; x++) { + zeromem(buf, sizeof(buf)); + + /* make a dummy message (of random length) */ + l3 = (rand() & 31) + 8; + for (y = 0; y < l3; y++) buf[0][y] = rand() & 255; + + /* encode it */ + l1 = sizeof(buf[1]); + if ((err = pkcs_1_oaep_encode(buf[0], l3, NULL, 0, 1024, hash_idx, prng_idx, &prng, buf[1], &l1)) != CRYPT_OK) { + printf("OAEP encode: %s\n", error_to_string(err)); + exit(-1); + } + + /* decode it */ + l2 = sizeof(buf[2]); + if ((err = pkcs_1_oaep_decode(buf[1], l1, NULL, 0, 1024, hash_idx, buf[2], &l2)) != CRYPT_OK) { + printf("OAEP decode: %s\n", error_to_string(err)); + exit(-1); + } + + if (l2 != l3 || memcmp(buf[2], buf[0], l3) != 0) { + printf("Outsize == %lu, should have been %lu, msg contents follow.\n", l2, l3); + printf("ORIGINAL:\n"); + for (x = 0; x < l3; x++) { + printf("%02x ", buf[0][x]); + } + printf("\nRESULT:\n"); + for (x = 0; x < l2; x++) { + printf("%02x ", buf[2][x]); + } + printf("\n\n"); + exit(-1); + } + + /* test PSS */ + l1 = sizeof(buf[1]); + if ((err = pkcs_1_pss_encode(buf[0], l3, l3>>2, hash_idx, prng_idx, &prng, 1024, buf[1], &l1)) != CRYPT_OK) { + printf("PSS encode: %s\n", error_to_string(err)); + exit(-1); + } + + if ((err = pkcs_1_pss_decode(buf[0], l3, buf[1], l1, l3>>2, hash_idx, 1024, &res1)) != CRYPT_OK) { + printf("PSS decode1: %s\n", error_to_string(err)); + exit(-1); + } + + buf[0][i1 = abs(rand()) % l3] ^= 1; + if ((err = pkcs_1_pss_decode(buf[0], l3, buf[1], l1, l3>>2, hash_idx, 1024, &res2)) != CRYPT_OK) { + printf("PSS decode2: %s\n", error_to_string(err)); + exit(-1); + } + + buf[0][i1] ^= 1; + buf[1][i2 = abs(rand()) % l1] ^= 1; + if ((err = pkcs_1_pss_decode(buf[0], l3, buf[1], l1, l3>>2, hash_idx, 1024, &res3)) != CRYPT_OK) { + printf("PSS decode3: %s\n", error_to_string(err)); + exit(-1); + } + + if (!(res1 == 1 && res2 == 0 && res3 == 0)) { + printf("PSS failed: %d, %d, %d, %lu\n", res1, res2, res3, l3); + exit(-1); + } + } + printf("PKCS #1: Passed\n"); +} + +#endif /* PKCS_1 */ int main (void) @@ -1818,6 +1900,7 @@ main (void) #ifdef SONY_PS2 TIMER_Init (); #endif + srand(time(NULL)); register_all_algs (); @@ -1834,7 +1917,6 @@ main (void) printf (crypt_build_settings); test_errs (); - #ifdef HMAC printf ("HMAC: %s\n", hmac_test () == CRYPT_OK ? "passed" : "failed"); if (hmac_test() != CRYPT_OK) exit(EXIT_FAILURE); @@ -1864,6 +1946,10 @@ main (void) cipher_tests (); hash_tests (); +#ifdef PKCS_1 + pkcs1_test(); +#endif + ecb_tests (); cbc_tests (); ctr_tests (); @@ -1882,7 +1968,6 @@ main (void) ecc_tests (); dh_tests (); - gf_tests (); base64_test (); diff --git a/demos/test.c~ b/demos/test.c~ new file mode 100644 index 0000000..8789399 --- /dev/null +++ b/demos/test.c~ @@ -0,0 +1,1985 @@ +/* This is the worst code you have ever seen written on purpose.... this code is just a big hack to test +out the functionality of the library */ + +#ifdef SONY_PS2 +#include +#include +#include "timer.h" +#endif + +#include + +int errnum; + + +int +null_setup (const unsigned char *key, int keylen, int num_rounds, + symmetric_key * skey) +{ + return CRYPT_OK; +} + +void +null_ecb_encrypt (const unsigned char *pt, unsigned char *ct, + symmetric_key * key) +{ + memcpy (ct, pt, 8); +} + +void +null_ecb_decrypt (const unsigned char *ct, unsigned char *pt, + symmetric_key * key) +{ + memcpy (pt, ct, 8); +} + +int +null_test (void) +{ + return CRYPT_OK; +} + +int +null_keysize (int *desired_keysize) +{ + return CRYPT_OK; +} + +const struct _cipher_descriptor null_desc = { + "memcpy()", + 255, + 8, 8, 8, 1, + &null_setup, + &null_ecb_encrypt, + &null_ecb_decrypt, + &null_test, + &null_keysize +}; + + +prng_state prng; + +void +store_tests (void) +{ + unsigned char buf[8]; + unsigned long L; + ulong64 LL; + + printf ("LOAD32/STORE32 tests\n"); + L = 0x12345678UL; + STORE32L (L, &buf[0]); + L = 0; + LOAD32L (L, &buf[0]); + if (L != 0x12345678UL) { + printf ("LOAD/STORE32 Little don't work\n"); + exit (-1); + } + LL = CONST64 (0x01020304050607); + STORE64L (LL, &buf[0]); + LL = 0; + LOAD64L (LL, &buf[0]) + if (LL != CONST64 (0x01020304050607)) { + printf ("LOAD/STORE64 Little don't work\n"); + exit (-1); + } + + L = 0x12345678UL; + STORE32H (L, &buf[0]); + L = 0; + LOAD32H (L, &buf[0]); + if (L != 0x12345678UL) { + printf ("LOAD/STORE32 High don't work, %08lx\n", L); + exit (-1); + } + LL = CONST64 (0x01020304050607); + STORE64H (LL, &buf[0]); + LL = 0; + LOAD64H (LL, &buf[0]) + if (LL != CONST64 (0x01020304050607)) { + printf ("LOAD/STORE64 High don't work\n"); + exit (-1); + } +} + +void +cipher_tests (void) +{ + int x; + + printf ("Ciphers compiled in\n"); + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + printf + (" %12s (%2d) Key Size: %4d to %4d, Block Size: %3d, Default # of rounds: %2d\n", + cipher_descriptor[x].name, cipher_descriptor[x].ID, + cipher_descriptor[x].min_key_length * 8, + cipher_descriptor[x].max_key_length * 8, + cipher_descriptor[x].block_length * 8, + cipher_descriptor[x].default_rounds); + } + +} + +void +ecb_tests (void) +{ + int x; + + printf ("ECB tests\n"); + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + printf (" %12s: ", cipher_descriptor[x].name); + if ((errnum = cipher_descriptor[x].test ()) != CRYPT_OK) { + printf (" **failed** Reason: %s\n", error_to_string (errnum)); + exit (-1); + } else { + printf ("passed\n"); + } + } +} + +#ifdef CBC +void +cbc_tests (void) +{ + symmetric_CBC cbc; + int x, y; + unsigned char blk[32], ct[32], key[32], IV[32]; + const unsigned char test[] = + { 0XFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + printf ("CBC tests\n"); + /* ---- CBC ENCODING ---- */ + /* make up a block and IV */ + for (x = 0; x < 32; x++) + blk[x] = IV[x] = x; + + /* now lets start a cbc session */ + if ((errnum = + cbc_start (find_cipher ("blowfish"), IV, key, 16, 0, + &cbc)) != CRYPT_OK) { + printf ("CBC Setup: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* now lets encode 32 bytes */ + for (x = 0; x < 4; x++) { + if ((errnum = cbc_encrypt (blk + 8 * x, ct + 8 * x, &cbc)) != CRYPT_OK) { + printf ("CBC encrypt: %s\n", error_to_string (errnum)); + exit (-1); + } + } + + zeromem (blk, sizeof (blk)); + + /* ---- CBC DECODING ---- */ + /* make up a IV */ + for (x = 0; x < 32; x++) + IV[x] = x; + + /* now lets start a cbc session */ + if ((errnum = + cbc_start (find_cipher ("blowfish"), IV, key, 16, 0, + &cbc)) != CRYPT_OK) { + printf ("CBC Setup: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* now lets decode 32 bytes */ + for (x = 0; x < 4; x++) { + if ((errnum = cbc_decrypt (ct + 8 * x, blk + 8 * x, &cbc)) != CRYPT_OK) { + printf ("CBC decrypt: %s\n", error_to_string (errnum)); + exit (-1); + } + } + + + /* print output */ + for (x = y = 0; x < 32; x++) + if (blk[x] != x) + y = 1; + printf (" %s\n", y ? "failed" : "passed"); + + /* lets actually check the bytes */ + memset (IV, 0, 8); + IV[0] = 0xFF; /* IV = FF 00 00 00 00 00 00 00 */ + memset (blk, 0, 32); + blk[8] = 0xFF; /* BLK = 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 */ + cbc_start (find_cipher ("memcpy()"), IV, key, 8, 0, &cbc); + cbc_encrypt (blk, ct, &cbc); /* expect: FF 00 00 00 00 00 00 00 */ + cbc_encrypt (blk + 8, ct + 8, &cbc); /* expect: 00 00 00 00 00 00 00 00 */ + if (memcmp (ct, test, 16)) { + printf ("CBC failed logical testing.\n"); + for (x = 0; x < 16; x++) + printf ("%02x ", ct[x]); + printf ("\n"); + exit (-1); + } else { + printf ("CBC passed logical testing.\n"); + } +} +#else +void +cbc_tests (void) +{ + printf ("CBC not compiled in\n"); +} +#endif + +#ifdef OFB +void +ofb_tests (void) +{ + symmetric_OFB ofb; + int x, y; + unsigned char blk[32], ct[32], key[32], IV[32]; + + printf ("OFB tests\n"); + /* ---- ofb ENCODING ---- */ + /* make up a block and IV */ + for (x = 0; x < 32; x++) + blk[x] = IV[x] = x; + + /* now lets start a ofb session */ + if ((errnum = + ofb_start (find_cipher ("cast5"), IV, key, 16, 0, &ofb)) != CRYPT_OK) { + printf ("OFB Setup: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* now lets encode 32 bytes */ + for (x = 0; x < 4; x++) { + if ((errnum = ofb_encrypt (blk + 8 * x, ct + 8 * x, 8, &ofb)) != CRYPT_OK) { + printf ("OFB encrypt: %s\n", error_to_string (errnum)); + exit (-1); + } + } + + zeromem (blk, sizeof (blk)); + + /* ---- ofb DECODING ---- */ + /* make up a IV */ + for (x = 0; x < 32; x++) + IV[x] = x; + + /* now lets start a ofb session */ + if ((errnum = + ofb_start (find_cipher ("cast5"), IV, key, 16, 0, &ofb)) != CRYPT_OK) { + printf ("OFB setup: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* now lets decode 32 bytes */ + for (x = 0; x < 4; x++) { + if ((errnum = ofb_decrypt (ct + 8 * x, blk + 8 * x, 8, &ofb)) != CRYPT_OK) { + printf ("OFB decrypt: %s\n", error_to_string (errnum)); + exit (-1); + } + } + + /* print output */ + for (x = y = 0; x < 32; x++) + if (blk[x] != x) + y = 1; + printf (" %s\n", y ? "failed" : "passed"); + if (y) + exit (-1); +} +#else +void +ofb_tests (void) +{ + printf ("OFB not compiled in\n"); +} +#endif + +#ifdef CFB +void +cfb_tests (void) +{ + symmetric_CFB cfb; + int x, y; + unsigned char blk[32], ct[32], key[32], IV[32]; + + printf ("CFB tests\n"); + /* ---- cfb ENCODING ---- */ + /* make up a block and IV */ + for (x = 0; x < 32; x++) + blk[x] = IV[x] = x; + + /* now lets start a cfb session */ + if ((errnum = + cfb_start (find_cipher ("blowfish"), IV, key, 16, 0, + &cfb)) != CRYPT_OK) { + printf ("CFB setup: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* now lets encode 32 bytes */ + for (x = 0; x < 4; x++) { + if ((errnum = cfb_encrypt (blk + 8 * x, ct + 8 * x, 8, &cfb)) != CRYPT_OK) { + printf ("CFB encrypt: %s\n", error_to_string (errnum)); + exit (-1); + } + } + + zeromem (blk, sizeof (blk)); + + /* ---- cfb DECODING ---- */ + /* make up ahash_descriptor[prng->yarrow.hash].hashsize IV */ + for (x = 0; x < 32; x++) + IV[x] = x; + + /* now lets start a cfb session */ + if ((errnum = + cfb_start (find_cipher ("blowfish"), IV, key, 16, 0, + &cfb)) != CRYPT_OK) { + printf ("CFB Setup: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* now lets decode 32 bytes */ + for (x = 0; x < 4; x++) { + if ((errnum = cfb_decrypt (ct + 8 * x, blk + 8 * x, 8, &cfb)) != CRYPT_OK) { + printf ("CFB decrypt: %s\n", error_to_string (errnum)); + exit (-1); + } + } + + /* print output */ + for (x = y = 0; x < 32; x++) + if (blk[x] != x) + y = 1; + printf (" %s\n", y ? "failed" : "passed"); + if (y) + exit (-1); +} +#else +void +cfb_tests (void) +{ + printf ("CFB not compiled in\n"); +} +#endif + +#ifdef CTR +void +ctr_tests (void) +{ + symmetric_CTR ctr; + int x, y; + unsigned char blk[32], ct[32], key[32], count[32]; + const unsigned char test[] = + { 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0 }; + + printf ("CTR tests\n"); + /* ---- CTR ENCODING ---- */ + /* make up a block and IV */ + for (x = 0; x < 32; x++) + blk[x] = count[x] = x; + + /* now lets start a ctr session */ + if ((errnum = + ctr_start (find_cipher ("xtea"), count, key, 16, 0, + &ctr)) != CRYPT_OK) { + printf ("CTR Setup: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* now lets encode 32 bytes */ + for (x = 0; x < 4; x++) { + if ((errnum = ctr_encrypt (blk + 8 * x, ct + 8 * x, 8, &ctr)) != CRYPT_OK) { + printf ("CTR encrypt: %s\n", error_to_string (errnum)); + exit (-1); + } + } + + zeromem (blk, sizeof (blk)); + + /* ---- CTR DECODING ---- */ + /* make up a IV */ + for (x = 0; x < 32; x++) + count[x] = x; + + /* now lets start a cbc session */ + if ((errnum = + ctr_start (find_cipher ("xtea"), count, key, 16, 0, + &ctr)) != CRYPT_OK) { + printf ("CTR Setup: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* now lets decode 32 bytes */ + for (x = 0; x < 4; x++) { + if ((errnum = ctr_decrypt (ct + 8 * x, blk + 8 * x, 8, &ctr)) != CRYPT_OK) { + printf ("CTR decrypt: %s\n", error_to_string (errnum)); + exit (-1); + } + } + + /* print output */ + for (x = y = 0; x < 32; x++) + if (blk[x] != x) + y = 1; + printf (" %s\n", y ? "failed" : "passed"); + if (y) + exit (-1); + + /* lets actually check the bytes */ + memset (count, 0, 8); + count[0] = 0xFF; /* IV = FF 00 00 00 00 00 00 00 */ + memset (blk, 0, 32); + blk[9] = 2; /* BLK = 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 */ + ctr_start (find_cipher ("memcpy()"), count, key, 8, 0, &ctr); + ctr_encrypt (blk, ct, 8, &ctr); /* expect: FF 00 00 00 00 00 00 00 */ + ctr_encrypt (blk + 8, ct + 8, 8, &ctr); /* expect: 00 03 00 00 00 00 00 00 */ + if (memcmp (ct, test, 16)) { + printf ("CTR failed logical testing.\n"); + for (x = 0; x < 16; x++) + printf ("%02x ", ct[x]); + printf ("\n"); + } else { + printf ("CTR passed logical testing.\n"); + } + +} +#else +void +ctr_tests (void) +{ + printf ("CTR not compiled in\n"); +} +#endif + +void +hash_tests (void) +{ + int x; + printf ("Hash tests\n"); + for (x = 0; hash_descriptor[x].name != NULL; x++) { + printf (" %10s (%2d) ", hash_descriptor[x].name, hash_descriptor[x].ID); + if ((errnum = hash_descriptor[x].test ()) != CRYPT_OK) { + printf ("**failed** Reason: %s\n", error_to_string (errnum)); + exit(-1); + } else { + printf ("passed\n"); + } + } +} + +#ifdef MRSA +void +pad_test (void) +{ + unsigned char in[100], out[100]; + unsigned long x, y; + + /* make a dummy message */ + for (x = 0; x < 16; x++) + in[x] = (unsigned char) x; + + /* pad the message so that random filler is placed before and after it */ + y = 100; + if ((errnum = + rsa_pad (in, 16, out, &y, find_prng ("yarrow"), &prng)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* depad the message to get the original content */ + memset (in, 0, sizeof (in)); + x = 100; + if ((errnum = rsa_depad (out, y, in, &x)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* check outcome */ + printf ("rsa_pad: "); + if (x != 16) { + printf ("Failed. Wrong size.\n"); + exit (-1); + } + for (x = 0; x < 16; x++) + if (in[x] != x) { + printf ("Failed. Expected %02lx and got %02x.\n", x, in[x]); + exit (-1); + } + printf ("passed.\n"); +} +void +rsa_test (void) +{ + unsigned char in[520], out[520]; + unsigned long x, y, z, limit; + int stat; + rsa_key key; + clock_t t; + + /* ---- SINGLE ENCRYPT ---- */ + /* encrypt a short 8 byte string */ + if ((errnum = + rsa_make_key (&prng, find_prng ("yarrow"), 1024 / 8, 65537, + &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + for (x = 0; x < 8; x++) + in[x] = (unsigned char) (x + 1); + y = sizeof (in); + if ((errnum = rsa_exptmod (in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* decrypt it */ + zeromem (in, sizeof (in)); + x = sizeof (out); + if ((errnum = rsa_exptmod (out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* compare */ + printf ("RSA : "); + for (x = 0; x < 8; x++) + if (in[x] != (x + 1)) { + printf ("Failed. x==%02lx, in[%ld]==%02x\n", x, x, in[x]); + exit (-1); + } + printf ("passed.\n"); + + /* test the rsa_encrypt_key functions */ + for (x = 0; x < 16; x++) + in[x] = x; + y = sizeof (out); + if ((errnum = + rsa_encrypt_key (in, 16, out, &y, &prng, find_prng ("yarrow"), + &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + zeromem (in, sizeof (in)); + x = sizeof (in); + if ((errnum = rsa_decrypt_key (out, y, in, &x, &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + printf ("RSA en/de crypt key routines: "); + if (x != 16) { + printf ("Failed (length)\n"); + exit (-1); + } + for (x = 0; x < 16; x++) + if (in[x] != x) { + printf ("Failed (contents)\n"); + exit (-1); + } + printf ("Passed\n"); + + /* test sign_hash functions */ + for (x = 0; x < 16; x++) + in[x] = x; + x = sizeof (in); + if ((errnum = rsa_sign_hash (in, 16, out, &x, &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + printf ("RSA signed hash: %lu bytes\n", x); + if ((errnum = rsa_verify_hash (out, x, in, &stat, &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + printf ("Verify hash: %s, ", stat ? "passed" : "failed"); + in[0] ^= 1; + if ((errnum = rsa_verify_hash (out, x, in, &stat, &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + printf ("%s\n", (!stat) ? "passed" : "failed"); + if (stat) + exit (-1); + rsa_free (&key); + + /* make a RSA key */ +#ifdef SONY_PS2_NOPE + limit = 1024; +#else + limit = 2048; +#endif + + { + int tt; + + for (z = 1024; z <= limit; z += 512) { + t = XCLOCK (); + for (tt = 0; tt < 3; tt++) { + if ((errnum = rsa_make_key (&prng, find_prng ("yarrow"), z / 8, 65537, &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* check modulus size */ + if (mp_unsigned_bin_size(&key.N) != (int)(z/8)) { + printf("\nRSA key supposed to be %lu bits but was %d bits\n", z, mp_count_bits(&key.N)); + exit(EXIT_FAILURE); + } + + if (tt < 2) { + rsa_free (&key); + } + } + t = XCLOCK () - t; + printf ("Took %.0f ms to make a %ld-bit RSA key.\n", 1000.0 * (((double) t / 3.0) / (double) XCLOCKS_PER_SEC), z); + + /* time encryption */ + t = XCLOCK (); + + for (tt = 0; tt < 20; tt++) { + y = sizeof (in); + if ((errnum = rsa_exptmod (in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + } + t = XCLOCK () - t; + printf ("Took %.0f ms to encrypt with a %ld-bit RSA key.\n", + 1000.0 * (((double) t / 20.0) / (double) XCLOCKS_PER_SEC), z); + + /* time decryption */ + t = XCLOCK (); + for (tt = 0; tt < 20; tt++) { + x = sizeof (out); + if ((errnum = rsa_exptmod (out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + } + t = XCLOCK () - t; + printf ("Took %.0f ms to decrypt with a %ld-bit RSA key.\n", + 1000.0 * (((double) t / 20.0) / (double) XCLOCKS_PER_SEC), z); + rsa_free (&key); + } + } +} +#else +void +pad_test (void) +{ + printf ("MRSA not compiled in\n"); +} + +void +rsa_test (void) +{ + printf ("MRSA not compiled in\n"); +} +#endif + +#ifdef BASE64 +void +base64_test (void) +{ + unsigned char buf[2][100]; + unsigned long x, y; + + printf ("Base64 tests\n"); + zeromem (buf, sizeof (buf)); + for (x = 0; x < 16; x++) + buf[0][x] = (unsigned char) x; + + x = 100; + if (base64_encode (buf[0], 16, buf[1], &x) != CRYPT_OK) { + printf (" error: %s\n", error_to_string (errnum)); + exit (-1); + } + printf (" encoded 16 bytes to %ld bytes...[%s]\n", x, buf[1]); + memset (buf[0], 0, 100); + y = 100; + if (base64_decode (buf[1], x, buf[0], &y) != CRYPT_OK) { + printf (" error: %s\n", error_to_string (errnum)); + exit (-1); + } + printf (" decoded %ld bytes to %ld bytes\n", x, y); + for (x = 0; x < 16; x++) + if (buf[0][x] != x) { + printf (" **failed**\n"); + exit (-1); + } + printf (" passed\n"); +} +#else +void +base64_test (void) +{ + printf ("Base64 not compiled in\n"); +} +#endif + +void +time_hash (void) +{ + clock_t t1; + int x, y; + unsigned long z; + unsigned char input[4096], out[MAXBLOCKSIZE]; + printf ("Hash Time Trials (4KB blocks):\n"); + for (x = 0; hash_descriptor[x].name != NULL; x++) { + t1 = XCLOCK (); + z = sizeof (out); + y = 0; + while (XCLOCK () - t1 < (5 * XCLOCKS_PER_SEC)) { + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + hash_memory (x, input, 4096, out, &z); + y += 32; + } + t1 = XCLOCK () - t1; + printf ("%-20s: Hash at %5.2f Mbit/sec\n", hash_descriptor[x].name, + ((8.0 * 4096.0) * + ((double) y / ((double) t1 / (double) XCLOCKS_PER_SEC))) / + 1000000.0); + } +} + +void +time_ecb (void) +{ + clock_t t1, t2; + long x, y1, y2; + unsigned char pt[32], key[32]; + symmetric_key skey; + void (*func) (const unsigned char *, unsigned char *, symmetric_key *); + + printf ("ECB Time Trials for the Symmetric Ciphers:\n"); + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + cipher_descriptor[x].setup (key, cipher_descriptor[x].min_key_length, 0, + &skey); + +#define DO1 func(pt,pt,&skey); +#define DO2 DO1 DO1 +#define DO4 DO2 DO2 +#define DO8 DO4 DO4 +#define DO16 DO8 DO8 +#define DO32 DO16 DO16 +#define DO64 DO32 DO32 +#define DO128 DO64 DO64 +#define DO256 DO128 DO128 + + func = cipher_descriptor[x].ecb_encrypt; + y1 = 0; + t1 = XCLOCK (); + while (XCLOCK () - t1 < 3 * XCLOCKS_PER_SEC) { + DO256; + y1 += 256; + } + t1 = XCLOCK () - t1; + + func = cipher_descriptor[x].ecb_decrypt; + y2 = 0; + t2 = XCLOCK (); + while (XCLOCK () - t2 < 3 * XCLOCKS_PER_SEC) { + DO256; + y2 += 256; + } + t2 = XCLOCK () - t2; + printf + ("%-20s: Encrypt at %5.2f Mbit/sec and Decrypt at %5.2f Mbit/sec\n", + cipher_descriptor[x].name, + ((8.0 * (double) cipher_descriptor[x].block_length) * + ((double) y1 / ((double) t1 / (double) XCLOCKS_PER_SEC))) / 1000000.0, + ((8.0 * (double) cipher_descriptor[x].block_length) * + ((double) y2 / ((double) t2 / (double) XCLOCKS_PER_SEC))) / + 1000000.0); + +#undef DO256 +#undef DO128 +#undef DO64 +#undef DO32 +#undef DO16 +#undef DO8 +#undef DO4 +#undef DO2 +#undef DO1 + } +} + +#ifdef MDH +void +dh_tests (void) +{ + unsigned char buf[3][4096]; + unsigned long x, y, z; + int low, high, stat, stat2; + dh_key usera, userb; + clock_t t1; + + printf("Testing builting DH parameters...."); fflush(stdout); + if ((errnum = dh_test()) != CRYPT_OK) { + printf("DH Error: %s\n", error_to_string(errnum)); + exit(-1); + } + printf("Passed.\n"); + + dh_sizes (&low, &high); + printf ("DH Keys from %d to %d supported.\n", low * 8, high * 8); + + /* make up two keys */ + if ((errnum = + dh_make_key (&prng, find_prng ("yarrow"), 96, &usera)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + if ((errnum = + dh_make_key (&prng, find_prng ("yarrow"), 96, &userb)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* make the shared secret */ + x = 4096; + if ((errnum = dh_shared_secret (&usera, &userb, buf[0], &x)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + + y = 4096; + if ((errnum = dh_shared_secret (&userb, &usera, buf[1], &y)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + if (y != x) { + printf ("DH Shared keys are not same size.\n"); + exit (-1); + } + if (memcmp (buf[0], buf[1], x)) { + printf ("DH Shared keys not same contents.\n"); + exit (-1); + } + + /* now export userb */ + y = 4096; + if ((errnum = dh_export (buf[1], &y, PK_PUBLIC, &userb)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + dh_free (&userb); + + /* import and make the shared secret again */ + if ((errnum = dh_import (buf[1], y, &userb)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + z = 4096; + if ((errnum = dh_shared_secret (&usera, &userb, buf[2], &z)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + + printf ("DH routines: "); + if (z != x) { + printf ("failed. Size don't match?\n"); + exit (-1); + } + if (memcmp (buf[0], buf[2], x)) { + printf ("Failed. Content didn't match.\n"); + exit (-1); + } + printf ("Passed\n"); + dh_free (&usera); + dh_free (&userb); + +/* time stuff */ + { + static int sizes[] = { 96, 128, 160, 192, 224, 256, 320, 384, 512 }; + int ii, tt; + + for (ii = 0; ii < (int) (sizeof (sizes) / sizeof (sizes[0])); ii++) { + t1 = XCLOCK (); + for (tt = 0; tt < 25; tt++) { + dh_make_key (&prng, find_prng ("yarrow"), sizes[ii], &usera); + dh_free (&usera); + } + t1 = XCLOCK () - t1; + printf ("Make dh-%d key took %f msec\n", sizes[ii] * 8, + 1000.0 * (((double) t1 / 25.0) / (double) XCLOCKS_PER_SEC)); + } + } + +/* test encrypt_key */ + dh_make_key (&prng, find_prng ("yarrow"), 128, &usera); + for (x = 0; x < 16; x++) + buf[0][x] = x; + y = sizeof (buf[1]); + if ((errnum = + dh_encrypt_key (buf[0], 16, buf[1], &y, &prng, find_prng ("yarrow"), + find_hash ("md5"), &usera)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + zeromem (buf[0], sizeof (buf[0])); + x = sizeof (buf[0]); + if ((errnum = dh_decrypt_key (buf[1], y, buf[0], &x, &usera)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + printf ("DH en/de crypt key routines: "); + if (x != 16) { + printf ("Failed (length)\n"); + exit (-1); + } + for (x = 0; x < 16; x++) + if (buf[0][x] != x) { + printf ("Failed (contents)\n"); + exit (-1); + } + printf ("Passed (size %lu)\n", y); + +/* test sign_hash */ + for (x = 0; x < 16; x++) + buf[0][x] = x; + x = sizeof (buf[1]); + if ((errnum = + dh_sign_hash (buf[0], 16, buf[1], &x, &prng, find_prng ("yarrow"), + &usera)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + if ((errnum = dh_verify_hash (buf[1], x, buf[0], 16, &stat, &usera)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + buf[0][0] ^= 1; + if ((errnum = dh_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + printf ("dh_sign/verify_hash: %s (%d,%d), %lu\n", + ((stat == 1) + && (stat2 == 0)) ? "passed" : "failed", stat, stat2, x); + dh_free (&usera); +} +#else +void +dh_tests (void) +{ + printf ("MDH not compiled in\n"); +} +#endif + +int callback_x = 0; +void +callback (void) +{ + printf ("%c\x08", "-\\|/"[++callback_x & 3]); +#ifndef SONY_PS2 + fflush (stdout); +#endif +} + +void +rng_tests (void) +{ + unsigned char buf[16]; + clock_t t1; + int x, y; + + printf ("RNG tests\n"); + t1 = XCLOCK (); + x = rng_get_bytes (buf, sizeof (buf), &callback); + t1 = XCLOCK () - t1; + printf (" %f bytes per second...", + (double) x / ((double) t1 / (double) XCLOCKS_PER_SEC)); + printf ("read %d bytes.\n ", x); + for (y = 0; y < x; y++) + printf ("%02x ", buf[y]); + printf ("\n"); + +#ifdef YARROW + if ((errnum = + rng_make_prng (128, find_prng ("yarrow"), &prng, + &callback)) != CRYPT_OK) { + printf (" starting yarrow error: %s\n", error_to_string (errnum)); + exit (-1); + } +#endif +} + +#ifdef MECC +void +ecc_tests (void) +{ + unsigned char buf[4][4096]; + unsigned long x, y, z; + int stat, stat2, low, high; + ecc_key usera, userb; + clock_t t1; + + if ((errnum = ecc_test ()) != CRYPT_OK) { + printf ("ecc Error: %s\n", error_to_string (errnum)); + exit (-1); + } + + ecc_sizes (&low, &high); + printf ("ecc Keys from %d to %d supported.\n", low * 8, high * 8); + + /* make up two keys */ + if ((errnum = + ecc_make_key (&prng, find_prng ("yarrow"), 24, &usera)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + if ((errnum = + ecc_make_key (&prng, find_prng ("yarrow"), 24, &userb)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* make the shared secret */ + x = 4096; + if ((errnum = ecc_shared_secret (&usera, &userb, buf[0], &x)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + + y = 4096; + if ((errnum = ecc_shared_secret (&userb, &usera, buf[1], &y)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + + if (y != x) { + printf ("ecc Shared keys are not same size.\n"); + exit (-1); + } + + if (memcmp (buf[0], buf[1], x)) { + printf ("ecc Shared keys not same contents.\n"); + exit (-1); + } + + /* now export userb */ + y = 4096; + if ((errnum = ecc_export (buf[1], &y, PK_PUBLIC, &userb)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + ecc_free (&userb); + printf ("ECC-192 export took %ld bytes\n", y); + + /* import and make the shared secret again */ + if ((errnum = ecc_import (buf[1], y, &userb)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + + z = 4096; + if ((errnum = ecc_shared_secret (&usera, &userb, buf[2], &z)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + + printf ("ecc routines: "); + if (z != x) { + printf ("failed. Size don't match?\n"); + exit (-1); + } + if (memcmp (buf[0], buf[2], x)) { + printf ("Failed. Content didn't match.\n"); + exit (-1); + } + printf ("Passed\n"); + ecc_free (&usera); + ecc_free (&userb); + +/* time stuff */ + { + static int sizes[] = { 20, 24, 28, 32, 48, 65 }; + int ii, tt; + + for (ii = 0; ii < (int) (sizeof (sizes) / sizeof (sizes[0])); ii++) { + t1 = XCLOCK (); + for (tt = 0; tt < 10; tt++) { + if ((errnum = + ecc_make_key (&prng, find_prng ("yarrow"), sizes[ii], + &usera)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + ecc_free (&usera); + } + t1 = XCLOCK () - t1; + printf ("Make ECC-%d key took %f msec\n", sizes[ii] * 8, + 1000.0 * (((double) t1 / 10.0) / (double) XCLOCKS_PER_SEC)); + } + } + +/* test encrypt_key */ + ecc_make_key (&prng, find_prng ("yarrow"), 20, &usera); + for (x = 0; x < 32; x++) + buf[0][x] = x; + y = sizeof (buf[1]); + if ((errnum = + ecc_encrypt_key (buf[0], 32, buf[1], &y, &prng, find_prng ("yarrow"), + find_hash ("sha256"), &usera)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + zeromem (buf[0], sizeof (buf[0])); + x = sizeof (buf[0]); + if ((errnum = ecc_decrypt_key (buf[1], y, buf[0], &x, &usera)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + printf ("ECC en/de crypt key routines: "); + if (x != 32) { + printf ("Failed (length)\n"); + exit (-1); + } + for (x = 0; x < 32; x++) + if (buf[0][x] != x) { + printf ("Failed (contents)\n"); + exit (-1); + } + printf ("Passed (size: %lu)\n", y); +/* test sign_hash */ + for (x = 0; x < 16; x++) + buf[0][x] = x; + x = sizeof (buf[1]); + if ((errnum = + ecc_sign_hash (buf[0], 16, buf[1], &x, &prng, find_prng ("yarrow"), + &usera)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + printf("Signature size: %lu\n", x); + if (ecc_verify_hash (buf[1], x, buf[0], 16, &stat, &usera)) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + buf[0][0] ^= 1; + if (ecc_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera)) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + printf ("ecc_sign/verify_hash: %s (%d,%d)\n", + ((stat == 1) && (stat2 == 0)) ? "passed" : "failed", stat, stat2); + ecc_free (&usera); +} +#else +void +ecc_tests (void) +{ + printf ("MECC not compiled in\n"); +} +#endif + +#ifdef GF +void +gf_tests (void) +{ + gf_int a, b, c, d; + int n; + unsigned char buf[1024]; + + printf ("GF tests\n"); + gf_zero (a); + gf_zero (b); + gf_zero (c); + gf_zero (d); + + /* a == 0x18000000b */ + a[1] = 1; + a[0] = 0x8000000bUL; + + /* b == 0x012345678 */ + b[0] = 0x012345678UL; + + /* find 1/b mod a */ + gf_invmod (b, a, c); + + /* find 1/1/b mod a */ + gf_invmod (c, a, d); + + /* display them */ + printf (" %08lx %08lx\n", c[0], d[0]); + + /* store as binary string */ + n = gf_size (a); + printf (" a takes %d bytes\n", n); + gf_toraw (a, buf); + gf_readraw (a, buf, n); + printf (" a == %08lx%08lx\n", a[1], a[0]); + + /* primality testing */ + gf_zero (a); + a[0] = 0x169; + printf (" GF prime: %s, ", gf_is_prime (a) ? "passed" : "failed"); + a[0] = 0x168; + printf (" %s\n", gf_is_prime (a) ? "failed" : "passed"); + + /* test sqrt code */ + gf_zero (a); + a[1] = 0x00000001; + a[0] = 0x8000000bUL; + gf_zero (b); + b[0] = 0x12345678UL; + + gf_sqrt (b, a, c); + gf_mulmod (c, c, a, b); + printf (" (%08lx)^2 = %08lx (mod %08lx%08lx) \n", c[0], b[0], a[1], a[0]); +} +#else +void +gf_tests (void) +{ + printf ("GF not compiled in\n"); +} +#endif + +#ifdef MPI +void +test_prime (void) +{ + char buf[1024]; + mp_int a; + int x; + + /* make a 1024 bit prime */ + mp_init (&a); + rand_prime (&a, 128*8, &prng, find_prng ("yarrow")); + + /* dump it */ + mp_todecimal (&a, buf); + printf ("1024-bit prime:\n"); + for (x = 0; x < (int) strlen (buf);) { + printf ("%c", buf[x]); + if (!(++x % 60)) + printf ("\\ \n"); + } + printf ("\n\n"); + + mp_clear (&a); +} +#else +void +test_prime (void) +{ + printf ("MPI not compiled in\n"); +} +#endif + +void +register_all_algs (void) +{ +#ifdef RIJNDAEL + register_cipher (&aes_desc); +#endif +#ifdef BLOWFISH + register_cipher (&blowfish_desc); +#endif +#ifdef XTEA + register_cipher (&xtea_desc); +#endif +#ifdef RC5 + register_cipher (&rc5_desc); +#endif +#ifdef RC6 + register_cipher (&rc6_desc); +#endif +#ifdef SAFERP + register_cipher (&saferp_desc); +#endif +#ifdef TWOFISH + register_cipher (&twofish_desc); +#endif +#ifdef SAFER + register_cipher (&safer_k64_desc); + register_cipher (&safer_sk64_desc); + register_cipher (&safer_k128_desc); + register_cipher (&safer_sk128_desc); +#endif +#ifdef RC2 + register_cipher (&rc2_desc); +#endif +#ifdef DES + register_cipher (&des_desc); + register_cipher (&des3_desc); +#endif +#ifdef CAST5 + register_cipher (&cast5_desc); +#endif +#ifdef NOEKEON + register_cipher (&noekeon_desc); +#endif +#ifdef SKIPJACK + register_cipher (&skipjack_desc); +#endif + register_cipher (&null_desc); + +#ifdef TIGER + register_hash (&tiger_desc); +#endif +#ifdef MD2 + register_hash (&md2_desc); +#endif +#ifdef MD4 + register_hash (&md4_desc); +#endif +#ifdef MD5 + register_hash (&md5_desc); +#endif +#ifdef SHA1 + register_hash (&sha1_desc); +#endif +#ifdef SHA256 + register_hash (&sha256_desc); +#endif +#ifdef SHA224 + register_hash (&sha224_desc); +#endif +#ifdef SHA384 + register_hash (&sha384_desc); +#endif +#ifdef SHA512 + register_hash (&sha512_desc); +#endif +#ifdef RIPEMD128 + register_hash (&rmd128_desc); +#endif +#ifdef RIPEMD160 + register_hash (&rmd160_desc); +#endif +#ifdef WHIRLPOOL + register_hash (&whirlpool_desc); +#endif + +#ifdef YARROW + register_prng (&yarrow_desc); +#endif +#ifdef SPRNG + register_prng (&sprng_desc); +#endif +} + +#ifdef KR +void +kr_display (pk_key * kr) +{ + static const char *sys[] = { "NON-KEY", "RSA", "DH", "ECC" }; + static const char *type[] = { "PRIVATE", "PUBLIC", "PRIVATE_OPTIMIZED" }; + + while (kr->system != NON_KEY) { + printf ("CRC [%08lx], System [%10s], Type [%20s], %s, %s, %s\n", kr->ID, + sys[kr->system], type[kr->key_type], kr->name, kr->email, + kr->description); + kr = kr->next; + } + printf ("\n"); +} + +void +kr_test_makekeys (pk_key ** kr) +{ + if ((errnum = kr_init (kr)) != CRYPT_OK) { + printf ("KR init error %s\n", error_to_string (errnum)); + exit (-1); + } + + /* make a DH key */ + printf ("KR: Making DH key...\n"); + if ((errnum = + kr_make_key (*kr, &prng, find_prng ("yarrow"), DH_KEY, 128, "dhkey", + "dh@dh.dh", "dhkey one")) != CRYPT_OK) { + printf ("Make key error: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* make a ECC key */ + printf ("KR: Making ECC key...\n"); + if ((errnum = + kr_make_key (*kr, &prng, find_prng ("yarrow"), ECC_KEY, 20, "ecckey", + "ecc@ecc.ecc", "ecckey one")) != CRYPT_OK) { + printf ("Make key error: %s\n", error_to_string (errnum)); + exit (-1); + } + + /* make a RSA key */ + printf ("KR: Making RSA key...\n"); + if ((errnum = + kr_make_key (*kr, &prng, find_prng ("yarrow"), RSA_KEY, 128, "rsakey", + "rsa@rsa.rsa", "rsakey one")) != CRYPT_OK) { + printf ("Make key error: %s\n", error_to_string (errnum)); + exit (-1); + } + +} + +void +kr_test (void) +{ + pk_key *kr, *_kr; + unsigned char buf[8192], buf2[8192], buf3[8192]; + unsigned long len; + int i, j, stat; +#ifndef NO_FILE + FILE *f; +#endif + + kr_test_makekeys (&kr); + + printf ("The original list:\n"); + kr_display (kr); + + for (i = 0; i < 3; i++) { + len = sizeof (buf); + if ((errnum = kr_export (kr, kr->ID, kr->key_type, buf, &len)) != CRYPT_OK) { + printf ("Error exporting key %d, %s\n", i, error_to_string (errnum)); + exit (-1); + } + printf ("Exported key was: %lu bytes\n", len); + if ((errnum = kr_del (&kr, kr->ID)) != CRYPT_OK) { + printf ("Error deleting key %d, %s\n", i, error_to_string (errnum)); + exit (-1); + } + kr_display (kr); + if ((errnum = kr_import (kr, buf, len)) != CRYPT_OK) { + printf ("Error importing key %d, %s\n", i, error_to_string (errnum)); + exit (-1); + } + kr_display (kr); + } + + for (i = 0; i < 3; i++) { + len = sizeof (buf); + if ((errnum = kr_export (kr, kr->ID, PK_PUBLIC, buf, &len)) != CRYPT_OK) { + printf ("Error exporting key %d, %s\n", i, error_to_string (errnum)); + exit (-1); + } + printf ("Exported key was: %lu bytes\n", len); + if ((errnum = kr_del (&kr, kr->ID)) != CRYPT_OK) { + printf ("Error deleting key %d, %s\n", i, error_to_string (errnum)); + exit (-1); + } + kr_display (kr); + if ((errnum = kr_import (kr, buf, len)) != CRYPT_OK) { + printf ("Error importing key %d, %s\n", i, error_to_string (errnum)); + exit (-1); + } + kr_display (kr); + } + + if ((errnum = kr_clear (&kr)) != CRYPT_OK) { + printf ("Error clearing ring: %s\n", error_to_string (errnum)); + exit (-1); + } + + +/* TEST output to file */ +#ifndef NO_FILE + + if ((errnum = kr_init (&kr)) != CRYPT_OK) { + printf ("KR init error %s\n", error_to_string (errnum)); + exit (-1); + } + kr_test_makekeys (&kr); + + /* save to file */ + f = fopen ("ring.dat", "wb"); + if ((errnum = kr_save (kr, f, NULL)) != CRYPT_OK) { + printf ("kr_save error %s\n", error_to_string (errnum)); + exit (-1); + } + fclose (f); + + /* delete and load */ + if ((errnum = kr_clear (&kr)) != CRYPT_OK) { + printf ("clear error: %s\n", error_to_string (errnum)); + exit (-1); + } + + f = fopen ("ring.dat", "rb"); + if ((errnum = kr_load (&kr, f, NULL)) != CRYPT_OK) { + printf ("kr_load error %s\n", error_to_string (errnum)); + exit (-1); + } + fclose (f); + remove ("ring.dat"); + printf ("After load and save...\n"); + kr_display (kr); + + if ((errnum = kr_clear (&kr)) != CRYPT_OK) { + printf ("clear error: %s\n", error_to_string (errnum)); + exit (-1); + } +#endif + +/* test the packet encryption/sign stuff */ + for (i = 0; i < 32; i++) + buf[i] = i; + kr_test_makekeys (&kr); + _kr = kr; + for (i = 0; i < 3; i++) { + printf ("Testing a key with system %d, type %d:\t", _kr->system, + _kr->key_type); + len = sizeof (buf2); + if ((errnum = + kr_encrypt_key (kr, _kr->ID, buf, 16, buf2, &len, &prng, + find_prng ("yarrow"), + find_hash ("md5"))) != CRYPT_OK) { + printf ("Encrypt error, %d, %s\n", i, error_to_string (errnum)); + exit (-1); + } + len = sizeof (buf3); + if ((errnum = kr_decrypt_key (kr, buf2, buf3, &len)) != CRYPT_OK) { + printf ("decrypt error, %d, %s\n", i, error_to_string (errnum)); + exit (-1); + } + if (len != 16 || memcmp (buf3, buf, 16)) { + printf ("kr_decrypt_key failed, %i, %lu\n", i, len); + exit (-1); + } + printf ("kr_encrypt_key passed, "); + + len = sizeof (buf2); + if ((errnum = + kr_sign_hash (kr, _kr->ID, buf, 32, buf2, &len, &prng, + find_prng ("yarrow"))) != CRYPT_OK) { + printf ("kr_sign_hash failed, %i, %s\n", i, error_to_string (errnum)); + exit (-1); + } + printf ("kr_sign_hash: "); + if ((errnum = kr_verify_hash (kr, buf2, buf, 32, &stat)) != CRYPT_OK) { + printf ("kr_sign_hash failed, %i, %s\n", i, error_to_string (errnum)); + exit (-1); + } + printf ("%s, ", stat ? "passed" : "failed"); + buf[15] ^= 1; + if ((errnum = kr_verify_hash (kr, buf2, buf, 32, &stat)) != CRYPT_OK) { + printf ("kr_sign_hash failed, %i, %s\n", i, error_to_string (errnum)); + exit (-1); + } + printf ("%s\n", (!stat) ? "passed" : "failed"); + buf[15] ^= 1; + + len = sizeof (buf); + if ((errnum = + kr_fingerprint (kr, _kr->ID, find_hash ("sha1"), buf, + &len)) != CRYPT_OK) { + printf ("kr_fingerprint failed, %i, %lu\n", i, len); + exit (-1); + } + printf ("Fingerprint: "); + for (j = 0; j < 20; j++) { + printf ("%02x", buf[j]); + if (j < 19) + printf (":"); + } + printf ("\n\n"); + + _kr = _kr->next; + } + +/* Test encrypting/decrypting to a public key */ +/* first dump the other two keys */ + kr_del (&kr, kr->ID); + kr_del (&kr, kr->ID); + kr_display (kr); + + /* now export it as public and private */ + len = sizeof (buf); + if ((errnum = kr_export (kr, kr->ID, PK_PUBLIC, buf, &len)) != CRYPT_OK) { + printf ("Error exporting key %d, %s\n", i, error_to_string (errnum)); + exit (-1); + } + + /* check boundaries */ + memset (buf + len, 0, sizeof (buf) - len); + + len = sizeof (buf2); + if ((errnum = kr_export (kr, kr->ID, PK_PRIVATE, buf2, &len)) != CRYPT_OK) { + printf ("Error exporting key %s\n", error_to_string (errnum)); + exit (-1); + } + + /* check boundaries */ + memset (buf2 + len, 0, sizeof (buf2) - len); + + /* delete the key and import the public */ + kr_clear (&kr); + kr_init (&kr); + kr_display (kr); + if ((errnum = kr_import (kr, buf, len)) != CRYPT_OK) { + printf ("Error importing key %s\n", error_to_string (errnum)); + exit (-1); + } + kr_display (kr); + + /* now encrypt a buffer */ + for (i = 0; i < 16; i++) + buf[i] = i; + len = sizeof (buf3); + if ((errnum = + kr_encrypt_key (kr, kr->ID, buf, 16, buf3, &len, &prng, + find_prng ("yarrow"), + find_hash ("md5"))) != CRYPT_OK) { + printf ("Encrypt error, %d, %s\n", i, error_to_string (errnum)); + exit (-1); + } + + /* now delete the key and import the private one */ + kr_clear (&kr); + kr_init (&kr); + kr_display (kr); + if ((errnum = kr_import (kr, buf2, len)) != CRYPT_OK) { + printf ("Error importing key %s\n", error_to_string (errnum)); + exit (-1); + } + kr_display (kr); + + /* now decrypt */ + len = sizeof (buf2); + if ((errnum = kr_decrypt_key (kr, buf3, buf2, &len)) != CRYPT_OK) { + printf ("decrypt error, %s\n", error_to_string (errnum)); + exit (-1); + } + + printf ("KR encrypt to public, decrypt with private: "); + if (len == 16 && !memcmp (buf2, buf, 16)) { + printf ("passed\n"); + } else { + printf ("failed\n"); + } + + kr_clear (&kr); +} +#endif + +void +test_errs (void) +{ +#define ERR(x) printf("%25s => %s\n", #x, error_to_string(x)); + + ERR (CRYPT_OK); + ERR (CRYPT_ERROR); + + ERR (CRYPT_INVALID_KEYSIZE); + ERR (CRYPT_INVALID_ROUNDS); + ERR (CRYPT_FAIL_TESTVECTOR); + + ERR (CRYPT_BUFFER_OVERFLOW); + ERR (CRYPT_INVALID_PACKET); + + ERR (CRYPT_INVALID_PRNGSIZE); + ERR (CRYPT_ERROR_READPRNG); + + ERR (CRYPT_INVALID_CIPHER); + ERR (CRYPT_INVALID_HASH); + ERR (CRYPT_INVALID_PRNG); + + ERR (CRYPT_MEM); + + ERR (CRYPT_PK_TYPE_MISMATCH); + ERR (CRYPT_PK_NOT_PRIVATE); + + ERR (CRYPT_INVALID_ARG); + ERR (CRYPT_FILE_NOTFOUND); + + ERR (CRYPT_PK_INVALID_TYPE); + ERR (CRYPT_PK_INVALID_SYSTEM); + ERR (CRYPT_PK_DUP); + ERR (CRYPT_PK_NOT_FOUND); + ERR (CRYPT_PK_INVALID_SIZE); + + ERR (CRYPT_INVALID_PRIME_SIZE); +} + + +void dsa_tests(void) +{ + unsigned char msg[16], out[1024], out2[1024]; + unsigned long x, y; + int err, stat1, stat2; + dsa_key key, key2; + + /* make a random key */ + if ((err = dsa_make_key(&prng, find_prng("yarrow"), 20, 128, &key)) != CRYPT_OK) { + printf("Error making DSA key: %s\n", error_to_string(err)); + exit(-1); + } + printf("DSA Key Made\n"); + + /* verify it */ + if ((err = dsa_verify_key(&key, &stat1)) != CRYPT_OK) { + printf("Error verifying DSA key: %s\n", error_to_string(err)); + exit(-1); + } + printf("DSA key verification: %s\n", stat1 == 1 ? "passed" : "failed"); + if (stat1 == 0) exit(-1); + + /* sign the message */ + x = sizeof(out); + if ((err = dsa_sign_hash(msg, sizeof(msg), out, &x, &prng, find_prng("yarrow"), &key)) != CRYPT_OK) { + printf("Error signing with DSA key: %s\n", error_to_string(err)); + exit(-1); + } + printf("DSA 160/1024 signature is %lu bytes long\n", x); + + /* verify it once */ + if ((err = dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key)) != CRYPT_OK) { + printf("Error verifying with DSA key 1: %s\n", error_to_string(err)); + exit(-1); + } + + /* Modify and verify again */ + msg[0] ^= 1; + if ((err = dsa_verify_hash(out, x, msg, sizeof(msg), &stat2, &key)) != CRYPT_OK) { + printf("Error verifying with DSA key 2: %s\n", error_to_string(err)); + exit(-1); + } + msg[0] ^= 1; + printf("DSA Verification: %d, %d, %s\n", stat1, stat2, (stat1 == 1 && stat2 == 0) ? "passed" : "failed"); + if (!(stat1 == 1 && stat2 == 0)) exit(-1); + + /* test exporting it */ + x = sizeof(out2); + if ((err = dsa_export(out2, &x, PK_PRIVATE, &key)) != CRYPT_OK) { + printf("Error export PK_PRIVATE DSA key: %s\n", error_to_string(err)); + exit(-1); + } + printf("Exported PK_PRIVATE DSA key in %lu bytes\n", x); + if ((err = dsa_import(out2, x, &key2)) != CRYPT_OK) { + printf("Error importing PK_PRIVATE DSA key: %s\n", error_to_string(err)); + exit(-1); + } + /* verify a signature with it */ + if ((err = dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2)) != CRYPT_OK) { + printf("Error verifying with DSA key 3: %s\n", error_to_string(err)); + exit(-1); + } + printf("PRIVATE Import Test: %s\n", stat1 == 1 ? "passed" : "failed"); + if (stat1 == 0) exit(-1); + dsa_free(&key2); + + /* export as public now */ + x = sizeof(out2); + if ((err = dsa_export(out2, &x, PK_PUBLIC, &key)) != CRYPT_OK) { + printf("Error export PK_PUBLIC DSA key: %s\n", error_to_string(err)); + exit(-1); + } + printf("Exported PK_PUBLIC DSA key in %lu bytes\n", x); + if ((err = dsa_import(out2, x, &key2)) != CRYPT_OK) { + printf("Error importing PK_PUBLIC DSA key: %s\n", error_to_string(err)); + exit(-1); + } + /* verify a signature with it */ + if ((err = dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2)) != CRYPT_OK) { + printf("Error verifying with DSA key 4: %s\n", error_to_string(err)); + exit(-1); + } + printf("PUBLIC Import Test: %s\n", stat1 == 1 ? "passed" : "failed"); + if (stat1 == 0) exit(-1); + + dsa_free(&key2); + dsa_free(&key); +} + +#ifdef PKCS_1 +void pkcs1_test(void) +{ + unsigned char buf[3][128]; + int err, res1, res2, res3, prng_idx, hash_idx; + unsigned long x, y, l1, l2, l3, i1, i2; + + /* get hash/prng */ + hash_idx = find_hash("sha1"); + prng_idx = find_prng("yarrow"); + + /* do many tests */ + for (x = 0; x < 10000; x++) { + zeromem(buf, sizeof(buf)); + + /* make a dummy message (of random length) */ + l3 = (rand() & 31) + 8; + for (y = 0; y < l3; y++) buf[0][y] = rand() & 255; + + /* encode it */ + l1 = sizeof(buf[1]); + if ((err = pkcs_1_oaep_encode(buf[0], l3, NULL, 0, 1024, hash_idx, prng_idx, &prng, buf[1], &l1)) != CRYPT_OK) { + printf("OAEP encode: %s\n", error_to_string(err)); + exit(-1); + } + + /* decode it */ + l2 = sizeof(buf[2]); + if ((err = pkcs_1_oaep_decode(buf[1], l1, NULL, 0, 1024, hash_idx, buf[2], &l2)) != CRYPT_OK) { + printf("OAEP decode: %s\n", error_to_string(err)); + exit(-1); + } + + if (l2 != l3 || memcmp(buf[2], buf[0], l3) != 0) { + printf("Outsize == %lu, should have been %lu, msg contents follow.\n", l2, l3); + printf("ORIGINAL:\n"); + for (x = 0; x < l3; x++) { + printf("%02x ", buf[0][x]); + } + printf("\nRESULT:\n"); + for (x = 0; x < l2; x++) { + printf("%02x ", buf[2][x]); + } + printf("\n\n"); + exit(-1); + } + + /* test PSS */ + l1 = sizeof(buf[1]); + if ((err = pkcs_1_pss_encode(buf[0], l3, l3>>2, hash_idx, prng_idx, &prng, 1024, buf[1], &l1)) != CRYPT_OK) { + printf("PSS encode: %s\n", error_to_string(err)); + exit(-1); + } + + if ((err = pkcs_1_pss_decode(buf[0], l3, buf[1], l1, l3>>2, hash_idx, 1024, &res1)) != CRYPT_OK) { + printf("PSS decode1: %s\n", error_to_string(err)); + exit(-1); + } + + buf[0][i1 = abs(rand()) % l3] ^= 1; + if ((err = pkcs_1_pss_decode(buf[0], l3, buf[1], l1, l3>>2, hash_idx, 1024, &res2)) != CRYPT_OK) { + printf("PSS decode2: %s\n", error_to_string(err)); + exit(-1); + } + + buf[0][i1] ^= 1; + buf[1][i2 = abs(rand()) % l1] ^= 1; + if ((err = pkcs_1_pss_decode(buf[0], l3, buf[1], l1, l3>>2, hash_idx, 1024, &res3)) != CRYPT_OK) { + printf("PSS decode3: %s\n", error_to_string(err)); + exit(-1); + } + + if (!(res1 == 1 && res2 == 0 && res3 == 0)) { + printf("PSS failed: %d, %d, %d, %lu\n", res1, res2, res3, l3); + exit(-1); + } + } + printf("PKCS #1: Passed\n"); +} + +#endif /* PKCS_1 */ + +int +main (void) +{ +#ifdef SONY_PS2 + TIMER_Init (); +#endif + srand(time(NULL)); + + register_all_algs (); + + if ((errnum = yarrow_start (&prng)) != CRYPT_OK) { + printf ("yarrow_start: %s\n", error_to_string (errnum)); + } + if ((errnum = yarrow_add_entropy ((unsigned char *)"hello", 5, &prng)) != CRYPT_OK) { + printf ("yarrow_add_entropy: %s\n", error_to_string (errnum)); + } + if ((errnum = yarrow_ready (&prng)) != CRYPT_OK) { + printf ("yarrow_ready: %s\n", error_to_string (errnum)); + } + + printf (crypt_build_settings); + test_errs (); + +#ifdef PKCS_1 + pkcs1_test(); + return 0; +#endif + + +#ifdef HMAC + printf ("HMAC: %s\n", hmac_test () == CRYPT_OK ? "passed" : "failed"); + if (hmac_test() != CRYPT_OK) exit(EXIT_FAILURE); +#endif + +#ifdef OMAC + printf ("OMAC: %s\n", omac_test () == CRYPT_OK ? "passed" : "failed"); + if (omac_test() != CRYPT_OK) exit(EXIT_FAILURE); +#endif + +#ifdef PMAC + printf ("PMAC: %s\n", pmac_test () == CRYPT_OK ? "passed" : "failed"); + if (pmac_test() != CRYPT_OK) exit(EXIT_FAILURE); +#endif + +#ifdef EAX_MODE + printf ("EAX : %s\n", eax_test () == CRYPT_OK ? "passed" : "failed"); + if (eax_test() != CRYPT_OK) exit(EXIT_FAILURE); +#endif + +#ifdef OCB_MODE + printf ("OCB : %s\n", ocb_test () == CRYPT_OK ? "passed" : "failed"); + if (ocb_test() != CRYPT_OK) exit(EXIT_FAILURE); +#endif + + store_tests (); + cipher_tests (); + hash_tests (); + + ecb_tests (); + cbc_tests (); + ctr_tests (); + ofb_tests (); + cfb_tests (); + + rng_tests (); + test_prime(); + +#ifdef KR + kr_test (); +#endif + dsa_tests(); + rsa_test (); + pad_test (); + ecc_tests (); + dh_tests (); + + + gf_tests (); + base64_test (); + + time_ecb (); + time_hash (); + +#ifdef SONY_PS2 + TIMER_Shutdown (); +#endif + + return 0; +} diff --git a/des.c b/des.c index 13059a2..090c594 100644 --- a/des.c +++ b/des.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -1747,7 +1747,7 @@ int des_test(void) for (y = 0; y < 1000; y++) des_ecb_encrypt(tmp, tmp, &des); for (y = 0; y < 1000; y++) des_ecb_decrypt(tmp, tmp, &des); for (y = 0; y < 8; y++) if (tmp[y] != 0) return CRYPT_FAIL_TESTVECTOR; - } +} return CRYPT_OK; #endif diff --git a/dh.c b/dh.c index 89bf7e6..8cf5632 100644 --- a/dh.c +++ b/dh.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -294,9 +294,9 @@ int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key) unsigned long y, z; int err; - _ARGCHK(out != NULL); + _ARGCHK(out != NULL); _ARGCHK(outlen != NULL); - _ARGCHK(key != NULL); + _ARGCHK(key != NULL); /* can we store the static header? */ if (*outlen < (PACKET_SIZE + 2)) { @@ -335,7 +335,7 @@ int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key) unsigned long x, y, s; int err; - _ARGCHK(in != NULL); + _ARGCHK(in != NULL); _ARGCHK(key != NULL); /* make sure valid length */ @@ -382,10 +382,10 @@ int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key) } /* load public value g^x mod p*/ - INPUT_BIGNUM(&key->y, in, x, y); + INPUT_BIGNUM(&key->y, in, x, y, inlen); if (key->type == PK_PRIVATE) { - INPUT_BIGNUM(&key->x, in, x, y); + INPUT_BIGNUM(&key->x, in, x, y, inlen); } /* eliminate private key if public */ diff --git a/dh_sys.c b/dh_sys.c index e400047..fb05aa3 100644 --- a/dh_sys.c +++ b/dh_sys.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -48,7 +48,7 @@ int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen, } /* now check if the out buffer is big enough */ - if (*len < (9 + PACKET_SIZE + pubkeysize + keylen)) { + if (*len < (1 + 4 + 4 + PACKET_SIZE + pubkeysize + keylen)) { dh_free(&pubkey); return CRYPT_BUFFER_OVERFLOW; } @@ -326,6 +326,8 @@ done: return err; } + +/* verify the signature in sig of the given hash */ int dh_verify_hash(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int *stat, dh_key *key) @@ -345,9 +347,7 @@ int dh_verify_hash(const unsigned char *sig, unsigned long siglen, /* check initial input length */ if (siglen < PACKET_SIZE+4+4) { return CRYPT_INVALID_PACKET; - } else { - siglen -= PACKET_SIZE + 4 + 4; - } + } /* header ok? */ if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_DH, PACKET_SUB_SIGNED)) != CRYPT_OK) { @@ -363,41 +363,23 @@ int dh_verify_hash(const unsigned char *sig, unsigned long siglen, } /* load a and b */ - LOAD32L(x, sig+y); - if (siglen < x) { - return CRYPT_INVALID_PACKET; - } else { - siglen -= x; - } - - y += 4; - if ((err = mp_read_unsigned_bin(&a, (unsigned char *)sig+y, x)) != MP_OKAY) { goto error; } - y += x; - - LOAD32L(x, sig+y); - if (siglen < x) { - return CRYPT_INVALID_PACKET; - } else { - siglen -= x; - } - y += 4; - if ((err = mp_read_unsigned_bin(&b, (unsigned char *)sig+y, x)) != MP_OKAY) { goto error; } - y += x; + INPUT_BIGNUM(&a, sig, x, y, siglen); + INPUT_BIGNUM(&b, sig, x, y, siglen); /* load p and g */ - if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY) { goto error; } - if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY) { goto error; } + if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY) { goto error1; } + if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY) { goto error1; } /* load m */ - if ((err = mp_read_unsigned_bin(&m, (unsigned char *)hash, hashlen)) != MP_OKAY) { goto error; } + if ((err = mp_read_unsigned_bin(&m, (unsigned char *)hash, hashlen)) != MP_OKAY) { goto error1; } /* find g^m mod p */ - if ((err = mp_exptmod(&g, &m, &p, &m)) != MP_OKAY) { goto error; } /* m = g^m mod p */ + if ((err = mp_exptmod(&g, &m, &p, &m)) != MP_OKAY) { goto error1; } /* m = g^m mod p */ /* find y^a * a^b */ - if ((err = mp_exptmod(&key->y, &a, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = y^a mod p */ - if ((err = mp_exptmod(&a, &b, &p, &a)) != MP_OKAY) { goto error; } /* a = a^b mod p */ - if ((err = mp_mulmod(&a, &tmp, &p, &a)) != MP_OKAY) { goto error; } /* a = y^a * a^b mod p */ + if ((err = mp_exptmod(&key->y, &a, &p, &tmp)) != MP_OKAY) { goto error1; } /* tmp = y^a mod p */ + if ((err = mp_exptmod(&a, &b, &p, &a)) != MP_OKAY) { goto error1; } /* a = a^b mod p */ + if ((err = mp_mulmod(&a, &tmp, &p, &a)) != MP_OKAY) { goto error1; } /* a = y^a * a^b mod p */ /* y^a * a^b == g^m ??? */ if (mp_cmp(&a, &m) == 0) { @@ -407,8 +389,9 @@ int dh_verify_hash(const unsigned char *sig, unsigned long siglen, /* clean up */ err = CRYPT_OK; goto done; -error: +error1: err = mpi_to_ltc_error(err); +error: done: mp_clear_multi(&tmp, &m, &g, &p, &b, &a, NULL); return err; diff --git a/dsa.c b/dsa.c deleted file mode 100644 index 1d08ff7..0000000 --- a/dsa.c +++ /dev/null @@ -1,477 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * gurantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org - */ -#include "mycrypt.h" - -#ifdef MDSA - -int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) -{ - mp_int tmp, tmp2; - int err, res; - unsigned char buf[512]; - - _ARGCHK(key != NULL); - - /* check prng */ - if ((err = prng_is_valid(wprng)) != CRYPT_OK) { - return err; - } - - /* check size */ - if (group_size >= 1024 || group_size <= 15 || - group_size >= modulus_size || (modulus_size - group_size) >= (int)sizeof(buf)) { - return CRYPT_INVALID_ARG; - } - - /* init mp_ints */ - if ((err = mp_init_multi(&tmp, &tmp2, &key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != MP_OKAY) { - return mpi_to_ltc_error(err); - } - - /* make our prime q */ - if ((err = rand_prime(&key->q, group_size, prng, wprng)) != CRYPT_OK) { goto error2; } - - /* double q */ - if ((err = mp_mul_2(&key->q, &tmp)) != MP_OKAY) { goto error; } - - /* now make a random string and multply it against q */ - if (prng_descriptor[wprng].read(buf, modulus_size - group_size, prng) != (unsigned long)(modulus_size - group_size)) { - err = CRYPT_ERROR_READPRNG; - goto error2; - } - - /* force magnitude */ - buf[0] |= 0x80; - - /* force even */ - buf[modulus_size - group_size - 1] &= ~1; - - if ((err = mp_read_unsigned_bin(&tmp2, buf, modulus_size - group_size)) != MP_OKAY) { goto error; } - if ((err = mp_mul(&key->q, &tmp2, &key->p)) != MP_OKAY) { goto error; } - if ((err = mp_add_d(&key->p, 1, &key->p)) != MP_OKAY) { goto error; } - - /* now loop until p is prime */ - for (;;) { - if ((err = is_prime(&key->p, &res)) != CRYPT_OK) { goto error2; } - if (res == MP_YES) break; - - /* add 2q to p and 2 to tmp2 */ - if ((err = mp_add(&tmp, &key->p, &key->p)) != MP_OKAY) { goto error; } - if ((err = mp_add_d(&tmp2, 2, &tmp2)) != MP_OKAY) { goto error; } - } - - /* now p = (q * tmp2) + 1 is prime, find a value g for which g^tmp2 != 1 */ - mp_set(&key->g, 1); - - do { - if ((err = mp_add_d(&key->g, 1, &key->g)) != MP_OKAY) { goto error; } - if ((err = mp_exptmod(&key->g, &tmp2, &key->p, &tmp)) != MP_OKAY) { goto error; } - } while (mp_cmp_d(&tmp, 1) == MP_EQ); - - /* at this point tmp generates a group of order q mod p */ - mp_exch(&tmp, &key->g); - - /* so now we have our DH structure, generator g, order q, modulus p - Now we need a random exponent [mod q] and it's power g^x mod p - */ - do { - if (prng_descriptor[wprng].read(buf, group_size, prng) != (unsigned long)group_size) { - err = CRYPT_ERROR_READPRNG; - goto error2; - } - if ((err = mp_read_unsigned_bin(&key->x, buf, group_size)) != MP_OKAY) { goto error; } - } while (mp_cmp_d(&key->x, 1) != MP_GT); - if ((err = mp_exptmod(&key->g, &key->x, &key->p, &key->y)) != MP_OKAY) { goto error; } - - key->type = PK_PRIVATE; - key->qord = group_size; - - /* shrink the ram required */ - if ((err = mp_shrink(&key->g)) != MP_OKAY) { goto error; } - if ((err = mp_shrink(&key->p)) != MP_OKAY) { goto error; } - if ((err = mp_shrink(&key->q)) != MP_OKAY) { goto error; } - if ((err = mp_shrink(&key->x)) != MP_OKAY) { goto error; } - if ((err = mp_shrink(&key->y)) != MP_OKAY) { goto error; } - - err = CRYPT_OK; - -#ifdef CLEAN_STACK - zeromem(buf, sizeof(buf)); -#endif - - goto done; -error : err = mpi_to_ltc_error(err); -error2: mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL); -done : mp_clear_multi(&tmp, &tmp2, NULL); - return err; -} - -void dsa_free(dsa_key *key) -{ - _ARGCHK(key != NULL); - mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL); -} - - -int dsa_sign_hash(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, dsa_key *key) -{ - mp_int k, kinv, tmp, r, s; - unsigned char buf[512]; - int err, y; - unsigned long len; - - - _ARGCHK(in != NULL); - _ARGCHK(out != NULL); - _ARGCHK(outlen != NULL); - _ARGCHK(key != NULL); - - if ((err = prng_is_valid(wprng)) != CRYPT_OK) { - return err; - } - if (key->type != PK_PRIVATE) { - return CRYPT_PK_NOT_PRIVATE; - } - - /* check group order size */ - if (key->qord >= (int)sizeof(buf)) { - return CRYPT_INVALID_ARG; - } - - /* Init our temps */ - if ((err = mp_init_multi(&k, &kinv, &r, &s, &tmp, NULL)) != MP_OKAY) { goto error; } - -retry: - - do { - /* gen random k */ - if (prng_descriptor[wprng].read(buf, key->qord, prng) != (unsigned long)key->qord) { - err = CRYPT_ERROR_READPRNG; - goto done; - } - - /* read k */ - if ((err = mp_read_unsigned_bin(&k, buf, key->qord)) != MP_OKAY) { goto error; } - - /* k > 1 ? */ - if (mp_cmp_d(&k, 1) != MP_GT) { goto retry; } - - /* test gcd */ - if ((err = mp_gcd(&k, &key->q, &tmp)) != MP_OKAY) { goto error; } - } while (mp_cmp_d(&tmp, 1) != MP_EQ); - - /* now find 1/k mod q */ - if ((err = mp_invmod(&k, &key->q, &kinv)) != MP_OKAY) { goto error; } - - /* now find r = g^k mod p mod q */ - if ((err = mp_exptmod(&key->g, &k, &key->p, &r)) != MP_OKAY) { goto error; } - if ((err = mp_mod(&r, &key->q, &r)) != MP_OKAY) { goto error; } - - if (mp_iszero(&r) == MP_YES) { goto retry; } - - /* now find s = (in + xr)/k mod q */ - if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, inlen)) != MP_OKAY) { goto error; } - if ((err = mp_mul(&key->x, &r, &s)) != MP_OKAY) { goto error; } - if ((err = mp_add(&s, &tmp, &s)) != MP_OKAY) { goto error; } - if ((err = mp_mulmod(&s, &kinv, &key->q, &s)) != MP_OKAY) { goto error; } - - if (mp_iszero(&s) == MP_YES) { goto retry; } - - /* now store em both */ - - /* first check that we have enough room */ - if (*outlen < (unsigned long)(PACKET_SIZE + 4 + mp_unsigned_bin_size(&s) + mp_unsigned_bin_size(&r))) { - err = CRYPT_BUFFER_OVERFLOW; - goto done; - } - - /* packet header */ - packet_store_header(out, PACKET_SECT_DSA, PACKET_SUB_SIGNED); - y = PACKET_SIZE; - - /* store length of r */ - len = mp_unsigned_bin_size(&r); - out[y++] = (len>>8)&255; - out[y++] = len&255; - - /* store r */ - if ((err = mp_to_unsigned_bin(&r, out+y)) != MP_OKAY) { goto error; } - y += len; - - /* store length of s */ - len = mp_unsigned_bin_size(&s); - out[y++] = (len>>8)&255; - out[y++] = len&255; - - /* store s */ - if ((err = mp_to_unsigned_bin(&s, out+y)) != MP_OKAY) { goto error; } - y += len; - - /* reset size */ - *outlen = y; - - err = CRYPT_OK; - goto done; - -error : err = mpi_to_ltc_error(err); -done : mp_clear_multi(&k, &kinv, &r, &s, &tmp, NULL); -#ifdef CLEAN_STACK - zeromem(buf, sizeof(buf)); -#endif - return err; -} - -int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long inlen, - int *stat, dsa_key *key) -{ - mp_int r, s, w, v, u1, u2; - unsigned long x, y; - int err; - - _ARGCHK(sig != NULL); - _ARGCHK(hash != NULL); - _ARGCHK(stat != NULL); - _ARGCHK(key != NULL); - - /* default to invalid signature */ - *stat = 0; - - if (siglen < PACKET_SIZE+2+2) { - return CRYPT_INVALID_PACKET; - } - - /* is the message format correct? */ - if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_DSA, PACKET_SUB_SIGNED)) != CRYPT_OK) { - return err; - } - - /* skip over header */ - y = PACKET_SIZE; - - /* init our variables */ - if ((err = mp_init_multi(&r, &s, &w, &v, &u1, &u2, NULL)) != MP_OKAY) { - return mpi_to_ltc_error(err); - } - - /* read in r followed by s */ - x = ((unsigned)sig[y]<<8)|((unsigned)sig[y+1]); - y += 2; - if (y + x > siglen) { - err = CRYPT_INVALID_PACKET; - goto done; - } - if ((err = mp_read_unsigned_bin(&r, (unsigned char *)sig+y, x)) != MP_OKAY) { goto error; } - y += x; - - /* load s */ - x = ((unsigned)sig[y]<<8)|((unsigned)sig[y+1]); - y += 2; - if (y + x > siglen) { - err = CRYPT_INVALID_PACKET; - goto done; - } - if ((err = mp_read_unsigned_bin(&s, (unsigned char *)sig+y, x)) != MP_OKAY) { goto error; } - - /* w = 1/s mod q */ - if ((err = mp_invmod(&s, &key->q, &w)) != MP_OKAY) { goto error; } - - /* u1 = m * w mod q */ - if ((err = mp_read_unsigned_bin(&u1, (unsigned char *)hash, inlen)) != MP_OKAY) { goto error; } - if ((err = mp_mulmod(&u1, &w, &key->q, &u1)) != MP_OKAY) { goto error; } - - /* u2 = r*w mod q */ - if ((err = mp_mulmod(&r, &w, &key->q, &u2)) != MP_OKAY) { goto error; } - - /* v = g^u1 * y^u2 mod p mod q */ - if ((err = mp_exptmod(&key->g, &u1, &key->p, &u1)) != MP_OKAY) { goto error; } - if ((err = mp_exptmod(&key->y, &u2, &key->p, &u2)) != MP_OKAY) { goto error; } - if ((err = mp_mulmod(&u1, &u2, &key->p, &v)) != MP_OKAY) { goto error; } - if ((err = mp_mod(&v, &key->q, &v)) != MP_OKAY) { goto error; } - - /* if r = v then we're set */ - if (mp_cmp(&r, &v) == MP_EQ) { - *stat = 1; - } - - err = CRYPT_OK; - goto done; - -error : err = mpi_to_ltc_error(err); -done : mp_clear_multi(&r, &s, &w, &v, &u1, &u2, NULL); - return err; -} - - -int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key) -{ - unsigned long y, z; - int err; - - _ARGCHK(out != NULL); - _ARGCHK(outlen != NULL); - _ARGCHK(key != NULL); - - /* can we store the static header? */ - if (*outlen < (PACKET_SIZE + 1 + 2)) { - return CRYPT_BUFFER_OVERFLOW; - } - - if (type == PK_PRIVATE && key->type != PK_PRIVATE) { - return CRYPT_PK_TYPE_MISMATCH; - } - - if (type != PK_PUBLIC && type != PK_PRIVATE) { - return CRYPT_INVALID_ARG; - } - - /* store header */ - packet_store_header(out, PACKET_SECT_DSA, PACKET_SUB_KEY); - y = PACKET_SIZE; - - /* store g, p, q, qord */ - out[y++] = type; - out[y++] = (key->qord>>8)&255; - out[y++] = key->qord & 255; - - OUTPUT_BIGNUM(&key->g,out,y,z); - OUTPUT_BIGNUM(&key->p,out,y,z); - OUTPUT_BIGNUM(&key->q,out,y,z); - - /* public exponent */ - OUTPUT_BIGNUM(&key->y,out,y,z); - - if (type == PK_PRIVATE) { - OUTPUT_BIGNUM(&key->x,out,y,z); - } - - *outlen = y; - return CRYPT_OK; -} - -int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) -{ - unsigned long x, y; - int err; - - _ARGCHK(in != NULL); - _ARGCHK(key != NULL); - - /* check length */ - if ((1+2+PACKET_SIZE) > inlen) { - return CRYPT_INVALID_PACKET; - } - - /* check type */ - if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DSA, PACKET_SUB_KEY)) != CRYPT_OK) { - return err; - } - y = PACKET_SIZE; - - /* init key */ - if (mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL) != MP_OKAY) { - return CRYPT_MEM; - } - - /* read type/qord */ - key->type = in[y++]; - key->qord = ((unsigned)in[y]<<8)|((unsigned)in[y+1]); - y += 2; - - /* input publics */ - INPUT_BIGNUM(&key->g,in,x,y); - INPUT_BIGNUM(&key->p,in,x,y); - INPUT_BIGNUM(&key->q,in,x,y); - INPUT_BIGNUM(&key->y,in,x,y); - if (key->type == PK_PRIVATE) { - INPUT_BIGNUM(&key->x,in,x,y); - } - - return CRYPT_OK; -error: - mp_clear_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL); - return err; -} - -int dsa_verify_key(dsa_key *key, int *stat) -{ - mp_int tmp, tmp2; - int res, err; - - _ARGCHK(key != NULL); - _ARGCHK(stat != NULL); - - *stat = 0; - - /* first make sure key->q and key->p are prime */ - if ((err = is_prime(&key->q, &res)) != CRYPT_OK) { - return err; - } - if (res == 0) { - return CRYPT_OK; - } - - - if ((err = is_prime(&key->p, &res)) != CRYPT_OK) { - return err; - } - if (res == 0) { - return CRYPT_OK; - } - - /* now make sure that g is not -1, 0 or 1 and

g, 0) == MP_EQ || mp_cmp_d(&key->g, 1) == MP_EQ) { - return CRYPT_OK; - } - if ((err = mp_init_multi(&tmp, &tmp2, NULL)) != MP_OKAY) { goto error; } - if ((err = mp_sub_d(&key->p, 1, &tmp)) != MP_OKAY) { goto error; } - if (mp_cmp(&tmp, &key->g) == MP_EQ || mp_cmp(&key->g, &key->p) != MP_LT) { - err = CRYPT_OK; - goto done; - } - - /* 1 < y < p-1 */ - if (!(mp_cmp_d(&key->y, 1) == MP_GT && mp_cmp(&key->y, &tmp) == MP_LT)) { - err = CRYPT_OK; - goto done; - } - - /* now we have to make sure that g^q = 1, and that p-1/q gives 0 remainder */ - if ((err = mp_div(&tmp, &key->q, &tmp, &tmp2)) != MP_OKAY) { goto error; } - if (mp_iszero(&tmp2) != MP_YES) { - err = CRYPT_OK; - goto done; - } - - if ((err = mp_exptmod(&key->g, &key->q, &key->p, &tmp)) != MP_OKAY) { goto error; } - if (mp_cmp_d(&tmp, 1) != MP_EQ) { - err = CRYPT_OK; - goto done; - } - - /* now we have to make sure that y^q = 1, this makes sure y \in g^x mod p */ - if ((err = mp_exptmod(&key->y, &key->q, &key->p, &tmp)) != MP_OKAY) { goto error; } - if (mp_cmp_d(&tmp, 1) != MP_EQ) { - err = CRYPT_OK; - goto done; - } - - /* at this point we are out of tests ;-( */ - err = CRYPT_OK; - *stat = 1; - goto done; -error: err = mpi_to_ltc_error(err); -done : mp_clear_multi(&tmp, &tmp2, NULL); - return err; -} -#endif diff --git a/dsa_export.c b/dsa_export.c new file mode 100644 index 0000000..995b1cf --- /dev/null +++ b/dsa_export.c @@ -0,0 +1,62 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef MDSA + +int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key) +{ + unsigned long y, z; + int err; + + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + _ARGCHK(key != NULL); + + /* can we store the static header? */ + if (*outlen < (PACKET_SIZE + 1 + 2)) { + return CRYPT_BUFFER_OVERFLOW; + } + + if (type == PK_PRIVATE && key->type != PK_PRIVATE) { + return CRYPT_PK_TYPE_MISMATCH; + } + + if (type != PK_PUBLIC && type != PK_PRIVATE) { + return CRYPT_INVALID_ARG; + } + + /* store header */ + packet_store_header(out, PACKET_SECT_DSA, PACKET_SUB_KEY); + y = PACKET_SIZE; + + /* store g, p, q, qord */ + out[y++] = type; + out[y++] = (key->qord>>8)&255; + out[y++] = key->qord & 255; + + OUTPUT_BIGNUM(&key->g,out,y,z); + OUTPUT_BIGNUM(&key->p,out,y,z); + OUTPUT_BIGNUM(&key->q,out,y,z); + + /* public exponent */ + OUTPUT_BIGNUM(&key->y,out,y,z); + + if (type == PK_PRIVATE) { + OUTPUT_BIGNUM(&key->x,out,y,z); + } + + *outlen = y; + return CRYPT_OK; +} + +#endif + diff --git a/dsa_free.c b/dsa_free.c new file mode 100644 index 0000000..c451951 --- /dev/null +++ b/dsa_free.c @@ -0,0 +1,21 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef MDSA + +void dsa_free(dsa_key *key) +{ + _ARGCHK(key != NULL); + mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL); +} + +#endif diff --git a/dsa_import.c b/dsa_import.c new file mode 100644 index 0000000..429876d --- /dev/null +++ b/dsa_import.c @@ -0,0 +1,59 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef MDSA + +int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) +{ + unsigned long x, y; + int err; + + _ARGCHK(in != NULL); + _ARGCHK(key != NULL); + + /* check length */ + if ((1+2+PACKET_SIZE) > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* check type */ + if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DSA, PACKET_SUB_KEY)) != CRYPT_OK) { + return err; + } + y = PACKET_SIZE; + + /* init key */ + if (mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL) != MP_OKAY) { + return CRYPT_MEM; + } + + /* read type/qord */ + key->type = in[y++]; + key->qord = ((unsigned)in[y]<<8)|((unsigned)in[y+1]); + y += 2; + + /* input publics */ + INPUT_BIGNUM(&key->g,in,x,y, inlen); + INPUT_BIGNUM(&key->p,in,x,y, inlen); + INPUT_BIGNUM(&key->q,in,x,y, inlen); + INPUT_BIGNUM(&key->y,in,x,y, inlen); + if (key->type == PK_PRIVATE) { + INPUT_BIGNUM(&key->x,in,x,y, inlen); + } + + return CRYPT_OK; +error: + mp_clear_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL); + return err; +} + +#endif diff --git a/dsa_make_key.c b/dsa_make_key.c new file mode 100644 index 0000000..4d2af24 --- /dev/null +++ b/dsa_make_key.c @@ -0,0 +1,117 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef MDSA + +int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) +{ + mp_int tmp, tmp2; + int err, res; + unsigned char buf[512]; + + _ARGCHK(key != NULL); + + /* check prng */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + /* check size */ + if (group_size >= 1024 || group_size <= 15 || + group_size >= modulus_size || (modulus_size - group_size) >= (int)sizeof(buf)) { + return CRYPT_INVALID_ARG; + } + + /* init mp_ints */ + if ((err = mp_init_multi(&tmp, &tmp2, &key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != MP_OKAY) { + return mpi_to_ltc_error(err); + } + + /* make our prime q */ + if ((err = rand_prime(&key->q, group_size*8, prng, wprng)) != CRYPT_OK) { goto error2; } + + /* double q */ + if ((err = mp_mul_2(&key->q, &tmp)) != MP_OKAY) { goto error; } + + /* now make a random string and multply it against q */ + if (prng_descriptor[wprng].read(buf+1, modulus_size - group_size, prng) != (unsigned long)(modulus_size - group_size)) { + err = CRYPT_ERROR_READPRNG; + goto error2; + } + + /* force magnitude */ + buf[0] = 1; + + /* force even */ + buf[modulus_size - group_size] &= ~1; + + if ((err = mp_read_unsigned_bin(&tmp2, buf, modulus_size - group_size+1)) != MP_OKAY) { goto error; } + if ((err = mp_mul(&key->q, &tmp2, &key->p)) != MP_OKAY) { goto error; } + if ((err = mp_add_d(&key->p, 1, &key->p)) != MP_OKAY) { goto error; } + + /* now loop until p is prime */ + for (;;) { + if ((err = is_prime(&key->p, &res)) != CRYPT_OK) { goto error2; } + if (res == MP_YES) break; + + /* add 2q to p and 2 to tmp2 */ + if ((err = mp_add(&tmp, &key->p, &key->p)) != MP_OKAY) { goto error; } + if ((err = mp_add_d(&tmp2, 2, &tmp2)) != MP_OKAY) { goto error; } + } + + /* now p = (q * tmp2) + 1 is prime, find a value g for which g^tmp2 != 1 */ + mp_set(&key->g, 1); + + do { + if ((err = mp_add_d(&key->g, 1, &key->g)) != MP_OKAY) { goto error; } + if ((err = mp_exptmod(&key->g, &tmp2, &key->p, &tmp)) != MP_OKAY) { goto error; } + } while (mp_cmp_d(&tmp, 1) == MP_EQ); + + /* at this point tmp generates a group of order q mod p */ + mp_exch(&tmp, &key->g); + + /* so now we have our DH structure, generator g, order q, modulus p + Now we need a random exponent [mod q] and it's power g^x mod p + */ + do { + if (prng_descriptor[wprng].read(buf, group_size, prng) != (unsigned long)group_size) { + err = CRYPT_ERROR_READPRNG; + goto error2; + } + if ((err = mp_read_unsigned_bin(&key->x, buf, group_size)) != MP_OKAY) { goto error; } + } while (mp_cmp_d(&key->x, 1) != MP_GT); + if ((err = mp_exptmod(&key->g, &key->x, &key->p, &key->y)) != MP_OKAY) { goto error; } + + key->type = PK_PRIVATE; + key->qord = group_size; + + /* shrink the ram required */ + if ((err = mp_shrink(&key->g)) != MP_OKAY) { goto error; } + if ((err = mp_shrink(&key->p)) != MP_OKAY) { goto error; } + if ((err = mp_shrink(&key->q)) != MP_OKAY) { goto error; } + if ((err = mp_shrink(&key->x)) != MP_OKAY) { goto error; } + if ((err = mp_shrink(&key->y)) != MP_OKAY) { goto error; } + + err = CRYPT_OK; + +#ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + + goto done; +error : err = mpi_to_ltc_error(err); +error2: mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL); +done : mp_clear_multi(&tmp, &tmp2, NULL); + return err; +} + +#endif diff --git a/dsa_sign_hash.c b/dsa_sign_hash.c new file mode 100644 index 0000000..b204371 --- /dev/null +++ b/dsa_sign_hash.c @@ -0,0 +1,125 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef MDSA + +int dsa_sign_hash(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, dsa_key *key) +{ + mp_int k, kinv, tmp, r, s; + unsigned char buf[512]; + int err, y; + unsigned long len; + + + _ARGCHK(in != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + _ARGCHK(key != NULL); + + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + if (key->type != PK_PRIVATE) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* check group order size */ + if (key->qord >= (int)sizeof(buf)) { + return CRYPT_INVALID_ARG; + } + + /* Init our temps */ + if ((err = mp_init_multi(&k, &kinv, &r, &s, &tmp, NULL)) != MP_OKAY) { goto error; } + +retry: + + do { + /* gen random k */ + if (prng_descriptor[wprng].read(buf, key->qord, prng) != (unsigned long)key->qord) { + err = CRYPT_ERROR_READPRNG; + goto done; + } + + /* read k */ + if ((err = mp_read_unsigned_bin(&k, buf, key->qord)) != MP_OKAY) { goto error; } + + /* k > 1 ? */ + if (mp_cmp_d(&k, 1) != MP_GT) { goto retry; } + + /* test gcd */ + if ((err = mp_gcd(&k, &key->q, &tmp)) != MP_OKAY) { goto error; } + } while (mp_cmp_d(&tmp, 1) != MP_EQ); + + /* now find 1/k mod q */ + if ((err = mp_invmod(&k, &key->q, &kinv)) != MP_OKAY) { goto error; } + + /* now find r = g^k mod p mod q */ + if ((err = mp_exptmod(&key->g, &k, &key->p, &r)) != MP_OKAY) { goto error; } + if ((err = mp_mod(&r, &key->q, &r)) != MP_OKAY) { goto error; } + + if (mp_iszero(&r) == MP_YES) { goto retry; } + + /* now find s = (in + xr)/k mod q */ + if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, inlen)) != MP_OKAY) { goto error; } + if ((err = mp_mul(&key->x, &r, &s)) != MP_OKAY) { goto error; } + if ((err = mp_add(&s, &tmp, &s)) != MP_OKAY) { goto error; } + if ((err = mp_mulmod(&s, &kinv, &key->q, &s)) != MP_OKAY) { goto error; } + + if (mp_iszero(&s) == MP_YES) { goto retry; } + + /* now store em both */ + + /* first check that we have enough room */ + if (*outlen < (unsigned long)(PACKET_SIZE + 4 + mp_unsigned_bin_size(&s) + mp_unsigned_bin_size(&r))) { + err = CRYPT_BUFFER_OVERFLOW; + goto done; + } + + /* packet header */ + packet_store_header(out, PACKET_SECT_DSA, PACKET_SUB_SIGNED); + y = PACKET_SIZE; + + /* store length of r */ + len = mp_unsigned_bin_size(&r); + out[y++] = (len>>8)&255; + out[y++] = len&255; + + /* store r */ + if ((err = mp_to_unsigned_bin(&r, out+y)) != MP_OKAY) { goto error; } + y += len; + + /* store length of s */ + len = mp_unsigned_bin_size(&s); + out[y++] = (len>>8)&255; + out[y++] = len&255; + + /* store s */ + if ((err = mp_to_unsigned_bin(&s, out+y)) != MP_OKAY) { goto error; } + y += len; + + /* reset size */ + *outlen = y; + + err = CRYPT_OK; + goto done; + +error : err = mpi_to_ltc_error(err); +done : mp_clear_multi(&k, &kinv, &r, &s, &tmp, NULL); +#ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + return err; +} + +#endif diff --git a/dsa_verify_hash.c b/dsa_verify_hash.c new file mode 100644 index 0000000..745cd7c --- /dev/null +++ b/dsa_verify_hash.c @@ -0,0 +1,97 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef MDSA + +int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long inlen, + int *stat, dsa_key *key) +{ + mp_int r, s, w, v, u1, u2; + unsigned long x, y; + int err; + + _ARGCHK(sig != NULL); + _ARGCHK(hash != NULL); + _ARGCHK(stat != NULL); + _ARGCHK(key != NULL); + + /* default to invalid signature */ + *stat = 0; + + if (siglen < PACKET_SIZE+2+2) { + return CRYPT_INVALID_PACKET; + } + + /* is the message format correct? */ + if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_DSA, PACKET_SUB_SIGNED)) != CRYPT_OK) { + return err; + } + + /* skip over header */ + y = PACKET_SIZE; + + /* init our variables */ + if ((err = mp_init_multi(&r, &s, &w, &v, &u1, &u2, NULL)) != MP_OKAY) { + return mpi_to_ltc_error(err); + } + + /* read in r followed by s */ + x = ((unsigned)sig[y]<<8)|((unsigned)sig[y+1]); + y += 2; + if (y + x > siglen) { + err = CRYPT_INVALID_PACKET; + goto done; + } + if ((err = mp_read_unsigned_bin(&r, (unsigned char *)sig+y, x)) != MP_OKAY) { goto error; } + y += x; + + /* load s */ + x = ((unsigned)sig[y]<<8)|((unsigned)sig[y+1]); + y += 2; + if (y + x > siglen) { + err = CRYPT_INVALID_PACKET; + goto done; + } + if ((err = mp_read_unsigned_bin(&s, (unsigned char *)sig+y, x)) != MP_OKAY) { goto error; } + + /* w = 1/s mod q */ + if ((err = mp_invmod(&s, &key->q, &w)) != MP_OKAY) { goto error; } + + /* u1 = m * w mod q */ + if ((err = mp_read_unsigned_bin(&u1, (unsigned char *)hash, inlen)) != MP_OKAY) { goto error; } + if ((err = mp_mulmod(&u1, &w, &key->q, &u1)) != MP_OKAY) { goto error; } + + /* u2 = r*w mod q */ + if ((err = mp_mulmod(&r, &w, &key->q, &u2)) != MP_OKAY) { goto error; } + + /* v = g^u1 * y^u2 mod p mod q */ + if ((err = mp_exptmod(&key->g, &u1, &key->p, &u1)) != MP_OKAY) { goto error; } + if ((err = mp_exptmod(&key->y, &u2, &key->p, &u2)) != MP_OKAY) { goto error; } + if ((err = mp_mulmod(&u1, &u2, &key->p, &v)) != MP_OKAY) { goto error; } + if ((err = mp_mod(&v, &key->q, &v)) != MP_OKAY) { goto error; } + + /* if r = v then we're set */ + if (mp_cmp(&r, &v) == MP_EQ) { + *stat = 1; + } + + err = CRYPT_OK; + goto done; + +error : err = mpi_to_ltc_error(err); +done : mp_clear_multi(&r, &s, &w, &v, &u1, &u2, NULL); + return err; +} + +#endif + diff --git a/dsa_verify_key.c b/dsa_verify_key.c new file mode 100644 index 0000000..c17bab8 --- /dev/null +++ b/dsa_verify_key.c @@ -0,0 +1,86 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef MDSA + +int dsa_verify_key(dsa_key *key, int *stat) +{ + mp_int tmp, tmp2; + int res, err; + + _ARGCHK(key != NULL); + _ARGCHK(stat != NULL); + + *stat = 0; + + /* first make sure key->q and key->p are prime */ + if ((err = is_prime(&key->q, &res)) != CRYPT_OK) { + return err; + } + if (res == 0) { + return CRYPT_OK; + } + + + if ((err = is_prime(&key->p, &res)) != CRYPT_OK) { + return err; + } + if (res == 0) { + return CRYPT_OK; + } + + /* now make sure that g is not -1, 0 or 1 and

g, 0) == MP_EQ || mp_cmp_d(&key->g, 1) == MP_EQ) { + return CRYPT_OK; + } + if ((err = mp_init_multi(&tmp, &tmp2, NULL)) != MP_OKAY) { goto error; } + if ((err = mp_sub_d(&key->p, 1, &tmp)) != MP_OKAY) { goto error; } + if (mp_cmp(&tmp, &key->g) == MP_EQ || mp_cmp(&key->g, &key->p) != MP_LT) { + err = CRYPT_OK; + goto done; + } + + /* 1 < y < p-1 */ + if (!(mp_cmp_d(&key->y, 1) == MP_GT && mp_cmp(&key->y, &tmp) == MP_LT)) { + err = CRYPT_OK; + goto done; + } + + /* now we have to make sure that g^q = 1, and that p-1/q gives 0 remainder */ + if ((err = mp_div(&tmp, &key->q, &tmp, &tmp2)) != MP_OKAY) { goto error; } + if (mp_iszero(&tmp2) != MP_YES) { + err = CRYPT_OK; + goto done; + } + + if ((err = mp_exptmod(&key->g, &key->q, &key->p, &tmp)) != MP_OKAY) { goto error; } + if (mp_cmp_d(&tmp, 1) != MP_EQ) { + err = CRYPT_OK; + goto done; + } + + /* now we have to make sure that y^q = 1, this makes sure y \in g^x mod p */ + if ((err = mp_exptmod(&key->y, &key->q, &key->p, &tmp)) != MP_OKAY) { goto error; } + if (mp_cmp_d(&tmp, 1) != MP_EQ) { + err = CRYPT_OK; + goto done; + } + + /* at this point we are out of tests ;-( */ + err = CRYPT_OK; + *stat = 1; + goto done; +error: err = mpi_to_ltc_error(err); +done : mp_clear_multi(&tmp, &tmp2, NULL); + return err; +} +#endif diff --git a/eax_addheader.c b/eax_addheader.c new file mode 100644 index 0000000..c7dfdd0 --- /dev/null +++ b/eax_addheader.c @@ -0,0 +1,25 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* EAX Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef EAX_MODE + +/* add header (metadata) to the stream */ +int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length) +{ + _ARGCHK(eax != NULL); + _ARGCHK(header != NULL); + return omac_process(&eax->headeromac, header, length); +} + +#endif diff --git a/eax_decrypt.c b/eax_decrypt.c new file mode 100644 index 0000000..de7c290 --- /dev/null +++ b/eax_decrypt.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* EAX Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef EAX_MODE + +int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length) +{ + int err; + + _ARGCHK(eax != NULL); + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + + /* omac ciphertext */ + if ((err = omac_process(&eax->ctomac, ct, length)) != CRYPT_OK) { + return err; + } + + /* decrypt */ + return ctr_decrypt(ct, pt, length, &eax->ctr); +} + +#endif diff --git a/eax_decrypt_verify_memory.c b/eax_decrypt_verify_memory.c new file mode 100644 index 0000000..3e68efe --- /dev/null +++ b/eax_decrypt_verify_memory.c @@ -0,0 +1,60 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* EAX Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef EAX_MODE + +int eax_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + unsigned char *tag, unsigned long taglen, + int *res) +{ + int err; + eax_state eax; + unsigned char buf[MAXBLOCKSIZE]; + unsigned long buflen; + + _ARGCHK(res != NULL); + + /* default to zero */ + *res = 0; + + if ((err = eax_init(&eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) { + return err; + } + + if ((err = eax_decrypt(&eax, ct, pt, ctlen)) != CRYPT_OK) { + return err; + } + + buflen = MIN(sizeof(buf), taglen); + if ((err = eax_done(&eax, buf, &buflen)) != CRYPT_OK) { + return err; + } + + /* compare tags */ + if (buflen >= taglen && memcmp(buf, tag, taglen) == 0) { + *res = 1; + } + +#ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + return CRYPT_OK; +} + +#endif diff --git a/eax_done.c b/eax_done.c new file mode 100644 index 0000000..8bc3706 --- /dev/null +++ b/eax_done.c @@ -0,0 +1,56 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* EAX Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef EAX_MODE + +int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen) +{ + int err; + unsigned char headermac[MAXBLOCKSIZE], ctmac[MAXBLOCKSIZE]; + unsigned long x, len; + + _ARGCHK(eax != NULL); + _ARGCHK(tag != NULL); + _ARGCHK(taglen != NULL); + + /* finish ctomac */ + len = sizeof(ctmac); + if ((err = omac_done(&eax->ctomac, ctmac, &len)) != CRYPT_OK) { + return err; + } + + /* finish headeromac */ + + /* note we specifically don't reset len so the two lens are minimal */ + + if ((err = omac_done(&eax->headeromac, headermac, &len)) != CRYPT_OK) { + return err; + } + + /* compute N xor H xor C */ + for (x = 0; x < len && x < *taglen; x++) { + tag[x] = eax->N[x] ^ headermac[x] ^ ctmac[x]; + } + *taglen = x; + +#ifdef CLEAN_STACK + zeromem(ctmac, sizeof(ctmac)); + zeromem(headermac, sizeof(headermac)); + zeromem(eax, sizeof(*eax)); +#endif + + return CRYPT_OK; +} + +#endif diff --git a/eax_encrypt.c b/eax_encrypt.c new file mode 100644 index 0000000..1b4930e --- /dev/null +++ b/eax_encrypt.c @@ -0,0 +1,35 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* EAX Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef EAX_MODE + +int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length) +{ + int err; + + _ARGCHK(eax != NULL); + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + + /* encrypt */ + if ((err = ctr_encrypt(pt, ct, length, &eax->ctr)) != CRYPT_OK) { + return err; + } + + /* omac ciphertext */ + return omac_process(&eax->ctomac, ct, length); +} + +#endif + diff --git a/eax_encrypt_authenticate_memory.c b/eax_encrypt_authenticate_memory.c new file mode 100644 index 0000000..60e9fa7 --- /dev/null +++ b/eax_encrypt_authenticate_memory.c @@ -0,0 +1,43 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* EAX Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef EAX_MODE + +int eax_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen) +{ + int err; + eax_state eax; + + if ((err = eax_init(&eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) { + return err; + } + + if ((err = eax_encrypt(&eax, pt, ct, ptlen)) != CRYPT_OK) { + return err; + } + + if ((err = eax_done(&eax, tag, taglen)) != CRYPT_OK) { + return err; + } + + return CRYPT_OK; +} + +#endif diff --git a/eax_init.c b/eax_init.c new file mode 100644 index 0000000..1b1bbba --- /dev/null +++ b/eax_init.c @@ -0,0 +1,106 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* EAX Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef EAX_MODE + +int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen) +{ + unsigned char buf[MAXBLOCKSIZE]; + int err, blklen; + omac_state omac; + unsigned long len; + + + _ARGCHK(eax != NULL); + _ARGCHK(key != NULL); + _ARGCHK(nonce != NULL); + if (headerlen > 0) { + _ARGCHK(header != NULL); + } + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + blklen = cipher_descriptor[cipher].block_length; + + /* N = OMAC_0K(nonce) */ + zeromem(buf, sizeof(buf)); + if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) { + return err; + } + + /* omac the [0]_n */ + if ((err = omac_process(&omac, buf, blklen)) != CRYPT_OK) { + return err; + } + /* omac the nonce */ + if ((err = omac_process(&omac, nonce, noncelen)) != CRYPT_OK) { + return err; + } + /* store result */ + len = sizeof(eax->N); + if ((err = omac_done(&omac, eax->N, &len)) != CRYPT_OK) { + return err; + } + + /* H = OMAC_1K(header) */ + zeromem(buf, sizeof(buf)); + buf[blklen - 1] = 1; + + if ((err = omac_init(&eax->headeromac, cipher, key, keylen)) != CRYPT_OK) { + return err; + } + + /* omac the [1]_n */ + if ((err = omac_process(&eax->headeromac, buf, blklen)) != CRYPT_OK) { + return err; + } + /* omac the header */ + if (headerlen != 0) { + if ((err = omac_process(&eax->headeromac, header, headerlen)) != CRYPT_OK) { + return err; + } + } + + /* note we don't finish the headeromac, this allows us to add more header later */ + + /* setup the CTR mode */ + if ((err = ctr_start(cipher, eax->N, key, keylen, 0, &eax->ctr)) != CRYPT_OK) { + return err; + } + /* use big-endian counter */ + eax->ctr.mode = 1; + + /* setup the OMAC for the ciphertext */ + if ((err = omac_init(&eax->ctomac, cipher, key, keylen)) != CRYPT_OK) { + return err; + } + + /* omac [2]_n */ + zeromem(buf, sizeof(buf)); + buf[blklen-1] = 2; + if ((err = omac_process(&eax->ctomac, buf, blklen)) != CRYPT_OK) { + return err; + } + +#ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); + zeromem(&omac, sizeof(omac)); +#endif + return CRYPT_OK; +} + +#endif diff --git a/eax.c b/eax_test.c similarity index 55% rename from eax.c rename to eax_test.c index 4326521..93774b0 100644 --- a/eax.c +++ b/eax_test.c @@ -1,513 +1,271 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * gurantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org - */ - -/* EAX Implementation by Tom St Denis */ -#include "mycrypt.h" - -#ifdef EAX_MODE - -int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *header, unsigned long headerlen) -{ - unsigned char buf[MAXBLOCKSIZE]; - int err, blklen; - omac_state omac; - unsigned long len; - - - _ARGCHK(eax != NULL); - _ARGCHK(key != NULL); - _ARGCHK(nonce != NULL); - if (headerlen > 0) { - _ARGCHK(header != NULL); - } - - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - blklen = cipher_descriptor[cipher].block_length; - - /* N = OMAC_0K(nonce) */ - zeromem(buf, sizeof(buf)); - if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) { - return err; - } - - /* omac the [0]_n */ - if ((err = omac_process(&omac, buf, blklen)) != CRYPT_OK) { - return err; - } - /* omac the nonce */ - if ((err = omac_process(&omac, nonce, noncelen)) != CRYPT_OK) { - return err; - } - /* store result */ - len = sizeof(eax->N); - if ((err = omac_done(&omac, eax->N, &len)) != CRYPT_OK) { - return err; - } - - /* H = OMAC_1K(header) */ - zeromem(buf, sizeof(buf)); - buf[blklen - 1] = 1; - - if ((err = omac_init(&eax->headeromac, cipher, key, keylen)) != CRYPT_OK) { - return err; - } - - /* omac the [1]_n */ - if ((err = omac_process(&eax->headeromac, buf, blklen)) != CRYPT_OK) { - return err; - } - /* omac the header */ - if (headerlen != 0) { - if ((err = omac_process(&eax->headeromac, header, headerlen)) != CRYPT_OK) { - return err; - } - } - - /* note we don't finish the headeromac, this allows us to add more header later */ - - /* setup the CTR mode */ - if ((err = ctr_start(cipher, eax->N, key, keylen, 0, &eax->ctr)) != CRYPT_OK) { - return err; - } - /* use big-endian counter */ - eax->ctr.mode = 1; - - /* setup the OMAC for the ciphertext */ - if ((err = omac_init(&eax->ctomac, cipher, key, keylen)) != CRYPT_OK) { - return err; - } - - /* omac [2]_n */ - zeromem(buf, sizeof(buf)); - buf[blklen-1] = 2; - if ((err = omac_process(&eax->ctomac, buf, blklen)) != CRYPT_OK) { - return err; - } - -#ifdef CLEAN_STACK - zeromem(buf, sizeof(buf)); - zeromem(&omac, sizeof(omac)); -#endif - return CRYPT_OK; -} - -int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length) -{ - int err; - - _ARGCHK(eax != NULL); - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - - /* encrypt */ - if ((err = ctr_encrypt(pt, ct, length, &eax->ctr)) != CRYPT_OK) { - return err; - } - - /* omac ciphertext */ - return omac_process(&eax->ctomac, ct, length); -} - -int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length) -{ - int err; - - _ARGCHK(eax != NULL); - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - - /* omac ciphertext */ - if ((err = omac_process(&eax->ctomac, ct, length)) != CRYPT_OK) { - return err; - } - - /* decrypt */ - return ctr_decrypt(ct, pt, length, &eax->ctr); -} - -/* add header (metadata) to the stream */ -int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length) -{ - _ARGCHK(eax != NULL); - _ARGCHK(header != NULL); - return omac_process(&eax->headeromac, header, length); -} - -int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen) -{ - int err; - unsigned char headermac[MAXBLOCKSIZE], ctmac[MAXBLOCKSIZE]; - unsigned long x, len; - - _ARGCHK(eax != NULL); - _ARGCHK(tag != NULL); - _ARGCHK(taglen != NULL); - - /* finish ctomac */ - len = sizeof(ctmac); - if ((err = omac_done(&eax->ctomac, ctmac, &len)) != CRYPT_OK) { - return err; - } - - /* finish headeromac */ - - /* note we specifically don't reset len so the two lens are minimal */ - - if ((err = omac_done(&eax->headeromac, headermac, &len)) != CRYPT_OK) { - return err; - } - - /* compute N xor H xor C */ - for (x = 0; x < len && x < *taglen; x++) { - tag[x] = eax->N[x] ^ headermac[x] ^ ctmac[x]; - } - *taglen = x; - -#ifdef CLEAN_STACK - zeromem(ctmac, sizeof(ctmac)); - zeromem(headermac, sizeof(headermac)); -#endif - - return CRYPT_OK; -} - -int eax_encrypt_authenticate_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *header, unsigned long headerlen, - const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - unsigned char *tag, unsigned long *taglen) -{ - int err; - eax_state eax; - - if ((err = eax_init(&eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) { - return err; - } - - if ((err = eax_encrypt(&eax, pt, ct, ptlen)) != CRYPT_OK) { - return err; - } - - if ((err = eax_done(&eax, tag, taglen)) != CRYPT_OK) { - return err; - } - -#ifdef CLEAN_STACK - zeromem(&eax, sizeof(eax)); -#endif - return CRYPT_OK; -} - -int eax_decrypt_verify_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, unsigned long noncelen, - const unsigned char *header, unsigned long headerlen, - const unsigned char *ct, unsigned long ctlen, - unsigned char *pt, - unsigned char *tag, unsigned long taglen, - int *res) -{ - int err; - eax_state eax; - unsigned char buf[MAXBLOCKSIZE]; - unsigned long buflen; - - _ARGCHK(res != NULL); - - /* default to zero */ - *res = 0; - - if ((err = eax_init(&eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) { - return err; - } - - if ((err = eax_decrypt(&eax, ct, pt, ctlen)) != CRYPT_OK) { - return err; - } - - buflen = MIN(sizeof(buf), taglen); - if ((err = eax_done(&eax, buf, &buflen)) != CRYPT_OK) { - return err; - } - - /* compare tags */ - if (buflen >= taglen && memcmp(buf, tag, taglen) == 0) { - *res = 1; - } - -#ifdef CLEAN_STACK - zeromem(&eax, sizeof(eax)); - zeromem(buf, sizeof(buf)); -#endif - return CRYPT_OK; -} - -int eax_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - int keylen, - noncelen, - headerlen, - msglen; - - unsigned char key[MAXBLOCKSIZE], - nonce[MAXBLOCKSIZE], - header[MAXBLOCKSIZE], - plaintext[MAXBLOCKSIZE], - ciphertext[MAXBLOCKSIZE], - tag[MAXBLOCKSIZE]; - } tests[] = { - -/* NULL message */ -{ - 16, 0, 0, 0, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0 }, - /* header */ - { 0 }, - /* plaintext */ - { 0 }, - /* ciphertext */ - { 0 }, - /* tag */ - { 0x9a, 0xd0, 0x7e, 0x7d, 0xbf, 0xf3, 0x01, 0xf5, - 0x05, 0xde, 0x59, 0x6b, 0x96, 0x15, 0xdf, 0xff } -}, - -/* test with nonce */ -{ - 16, 16, 0, 0, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* header */ - { 0 }, - /* plaintext */ - { 0 }, - /* ciphertext */ - { 0 }, - /* tag */ - { 0x1c, 0xe1, 0x0d, 0x3e, 0xff, 0xd4, 0xca, 0xdb, - 0xe2, 0xe4, 0x4b, 0x58, 0xd6, 0x0a, 0xb9, 0xec } -}, - -/* test with header [no nonce] */ -{ - 16, 0, 16, 0, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0 }, - /* header */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* plaintext */ - { 0 }, - /* ciphertext */ - { 0 }, - /* tag */ - { 0x3a, 0x69, 0x8f, 0x7a, 0x27, 0x0e, 0x51, 0xb0, - 0xf6, 0x5b, 0x3d, 0x3e, 0x47, 0x19, 0x3c, 0xff } -}, - -/* test with header + nonce + plaintext */ -{ - 16, 16, 16, 32, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* header */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* plaintext */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, - /* ciphertext */ - { 0x29, 0xd8, 0x78, 0xd1, 0xa3, 0xbe, 0x85, 0x7b, - 0x6f, 0xb8, 0xc8, 0xea, 0x59, 0x50, 0xa7, 0x78, - 0x33, 0x1f, 0xbf, 0x2c, 0xcf, 0x33, 0x98, 0x6f, - 0x35, 0xe8, 0xcf, 0x12, 0x1d, 0xcb, 0x30, 0xbc }, - /* tag */ - { 0x4f, 0xbe, 0x03, 0x38, 0xbe, 0x1c, 0x8c, 0x7e, - 0x1d, 0x7a, 0xe7, 0xe4, 0x5b, 0x92, 0xc5, 0x87 } -}, - -/* test with header + nonce + plaintext [not even sizes!] */ -{ - 16, 15, 14, 29, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e }, - /* header */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d }, - /* plaintext */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c }, - /* ciphertext */ - { 0xdd, 0x25, 0xc7, 0x54, 0xc5, 0xb1, 0x7c, 0x59, - 0x28, 0xb6, 0x9b, 0x73, 0x15, 0x5f, 0x7b, 0xb8, - 0x88, 0x8f, 0xaf, 0x37, 0x09, 0x1a, 0xd9, 0x2c, - 0x8a, 0x24, 0xdb, 0x86, 0x8b }, - /* tag */ - { 0x0d, 0x1a, 0x14, 0xe5, 0x22, 0x24, 0xff, 0xd2, - 0x3a, 0x05, 0xfa, 0x02, 0xcd, 0xef, 0x52, 0xda } -}, - -/* Vectors from Brian Gladman */ - -{ - 16, 16, 8, 0, - /* key */ - { 0x23, 0x39, 0x52, 0xde, 0xe4, 0xd5, 0xed, 0x5f, - 0x9b, 0x9c, 0x6d, 0x6f, 0xf8, 0x0f, 0xf4, 0x78 }, - /* nonce */ - { 0x62, 0xec, 0x67, 0xf9, 0xc3, 0xa4, 0xa4, 0x07, - 0xfc, 0xb2, 0xa8, 0xc4, 0x90, 0x31, 0xa8, 0xb3 }, - /* header */ - { 0x6b, 0xfb, 0x91, 0x4f, 0xd0, 0x7e, 0xae, 0x6b }, - /* PT */ - { 0x00 }, - /* CT */ - { 0x00 }, - /* tag */ - { 0xe0, 0x37, 0x83, 0x0e, 0x83, 0x89, 0xf2, 0x7b, - 0x02, 0x5a, 0x2d, 0x65, 0x27, 0xe7, 0x9d, 0x01 } -}, - -{ - 16, 16, 8, 2, - /* key */ - { 0x91, 0x94, 0x5d, 0x3f, 0x4d, 0xcb, 0xee, 0x0b, - 0xf4, 0x5e, 0xf5, 0x22, 0x55, 0xf0, 0x95, 0xa4 }, +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* EAX Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef EAX_MODE + +int eax_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + int keylen, + noncelen, + headerlen, + msglen; + + unsigned char key[MAXBLOCKSIZE], + nonce[MAXBLOCKSIZE], + header[MAXBLOCKSIZE], + plaintext[MAXBLOCKSIZE], + ciphertext[MAXBLOCKSIZE], + tag[MAXBLOCKSIZE]; + } tests[] = { + +/* NULL message */ +{ + 16, 0, 0, 0, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* nonce */ - { 0xbe, 0xca, 0xf0, 0x43, 0xb0, 0xa2, 0x3d, 0x84, - 0x31, 0x94, 0xba, 0x97, 0x2c, 0x66, 0xde, 0xbd }, - /* header */ - { 0xfa, 0x3b, 0xfd, 0x48, 0x06, 0xeb, 0x53, 0xfa }, - /* PT */ - { 0xf7, 0xfb }, - /* CT */ - { 0x19, 0xdd }, - /* tag */ - { 0x5c, 0x4c, 0x93, 0x31, 0x04, 0x9d, 0x0b, 0xda, - 0xb0, 0x27, 0x74, 0x08, 0xf6, 0x79, 0x67, 0xe5 } -}, - -{ - 16, 16, 8, 5, - /* key */ - { 0x01, 0xf7, 0x4a, 0xd6, 0x40, 0x77, 0xf2, 0xe7, - 0x04, 0xc0, 0xf6, 0x0a, 0xda, 0x3d, 0xd5, 0x23 }, - /* nonce */ - { 0x70, 0xc3, 0xdb, 0x4f, 0x0d, 0x26, 0x36, 0x84, - 0x00, 0xa1, 0x0e, 0xd0, 0x5d, 0x2b, 0xff, 0x5e }, - /* header */ - { 0x23, 0x4a, 0x34, 0x63, 0xc1, 0x26, 0x4a, 0xc6 }, - /* PT */ - { 0x1a, 0x47, 0xcb, 0x49, 0x33 }, - /* CT */ - { 0xd8, 0x51, 0xd5, 0xba, 0xe0 }, - /* Tag */ - { 0x3a, 0x59, 0xf2, 0x38, 0xa2, 0x3e, 0x39, 0x19, - 0x9d, 0xc9, 0x26, 0x66, 0x26, 0xc4, 0x0f, 0x80 } -} - -}; - int err, x, idx, res; - unsigned long len; - unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE]; - - /* AES can be under rijndael or aes... try to find it */ - if ((idx = find_cipher("aes")) == -1) { - if ((idx = find_cipher("rijndael")) == -1) { - return CRYPT_NOP; - } - } - - for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { - len = sizeof(outtag); - if ((err = eax_encrypt_authenticate_memory(idx, tests[x].key, tests[x].keylen, - tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen, - tests[x].plaintext, tests[x].msglen, outct, outtag, &len)) != CRYPT_OK) { - return err; - } - if (memcmp(outct, tests[x].ciphertext, tests[x].msglen) || memcmp(outtag, tests[x].tag, len)) { -#if 0 - unsigned long y; - printf("\n\nFailure: \nCT:\n"); - for (y = 0; y < (unsigned long)tests[x].msglen; ) { - printf("0x%02x", outct[y]); - if (y < (unsigned long)(tests[x].msglen-1)) printf(", "); - if (!(++y % 8)) printf("\n"); - } - printf("\nTAG:\n"); - for (y = 0; y < len; ) { - printf("0x%02x", outtag[y]); - if (y < len-1) printf(", "); - if (!(++y % 8)) printf("\n"); - } -#endif - return CRYPT_FAIL_TESTVECTOR; - } - - /* test decrypt */ - if ((err = eax_decrypt_verify_memory(idx, tests[x].key, tests[x].keylen, - tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen, - outct, tests[x].msglen, outct, outtag, len, &res)) != CRYPT_OK) { - return err; - } - if (res != 1 || memcmp(outct, tests[x].plaintext, tests[x].msglen)) { -#if 0 - unsigned long y; - printf("\n\nFailure (res == %d): \nPT:\n", res); - for (y = 0; y < (unsigned long)tests[x].msglen; ) { - printf("0x%02x", outct[y]); - if (y < (unsigned long)(tests[x].msglen-1)) printf(", "); - if (!(++y % 8)) printf("\n"); - } - printf("\n\n"); -#endif - return CRYPT_FAIL_TESTVECTOR; - } - - } - return CRYPT_OK; -#endif /* LTC_TEST */ -} - -#endif /* EAX_MODE */ + { 0 }, + /* header */ + { 0 }, + /* plaintext */ + { 0 }, + /* ciphertext */ + { 0 }, + /* tag */ + { 0x9a, 0xd0, 0x7e, 0x7d, 0xbf, 0xf3, 0x01, 0xf5, + 0x05, 0xde, 0x59, 0x6b, 0x96, 0x15, 0xdf, 0xff } +}, + +/* test with nonce */ +{ + 16, 16, 0, 0, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* header */ + { 0 }, + /* plaintext */ + { 0 }, + /* ciphertext */ + { 0 }, + /* tag */ + { 0x1c, 0xe1, 0x0d, 0x3e, 0xff, 0xd4, 0xca, 0xdb, + 0xe2, 0xe4, 0x4b, 0x58, 0xd6, 0x0a, 0xb9, 0xec } +}, + +/* test with header [no nonce] */ +{ + 16, 0, 16, 0, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0 }, + /* header */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* plaintext */ + { 0 }, + /* ciphertext */ + { 0 }, + /* tag */ + { 0x3a, 0x69, 0x8f, 0x7a, 0x27, 0x0e, 0x51, 0xb0, + 0xf6, 0x5b, 0x3d, 0x3e, 0x47, 0x19, 0x3c, 0xff } +}, + +/* test with header + nonce + plaintext */ +{ + 16, 16, 16, 32, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* header */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* plaintext */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + /* ciphertext */ + { 0x29, 0xd8, 0x78, 0xd1, 0xa3, 0xbe, 0x85, 0x7b, + 0x6f, 0xb8, 0xc8, 0xea, 0x59, 0x50, 0xa7, 0x78, + 0x33, 0x1f, 0xbf, 0x2c, 0xcf, 0x33, 0x98, 0x6f, + 0x35, 0xe8, 0xcf, 0x12, 0x1d, 0xcb, 0x30, 0xbc }, + /* tag */ + { 0x4f, 0xbe, 0x03, 0x38, 0xbe, 0x1c, 0x8c, 0x7e, + 0x1d, 0x7a, 0xe7, 0xe4, 0x5b, 0x92, 0xc5, 0x87 } +}, + +/* test with header + nonce + plaintext [not even sizes!] */ +{ + 16, 15, 14, 29, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e }, + /* header */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d }, + /* plaintext */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c }, + /* ciphertext */ + { 0xdd, 0x25, 0xc7, 0x54, 0xc5, 0xb1, 0x7c, 0x59, + 0x28, 0xb6, 0x9b, 0x73, 0x15, 0x5f, 0x7b, 0xb8, + 0x88, 0x8f, 0xaf, 0x37, 0x09, 0x1a, 0xd9, 0x2c, + 0x8a, 0x24, 0xdb, 0x86, 0x8b }, + /* tag */ + { 0x0d, 0x1a, 0x14, 0xe5, 0x22, 0x24, 0xff, 0xd2, + 0x3a, 0x05, 0xfa, 0x02, 0xcd, 0xef, 0x52, 0xda } +}, + +/* Vectors from Brian Gladman */ + +{ + 16, 16, 8, 0, + /* key */ + { 0x23, 0x39, 0x52, 0xde, 0xe4, 0xd5, 0xed, 0x5f, + 0x9b, 0x9c, 0x6d, 0x6f, 0xf8, 0x0f, 0xf4, 0x78 }, + /* nonce */ + { 0x62, 0xec, 0x67, 0xf9, 0xc3, 0xa4, 0xa4, 0x07, + 0xfc, 0xb2, 0xa8, 0xc4, 0x90, 0x31, 0xa8, 0xb3 }, + /* header */ + { 0x6b, 0xfb, 0x91, 0x4f, 0xd0, 0x7e, 0xae, 0x6b }, + /* PT */ + { 0x00 }, + /* CT */ + { 0x00 }, + /* tag */ + { 0xe0, 0x37, 0x83, 0x0e, 0x83, 0x89, 0xf2, 0x7b, + 0x02, 0x5a, 0x2d, 0x65, 0x27, 0xe7, 0x9d, 0x01 } +}, + +{ + 16, 16, 8, 2, + /* key */ + { 0x91, 0x94, 0x5d, 0x3f, 0x4d, 0xcb, 0xee, 0x0b, + 0xf4, 0x5e, 0xf5, 0x22, 0x55, 0xf0, 0x95, 0xa4 }, + /* nonce */ + { 0xbe, 0xca, 0xf0, 0x43, 0xb0, 0xa2, 0x3d, 0x84, + 0x31, 0x94, 0xba, 0x97, 0x2c, 0x66, 0xde, 0xbd }, + /* header */ + { 0xfa, 0x3b, 0xfd, 0x48, 0x06, 0xeb, 0x53, 0xfa }, + /* PT */ + { 0xf7, 0xfb }, + /* CT */ + { 0x19, 0xdd }, + /* tag */ + { 0x5c, 0x4c, 0x93, 0x31, 0x04, 0x9d, 0x0b, 0xda, + 0xb0, 0x27, 0x74, 0x08, 0xf6, 0x79, 0x67, 0xe5 } +}, + +{ + 16, 16, 8, 5, + /* key */ + { 0x01, 0xf7, 0x4a, 0xd6, 0x40, 0x77, 0xf2, 0xe7, + 0x04, 0xc0, 0xf6, 0x0a, 0xda, 0x3d, 0xd5, 0x23 }, + /* nonce */ + { 0x70, 0xc3, 0xdb, 0x4f, 0x0d, 0x26, 0x36, 0x84, + 0x00, 0xa1, 0x0e, 0xd0, 0x5d, 0x2b, 0xff, 0x5e }, + /* header */ + { 0x23, 0x4a, 0x34, 0x63, 0xc1, 0x26, 0x4a, 0xc6 }, + /* PT */ + { 0x1a, 0x47, 0xcb, 0x49, 0x33 }, + /* CT */ + { 0xd8, 0x51, 0xd5, 0xba, 0xe0 }, + /* Tag */ + { 0x3a, 0x59, 0xf2, 0x38, 0xa2, 0x3e, 0x39, 0x19, + 0x9d, 0xc9, 0x26, 0x66, 0x26, 0xc4, 0x0f, 0x80 } +} + +}; + int err, x, idx, res; + unsigned long len; + unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE]; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + len = sizeof(outtag); + if ((err = eax_encrypt_authenticate_memory(idx, tests[x].key, tests[x].keylen, + tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen, + tests[x].plaintext, tests[x].msglen, outct, outtag, &len)) != CRYPT_OK) { + return err; + } + if (memcmp(outct, tests[x].ciphertext, tests[x].msglen) || memcmp(outtag, tests[x].tag, len)) { +#if 0 + unsigned long y; + printf("\n\nFailure: \nCT:\n"); + for (y = 0; y < (unsigned long)tests[x].msglen; ) { + printf("0x%02x", outct[y]); + if (y < (unsigned long)(tests[x].msglen-1)) printf(", "); + if (!(++y % 8)) printf("\n"); + } + printf("\nTAG:\n"); + for (y = 0; y < len; ) { + printf("0x%02x", outtag[y]); + if (y < len-1) printf(", "); + if (!(++y % 8)) printf("\n"); + } +#endif + return CRYPT_FAIL_TESTVECTOR; + } + + /* test decrypt */ + if ((err = eax_decrypt_verify_memory(idx, tests[x].key, tests[x].keylen, + tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen, + outct, tests[x].msglen, outct, outtag, len, &res)) != CRYPT_OK) { + return err; + } + if ((res != 1) || memcmp(outct, tests[x].plaintext, tests[x].msglen)) { +#if 0 + unsigned long y; + printf("\n\nFailure (res == %d): \nPT:\n", res); + for (y = 0; y < (unsigned long)tests[x].msglen; ) { + printf("0x%02x", outct[y]); + if (y < (unsigned long)(tests[x].msglen-1)) printf(", "); + if (!(++y % 8)) printf("\n"); + } + printf("\n\n"); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; +#endif /* LTC_TEST */ +} + +#endif /* EAX_MODE */ diff --git a/ecb_decrypt.c b/ecb_decrypt.c new file mode 100644 index 0000000..c25644f --- /dev/null +++ b/ecb_decrypt.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef ECB + +int ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_ECB *ecb) +{ + int err; + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + _ARGCHK(ecb != NULL); + + if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[ecb->cipher].ecb_decrypt(ct, pt, &ecb->key); + return CRYPT_OK; +} + +#endif + + diff --git a/ecb_encrypt.c b/ecb_encrypt.c new file mode 100644 index 0000000..51b7646 --- /dev/null +++ b/ecb_encrypt.c @@ -0,0 +1,29 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef ECB + +int ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_ECB *ecb) +{ + int err; + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + _ARGCHK(ecb != NULL); + + if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[ecb->cipher].ecb_encrypt(pt, ct, &ecb->key); + return CRYPT_OK; +} + +#endif diff --git a/ecb.c b/ecb_start.c similarity index 52% rename from ecb.c rename to ecb_start.c index d4bced4..073bbe9 100644 --- a/ecb.c +++ b/ecb_start.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -26,34 +26,4 @@ int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ecb->key); } -int ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_ECB *ecb) -{ - int err; - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - _ARGCHK(ecb != NULL); - - if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { - return err; - } - cipher_descriptor[ecb->cipher].ecb_encrypt(pt, ct, &ecb->key); - return CRYPT_OK; -} - -int ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_ECB *ecb) -{ - int err; - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - _ARGCHK(ecb != NULL); - - if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { - return err; - } - cipher_descriptor[ecb->cipher].ecb_decrypt(ct, pt, &ecb->key); - return CRYPT_OK; -} - #endif - - diff --git a/ecc.c b/ecc.c index 9e67a1f..ee19681 100644 --- a/ecc.c +++ b/ecc.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -216,9 +216,12 @@ void ecc_find_base(void) mp_clear_multi(&tx, &ty, &x, &y, &p, &pp, &r, &B, &tmp1, &tmp2, NULL); } - + #endif + + + static int is_valid_idx(int n) { int x; @@ -575,7 +578,7 @@ done: void ecc_sizes(int *low, int *high) { int i; - _ARGCHK(low != NULL); + _ARGCHK(low != NULL); _ARGCHK(high != NULL); *low = INT_MAX; @@ -837,7 +840,7 @@ int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key) } /* load x coordinate */ - INPUT_BIGNUM(&key->pubkey.x, in, x, y); + INPUT_BIGNUM(&key->pubkey.x, in, x, y, inlen); /* load y */ x = (unsigned long)in[y++]; @@ -847,7 +850,7 @@ int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key) if (key->type == PK_PRIVATE) { /* load private key */ - INPUT_BIGNUM(&key->k, in, x, y); + INPUT_BIGNUM(&key->k, in, x, y, inlen); } /* eliminate private key if public */ diff --git a/ecc_sys.c b/ecc_sys.c index 34cd8d7..33e1311 100644 --- a/ecc_sys.c +++ b/ecc_sys.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/gf.c b/gf.c index 35a6ffc..34abb15 100644 --- a/gf.c +++ b/gf.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/hash.c b/hash.c deleted file mode 100644 index 5f21f58..0000000 --- a/hash.c +++ /dev/null @@ -1,102 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * gurantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org - */ -#include "mycrypt.h" - -int hash_memory(int hash, const unsigned char *data, unsigned long len, unsigned char *dst, unsigned long *outlen) -{ - hash_state md; - int err; - - _ARGCHK(data != NULL); - _ARGCHK(dst != NULL); - _ARGCHK(outlen != NULL); - - if ((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - - if (*outlen < hash_descriptor[hash].hashsize) { - return CRYPT_BUFFER_OVERFLOW; - } - *outlen = hash_descriptor[hash].hashsize; - - hash_descriptor[hash].init(&md); - hash_descriptor[hash].process(&md, data, len); - hash_descriptor[hash].done(&md, dst); - return CRYPT_OK; -} - -int hash_filehandle(int hash, FILE *in, unsigned char *dst, unsigned long *outlen) -{ -#ifdef NO_FILE - return CRYPT_NOP; -#else - hash_state md; - unsigned char buf[512]; - size_t x; - int err; - - _ARGCHK(dst != NULL); - _ARGCHK(outlen != NULL); - _ARGCHK(in != NULL); - - if ((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - - if (*outlen < hash_descriptor[hash].hashsize) { - return CRYPT_BUFFER_OVERFLOW; - } - *outlen = hash_descriptor[hash].hashsize; - - hash_descriptor[hash].init(&md); - do { - x = fread(buf, 1, sizeof(buf), in); - hash_descriptor[hash].process(&md, buf, x); - } while (x == sizeof(buf)); - hash_descriptor[hash].done(&md, dst); - -#ifdef CLEAN_STACK - zeromem(buf, sizeof(buf)); -#endif - return CRYPT_OK; -#endif -} - -int hash_file(int hash, const char *fname, unsigned char *dst, unsigned long *outlen) -{ -#ifdef NO_FILE - return CRYPT_NOP; -#else - FILE *in; - int err; - _ARGCHK(fname != NULL); - _ARGCHK(dst != NULL); - _ARGCHK(outlen != NULL); - - if ((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - - in = fopen(fname, "rb"); - if (in == NULL) { - return CRYPT_FILE_NOTFOUND; - } - - err = hash_filehandle(hash, in, dst, outlen); - if (fclose(in) != 0) { - return CRYPT_ERROR; - } - - return err; -#endif -} - diff --git a/hash_file.c b/hash_file.c new file mode 100644 index 0000000..0511f2c --- /dev/null +++ b/hash_file.c @@ -0,0 +1,41 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int hash_file(int hash, const char *fname, unsigned char *dst, unsigned long *outlen) +{ +#ifdef NO_FILE + return CRYPT_NOP; +#else + FILE *in; + int err; + _ARGCHK(fname != NULL); + _ARGCHK(dst != NULL); + _ARGCHK(outlen != NULL); + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + in = fopen(fname, "rb"); + if (in == NULL) { + return CRYPT_FILE_NOTFOUND; + } + + err = hash_filehandle(hash, in, dst, outlen); + if (fclose(in) != 0) { + return CRYPT_ERROR; + } + + return err; +#endif +} + diff --git a/hash_filehandle.c b/hash_filehandle.c new file mode 100644 index 0000000..ca6be90 --- /dev/null +++ b/hash_filehandle.c @@ -0,0 +1,49 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int hash_filehandle(int hash, FILE *in, unsigned char *dst, unsigned long *outlen) +{ +#ifdef NO_FILE + return CRYPT_NOP; +#else + hash_state md; + unsigned char buf[512]; + size_t x; + int err; + + _ARGCHK(dst != NULL); + _ARGCHK(outlen != NULL); + _ARGCHK(in != NULL); + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + if (*outlen < hash_descriptor[hash].hashsize) { + return CRYPT_BUFFER_OVERFLOW; + } + *outlen = hash_descriptor[hash].hashsize; + + hash_descriptor[hash].init(&md); + do { + x = fread(buf, 1, sizeof(buf), in); + hash_descriptor[hash].process(&md, buf, x); + } while (x == sizeof(buf)); + hash_descriptor[hash].done(&md, dst); + +#ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + return CRYPT_OK; +#endif +} + diff --git a/hash_memory.c b/hash_memory.c new file mode 100644 index 0000000..976a145 --- /dev/null +++ b/hash_memory.c @@ -0,0 +1,35 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +int hash_memory(int hash, const unsigned char *data, unsigned long len, unsigned char *dst, unsigned long *outlen) +{ + hash_state md; + int err; + + _ARGCHK(data != NULL); + _ARGCHK(dst != NULL); + _ARGCHK(outlen != NULL); + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + if (*outlen < hash_descriptor[hash].hashsize) { + return CRYPT_BUFFER_OVERFLOW; + } + *outlen = hash_descriptor[hash].hashsize; + + hash_descriptor[hash].init(&md); + hash_descriptor[hash].process(&md, data, len); + hash_descriptor[hash].done(&md, dst); + return CRYPT_OK; +} diff --git a/hmac_done.c b/hmac_done.c new file mode 100644 index 0000000..57ebbcd --- /dev/null +++ b/hmac_done.c @@ -0,0 +1,84 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +/* Submited by Dobes Vandermeer (dobes@smartt.com) */ + +#include "mycrypt.h" + +/* + (1) append zeros to the end of K to create a B byte string + (e.g., if K is of length 20 bytes and B=64, then K will be + appended with 44 zero bytes 0x00) + (2) XOR (bitwise exclusive-OR) the B byte string computed in step + (1) with ipad (ipad = the byte 0x36 repeated B times) + (3) append the stream of data 'text' to the B byte string resulting + from step (2) + (4) apply H to the stream generated in step (3) + (5) XOR (bitwise exclusive-OR) the B byte string computed in + step (1) with opad (opad = the byte 0x5C repeated B times.) + (6) append the H result from step (4) to the B byte string + resulting from step (5) + (7) apply H to the stream generated in step (6) and output + the result +*/ + +#ifdef HMAC + +#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize + +int hmac_done(hmac_state *hmac, unsigned char *hashOut, unsigned long *outlen) +{ + unsigned char buf[MAXBLOCKSIZE]; + unsigned char isha[MAXBLOCKSIZE]; + unsigned long hashsize, i; + int hash, err; + + _ARGCHK(hmac != NULL); + _ARGCHK(hashOut != NULL); + + hash = hmac->hash; + if((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + /* get the hash message digest size */ + hashsize = hash_descriptor[hash].hashsize; + + // Get the hash of the first HMAC vector plus the data + if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) { + return err; + } + + // Create the second HMAC vector vector for step (3) + for(i=0; i < HMAC_BLOCKSIZE; i++) { + buf[i] = hmac->key[i] ^ 0x5C; + } + + // Now calculate the "outer" hash for step (5), (6), and (7) + hash_descriptor[hash].init(&hmac->md); + hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE); + hash_descriptor[hash].process(&hmac->md, isha, hashsize); + hash_descriptor[hash].done(&hmac->md, buf); + + // copy to output + for (i = 0; i < hashsize && i < *outlen; i++) { + hashOut[i] = buf[i]; + } + *outlen = i; + +#ifdef CLEAN_STACK + zeromem(isha, sizeof(buf)); + zeromem(buf, sizeof(isha)); + zeromem(hmac, sizeof(*hmac)); +#endif + return CRYPT_OK; +} + +#endif diff --git a/hmac_file.c b/hmac_file.c new file mode 100644 index 0000000..23194bd --- /dev/null +++ b/hmac_file.c @@ -0,0 +1,96 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +/* Submited by Dobes Vandermeer (dobes@smartt.com) */ + +#include "mycrypt.h" + +/* + (1) append zeros to the end of K to create a B byte string + (e.g., if K is of length 20 bytes and B=64, then K will be + appended with 44 zero bytes 0x00) + (2) XOR (bitwise exclusive-OR) the B byte string computed in step + (1) with ipad (ipad = the byte 0x36 repeated B times) + (3) append the stream of data 'text' to the B byte string resulting + from step (2) + (4) apply H to the stream generated in step (3) + (5) XOR (bitwise exclusive-OR) the B byte string computed in + step (1) with opad (opad = the byte 0x5C repeated B times.) + (6) append the H result from step (4) to the B byte string + resulting from step (5) + (7) apply H to the stream generated in step (6) and output + the result +*/ + +#ifdef HMAC + +#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize + +/* hmac_file added by Tom St Denis */ +int hmac_file(int hash, const char *fname, + const unsigned char *key, unsigned long keylen, + unsigned char *dst, unsigned long *dstlen) +{ +#ifdef NO_FILE + return CRYPT_NOP; +#else + hmac_state hmac; + FILE *in; + unsigned char buf[512]; + size_t x; + int err; + + _ARGCHK(fname != NULL); + _ARGCHK(key != NULL); + _ARGCHK(dst != NULL); + _ARGCHK(dstlen != NULL); + + if((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) { + return err; + } + + in = fopen(fname, "rb"); + if (in == NULL) { + return CRYPT_FILE_NOTFOUND; + } + + /* process the file contents */ + do { + x = fread(buf, 1, sizeof(buf), in); + if ((err = hmac_process(&hmac, buf, (unsigned long)x)) != CRYPT_OK) { + /* we don't trap this error since we're already returning an error! */ + fclose(in); + return err; + } + } while (x == sizeof(buf)); + + if (fclose(in) != 0) { + return CRYPT_ERROR; + } + + /* get final hmac */ + if ((err = hmac_done(&hmac, dst, dstlen)) != CRYPT_OK) { + return err; + } + +#ifdef CLEAN_STACK + /* clear memory */ + zeromem(buf, sizeof(buf)); +#endif + return CRYPT_OK; +#endif +} + +#endif + diff --git a/hmac_init.c b/hmac_init.c new file mode 100644 index 0000000..7a9b801 --- /dev/null +++ b/hmac_init.c @@ -0,0 +1,87 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +/* Submited by Dobes Vandermeer (dobes@smartt.com) */ + +#include "mycrypt.h" + +/* + (1) append zeros to the end of K to create a B byte string + (e.g., if K is of length 20 bytes and B=64, then K will be + appended with 44 zero bytes 0x00) + (2) XOR (bitwise exclusive-OR) the B byte string computed in step + (1) with ipad (ipad = the byte 0x36 repeated B times) + (3) append the stream of data 'text' to the B byte string resulting + from step (2) + (4) apply H to the stream generated in step (3) + (5) XOR (bitwise exclusive-OR) the B byte string computed in + step (1) with opad (opad = the byte 0x5C repeated B times.) + (6) append the H result from step (4) to the B byte string + resulting from step (5) + (7) apply H to the stream generated in step (6) and output + the result +*/ + +#ifdef HMAC + +#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize + +int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen) +{ + unsigned char buf[MAXBLOCKSIZE]; + unsigned long hashsize; + unsigned long i, z; + int err; + + _ARGCHK(hmac != NULL); + _ARGCHK(key != NULL); + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + /* valid key length? */ + if (keylen == 0) { + return CRYPT_INVALID_KEYSIZE; + } + + hmac->hash = hash; + + // (1) make sure we have a large enough key + hashsize = hash_descriptor[hash].hashsize; + if(keylen > HMAC_BLOCKSIZE) { + z = (unsigned long)sizeof(hmac->key); + if ((err = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) { + return err; + } + if(hashsize < HMAC_BLOCKSIZE) { + zeromem((hmac->key) + hashsize, (size_t)(HMAC_BLOCKSIZE - hashsize)); + } + keylen = hashsize; + } else { + memcpy(hmac->key, key, (size_t)keylen); + if(keylen < HMAC_BLOCKSIZE) { + zeromem((hmac->key) + keylen, (size_t)(HMAC_BLOCKSIZE - keylen)); + } + } + + // Create the initial vector for step (3) + for(i=0; i < HMAC_BLOCKSIZE; i++) { + buf[i] = hmac->key[i] ^ 0x36; + } + + // Pre-pend that to the hash data + hash_descriptor[hash].init(&hmac->md); + hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE); + + return CRYPT_OK; +} + +#endif diff --git a/hmac_memory.c b/hmac_memory.c new file mode 100644 index 0000000..e438a30 --- /dev/null +++ b/hmac_memory.c @@ -0,0 +1,67 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +/* Submited by Dobes Vandermeer (dobes@smartt.com) */ + +#include "mycrypt.h" + +/* + (1) append zeros to the end of K to create a B byte string + (e.g., if K is of length 20 bytes and B=64, then K will be + appended with 44 zero bytes 0x00) + (2) XOR (bitwise exclusive-OR) the B byte string computed in step + (1) with ipad (ipad = the byte 0x36 repeated B times) + (3) append the stream of data 'text' to the B byte string resulting + from step (2) + (4) apply H to the stream generated in step (3) + (5) XOR (bitwise exclusive-OR) the B byte string computed in + step (1) with opad (opad = the byte 0x5C repeated B times.) + (6) append the H result from step (4) to the B byte string + resulting from step (5) + (7) apply H to the stream generated in step (6) and output + the result +*/ + +#ifdef HMAC + +#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize + +int hmac_memory(int hash, const unsigned char *key, unsigned long keylen, + const unsigned char *data, unsigned long len, + unsigned char *dst, unsigned long *dstlen) +{ + hmac_state hmac; + int err; + + _ARGCHK(key != NULL); + _ARGCHK(data != NULL); + _ARGCHK(dst != NULL); + _ARGCHK(dstlen != NULL); + + if((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) { + return err; + } + + if ((err = hmac_process(&hmac, data, len)) != CRYPT_OK) { + return err; + } + + if ((err = hmac_done(&hmac, dst, dstlen)) != CRYPT_OK) { + return err; + } + return CRYPT_OK; +} + +#endif + diff --git a/hmac_process.c b/hmac_process.c new file mode 100644 index 0000000..fa4c1e6 --- /dev/null +++ b/hmac_process.c @@ -0,0 +1,48 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +/* Submited by Dobes Vandermeer (dobes@smartt.com) */ + +#include "mycrypt.h" + +/* + (1) append zeros to the end of K to create a B byte string + (e.g., if K is of length 20 bytes and B=64, then K will be + appended with 44 zero bytes 0x00) + (2) XOR (bitwise exclusive-OR) the B byte string computed in step + (1) with ipad (ipad = the byte 0x36 repeated B times) + (3) append the stream of data 'text' to the B byte string resulting + from step (2) + (4) apply H to the stream generated in step (3) + (5) XOR (bitwise exclusive-OR) the B byte string computed in + step (1) with opad (opad = the byte 0x5C repeated B times.) + (6) append the H result from step (4) to the B byte string + resulting from step (5) + (7) apply H to the stream generated in step (6) and output + the result +*/ + +#ifdef HMAC + +#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize + +int hmac_process(hmac_state *hmac, const unsigned char *buf, unsigned long len) +{ + int err; + _ARGCHK(hmac != NULL); + _ARGCHK(buf != NULL); + if ((err = hash_is_valid(hmac->hash)) != CRYPT_OK) { + return err; + } + return hash_descriptor[hmac->hash].process(&hmac->md, buf, len); +} + +#endif + diff --git a/hmac.c b/hmac_test.c similarity index 71% rename from hmac.c rename to hmac_test.c index 7685448..4ec7d94 100644 --- a/hmac.c +++ b/hmac_test.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -33,205 +33,6 @@ #define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize -int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen) -{ - unsigned char buf[MAXBLOCKSIZE]; - unsigned long hashsize; - unsigned long i, z; - int err; - - _ARGCHK(hmac != NULL); - _ARGCHK(key != NULL); - - if ((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - - /* valid key length? */ - if (keylen == 0) { - return CRYPT_INVALID_KEYSIZE; - } - - hmac->hash = hash; - - // (1) make sure we have a large enough key - hashsize = hash_descriptor[hash].hashsize; - if(keylen > HMAC_BLOCKSIZE) { - z = (unsigned long)sizeof(hmac->key); - if ((err = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) { - return err; - } - if(hashsize < HMAC_BLOCKSIZE) { - zeromem((hmac->key) + hashsize, (size_t)(HMAC_BLOCKSIZE - hashsize)); - } - keylen = hashsize; - } else { - memcpy(hmac->key, key, (size_t)keylen); - if(keylen < HMAC_BLOCKSIZE) { - zeromem((hmac->key) + keylen, (size_t)(HMAC_BLOCKSIZE - keylen)); - } - } - - // Create the initial vector for step (3) - for(i=0; i < HMAC_BLOCKSIZE; i++) { - buf[i] = hmac->key[i] ^ 0x36; - } - - // Pre-pend that to the hash data - hash_descriptor[hash].init(&hmac->md); - hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE); - - return CRYPT_OK; -} - -int hmac_process(hmac_state *hmac, const unsigned char *buf, unsigned long len) -{ - int err; - _ARGCHK(hmac != NULL); - _ARGCHK(buf != NULL); - if ((err = hash_is_valid(hmac->hash)) != CRYPT_OK) { - return err; - } - return hash_descriptor[hmac->hash].process(&hmac->md, buf, len); -} - -int hmac_done(hmac_state *hmac, unsigned char *hashOut, unsigned long *outlen) -{ - unsigned char buf[MAXBLOCKSIZE]; - unsigned char isha[MAXBLOCKSIZE]; - unsigned long hashsize, i; - int hash, err; - - _ARGCHK(hmac != NULL); - _ARGCHK(hashOut != NULL); - - hash = hmac->hash; - if((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - - /* get the hash message digest size */ - hashsize = hash_descriptor[hash].hashsize; - - // Get the hash of the first HMAC vector plus the data - if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) { - return err; - } - - // Create the second HMAC vector vector for step (3) - for(i=0; i < HMAC_BLOCKSIZE; i++) { - buf[i] = hmac->key[i] ^ 0x5C; - } - - // Now calculate the "outer" hash for step (5), (6), and (7) - hash_descriptor[hash].init(&hmac->md); - hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE); - hash_descriptor[hash].process(&hmac->md, isha, hashsize); - hash_descriptor[hash].done(&hmac->md, buf); - - // copy to output - for (i = 0; i < hashsize && i < *outlen; i++) { - hashOut[i] = buf[i]; - } - *outlen = i; - -#ifdef CLEAN_STACK - zeromem(isha, sizeof(buf)); - zeromem(buf, sizeof(isha)); - zeromem(hmac, sizeof(*hmac)); -#endif - return CRYPT_OK; -} - -int hmac_memory(int hash, const unsigned char *key, unsigned long keylen, - const unsigned char *data, unsigned long len, - unsigned char *dst, unsigned long *dstlen) -{ - hmac_state hmac; - int err; - - _ARGCHK(key != NULL); - _ARGCHK(data != NULL); - _ARGCHK(dst != NULL); - _ARGCHK(dstlen != NULL); - - if((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - - if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) { - return err; - } - - if ((err = hmac_process(&hmac, data, len)) != CRYPT_OK) { - return err; - } - - if ((err = hmac_done(&hmac, dst, dstlen)) != CRYPT_OK) { - return err; - } - return CRYPT_OK; -} - -/* hmac_file added by Tom St Denis */ -int hmac_file(int hash, const char *fname, - const unsigned char *key, unsigned long keylen, - unsigned char *dst, unsigned long *dstlen) -{ -#ifdef NO_FILE - return CRYPT_NOP; -#else - hmac_state hmac; - FILE *in; - unsigned char buf[512]; - size_t x; - int err; - - _ARGCHK(fname != NULL); - _ARGCHK(key != NULL); - _ARGCHK(dst != NULL); - _ARGCHK(dstlen != NULL); - - if((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - - if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) { - return err; - } - - in = fopen(fname, "rb"); - if (in == NULL) { - return CRYPT_FILE_NOTFOUND; - } - - /* process the file contents */ - do { - x = fread(buf, 1, sizeof(buf), in); - if ((err = hmac_process(&hmac, buf, (unsigned long)x)) != CRYPT_OK) { - /* we don't trap this error since we're already returning an error! */ - fclose(in); - return err; - } - } while (x == sizeof(buf)); - - if (fclose(in) != 0) { - return CRYPT_ERROR; - } - - /* get final hmac */ - if ((err = hmac_done(&hmac, dst, dstlen)) != CRYPT_OK) { - return err; - } - -#ifdef CLEAN_STACK - /* clear memory */ - zeromem(buf, sizeof(buf)); -#endif - return CRYPT_OK; -#endif -} - /* TEST CASES SOURCE: diff --git a/is_prime.c b/is_prime.c new file mode 100644 index 0000000..d6fc84e --- /dev/null +++ b/is_prime.c @@ -0,0 +1,27 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef MPI + +/* figures out if a number is prime (MR test) */ +int is_prime(mp_int *N, int *result) +{ + int err; + _ARGCHK(N != NULL); + _ARGCHK(result != NULL); + if ((err = mp_prime_is_prime(N, mp_prime_rabin_miller_trials(mp_count_bits(N)), result)) != MP_OKAY) { + return mpi_to_ltc_error(err); + } + return CRYPT_OK; +} + +#endif diff --git a/keyring.c b/keyring.c index 565d4ec..56f128d 100644 --- a/keyring.c +++ b/keyring.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/makefile b/makefile index ecaa741..53ca3a6 100644 --- a/makefile +++ b/makefile @@ -9,7 +9,7 @@ # a build. This is easy to remedy though, for those that have problems. # The version -VERSION=0.94 +VERSION=0.95 #ch1-01-1 # Compiler and Linker Names @@ -23,7 +23,8 @@ VERSION=0.94 #ch1-01-3 # Compilation flags. Note the += does not write over the user's CFLAGS! -CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wno-unused -Wshadow -Werror +CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wshadow +# -Werror # optimize for SPEED #CFLAGS += -O3 -funroll-loops @@ -62,12 +63,63 @@ DATAPATH=/usr/share/doc/libtomcrypt/pdf #Leave MPI built-in or force developer to link against libtommath? MPIOBJECT=mpi.o -OBJECTS=keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o \ -bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o \ -md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o des.o \ -safer_tab.o safer.o saferp.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o \ -prime.o twofish.o packet.o hmac.o strings.o rmd128.o rmd160.o skipjack.o omac.o dsa.o \ -eax.o ocb.o pmac.o whirl.o $(MPIOBJECT) +OBJECTS=keyring.o gf.o strings.o base64.o \ +\ +crypt.o crypt_find_cipher.o crypt_find_hash_any.o \ +crypt_hash_is_valid.o crypt_register_hash.o crypt_unregister_prng.o \ +crypt_argchk.o crypt_find_cipher_any.o crypt_find_hash_id.o \ +crypt_prng_descriptor.o crypt_register_prng.o crypt_cipher_descriptor.o \ +crypt_find_cipher_id.o crypt_find_prng.o crypt_prng_is_valid.o \ +crypt_unregister_cipher.o crypt_cipher_is_valid.o crypt_find_hash.o \ +crypt_hash_descriptor.o crypt_register_cipher.o crypt_unregister_hash.o \ +\ +sprng.o yarrow.o rc4.o rng_get_bytes.o rng_make_prng.o \ +\ +rand_prime.o is_prime.o \ +\ +ecc.o dh.o \ +\ +rsa.o rsa_exptmod.o rsa_free.o rsa_make_key.o \ +\ +dsa_export.o dsa_free.o dsa_import.o dsa_make_key.o dsa_sign_hash.o dsa_verify_hash.o dsa_verify_key.o \ +\ +xtea.o aes.o des.o safer_tab.o safer.o saferp.o rc2.o \ +rc6.o rc5.o cast5.o noekeon.o blowfish.o twofish.o skipjack.o \ +\ +md2.o md4.o md5.o sha1.o sha256.o sha512.o tiger.o whirl.o \ +rmd128.o rmd160.o \ +\ +packet_store_header.o packet_valid_header.o \ +\ +eax_addheader.o eax_decrypt.o eax_decrypt_verify_memory.o eax_done.o eax_encrypt.o \ +eax_encrypt_authenticate_memory.o eax_init.o eax_test.o \ +\ +ocb_decrypt.o ocb_decrypt_verify_memory.o ocb_done_decrypt.o ocb_done_encrypt.o \ +ocb_encrypt.o ocb_encrypt_authenticate_memory.o ocb_init.o ocb_ntz.o \ +ocb_shift_xor.o ocb_test.o s_ocb_done.o \ +\ +omac_done.o omac_file.o omac_init.o omac_memory.o omac_process.o omac_test.o \ +\ +pmac_done.o pmac_file.o pmac_init.o pmac_memory.o pmac_ntz.o pmac_process.o \ +pmac_shift_xor.o pmac_test.o \ +\ +cbc_start.o cbc_encrypt.o cbc_decrypt.o \ +cfb_start.o cfb_encrypt.o cfb_decrypt.o \ +ofb_start.o ofb_encrypt.o ofb_decrypt.o \ +ctr_start.o ctr_encrypt.o ctr_decrypt.o \ +ecb_start.o ecb_encrypt.o ecb_decrypt.o \ +\ +hash_file.o hash_filehandle.o hash_memory.o \ +\ +hmac_done.o hmac_file.o hmac_init.o hmac_memory.o hmac_process.o hmac_test.o \ +\ +pkcs_1_mgf1.o pkcs_1_oaep_encode.o pkcs_1_oaep_decode.o \ +pkcs_1_pss_encode.o pkcs_1_pss_decode.o pkcs_1_i2osp.o pkcs_1_os2ip.o \ +\ +pkcs_5_1.o pkcs_5_2.o \ +\ +burn_stack.o zeromem.o \ +$(MPIOBJECT) TESTOBJECTS=demos/test.o HASHOBJECTS=demos/hashsum.o @@ -85,7 +137,8 @@ COMPRESSED=crypt.tar.bz2 crypt.zip crypt.tar.gz #Header files used by libtomcrypt. HEADERS=tommath.h mycrypt_cfg.h mycrypt_gf.h mycrypt_kr.h \ mycrypt_misc.h mycrypt_prng.h mycrypt_cipher.h mycrypt_hash.h \ -mycrypt_macros.h mycrypt_pk.h mycrypt.h mycrypt_argchk.h mycrypt_custom.h +mycrypt_macros.h mycrypt_pk.h mycrypt.h mycrypt_argchk.h \ +mycrypt_custom.h mycrypt_pkcs.h #The default rule for make builds the libtomcrypt library. default:library mycrypt.h mycrypt_cfg.h @@ -127,6 +180,34 @@ x86_prof: library $(PROFS) tv_gen: library $(TVS) $(CC) $(TVS) $(LIBNAME) -o $(TV) + +#make a profiled library (takes a while!!!) +# +# This will build the library with profile generation +# then run the test demo and rebuild the library. +# +# So far I've seen improvements in the MP math +# +# This works with GCC v3.3.x [tested with 3.3.3] +profiled: $(TESTOBJECTS) + make CFLAGS="$(CFLAGS) -fprofile-arcs" + $(CC) $(TESTOBJECTS) $(LIBNAME) -o $(TEST) + ./test + rm -f *.a *.o test demos/test.o + make CFLAGS="$(CFLAGS) -fbranch-probabilities" + + +#Profiling in GCC 3.4.x is a little diff. +# +#Tested with GCC v3.4.0 +profiled34: $(TESTOBJECTS) + make CFLAGS="$(CFLAGS) -fprofile-generate" + $(CC) $(TESTOBJECTS) $(LIBNAME) -lgcov -o $(TEST) + ./test + rm -f *.a *.o test demos/test.o + make CFLAGS="$(CFLAGS) -fprofile-use" + + #This rule installs the library and the header files. This must be run #as root in order to have a high enough permission to write to the correct #directories and to set the owner and group to root. @@ -143,7 +224,8 @@ install: library docs clean: rm -f $(OBJECTS) $(TESTOBJECTS) $(HASHOBJECTS) $(CRYPTOBJECTS) $(SMALLOBJECTS) $(LEFTOVERS) $(LIBNAME) rm -f $(TEST) $(HASH) $(COMPRESSED) $(PROFS) $(PROF) $(TVS) $(TV) - rm -f *.a *.dll *stackdump *.lib *.exe *.obj demos/*.obj demos/*.o *.bat *.txt + rm -f *.a *.dll *stackdump *.lib *.exe *.obj demos/*.obj demos/*.o *.bat *.txt *.il *.da demos/*.il demos/*.da *.dyn *.dpi \ + *.gcda *.gcno demos/*.gcno demos/*.gcda *~ #This builds the crypt.pdf file. Note that the rm -f *.pdf has been removed #from the clean command! This is because most people would like to keep the diff --git a/makefile.cygwin_dll b/makefile.cygwin_dll index 1231e9d..abec0a5 100644 --- a/makefile.cygwin_dll +++ b/makefile.cygwin_dll @@ -4,7 +4,7 @@ default: ltc_dll # Compilation flags. Note the += does not write over the user's CFLAGS! -CFLAGS += -I./ -Wall -Wsign-compare -W -Wno-unused -Wshadow -Werror -mno-cygwin -DWIN32 +CFLAGS += -I./ -Wall -Wsign-compare -W -Wno-unused -Wshadow -mno-cygwin -DWIN32 # optimize for SPEED #CFLAGS += -O3 -funroll-loops @@ -18,12 +18,63 @@ CFLAGS += -Os #Leave MPI built-in or force developer to link against libtommath? MPIOBJECT=mpi.o -OBJECTS=keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o \ -bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o \ -md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o des.o \ -safer_tab.o safer.o saferp.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o \ -prime.o twofish.o packet.o hmac.o strings.o rmd128.o rmd160.o skipjack.o omac.o dsa.o eax.o \ -ocb.o pmac.o whirl.o $(MPIOBJECT) +OBJECTS=keyring.o gf.o strings.o base64.o \ +\ +crypt.o crypt_find_cipher.o crypt_find_hash_any.o \ +crypt_hash_is_valid.o crypt_register_hash.o crypt_unregister_prng.o \ +crypt_argchk.o crypt_find_cipher_any.o crypt_find_hash_id.o \ +crypt_prng_descriptor.o crypt_register_prng.o crypt_cipher_descriptor.o \ +crypt_find_cipher_id.o crypt_find_prng.o crypt_prng_is_valid.o \ +crypt_unregister_cipher.o crypt_cipher_is_valid.o crypt_find_hash.o \ +crypt_hash_descriptor.o crypt_register_cipher.o crypt_unregister_hash.o \ +\ +sprng.o yarrow.o rc4.o rng_get_bytes.o rng_make_prng.o \ +\ +rand_prime.o is_prime.o \ +\ +ecc.o dh.o \ +\ +rsa.o rsa_exptmod.o rsa_free.o rsa_make_key.o \ +\ +dsa_export.o dsa_free.o dsa_import.o dsa_make_key.o dsa_sign_hash.o dsa_verify_hash.o dsa_verify_key.o \ +\ +xtea.o aes.o des.o safer_tab.o safer.o saferp.o rc2.o \ +rc6.o rc5.o cast5.o noekeon.o blowfish.o twofish.o skipjack.o \ +\ +md2.o md4.o md5.o sha1.o sha256.o sha512.o tiger.o whirl.o \ +rmd128.o rmd160.o \ +\ +packet_store_header.o packet_valid_header.o \ +\ +eax_addheader.o eax_decrypt.o eax_decrypt_verify_memory.o eax_done.o eax_encrypt.o \ +eax_encrypt_authenticate_memory.o eax_init.o eax_test.o \ +\ +ocb_decrypt.o ocb_decrypt_verify_memory.o ocb_done_decrypt.o ocb_done_encrypt.o \ +ocb_encrypt.o ocb_encrypt_authenticate_memory.o ocb_init.o ocb_ntz.o \ +ocb_shift_xor.o ocb_test.o s_ocb_done.o \ +\ +omac_done.o omac_file.o omac_init.o omac_memory.o omac_process.o omac_test.o \ +\ +pmac_done.o pmac_file.o pmac_init.o pmac_memory.o pmac_ntz.o pmac_process.o \ +pmac_shift_xor.o pmac_test.o \ +\ +cbc_start.o cbc_encrypt.o cbc_decrypt.o \ +cfb_start.o cfb_encrypt.o cfb_decrypt.o \ +ofb_start.o ofb_encrypt.o ofb_decrypt.o \ +ctr_start.o ctr_encrypt.o ctr_decrypt.o \ +ecb_start.o ecb_encrypt.o ecb_decrypt.o \ +\ +hash_file.o hash_filehandle.o hash_memory.o \ +\ +hmac_done.o hmac_file.o hmac_init.o hmac_memory.o hmac_process.o hmac_test.o \ +\ +pkcs_1_mgf1.o pkcs_1_oaep_encode.o pkcs_1_oaep_decode.o \ +pkcs_1_pss_encode.o pkcs_1_pss_decode.o pkcs_1_i2osp.o pkcs_1_os2ip.o \ +\ +pkcs_5_1.o pkcs_5_2.o \ +\ +burn_stack.o zeromem.o \ +$(MPIOBJECT) ltc_dll: $(OBJECTS) $(MPIOBJECT) gcc -mno-cygwin -mdll -o libtomcrypt.dll -Wl,--out-implib=libtomcrypt.dll.a -Wl,--export-all-symbols *.o -ladvapi32 diff --git a/makefile.icc b/makefile.icc new file mode 100644 index 0000000..de547a0 --- /dev/null +++ b/makefile.icc @@ -0,0 +1,213 @@ +# MAKEFILE for linux ICC (Intel C compiler) +# +# Tested with ICC v8.... +# +# Be aware that ICC isn't quite as stable as GCC and several optimization switches +# seem to break the code (that GCC and MSVC compile just fine). In particular +# "-ip" and "-x*" seem to break the code (ROL/ROR macro problems). As the makefile +# is shipped the code will build and execute properly. +# +# Also note that ICC often makes code that is slower than GCC. This is probably due to +# a mix of not being able to use "-ip" and just having fewer optimization algos than GCC. +# +# Tom St Denis + +#ch1-01-1 +# Compiler and Linker Names +CC=icc +#LD=ld + +# Archiver [makes .a files] +#AR=ar +#ARFLAGS=r + +# Compilation flags. Note the += does not write over the user's CFLAGS! +CFLAGS += -c -I./ -DINTEL_CC + +# optimize for SPEED +# +# -mcpu= can be pentium, pentiumpro (covers PII through PIII) or pentium4 +# -ax? specifies make code specifically for ? but compatible with IA-32 +# -x? specifies compile solely for ? [not specifically IA-32 compatible] +# +# where ? is +# K - PIII +# W - first P4 [Williamette] +# N - P4 Northwood +# P - P4 Prescott +# B - Blend of P4 and PM [mobile] +# +# Default to just generic max opts +CFLAGS += -O3 -xN -ip + +# want to see stuff? +#CFLAGS += -opt_report + +#These flags control how the library gets built. + +#Output filenames for various targets. +LIBNAME=libtomcrypt.a +TEST=test +HASH=hashsum +CRYPT=encrypt +SMALL=small +PROF=x86_prof +TV=tv_gen + +#LIBPATH-The directory for libtomcrypt to be installed to. +#INCPATH-The directory to install the header files for libtomcrypt. +#DATAPATH-The directory to install the pdf docs. +DESTDIR= +LIBPATH=/usr/lib +INCPATH=/usr/include +DATAPATH=/usr/share/doc/libtomcrypt/pdf + +#List of objects to compile. + +#Leave MPI built-in or force developer to link against libtommath? +MPIOBJECT=mpi.o + +OBJECTS=keyring.o gf.o strings.o base64.o \ +\ +crypt.o crypt_find_cipher.o crypt_find_hash_any.o \ +crypt_hash_is_valid.o crypt_register_hash.o crypt_unregister_prng.o \ +crypt_argchk.o crypt_find_cipher_any.o crypt_find_hash_id.o \ +crypt_prng_descriptor.o crypt_register_prng.o crypt_cipher_descriptor.o \ +crypt_find_cipher_id.o crypt_find_prng.o crypt_prng_is_valid.o \ +crypt_unregister_cipher.o crypt_cipher_is_valid.o crypt_find_hash.o \ +crypt_hash_descriptor.o crypt_register_cipher.o crypt_unregister_hash.o \ +\ +sprng.o yarrow.o rc4.o rng_get_bytes.o rng_make_prng.o \ +\ +rand_prime.o is_prime.o \ +\ +ecc.o dh.o \ +\ +rsa.o rsa_exptmod.o rsa_free.o rsa_make_key.o \ +\ +dsa_export.o dsa_free.o dsa_import.o dsa_make_key.o dsa_sign_hash.o dsa_verify_hash.o dsa_verify_key.o \ +\ +xtea.o aes.o des.o safer_tab.o safer.o saferp.o rc2.o \ +rc6.o rc5.o cast5.o noekeon.o blowfish.o twofish.o skipjack.o \ +\ +md2.o md4.o md5.o sha1.o sha256.o sha512.o tiger.o whirl.o \ +rmd128.o rmd160.o \ +\ +packet_store_header.o packet_valid_header.o \ +\ +eax_addheader.o eax_decrypt.o eax_decrypt_verify_memory.o eax_done.o eax_encrypt.o \ +eax_encrypt_authenticate_memory.o eax_init.o eax_test.o \ +\ +ocb_decrypt.o ocb_decrypt_verify_memory.o ocb_done_decrypt.o ocb_done_encrypt.o \ +ocb_encrypt.o ocb_encrypt_authenticate_memory.o ocb_init.o ocb_ntz.o \ +ocb_shift_xor.o ocb_test.o s_ocb_done.o \ +\ +omac_done.o omac_file.o omac_init.o omac_memory.o omac_process.o omac_test.o \ +\ +pmac_done.o pmac_file.o pmac_init.o pmac_memory.o pmac_ntz.o pmac_process.o \ +pmac_shift_xor.o pmac_test.o \ +\ +cbc_start.o cbc_encrypt.o cbc_decrypt.o \ +cfb_start.o cfb_encrypt.o cfb_decrypt.o \ +ofb_start.o ofb_encrypt.o ofb_decrypt.o \ +ctr_start.o ctr_encrypt.o ctr_decrypt.o \ +ecb_start.o ecb_encrypt.o ecb_decrypt.o \ +\ +hash_file.o hash_filehandle.o hash_memory.o \ +\ +hmac_done.o hmac_file.o hmac_init.o hmac_memory.o hmac_process.o hmac_test.o \ +\ +pkcs_1_mgf1.o pkcs_1_oaep_encode.o pkcs_1_oaep_decode.o \ +pkcs_1_pss_encode.o pkcs_1_pss_decode.o pkcs_1_i2osp.o pkcs_1_os2ip.o \ +\ +pkcs_5_1.o pkcs_5_2.o \ +\ +burn_stack.o zeromem.o \ +$(MPIOBJECT) + +TESTOBJECTS=demos/test.o +HASHOBJECTS=demos/hashsum.o +CRYPTOBJECTS=demos/encrypt.o +SMALLOBJECTS=demos/small.o +PROFS=demos/x86_prof.o +TVS=demos/tv_gen.o + +#Files left over from making the crypt.pdf. +LEFTOVERS=*.dvi *.log *.aux *.toc *.idx *.ilg *.ind + +#Compressed filenames +COMPRESSED=crypt.tar.bz2 crypt.zip crypt.tar.gz + +#Header files used by libtomcrypt. +HEADERS=tommath.h mycrypt_cfg.h mycrypt_gf.h mycrypt_kr.h \ +mycrypt_misc.h mycrypt_prng.h mycrypt_cipher.h mycrypt_hash.h \ +mycrypt_macros.h mycrypt_pk.h mycrypt.h mycrypt_argchk.h mycrypt_custom.h + +#The default rule for make builds the libtomcrypt library. +default:library mycrypt.h mycrypt_cfg.h + +#These are the rules to make certain object files. +rsa.o: rsa.c rsa_sys.c +ecc.o: ecc.c ecc_sys.c +dh.o: dh.c dh_sys.c +aes.o: aes.c aes_tab.c +twofish.o: twofish.c twofish_tab.c +sha512.o: sha512.c sha384.c +sha256.o: sha256.c sha224.c + +#This rule makes the libtomcrypt library. +library: $(LIBNAME) + +$(LIBNAME): $(OBJECTS) + $(AR) $(ARFLAGS) $@ $(OBJECTS) + +#This rule makes the test program included with libtomcrypt +test: library $(TESTOBJECTS) + $(CC) $(TESTOBJECTS) $(LIBNAME) -o $(TEST) $(WARN) + +#This rule makes the hash program included with libtomcrypt +hashsum: library $(HASHOBJECTS) + $(CC) $(HASHOBJECTS) $(LIBNAME) -o $(HASH) $(WARN) + +#makes the crypt program +crypt: library $(CRYPTOBJECTS) + $(CC) $(CRYPTOBJECTS) $(LIBNAME) -o $(CRYPT) $(WARN) + +#makes the small program +small: library $(SMALLOBJECTS) + $(CC) $(SMALLOBJECTS) $(LIBNAME) -o $(SMALL) $(WARN) + +x86_prof: library $(PROFS) + $(CC) $(PROFS) $(LIBNAME) -o $(PROF) + +tv_gen: library $(TVS) + $(CC) $(TVS) $(LIBNAME) -o $(TV) + + +#make a profiled library (takes a while!!!) +# +# This will build the library with profile generation +# then run the test demo and rebuild the library. +# +# So far I've seen improvements in the MP math +profiled: + make -f makefile.icc CFLAGS="$(CFLAGS) -prof_gen" test + ./test + rm -f *.a *.o test demos/test.o + make -f makefile.icc CFLAGS="$(CFLAGS) -prof_use" + +#This rule installs the library and the header files. This must be run +#as root in order to have a high enough permission to write to the correct +#directories and to set the owner and group to root. +install: library + install -d -g root -o root $(DESTDIR)$(LIBPATH) + install -d -g root -o root $(DESTDIR)$(INCPATH) + install -g root -o root $(LIBNAME) $(DESTDIR)$(LIBPATH) + install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH) + +#This rule cleans the source tree of all compiled code, not including the pdf +#documentation. +clean: + rm -f $(OBJECTS) $(TESTOBJECTS) $(HASHOBJECTS) $(CRYPTOBJECTS) $(SMALLOBJECTS) $(LEFTOVERS) $(LIBNAME) + rm -f $(TEST) $(HASH) $(COMPRESSED) $(PROFS) $(PROF) $(TVS) $(TV) + rm -f *.a *.dll *stackdump *.lib *.exe *.obj demos/*.obj demos/*.o *.bat *.txt *.il *.da demos/*.il demos/*.da *.dyn diff --git a/makefile.msvc b/makefile.msvc index a587495..5c3c410 100644 --- a/makefile.msvc +++ b/makefile.msvc @@ -5,13 +5,67 @@ CFLAGS = /I. /Ox /DWIN32 /W3 default: library +# leave this blank and link against libtommath if you want better link resolution +MPIOBJECT=mpi.obj + #List of objects to compile. -OBJECTS=keyring.obj gf.obj mem.obj sprng.obj ecc.obj base64.obj dh.obj rsa.obj \ -bits.obj yarrow.obj cfb.obj ofb.obj ecb.obj ctr.obj cbc.obj hash.obj tiger.obj sha1.obj \ -md5.obj md4.obj md2.obj sha256.obj sha512.obj xtea.obj aes.obj des.obj \ -safer_tab.obj safer.obj saferp.obj rc4.obj rc2.obj rc6.obj rc5.obj cast5.obj noekeon.obj \ -blowfish.obj crypt.obj mpi.obj prime.obj twofish.obj packet.obj hmac.obj strings.obj rmd128.obj rmd160.obj \ -skipjack.obj omac.obj dsa.obj eax.obj ocb.obj pmac.obj whirl.obj +OBJECTS=keyring.obj gf.obj strings.obj base64.obj \ +\ +crypt.obj crypt_find_cipher.obj crypt_find_hash_any.obj \ +crypt_hash_is_valid.obj crypt_register_hash.obj crypt_unregister_prng.obj \ +crypt_argchk.obj crypt_find_cipher_any.obj crypt_find_hash_id.obj \ +crypt_prng_descriptor.obj crypt_register_prng.obj crypt_cipher_descriptor.obj \ +crypt_find_cipher_id.obj crypt_find_prng.obj crypt_prng_is_valid.obj \ +crypt_unregister_cipher.obj crypt_cipher_is_valid.obj crypt_find_hash.obj \ +crypt_hash_descriptor.obj crypt_register_cipher.obj crypt_unregister_hash.obj \ +\ +sprng.obj yarrow.obj rc4.obj rng_get_bytes.obj rng_make_prng.obj \ +\ +rand_prime.obj is_prime.obj \ +\ +ecc.obj dh.obj \ +\ +rsa.obj rsa_exptmod.obj rsa_free.obj rsa_make_key.obj \ +\ +dsa_export.obj dsa_free.obj dsa_import.obj dsa_make_key.obj dsa_sign_hash.obj dsa_verify_hash.obj dsa_verify_key.obj \ +\ +xtea.obj aes.obj des.obj safer_tab.obj safer.obj saferp.obj rc2.obj \ +rc6.obj rc5.obj cast5.obj noekeon.obj blowfish.obj twofish.obj skipjack.obj \ +\ +md2.obj md4.obj md5.obj sha1.obj sha256.obj sha512.obj tiger.obj whirl.obj \ +rmd128.obj rmd160.obj \ +\ +packet_store_header.obj packet_valid_header.obj \ +\ +eax_addheader.obj eax_decrypt.obj eax_decrypt_verify_memory.obj eax_done.obj eax_encrypt.obj \ +eax_encrypt_authenticate_memory.obj eax_init.obj eax_test.obj \ +\ +ocb_decrypt.obj ocb_decrypt_verify_memory.obj ocb_done_decrypt.obj ocb_done_encrypt.obj \ +ocb_encrypt.obj ocb_encrypt_authenticate_memory.obj ocb_init.obj ocb_ntz.obj \ +ocb_shift_xor.obj ocb_test.obj s_ocb_done.obj \ +\ +omac_done.obj omac_file.obj omac_init.obj omac_memory.obj omac_process.obj omac_test.obj \ +\ +pmac_done.obj pmac_file.obj pmac_init.obj pmac_memory.obj pmac_ntz.obj pmac_process.obj \ +pmac_shift_xor.obj pmac_test.obj \ +\ +cbc_start.obj cbc_encrypt.obj cbc_decrypt.obj \ +cfb_start.obj cfb_encrypt.obj cfb_decrypt.obj \ +ofb_start.obj ofb_encrypt.obj ofb_decrypt.obj \ +ctr_start.obj ctr_encrypt.obj ctr_decrypt.obj \ +ecb_start.obj ecb_encrypt.obj ecb_decrypt.obj \ +\ +hash_file.obj hash_filehandle.obj hash_memory.obj \ +\ +hmac_done.obj hmac_file.obj hmac_init.obj hmac_memory.obj hmac_process.obj hmac_test.obj \ +\ +pkcs_1_mgf1.obj pkcs_1_oaep_encode.obj pkcs_1_oaep_decode.obj \ +pkcs_1_pss_encode.obj pkcs_1_pss_decode.obj pkcs_1_i2osp.obj pkcs_1_os2ip.obj \ +\ +pkcs_5_1.obj pkcs_5_2.obj \ +\ +burn_stack.obj zeromem.obj \ +$(MPIOBJECT) library: $(OBJECTS) lib /out:tomcrypt.lib $(OBJECTS) diff --git a/makefile.out b/makefile.out deleted file mode 100644 index 235ba18..0000000 --- a/makefile.out +++ /dev/null @@ -1,28 +0,0 @@ -#makefile generated with config.pl -# -#Tom St Denis (tomstdenis@yahoo.com, http://tom.iahu.ca) - -CC = gcc -AR = ar -LD = ld -CFLAGS += -Os -Wall -Wsign-compare -W -Wno-unused -Werror -I./ - -default: library - -OBJECTS = keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o des.o safer_tab.o safer.o saferp.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o mpi.o prime.o twofish.o packet.o hmac.o strings.o rmd128.o rmd160.o skipjack.o omac.o dsa.o eax.o ocb.o pmac.o whirl.o - -rsa.o: rsa_sys.c -dh.o: dh_sys.c -ecc.o: ecc_sys.c -aes.o: aes.c aes_tab.c -twofish.o: twofish.c twofish_tab.c -sha512.o: sha384.c sha512.c -sha256.o: sha256.c sha224.c - -library: $(OBJECTS) - $(AR) r libtomcrypt.a $(OBJECTS) - ranlib libtomcrypt.a - -clean: - rm -f $(OBJECTS) libtomcrypt.a - diff --git a/md2.c b/md2.c index 96cea65..73b0092 100644 --- a/md2.c +++ b/md2.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -65,7 +65,7 @@ static void md2_compress(hash_state *md) { int j, k; unsigned char t; - + /* copy block */ for (j = 0; j < 16; j++) { md->md2.X[16+j] = md->md2.buf[j]; diff --git a/md4.c b/md4.c index 788e46f..1017b03 100644 --- a/md4.c +++ b/md4.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -71,8 +71,6 @@ static void md4_compress(hash_state *md, unsigned char *buf) ulong32 x[16], a, b, c, d; int i; - _ARGCHK(md != NULL); - /* copy state */ a = md->md4.state[0]; b = md->md4.state[1]; diff --git a/md5.c b/md5.c index a3eddd6..768c711 100644 --- a/md5.c +++ b/md5.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -52,8 +52,6 @@ static void md5_compress(hash_state *md, unsigned char *buf) { ulong32 i, W[16], a, b, c, d; - _ARGCHK(md != NULL); - /* copy the state into 512-bits into W[0..15] */ for (i = 0; i < 16; i++) { LOAD32L(W[i], buf + (4*i)); diff --git a/mpi.c b/mpi.c index 52288a9..584bb00 100644 --- a/mpi.c +++ b/mpi.c @@ -631,8 +631,7 @@ fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) * Based on Algorithm 14.16 on pp.597 of HAC. * */ -int -fast_s_mp_sqr (mp_int * a, mp_int * b) +int fast_s_mp_sqr (mp_int * a, mp_int * b) { int olduse, newused, res, ix, pa; mp_word W2[MP_WARRAY], W[MP_WARRAY]; @@ -1345,11 +1344,15 @@ int mp_cmp_mag (mp_int * a, mp_int * b) */ #include +static const int lnz[16] = { + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 +}; + /* Counts the number of lsbs which are zero before the first zero bit */ int mp_cnt_lsb(mp_int *a) { int x; - mp_digit q; + mp_digit q, qq; /* easy out */ if (mp_iszero(a) == 1) { @@ -1362,11 +1365,13 @@ int mp_cnt_lsb(mp_int *a) x *= DIGIT_BIT; /* now scan this digit until a 1 is found */ - while ((q & 1) == 0) { - q >>= 1; - x += 1; + if ((q & 1) == 0) { + do { + qq = q & 15; + x += lnz[qq]; + q >>= 4; + } while (qq == 0); } - return x; } @@ -2665,75 +2670,75 @@ __M: /* End: bn_mp_exptmod_fast.c */ /* Start: bn_mp_exteuclid.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is a library that provides multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library was designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* Extended euclidean algorithm of (a, b) produces - a*u1 + b*u2 = u3 - */ -int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) -{ - mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp; - int err; - - if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) { - return err; - } - - /* initialize, (u1,u2,u3) = (1,0,a) */ - mp_set(&u1, 1); - if ((err = mp_copy(a, &u3)) != MP_OKAY) { goto _ERR; } - - /* initialize, (v1,v2,v3) = (0,1,b) */ - mp_set(&v2, 1); - if ((err = mp_copy(b, &v3)) != MP_OKAY) { goto _ERR; } - - /* loop while v3 != 0 */ - while (mp_iszero(&v3) == MP_NO) { - /* q = u3/v3 */ - if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) { goto _ERR; } - - /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */ - if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) { goto _ERR; } - if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) { goto _ERR; } - if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) { goto _ERR; } - if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) { goto _ERR; } - if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) { goto _ERR; } - if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) { goto _ERR; } - - /* (u1,u2,u3) = (v1,v2,v3) */ - if ((err = mp_copy(&v1, &u1)) != MP_OKAY) { goto _ERR; } - if ((err = mp_copy(&v2, &u2)) != MP_OKAY) { goto _ERR; } - if ((err = mp_copy(&v3, &u3)) != MP_OKAY) { goto _ERR; } - - /* (v1,v2,v3) = (t1,t2,t3) */ - if ((err = mp_copy(&t1, &v1)) != MP_OKAY) { goto _ERR; } - if ((err = mp_copy(&t2, &v2)) != MP_OKAY) { goto _ERR; } - if ((err = mp_copy(&t3, &v3)) != MP_OKAY) { goto _ERR; } - } - - /* copy result out */ - if (U1 != NULL) { mp_exch(U1, &u1); } - if (U2 != NULL) { mp_exch(U2, &u2); } - if (U3 != NULL) { mp_exch(U3, &u3); } - - err = MP_OKAY; -_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL); - return err; -} +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* Extended euclidean algorithm of (a, b) produces + a*u1 + b*u2 = u3 + */ +int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) +{ + mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp; + int err; + + if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) { + return err; + } + + /* initialize, (u1,u2,u3) = (1,0,a) */ + mp_set(&u1, 1); + if ((err = mp_copy(a, &u3)) != MP_OKAY) { goto _ERR; } + + /* initialize, (v1,v2,v3) = (0,1,b) */ + mp_set(&v2, 1); + if ((err = mp_copy(b, &v3)) != MP_OKAY) { goto _ERR; } + + /* loop while v3 != 0 */ + while (mp_iszero(&v3) == MP_NO) { + /* q = u3/v3 */ + if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) { goto _ERR; } + + /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */ + if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) { goto _ERR; } + if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) { goto _ERR; } + if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) { goto _ERR; } + if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) { goto _ERR; } + if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) { goto _ERR; } + if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) { goto _ERR; } + + /* (u1,u2,u3) = (v1,v2,v3) */ + if ((err = mp_copy(&v1, &u1)) != MP_OKAY) { goto _ERR; } + if ((err = mp_copy(&v2, &u2)) != MP_OKAY) { goto _ERR; } + if ((err = mp_copy(&v3, &u3)) != MP_OKAY) { goto _ERR; } + + /* (v1,v2,v3) = (t1,t2,t3) */ + if ((err = mp_copy(&t1, &v1)) != MP_OKAY) { goto _ERR; } + if ((err = mp_copy(&t2, &v2)) != MP_OKAY) { goto _ERR; } + if ((err = mp_copy(&t3, &v3)) != MP_OKAY) { goto _ERR; } + } + + /* copy result out */ + if (U1 != NULL) { mp_exch(U1, &u1); } + if (U2 != NULL) { mp_exch(U2, &u2); } + if (U3 != NULL) { mp_exch(U3, &u3); } + + err = MP_OKAY; +_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL); + return err; +} /* End: bn_mp_exteuclid.c */ @@ -2828,7 +2833,7 @@ int mp_fwrite(mp_int *a, int radix, FILE *stream) return err; } - buf = XMALLOC (len); + buf = OPT_CAST(char) XMALLOC (len); if (buf == NULL) { return MP_MEM; } @@ -2963,6 +2968,49 @@ __U:mp_clear (&v); /* End: bn_mp_gcd.c */ +/* Start: bn_mp_get_int.c */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* get the lower 32-bits of an mp_int */ +unsigned long mp_get_int(mp_int * a) +{ + int i; + unsigned long res; + + if (a->used == 0) { + return 0; + } + + /* get number of digits of the lsb we have to read */ + i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1; + + /* get most significant digit of result */ + res = DIGIT(a,i); + + while (--i >= 0) { + res = (res << DIGIT_BIT) | DIGIT(a,i); + } + + /* force result to 32-bits always so it is consistent on non 32-bit platforms */ + return res & 0xFFFFFFFFUL; +} + +/* End: bn_mp_get_int.c */ + /* Start: bn_mp_grow.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * @@ -2997,7 +3045,7 @@ int mp_grow (mp_int * a, int size) * in case the operation failed we don't want * to overwrite the dp member of a. */ - tmp = OPT_CAST XREALLOC (a->dp, sizeof (mp_digit) * size); + tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size); if (tmp == NULL) { /* reallocation failed but "a" is still valid [can be freed] */ return MP_MEM; @@ -3039,7 +3087,7 @@ int mp_grow (mp_int * a, int size) int mp_init (mp_int * a) { /* allocate memory required and clear it */ - a->dp = OPT_CAST XCALLOC (sizeof (mp_digit), MP_PREC); + a->dp = OPT_CAST(mp_digit) XCALLOC (sizeof (mp_digit), MP_PREC); if (a->dp == NULL) { return MP_MEM; } @@ -3142,6 +3190,65 @@ int mp_init_multi(mp_int *mp, ...) /* End: bn_mp_init_multi.c */ +/* Start: bn_mp_init_set.c */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* initialize and set a digit */ +int mp_init_set (mp_int * a, mp_digit b) +{ + int err; + if ((err = mp_init(a)) != MP_OKAY) { + return err; + } + mp_set(a, b); + return err; +} + +/* End: bn_mp_init_set.c */ + +/* Start: bn_mp_init_set_int.c */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* initialize and set a digit */ +int mp_init_set_int (mp_int * a, unsigned long b) +{ + int err; + if ((err = mp_init(a)) != MP_OKAY) { + return err; + } + return mp_set_int(a, b); +} + +/* End: bn_mp_init_set_int.c */ + /* Start: bn_mp_init_size.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * @@ -3166,7 +3273,7 @@ int mp_init_size (mp_int * a, int size) size += (MP_PREC * 2) - (size % MP_PREC); /* alloc mem */ - a->dp = OPT_CAST XCALLOC (sizeof (mp_digit), size); + a->dp = OPT_CAST(mp_digit) XCALLOC (sizeof (mp_digit), size); if (a->dp == NULL) { return MP_MEM; } @@ -3357,6 +3464,113 @@ __ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL); /* End: bn_mp_invmod.c */ +/* Start: bn_mp_is_square.c */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* Check if remainders are possible squares - fast exclude non-squares */ +static const char rem_128[128] = { + 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1 +}; + +static const char rem_105[105] = { + 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1 +}; + +/* Store non-zero to ret if arg is square, and zero if not */ +int mp_is_square(mp_int *arg,int *ret) +{ + int res; + mp_digit c; + mp_int t; + unsigned long r; + + /* Default to Non-square :) */ + *ret = MP_NO; + + if (arg->sign == MP_NEG) { + return MP_VAL; + } + + /* digits used? (TSD) */ + if (arg->used == 0) { + return MP_OKAY; + } + + /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */ + if (rem_128[127 & DIGIT(arg,0)] == 1) { + return MP_OKAY; + } + + /* Next check mod 105 (3*5*7) */ + if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) { + return res; + } + if (rem_105[c] == 1) { + return MP_OKAY; + } + + /* product of primes less than 2^31 */ + if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) { + return res; + } + if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) { + goto ERR; + } + r = mp_get_int(&t); + /* Check for other prime modules, note it's not an ERROR but we must + * free "t" so the easiest way is to goto ERR. We know that res + * is already equal to MP_OKAY from the mp_mod call + */ + if ( (1L<<(r%11)) & 0x5C4L ) goto ERR; + if ( (1L<<(r%13)) & 0x9E4L ) goto ERR; + if ( (1L<<(r%17)) & 0x5CE8L ) goto ERR; + if ( (1L<<(r%19)) & 0x4F50CL ) goto ERR; + if ( (1L<<(r%23)) & 0x7ACCA0L ) goto ERR; + if ( (1L<<(r%29)) & 0xC2EDD0CL ) goto ERR; + if ( (1L<<(r%31)) & 0x6DE2B848L ) goto ERR; + + /* Final check - is sqr(sqrt(arg)) == arg ? */ + if ((res = mp_sqrt(arg,&t)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sqr(&t,&t)) != MP_OKAY) { + goto ERR; + } + + *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO; +ERR:mp_clear(&t); + return res; +} + +/* End: bn_mp_is_square.c */ + /* Start: bn_mp_jacobi.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * @@ -3506,8 +3720,7 @@ __A1:mp_clear (&a1); * Generally though the overhead of this method doesn't pay off * until a certain size (N ~ 80) is reached. */ -int -mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c) +int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c) { mp_int x0, x1, y0, y1, t1, x0y0, x1y1; int B, err; @@ -3519,7 +3732,7 @@ mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c) B = MIN (a->used, b->used); /* now divide in two */ - B = B / 2; + B = B >> 1; /* init copy all the temps */ if (mp_init_size (&x0, B) != MP_OKAY) @@ -3653,8 +3866,7 @@ ERR: * is essentially the same algorithm but merely * tuned to perform recursive squarings. */ -int -mp_karatsuba_sqr (mp_int * a, mp_int * b) +int mp_karatsuba_sqr (mp_int * a, mp_int * b) { mp_int x0, x1, t1, t2, x0x0, x1x1; int B, err; @@ -3665,7 +3877,7 @@ mp_karatsuba_sqr (mp_int * a, mp_int * b) B = a->used; /* now divide in two */ - B = B / 2; + B = B >> 1; /* init copy all the temps */ if (mp_init_size (&x0, B) != MP_OKAY) @@ -3896,7 +4108,6 @@ mp_mod (mp_int * a, mp_int * b, mp_int * c) mp_int t; int res; - if ((res = mp_init (&t)) != MP_OKAY) { return res; } @@ -3906,7 +4117,7 @@ mp_mod (mp_int * a, mp_int * b, mp_int * c) return res; } - if (t.sign == MP_NEG) { + if (t.sign != b->sign) { res = mp_add (b, &t, c); } else { res = MP_OKAY; @@ -4661,7 +4872,7 @@ int mp_n_root (mp_int * a, mp_digit b, mp_int * c) if (mp_cmp (&t2, a) == MP_GT) { if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) { - goto __T3; + goto __T3; } } else { break; @@ -4711,7 +4922,7 @@ int mp_neg (mp_int * a, mp_int * b) if ((res = mp_copy (a, b)) != MP_OKAY) { return res; } - if (mp_iszero(b) != 1) { + if (mp_iszero(b) != MP_YES) { b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; } return MP_OKAY; @@ -5225,7 +5436,7 @@ __ERR: /* End: bn_mp_prime_next_prime.c */ -/* Start: bn_mp_prime_random.c */ +/* Start: bn_mp_prime_random_ex.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision @@ -5242,57 +5453,101 @@ __ERR: */ #include -/* makes a truly random prime of a given size (bytes), - * call with bbs = 1 if you want it to be congruent to 3 mod 4 +/* makes a truly random prime of a given size (bits), + * + * Flags are as follows: + * + * LTM_PRIME_BBS - make prime congruent to 3 mod 4 + * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS) + * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero + * LTM_PRIME_2MSB_ON - make the 2nd highest bit one * * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself * so it can be NULL * - * The prime generated will be larger than 2^(8*size). */ -/* this sole function may hold the key to enslaving all mankind! */ -int mp_prime_random(mp_int *a, int t, int size, int bbs, ltm_prime_callback cb, void *dat) +/* This is possibly the mother of all prime generation functions, muahahahahaha! */ +int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat) { - unsigned char *tmp; - int res, err; + unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb; + int res, err, bsize, maskOR_msb_offset; /* sanity check the input */ - if (size <= 0) { + if (size <= 1 || t <= 0) { return MP_VAL; } - /* we need a buffer of size+1 bytes */ - tmp = XMALLOC(size+1); + /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */ + if (flags & LTM_PRIME_SAFE) { + flags |= LTM_PRIME_BBS; + } + + /* calc the byte size */ + bsize = (size>>3)+(size&7?1:0); + + /* we need a buffer of bsize bytes */ + tmp = OPT_CAST(unsigned char) XMALLOC(bsize); if (tmp == NULL) { return MP_MEM; } - /* fix MSB */ - tmp[0] = 1; + /* calc the maskAND value for the MSbyte*/ + maskAND = 0xFF >> (8 - (size & 7)); + + /* calc the maskOR_msb */ + maskOR_msb = 0; + maskOR_msb_offset = (size - 2) >> 3; + if (flags & LTM_PRIME_2MSB_ON) { + maskOR_msb |= 1 << ((size - 2) & 7); + } else if (flags & LTM_PRIME_2MSB_OFF) { + maskAND &= ~(1 << ((size - 2) & 7)); + } + + /* get the maskOR_lsb */ + maskOR_lsb = 0; + if (flags & LTM_PRIME_BBS) { + maskOR_lsb |= 3; + } do { /* read the bytes */ - if (cb(tmp+1, size, dat) != size) { + if (cb(tmp, bsize, dat) != bsize) { err = MP_VAL; goto error; } - /* fix the LSB */ - tmp[size] |= (bbs ? 3 : 1); + /* work over the MSbyte */ + tmp[0] &= maskAND; + tmp[0] |= 1 << ((size - 1) & 7); + + /* mix in the maskORs */ + tmp[maskOR_msb_offset] |= maskOR_msb; + tmp[bsize-1] |= maskOR_lsb; /* read it in */ - if ((err = mp_read_unsigned_bin(a, tmp, size+1)) != MP_OKAY) { - goto error; - } + if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY) { goto error; } /* is it prime? */ - if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { - goto error; + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; } + + if (flags & LTM_PRIME_SAFE) { + /* see if (a-1)/2 is prime */ + if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) { goto error; } + if ((err = mp_div_2(a, a)) != MP_OKAY) { goto error; } + + /* is it prime? */ + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; } } } while (res == MP_NO); + if (flags & LTM_PRIME_SAFE) { + /* restore a to the original value */ + if ((err = mp_mul_2(a, a)) != MP_OKAY) { goto error; } + if ((err = mp_add_d(a, 1, a)) != MP_OKAY) { goto error; } + } + err = MP_OKAY; error: XFREE(tmp); @@ -5301,7 +5556,7 @@ error: -/* End: bn_mp_prime_random.c */ +/* End: bn_mp_prime_random_ex.c */ /* Start: bn_mp_radix_size.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis @@ -5726,9 +5981,9 @@ CLEANUP: */ #include -/* reduces a modulo n where n is of the form 2**p - k */ +/* reduces a modulo n where n is of the form 2**p - d */ int -mp_reduce_2k(mp_int *a, mp_int *n, mp_digit k) +mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d) { mp_int q; int p, res; @@ -5744,9 +5999,9 @@ top: goto ERR; } - if (k != 1) { - /* q = q * k */ - if ((res = mp_mul_d(&q, k, &q)) != MP_OKAY) { + if (d != 1) { + /* q = q * d */ + if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) { goto ERR; } } @@ -6062,7 +6317,7 @@ int mp_shrink (mp_int * a) { mp_digit *tmp; if (a->alloc != a->used && a->used > 0) { - if ((tmp = OPT_CAST XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) { + if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) { return MP_MEM; } a->dp = tmp; @@ -6182,6 +6437,85 @@ mp_sqrmod (mp_int * a, mp_int * b, mp_int * c) /* End: bn_mp_sqrmod.c */ +/* Start: bn_mp_sqrt.c */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* this function is less generic than mp_n_root, simpler and faster */ +int mp_sqrt(mp_int *arg, mp_int *ret) +{ + int res; + mp_int t1,t2; + + /* must be positive */ + if (arg->sign == MP_NEG) { + return MP_VAL; + } + + /* easy out */ + if (mp_iszero(arg) == MP_YES) { + mp_zero(ret); + return MP_OKAY; + } + + if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) { + return res; + } + + if ((res = mp_init(&t2)) != MP_OKAY) { + goto E2; + } + + /* First approx. (not very bad for large arg) */ + mp_rshd (&t1,t1.used/2); + + /* t1 > 0 */ + if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) { + goto E1; + } + if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { + goto E1; + } + if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { + goto E1; + } + /* And now t1 > sqrt(arg) */ + do { + if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) { + goto E1; + } + if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { + goto E1; + } + if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { + goto E1; + } + /* t1 >= sqrt(arg) >= t2 at this point */ + } while (mp_cmp_mag(&t1,&t2) == MP_GT); + + mp_exch(&t1,ret); + +E1: mp_clear(&t2); +E2: mp_clear(&t1); + return res; +} + + +/* End: bn_mp_sqrt.c */ + /* Start: bn_mp_sub.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * @@ -6463,8 +6797,7 @@ mp_to_unsigned_bin (mp_int * a, unsigned char *b) #include /* multiplication using the Toom-Cook 3-way algorithm */ -int -mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) +int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) { mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2; int res, B; @@ -7019,6 +7352,93 @@ int mp_toradix (mp_int * a, char *str, int radix) /* End: bn_mp_toradix.c */ +/* Start: bn_mp_toradix_n.c */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* stores a bignum as a ASCII string in a given radix (2..64) + * + * Stores upto maxlen-1 chars and always a NULL byte + */ +int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen) +{ + int res, digs; + mp_int t; + mp_digit d; + char *_s = str; + + /* check range of the maxlen, radix */ + if (maxlen < 3 || radix < 2 || radix > 64) { + return MP_VAL; + } + + /* quick out if its zero */ + if (mp_iszero(a) == 1) { + *str++ = '0'; + *str = '\0'; + return MP_OKAY; + } + + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + /* if it is negative output a - */ + if (t.sign == MP_NEG) { + /* we have to reverse our digits later... but not the - sign!! */ + ++_s; + + /* store the flag and mark the number as positive */ + *str++ = '-'; + t.sign = MP_ZPOS; + + /* subtract a char */ + --maxlen; + } + + digs = 0; + while (mp_iszero (&t) == 0) { + if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { + mp_clear (&t); + return res; + } + *str++ = mp_s_rmap[d]; + ++digs; + + if (--maxlen == 1) { + /* no more room */ + break; + } + } + + /* reverse the digits of the string. In this case _s points + * to the first digit [exluding the sign] of the number] + */ + bn_reverse ((unsigned char *)_s, digs); + + /* append a NULL so the string is properly terminated */ + *str = '\0'; + + mp_clear (&t); + return MP_OKAY; +} + + +/* End: bn_mp_toradix_n.c */ + /* Start: bn_mp_unsigned_bin_size.c */ /* LibTomMath, multiple-precision integer library -- Tom St Denis * @@ -7814,8 +8234,8 @@ s_mp_sqr (mp_int * a, mp_int * b) pa = a->used; if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) { return res; - } - + } + /* default used is maximum possible size */ t.used = 2*pa + 1; @@ -7982,8 +8402,8 @@ s_mp_sub (mp_int * a, mp_int * b, mp_int * c) */ /* configured for a AMD XP Thoroughbred core with etc/tune.c */ -int KARATSUBA_MUL_CUTOFF = 109, /* Min. number of digits before Karatsuba multiplication is used. */ - KARATSUBA_SQR_CUTOFF = 127, /* Min. number of digits before Karatsuba squaring is used. */ +int KARATSUBA_MUL_CUTOFF = 70, /* Min. number of digits before Karatsuba multiplication is used. */ + KARATSUBA_SQR_CUTOFF = 108, /* Min. number of digits before Karatsuba squaring is used. */ TOOM_MUL_CUTOFF = 350, /* no optimal values of these are known yet so set em high */ TOOM_SQR_CUTOFF = 400; diff --git a/mycrypt.h b/mycrypt.h index ca93b84..4e013ed 100644 --- a/mycrypt.h +++ b/mycrypt.h @@ -16,13 +16,15 @@ extern "C" { #endif /* version */ -#define CRYPT 0x0094 -#define SCRYPT "0.94" +#define CRYPT 0x0095 +#define SCRYPT "0.95" /* max size of either a cipher/hash block or symmetric key [largest of the two] */ #define MAXBLOCKSIZE 128 -/* ch1-01-1 */ +/* descriptor table size */ +#define TAB_SIZE 32 + /* error codes [will be expanded in future releases] */ enum { CRYPT_OK=0, /* Result OK */ @@ -59,7 +61,6 @@ enum { CRYPT_INVALID_PRIME_SIZE/* Invalid size of prime requested */ }; -/* ch1-01-1 */ #include #include @@ -71,6 +72,7 @@ enum { #include #include #include +#include #ifdef __cplusplus } diff --git a/mycrypt_cfg.h b/mycrypt_cfg.h index 02107fc..4d6c5db 100644 --- a/mycrypt_cfg.h +++ b/mycrypt_cfg.h @@ -23,7 +23,7 @@ extern clock_t XCLOCK(void); /* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code */ /* detect x86-32 machines somewhat */ -#if (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__))) +#if defined(INTEL_CC) || (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__))) #define ENDIAN_LITTLE #define ENDIAN_32BITWORD #endif diff --git a/mycrypt_custom.h b/mycrypt_custom.h index c0eb590..4f72dda 100644 --- a/mycrypt_custom.h +++ b/mycrypt_custom.h @@ -57,6 +57,7 @@ #define SPRNG #define RC4 #define DEVRANDOM +#define TRY_URANDOM_FIRST #define MRSA #define MDSA #define MDH @@ -78,6 +79,9 @@ #define ECC521 #define MPI +#define PKCS_1 +#define PKCS_5 + #include diff --git a/mycrypt_hash.h b/mycrypt_hash.h index 3174595..e59b5d6 100644 --- a/mycrypt_hash.h +++ b/mycrypt_hash.h @@ -341,6 +341,10 @@ extern int pmac_file(int cipher, const unsigned char *key, unsigned long keylen, extern int pmac_test(void); +/* internal functions */ +extern int pmac_ntz(unsigned long x); +extern void pmac_shift_xor(pmac_state *pmac); + #endif /* PMAC */ #ifdef EAX_MODE @@ -432,6 +436,12 @@ extern int ocb_decrypt_verify_memory(int cipher, extern int ocb_test(void); +/* internal functions */ +extern void ocb_shift_xor(ocb_state *ocb, unsigned char *Z); +extern int ocb_ntz(unsigned long x); +extern int __ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode); + #endif /* OCB_MODE */ diff --git a/mycrypt_macros.h b/mycrypt_macros.h index bfbddad..9fa6899 100644 --- a/mycrypt_macros.h +++ b/mycrypt_macros.h @@ -125,7 +125,7 @@ typedef unsigned long ulong32; #ifdef ENDIAN_BIG #define STORE32L(x, y) \ - { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ + { (y)[z0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } #define LOAD32L(x, y) \ @@ -194,7 +194,7 @@ typedef unsigned long ulong32; #define ROR(x,n) _lrotr(x,n) #define ROL(x,n) _lrotl(x,n) -#elif defined(__GNUC__) && defined(__i386__) +#elif defined(__GNUC__) && defined(__i386__) && !defined(INTEL_CC) static inline unsigned long ROL(unsigned long word, int i) { diff --git a/mycrypt_pk.h b/mycrypt_pk.h index 5a1c3dd..47e1c02 100644 --- a/mycrypt_pk.h +++ b/mycrypt_pk.h @@ -16,7 +16,7 @@ } -#define INPUT_BIGNUM(num, in, x, y) \ +#define INPUT_BIGNUM(num, in, x, y, inlen) \ { \ /* load value */ \ if ((y + 4) > inlen) { \ @@ -44,11 +44,8 @@ } \ } - extern int is_prime(mp_int *, int *); extern int rand_prime(mp_int *N, long len, prng_state *prng, int wprng); -extern mp_err mp_init_multi(mp_int* mp, ...); -extern void mp_clear_multi(mp_int* mp, ...); #else #ifdef MRSA @@ -83,6 +80,14 @@ extern int packet_valid_header(unsigned char *src, int section, int subsection); /* ---- RSA ---- */ #ifdef MRSA + +/* Min and Max RSA key sizes (in bits) */ +#define MIN_RSA_SIZE 1024 +#define MAX_RSA_SIZE 4096 + +/* Stack required for temps (plus padding) */ +#define RSA_STACK (8 + (MAX_RSA_SIZE/8)) + typedef struct Rsa_key { int type; mp_int e, d, N, qP, pQ, dP, dQ, p, q; diff --git a/mycrypt_pkcs.h b/mycrypt_pkcs.h new file mode 100644 index 0000000..72d8d67 --- /dev/null +++ b/mycrypt_pkcs.h @@ -0,0 +1,53 @@ +/* PKCS Header Info */ + +/* ===> PKCS #1 -- RSA Cryptography <=== */ +#ifdef PKCS_1 + +int pkcs_1_mgf1(const unsigned char *seed, unsigned long seedlen, + int hash_idx, + unsigned char *mask, unsigned long masklen); + +int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, int hash_idx, + int prng_idx, prng_state *prng, + unsigned char *out, unsigned long *outlen); + +int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, int hash_idx, + unsigned char *out, unsigned long *outlen); + +int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, + unsigned long saltlen, int hash_idx, + int prng_idx, prng_state *prng, + unsigned long modulus_bitlen, + unsigned char *out, unsigned long *outlen); + +int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, + const unsigned char *sig, unsigned long siglen, + unsigned long saltlen, int hash_idx, + unsigned long modulus_bitlen, int *res); + +int pkcs_1_i2osp(mp_int *n, unsigned long modulus_len, unsigned char *out); +int pkcs_1_os2ip(mp_int *n, unsigned char *in, unsigned long inlen); + + +#endif /* PKCS_1 */ + +/* ===> PKCS #5 -- Password Based Cryptography <=== */ +#ifdef PKCS_5 + +/* Algorithm #1 (old) */ +int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen); + +/* Algorithm #2 (new) */ +int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, unsigned long salt_len, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen); + +#endif /* PKCS_5 */ diff --git a/noekeon.c b/noekeon.c index 9f5320c..7c6e87f 100644 --- a/noekeon.c +++ b/noekeon.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/notes/etc/whirlgen.c b/notes/etc/whirlgen.c index d24d4bd..2880d3f 100644 --- a/notes/etc/whirlgen.c +++ b/notes/etc/whirlgen.c @@ -1,91 +1,91 @@ -#include - -unsigned E[16] = { 1, 0xb, 9, 0xc, 0xd, 6, 0xf, 3, 0xe, 8, 7, 4, 0xa, 2, 5, 0 }; -unsigned Ei[16]; -unsigned R[16] = { 7, 0xc, 0xb, 0xd, 0xe, 4, 9, 0xf, 6, 3, 8, 0xa, 2, 5, 1, 0 }; -unsigned cir[8][8] = { - {1, 1, 4, 1, 8, 5, 2, 9 }, -}; - - -unsigned gf_mul(unsigned a, unsigned b) -{ - unsigned r; - - r = 0; - while (a) { - if (a & 1) r ^= b; - a >>= 1; - b = (b << 1) ^ (b & 0x80 ? 0x11d : 0x00); - } - return r; -} - -unsigned sbox(unsigned x) -{ - unsigned a, b, w; - - a = x >> 4; - b = x & 15; - - a = E[a]; b = Ei[b]; - w = a ^ b; w = R[w]; - a = E[a ^ w]; b = Ei[b ^ w]; - - - return (a << 4) | b; -} - -int main(void) -{ - unsigned x, y; - - for (x = 0; x < 16; x++) Ei[E[x]] = x; - -// for (x = 0; x < 16; x++) printf("%2x ", sbox(x)); - for (y = 1; y < 8; y++) { - for (x = 0; x < 8; x++) { - cir[y][x] = cir[y-1][(x-1)&7]; - } - } - -/* - printf("\n"); - for (y = 0; y < 8; y++) { - for (x = 0; x < 8; x++) printf("%2d ", cir[y][x]); - printf("\n"); - } -*/ - - for (y = 0; y < 8; y++) { - printf("static const ulong64 sbox%d[] = {\n", y); - for (x = 0; x < 256; ) { - printf("CONST64(0x%02x%02x%02x%02x%02x%02x%02x%02x)", - gf_mul(sbox(x), cir[y][0]), - gf_mul(sbox(x), cir[y][1]), - gf_mul(sbox(x), cir[y][2]), - gf_mul(sbox(x), cir[y][3]), - gf_mul(sbox(x), cir[y][4]), - gf_mul(sbox(x), cir[y][5]), - gf_mul(sbox(x), cir[y][6]), - gf_mul(sbox(x), cir[y][7])); - if (x < 255) printf(", "); - if (!(++x & 3)) printf("\n"); - } - printf("};\n\n"); - } - - printf("static const ulong64 cont[] = {\n"); - for (y = 0; y <= 10; y++) { - printf("CONST64(0x"); - for (x = 0; x < 8; x++) { - printf("%02x", sbox((8*y + x)&255)); - } - printf("),\n"); - } - printf("};\n\n"); - return 0; - -} - - +#include + +unsigned E[16] = { 1, 0xb, 9, 0xc, 0xd, 6, 0xf, 3, 0xe, 8, 7, 4, 0xa, 2, 5, 0 }; +unsigned Ei[16]; +unsigned R[16] = { 7, 0xc, 0xb, 0xd, 0xe, 4, 9, 0xf, 6, 3, 8, 0xa, 2, 5, 1, 0 }; +unsigned cir[8][8] = { + {1, 1, 4, 1, 8, 5, 2, 9 }, +}; + + +unsigned gf_mul(unsigned a, unsigned b) +{ + unsigned r; + + r = 0; + while (a) { + if (a & 1) r ^= b; + a >>= 1; + b = (b << 1) ^ (b & 0x80 ? 0x11d : 0x00); + } + return r; +} + +unsigned sbox(unsigned x) +{ + unsigned a, b, w; + + a = x >> 4; + b = x & 15; + + a = E[a]; b = Ei[b]; + w = a ^ b; w = R[w]; + a = E[a ^ w]; b = Ei[b ^ w]; + + + return (a << 4) | b; +} + +int main(void) +{ + unsigned x, y; + + for (x = 0; x < 16; x++) Ei[E[x]] = x; + +// for (x = 0; x < 16; x++) printf("%2x ", sbox(x)); + for (y = 1; y < 8; y++) { + for (x = 0; x < 8; x++) { + cir[y][x] = cir[y-1][(x-1)&7]; + } + } + +/* + printf("\n"); + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) printf("%2d ", cir[y][x]); + printf("\n"); + } +*/ + + for (y = 0; y < 8; y++) { + printf("static const ulong64 sbox%d[] = {\n", y); + for (x = 0; x < 256; ) { + printf("CONST64(0x%02x%02x%02x%02x%02x%02x%02x%02x)", + gf_mul(sbox(x), cir[y][0]), + gf_mul(sbox(x), cir[y][1]), + gf_mul(sbox(x), cir[y][2]), + gf_mul(sbox(x), cir[y][3]), + gf_mul(sbox(x), cir[y][4]), + gf_mul(sbox(x), cir[y][5]), + gf_mul(sbox(x), cir[y][6]), + gf_mul(sbox(x), cir[y][7])); + if (x < 255) printf(", "); + if (!(++x & 3)) printf("\n"); + } + printf("};\n\n"); + } + + printf("static const ulong64 cont[] = {\n"); + for (y = 0; y <= 10; y++) { + printf("CONST64(0x"); + for (x = 0; x < 8; x++) { + printf("%02x", sbox((8*y + x)&255)); + } + printf("),\n"); + } + printf("};\n\n"); + return 0; + +} + + diff --git a/notes/etc/whirltest.c b/notes/etc/whirltest.c index 8dccf8f..9184f77 100644 --- a/notes/etc/whirltest.c +++ b/notes/etc/whirltest.c @@ -1,15 +1,15 @@ -#include - -int main(void) -{ - char buf[4096]; - int x; - - while (fgets(buf, sizeof(buf)-2, stdin) != NULL) { - for (x = 0; x < 128; ) { - printf("0x%c%c, ", buf[x], buf[x+1]); - if (!((x += 2) & 31)) printf("\n"); - } - } -} - +#include + +int main(void) +{ + char buf[4096]; + int x; + + while (fgets(buf, sizeof(buf)-2, stdin) != NULL) { + for (x = 0; x < 128; ) { + printf("0x%c%c, ", buf[x], buf[x+1]); + if (!((x += 2) & 31)) printf("\n"); + } + } +} + diff --git a/notes/tech0001.txt b/notes/tech0001.txt index 980b5f3..daf7e57 100644 --- a/notes/tech0001.txt +++ b/notes/tech0001.txt @@ -1,73 +1,73 @@ -Tech Note 0001 -How to Gather Entropy on Embedded Systems -Tom St Denis - -Introduction ------------- - -This tech note explains a relatively simple way to gather entropy for a PRNG (Yarrow in this case) in embedded systems -where there are few sources of entropy or physical sources. - -When trying to setup a secure random number generator a fresh source of random data (entropy) is required to ensure the -deterministic state of the PRNG is not known or predetermined with respect to an attacker. - -At the very least the system requires one timer and one source of un-timed interrupts. by "un-timed" I mean interrupts -that do not occur at regular intervals [e.g. joypad/keypad input, network packets, etc...]. - -First we shall begin by taking an overview of how the Yarrow PRNG works within libtomcrypt. At the heart of all -PRNGs is the "prng_state" data type. This is a union of structures that hold the PRNG state for the various prngs. The -first thing we require is a state... - - prng_state myPrng; - -Next we must initialize the state once to get the ball rolling - - if (yarrow_start(&myPrng) != CRYPT_OK) { - // error should never happen! - } - -At this point the PRNG is ready to accept fresh entropy which is added with - - int yarrow_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng) - -This function is **NOT** thread safe which will come under consideration later. To add entropy to our PRNG we must -call this function with fresh data as its sampled. Lets say we have a timer counter called "uTimer" which is a 32-bit -long and say a 32-bit joyPad state called "uPad". An example interrupt handler would look like - - void joypad_interrupt(...) { - unsigned char buf[8]; - - STORE32L(uTimer, buf); - STORE32L(uPad, buf+4) - if (yarrow_add_entropy(buf, 8, &myPrng) != CRYPT_OK) { - // this should never occur either unless you didn't call yarrow_start - } - - // handle interrupt - } - -In this snippet the timer count and state of the joypad are added together into the entropy pool. The timer is important -because with respect to the joypad it is a good source of entropy (on its own its not). For example, the probability of -the user pushing the up arrow is fairly high, but at a specific time is not. - -This method doesn't gather alot of entropy and has to be used to for quite a while. One way to speed it up is to tap -multiple sources. If you have a network adapter and other sources of events (keyboard, mouse, etc...) trapping their -data is ideal as well. Its important to gather the timer along with the event data. - -As mentioned the "yarrow_add_entropy()" function is not thread safe. If your system allows interrupt handlers to be -interrupted themselves then you could have trouble. One simple way is to detect when an interrupt is in progress and -simply not add entropy during the call (jump over the yarrow_add_entropy() call) - -Once you feel that there has been enough entropy added to the pool then within a single thread you can call - - int yarrow_ready(prng_state *prng) - -Now the PRNG is ready to read via the - - unsigned long yarrow_read(unsigned char *buf, unsigned long len, prng_state *prng) - -It is a very good idea that once you call the yarrow_ready() function that you stop harvesting entropy in your interrupt -functions. This will free up alot of CPU time. Also one more final note. The yarrow_read() function is not thread -safe either. This means if you have multiple threads or processes that read from it you will have to add your own semaphores -around calls to it. - +Tech Note 0001 +How to Gather Entropy on Embedded Systems +Tom St Denis + +Introduction +------------ + +This tech note explains a relatively simple way to gather entropy for a PRNG (Yarrow in this case) in embedded systems +where there are few sources of entropy or physical sources. + +When trying to setup a secure random number generator a fresh source of random data (entropy) is required to ensure the +deterministic state of the PRNG is not known or predetermined with respect to an attacker. + +At the very least the system requires one timer and one source of un-timed interrupts. by "un-timed" I mean interrupts +that do not occur at regular intervals [e.g. joypad/keypad input, network packets, etc...]. + +First we shall begin by taking an overview of how the Yarrow PRNG works within libtomcrypt. At the heart of all +PRNGs is the "prng_state" data type. This is a union of structures that hold the PRNG state for the various prngs. The +first thing we require is a state... + + prng_state myPrng; + +Next we must initialize the state once to get the ball rolling + + if (yarrow_start(&myPrng) != CRYPT_OK) { + // error should never happen! + } + +At this point the PRNG is ready to accept fresh entropy which is added with + + int yarrow_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng) + +This function is **NOT** thread safe which will come under consideration later. To add entropy to our PRNG we must +call this function with fresh data as its sampled. Lets say we have a timer counter called "uTimer" which is a 32-bit +long and say a 32-bit joyPad state called "uPad". An example interrupt handler would look like + + void joypad_interrupt(...) { + unsigned char buf[8]; + + STORE32L(uTimer, buf); + STORE32L(uPad, buf+4) + if (yarrow_add_entropy(buf, 8, &myPrng) != CRYPT_OK) { + // this should never occur either unless you didn't call yarrow_start + } + + // handle interrupt + } + +In this snippet the timer count and state of the joypad are added together into the entropy pool. The timer is important +because with respect to the joypad it is a good source of entropy (on its own its not). For example, the probability of +the user pushing the up arrow is fairly high, but at a specific time is not. + +This method doesn't gather alot of entropy and has to be used to for quite a while. One way to speed it up is to tap +multiple sources. If you have a network adapter and other sources of events (keyboard, mouse, etc...) trapping their +data is ideal as well. Its important to gather the timer along with the event data. + +As mentioned the "yarrow_add_entropy()" function is not thread safe. If your system allows interrupt handlers to be +interrupted themselves then you could have trouble. One simple way is to detect when an interrupt is in progress and +simply not add entropy during the call (jump over the yarrow_add_entropy() call) + +Once you feel that there has been enough entropy added to the pool then within a single thread you can call + + int yarrow_ready(prng_state *prng) + +Now the PRNG is ready to read via the + + unsigned long yarrow_read(unsigned char *buf, unsigned long len, prng_state *prng) + +It is a very good idea that once you call the yarrow_ready() function that you stop harvesting entropy in your interrupt +functions. This will free up alot of CPU time. Also one more final note. The yarrow_read() function is not thread +safe either. This means if you have multiple threads or processes that read from it you will have to add your own semaphores +around calls to it. + diff --git a/ocb.c b/ocb.c deleted file mode 100644 index 4ab4aec..0000000 --- a/ocb.c +++ /dev/null @@ -1,636 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * gurantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org - */ - -/* OCB Implementation by Tom St Denis */ -#include "mycrypt.h" - -#define OCB_MODE -#ifdef OCB_MODE - -static const struct { - int len; - unsigned char poly_div[MAXBLOCKSIZE], - poly_mul[MAXBLOCKSIZE]; -} polys[] = { -{ - 8, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } -}, { - 16, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 } -} -}; - -int ocb_init(ocb_state *ocb, int cipher, - const unsigned char *key, unsigned long keylen, const unsigned char *nonce) -{ - int poly, x, y, m, err; - - _ARGCHK(ocb != NULL); - _ARGCHK(key != NULL); - _ARGCHK(nonce != NULL); - - /* valid cipher? */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - /* determine which polys to use */ - ocb->block_len = cipher_descriptor[cipher].block_length; - for (poly = 0; poly < (int)(sizeof(polys)/sizeof(polys[0])); poly++) { - if (polys[poly].len == ocb->block_len) { - break; - } - } - if (polys[poly].len != ocb->block_len) { - return CRYPT_INVALID_ARG; - } - - /* schedule the key */ - if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &ocb->key)) != CRYPT_OK) { - return err; - } - - /* find L = E[0] */ - zeromem(ocb->L, ocb->block_len); - cipher_descriptor[cipher].ecb_encrypt(ocb->L, ocb->L, &ocb->key); - - /* find R = E[N xor L] */ - for (x = 0; x < ocb->block_len; x++) { - ocb->R[x] = ocb->L[x] ^ nonce[x]; - } - cipher_descriptor[cipher].ecb_encrypt(ocb->R, ocb->R, &ocb->key); - - /* find Ls[i] = L << i for i == 0..31 */ - memcpy(ocb->Ls[0], ocb->L, ocb->block_len); - for (x = 1; x < 32; x++) { - m = ocb->Ls[x-1][0] >> 7; - for (y = 0; y < ocb->block_len-1; y++) { - ocb->Ls[x][y] = ((ocb->Ls[x-1][y] << 1) | (ocb->Ls[x-1][y+1] >> 7)) & 255; - } - ocb->Ls[x][ocb->block_len-1] = (ocb->Ls[x-1][ocb->block_len-1] << 1) & 255; - - if (m == 1) { - for (y = 0; y < ocb->block_len; y++) { - ocb->Ls[x][y] ^= polys[poly].poly_mul[y]; - } - } - } - - /* find Lr = L / x */ - m = ocb->L[ocb->block_len-1] & 1; - - /* shift right */ - for (x = ocb->block_len - 1; x > 0; x--) { - ocb->Lr[x] = ((ocb->L[x] >> 1) | (ocb->L[x-1] << 7)) & 255; - } - ocb->Lr[0] = ocb->L[0] >> 1; - - if (m == 1) { - for (x = 0; x < ocb->block_len; x++) { - ocb->Lr[x] ^= polys[poly].poly_div[x]; - } - } - - /* set Li, checksum */ - zeromem(ocb->Li, ocb->block_len); - zeromem(ocb->checksum, ocb->block_len); - - /* set other params */ - ocb->block_index = 1; - ocb->cipher = cipher; - - return CRYPT_OK; -} - -static int ntz(unsigned long x) -{ - int c; - x &= 0xFFFFFFFFUL; - c = 0; - while ((x & 1) == 0) { - ++c; - x >>= 1; - } - return c; -} - -static void shift_xor(ocb_state *ocb, unsigned char *Z) -{ - int x, y; - y = ntz(ocb->block_index++); - for (x = 0; x < ocb->block_len; x++) { - ocb->Li[x] ^= ocb->Ls[y][x]; - Z[x] = ocb->Li[x] ^ ocb->R[x]; - } -} - -int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct) -{ - unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE]; - int err, x; - - _ARGCHK(ocb != NULL); - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { - return err; - } - if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) { - return CRYPT_INVALID_ARG; - } - - /* compute checksum */ - for (x = 0; x < ocb->block_len; x++) { - ocb->checksum[x] ^= pt[x]; - } - - /* Get Z[i] value */ - shift_xor(ocb, Z); - - /* xor pt in, encrypt, xor Z out */ - for (x = 0; x < ocb->block_len; x++) { - tmp[x] = pt[x] ^ Z[x]; - } - cipher_descriptor[ocb->cipher].ecb_encrypt(tmp, ct, &ocb->key); - for (x = 0; x < ocb->block_len; x++) { - ct[x] ^= Z[x]; - } - -#ifdef CLEAN_STACK - zeromem(Z, sizeof(Z)); - zeromem(tmp, sizeof(tmp)); -#endif - return CRYPT_OK; -} - -int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt) -{ - unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE]; - int err, x; - - _ARGCHK(ocb != NULL); - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { - return err; - } - if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) { - return CRYPT_INVALID_ARG; - } - - /* Get Z[i] value */ - shift_xor(ocb, Z); - - /* xor ct in, encrypt, xor Z out */ - for (x = 0; x < ocb->block_len; x++) { - tmp[x] = ct[x] ^ Z[x]; - } - cipher_descriptor[ocb->cipher].ecb_decrypt(tmp, pt, &ocb->key); - for (x = 0; x < ocb->block_len; x++) { - pt[x] ^= Z[x]; - } - - /* compute checksum */ - for (x = 0; x < ocb->block_len; x++) { - ocb->checksum[x] ^= pt[x]; - } - - -#ifdef CLEAN_STACK - zeromem(Z, sizeof(Z)); - zeromem(tmp, sizeof(tmp)); -#endif - return CRYPT_OK; -} - - -/* Since the last block is encrypted in CTR mode the same code can - * be used to finish a decrypt or encrypt stream. The only difference - * is we XOR the final ciphertext into the checksum so we have to xor it - * before we CTR [decrypt] or after [encrypt] - * - * the names pt/ptlen/ct really just mean in/inlen/out but this is the way I wrote it... - */ -static int _ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode) - -{ - unsigned char Z[MAXBLOCKSIZE], Y[MAXBLOCKSIZE], X[MAXBLOCKSIZE]; - int err, x; - - _ARGCHK(ocb != NULL); - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - _ARGCHK(tag != NULL); - _ARGCHK(taglen != NULL); - if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { - return err; - } - if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length || - (int)ptlen > ocb->block_len || (int)ptlen < 0) { - return CRYPT_INVALID_ARG; - } - - /* compute X[m] = len(pt[m]) XOR Lr XOR Z[m] */ - shift_xor(ocb, X); - memcpy(Z, X, ocb->block_len); - - X[ocb->block_len-1] ^= (ptlen*8)&255; - X[ocb->block_len-2] ^= ((ptlen*8)>>8)&255; - for (x = 0; x < ocb->block_len; x++) { - X[x] ^= ocb->Lr[x]; - } - - /* Y[m] = E(X[m])) */ - cipher_descriptor[ocb->cipher].ecb_encrypt(X, Y, &ocb->key); - - if (mode == 1) { - /* decrypt mode, so let's xor it first */ - /* xor C[m] into checksum */ - for (x = 0; x < (int)ptlen; x++) { - ocb->checksum[x] ^= ct[x]; - } - } - - /* C[m] = P[m] xor Y[m] */ - for (x = 0; x < (int)ptlen; x++) { - ct[x] = pt[x] ^ Y[x]; - } - - if (mode == 0) { - /* encrypt mode */ - /* xor C[m] into checksum */ - for (x = 0; x < (int)ptlen; x++) { - ocb->checksum[x] ^= ct[x]; - } - } - - /* xor Y[m] and Z[m] into checksum */ - for (x = 0; x < ocb->block_len; x++) { - ocb->checksum[x] ^= Y[x] ^ Z[x]; - } - - /* encrypt checksum, er... tag!! */ - cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->checksum, X, &ocb->key); - - /* now store it */ - for (x = 0; x < ocb->block_len && x < (int)*taglen; x++) { - tag[x] = X[x]; - } - *taglen = x; - -#ifdef CLEAN_STACK - zeromem(X, sizeof(X)); - zeromem(Y, sizeof(Y)); - zeromem(Z, sizeof(Z)); - zeromem(ocb, sizeof(*ocb)); -#endif - return CRYPT_OK; -} - -int ocb_done_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, unsigned char *tag, unsigned long *taglen) -{ - _ARGCHK(ocb != NULL); - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - _ARGCHK(tag != NULL); - _ARGCHK(taglen != NULL); - return _ocb_done(ocb, pt, ptlen, ct, tag, taglen, 0); -} - - -int ocb_done_decrypt(ocb_state *ocb, - const unsigned char *ct, unsigned long ctlen, - unsigned char *pt, - const unsigned char *tag, unsigned long taglen, int *res) -{ - int err; - unsigned char tagbuf[MAXBLOCKSIZE]; - unsigned long tagbuflen; - - _ARGCHK(ocb != NULL); - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - _ARGCHK(tag != NULL); - _ARGCHK(res != NULL); - - *res = 0; - - tagbuflen = sizeof(tagbuf); - if ((err = _ocb_done(ocb, ct, ctlen, pt, tagbuf, &tagbuflen, 1)) != CRYPT_OK) { - return err; - } - - if (taglen <= tagbuflen && memcmp(tagbuf, tag, taglen) == 0) { - *res = 1; - } - -#ifdef CLEAN_STACK - zeromem(tagbuf, sizeof(tagbuf)); -#endif - - return CRYPT_OK; -} - -int ocb_encrypt_authenticate_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, - const unsigned char *pt, unsigned long ptlen, - unsigned char *ct, - unsigned char *tag, unsigned long *taglen) -{ - int err; - ocb_state ocb; - - _ARGCHK(key != NULL); - _ARGCHK(nonce != NULL); - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - _ARGCHK(tag != NULL); - _ARGCHK(taglen != NULL); - - if ((err = ocb_init(&ocb, cipher, key, keylen, nonce)) != CRYPT_OK) { - return err; - } - - while (ptlen > (unsigned long)ocb.block_len) { - if ((err = ocb_encrypt(&ocb, pt, ct)) != CRYPT_OK) { - return err; - } - ptlen -= ocb.block_len; - pt += ocb.block_len; - ct += ocb.block_len; - } - - err = ocb_done_encrypt(&ocb, pt, ptlen, ct, tag, taglen); - -#ifdef CLEAN_STACK - zeromem(&ocb, sizeof(ocb)); -#endif - return err; -} - -int ocb_decrypt_verify_memory(int cipher, - const unsigned char *key, unsigned long keylen, - const unsigned char *nonce, - const unsigned char *ct, unsigned long ctlen, - unsigned char *pt, - const unsigned char *tag, unsigned long taglen, - int *res) -{ - int err; - ocb_state ocb; - - - _ARGCHK(key != NULL); - _ARGCHK(nonce != NULL); - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - _ARGCHK(tag != NULL); - _ARGCHK(res != NULL); - - if ((err = ocb_init(&ocb, cipher, key, keylen, nonce)) != CRYPT_OK) { - return err; - } - - while (ctlen > (unsigned long)ocb.block_len) { - if ((err = ocb_decrypt(&ocb, ct, pt)) != CRYPT_OK) { - return err; - } - ctlen -= ocb.block_len; - pt += ocb.block_len; - ct += ocb.block_len; - } - - err = ocb_done_decrypt(&ocb, ct, ctlen, pt, tag, taglen, res); - -#ifdef CLEAN_STACK - zeromem(&ocb, sizeof(ocb)); -#endif - return err; -} - -int ocb_test(void) -{ -#ifndef LTC_TEST - return CRYPT_NOP; -#else - static const struct { - int ptlen; - unsigned char key[16], nonce[16], pt[34], ct[34], tag[16]; - } tests[] = { - - /* OCB-AES-128-0B */ -{ - 0, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - /* pt */ - { 0 }, - /* ct */ - { 0 }, - /* tag */ - { 0x15, 0xd3, 0x7d, 0xd7, 0xc8, 0x90, 0xd5, 0xd6, - 0xac, 0xab, 0x92, 0x7b, 0xc0, 0xdc, 0x60, 0xee }, -}, - - - /* OCB-AES-128-3B */ -{ - 3, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - /* pt */ - { 0x00, 0x01, 0x02 }, - /* ct */ - { 0xfc, 0xd3, 0x7d }, - /* tag */ - { 0x02, 0x25, 0x47, 0x39, 0xa5, 0xe3, 0x56, 0x5a, - 0xe2, 0xdc, 0xd6, 0x2c, 0x65, 0x97, 0x46, 0xba }, -}, - - /* OCB-AES-128-16B */ -{ - 16, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - /* pt */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* ct */ - { 0x37, 0xdf, 0x8c, 0xe1, 0x5b, 0x48, 0x9b, 0xf3, - 0x1d, 0x0f, 0xc4, 0x4d, 0xa1, 0xfa, 0xf6, 0xd6 }, - /* tag */ - { 0xdf, 0xb7, 0x63, 0xeb, 0xdb, 0x5f, 0x0e, 0x71, - 0x9c, 0x7b, 0x41, 0x61, 0x80, 0x80, 0x04, 0xdf }, -}, - - /* OCB-AES-128-20B */ -{ - 20, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - /* pt */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13 }, - /* ct */ - { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, - 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, - 0x70, 0x03, 0xeb, 0x55}, - /* tag */ - { 0x75, 0x30, 0x84, 0x14, 0x4e, 0xb6, 0x3b, 0x77, - 0x0b, 0x06, 0x3c, 0x2e, 0x23, 0xcd, 0xa0, 0xbb }, -}, - - /* OCB-AES-128-32B */ -{ - 32, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - /* pt */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, - /* ct */ - { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, - 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, - 0x4a, 0xfc, 0xbb, 0x7f, 0xed, 0xc0, 0x8c, 0xa8, - 0x65, 0x4c, 0x6d, 0x30, 0x4d, 0x16, 0x12, 0xfa }, - - /* tag */ - { 0xc1, 0x4c, 0xbf, 0x2c, 0x1a, 0x1f, 0x1c, 0x3c, - 0x13, 0x7e, 0xad, 0xea, 0x1f, 0x2f, 0x2f, 0xcf }, -}, - - /* OCB-AES-128-34B */ -{ - 34, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* nonce */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - /* pt */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21 }, - /* ct */ - { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, - 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, - 0xd4, 0x90, 0x3d, 0xd0, 0x02, 0x5b, 0xa4, 0xaa, - 0x83, 0x7c, 0x74, 0xf1, 0x21, 0xb0, 0x26, 0x0f, - 0xa9, 0x5d }, - - /* tag */ - { 0xcf, 0x83, 0x41, 0xbb, 0x10, 0x82, 0x0c, 0xcf, - 0x14, 0xbd, 0xec, 0x56, 0xb8, 0xd7, 0xd6, 0xab }, -}, - -}; - - int err, x, idx, res; - unsigned long len; - unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE]; - - /* AES can be under rijndael or aes... try to find it */ - if ((idx = find_cipher("aes")) == -1) { - if ((idx = find_cipher("rijndael")) == -1) { - return CRYPT_NOP; - } - } - - for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { - len = sizeof(outtag); - if ((err = ocb_encrypt_authenticate_memory(idx, tests[x].key, 16, - tests[x].nonce, tests[x].pt, tests[x].ptlen, outct, outtag, &len)) != CRYPT_OK) { - return err; - } - - if (memcmp(outtag, tests[x].tag, len) || memcmp(outct, tests[x].ct, tests[x].ptlen)) { -#if 0 - unsigned long y; - printf("\n\nFailure: \nCT:\n"); - for (y = 0; y < (unsigned long)tests[x].ptlen; ) { - printf("0x%02x", outct[y]); - if (y < (unsigned long)(tests[x].ptlen-1)) printf(", "); - if (!(++y % 8)) printf("\n"); - } - printf("\nTAG:\n"); - for (y = 0; y < len; ) { - printf("0x%02x", outtag[y]); - if (y < len-1) printf(", "); - if (!(++y % 8)) printf("\n"); - } -#endif - return CRYPT_FAIL_TESTVECTOR; - } - - if ((err = ocb_decrypt_verify_memory(idx, tests[x].key, 16, tests[x].nonce, outct, tests[x].ptlen, - outct, tests[x].tag, len, &res)) != CRYPT_OK) { - return err; - } - if (res != 1 || memcmp(tests[x].pt, outct, tests[x].ptlen)) { -#if 0 - unsigned long y; - printf("\n\nFailure-decrypt: \nPT:\n"); - for (y = 0; y < (unsigned long)tests[x].ptlen; ) { - printf("0x%02x", outct[y]); - if (y < (unsigned long)(tests[x].ptlen-1)) printf(", "); - if (!(++y % 8)) printf("\n"); - } - printf("\nres = %d\n\n", res); -#endif - } - } - return CRYPT_OK; -#endif /* LTC_TEST */ -} - -#endif /* OCB_MODE */ - - -/* some comments - - -- it's hard to seek - -- hard to stream [you can't emit ciphertext until full block] - -- The setup is somewhat complicated... -*/ diff --git a/ocb_decrypt.c b/ocb_decrypt.c new file mode 100644 index 0000000..1e409f2 --- /dev/null +++ b/ocb_decrypt.c @@ -0,0 +1,58 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* OCB Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef OCB_MODE + +int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt) +{ + unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE]; + int err, x; + + _ARGCHK(ocb != NULL); + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + return err; + } + if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) { + return CRYPT_INVALID_ARG; + } + + /* Get Z[i] value */ + ocb_shift_xor(ocb, Z); + + /* xor ct in, encrypt, xor Z out */ + for (x = 0; x < ocb->block_len; x++) { + tmp[x] = ct[x] ^ Z[x]; + } + cipher_descriptor[ocb->cipher].ecb_decrypt(tmp, pt, &ocb->key); + for (x = 0; x < ocb->block_len; x++) { + pt[x] ^= Z[x]; + } + + /* compute checksum */ + for (x = 0; x < ocb->block_len; x++) { + ocb->checksum[x] ^= pt[x]; + } + + +#ifdef CLEAN_STACK + zeromem(Z, sizeof(Z)); + zeromem(tmp, sizeof(tmp)); +#endif + return CRYPT_OK; +} + +#endif + diff --git a/ocb_decrypt_verify_memory.c b/ocb_decrypt_verify_memory.c new file mode 100644 index 0000000..f0e29fa --- /dev/null +++ b/ocb_decrypt_verify_memory.c @@ -0,0 +1,52 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* OCB Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef OCB_MODE + +int ocb_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, + int *res) +{ + int err; + ocb_state ocb; + + + _ARGCHK(key != NULL); + _ARGCHK(nonce != NULL); + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + _ARGCHK(tag != NULL); + _ARGCHK(res != NULL); + + if ((err = ocb_init(&ocb, cipher, key, keylen, nonce)) != CRYPT_OK) { + return err; + } + + while (ctlen > (unsigned long)ocb.block_len) { + if ((err = ocb_decrypt(&ocb, ct, pt)) != CRYPT_OK) { + return err; + } + ctlen -= ocb.block_len; + pt += ocb.block_len; + ct += ocb.block_len; + } + + return ocb_done_decrypt(&ocb, ct, ctlen, pt, tag, taglen, res); +} + +#endif diff --git a/ocb_done_decrypt.c b/ocb_done_decrypt.c new file mode 100644 index 0000000..97ba393 --- /dev/null +++ b/ocb_done_decrypt.c @@ -0,0 +1,51 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* OCB Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef OCB_MODE + +int ocb_done_decrypt(ocb_state *ocb, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, int *res) +{ + int err; + unsigned char tagbuf[MAXBLOCKSIZE]; + unsigned long tagbuflen; + + _ARGCHK(ocb != NULL); + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + _ARGCHK(tag != NULL); + _ARGCHK(res != NULL); + + *res = 0; + + tagbuflen = sizeof(tagbuf); + if ((err = __ocb_done(ocb, ct, ctlen, pt, tagbuf, &tagbuflen, 1)) != CRYPT_OK) { + return err; + } + + if (taglen <= tagbuflen && memcmp(tagbuf, tag, taglen) == 0) { + *res = 1; + } + +#ifdef CLEAN_STACK + zeromem(tagbuf, sizeof(tagbuf)); +#endif + + return CRYPT_OK; +} + +#endif + diff --git a/ocb_done_encrypt.c b/ocb_done_encrypt.c new file mode 100644 index 0000000..209892e --- /dev/null +++ b/ocb_done_encrypt.c @@ -0,0 +1,29 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* OCB Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef OCB_MODE + +int ocb_done_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, unsigned char *tag, unsigned long *taglen) +{ + _ARGCHK(ocb != NULL); + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + _ARGCHK(tag != NULL); + _ARGCHK(taglen != NULL); + return __ocb_done(ocb, pt, ptlen, ct, tag, taglen, 0); +} + +#endif + diff --git a/ocb_encrypt.c b/ocb_encrypt.c new file mode 100644 index 0000000..d951933 --- /dev/null +++ b/ocb_encrypt.c @@ -0,0 +1,56 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* OCB Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef OCB_MODE + +int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct) +{ + unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE]; + int err, x; + + _ARGCHK(ocb != NULL); + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + return err; + } + if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) { + return CRYPT_INVALID_ARG; + } + + /* compute checksum */ + for (x = 0; x < ocb->block_len; x++) { + ocb->checksum[x] ^= pt[x]; + } + + /* Get Z[i] value */ + ocb_shift_xor(ocb, Z); + + /* xor pt in, encrypt, xor Z out */ + for (x = 0; x < ocb->block_len; x++) { + tmp[x] = pt[x] ^ Z[x]; + } + cipher_descriptor[ocb->cipher].ecb_encrypt(tmp, ct, &ocb->key); + for (x = 0; x < ocb->block_len; x++) { + ct[x] ^= Z[x]; + } + +#ifdef CLEAN_STACK + zeromem(Z, sizeof(Z)); + zeromem(tmp, sizeof(tmp)); +#endif + return CRYPT_OK; +} + +#endif diff --git a/ocb_encrypt_authenticate_memory.c b/ocb_encrypt_authenticate_memory.c new file mode 100644 index 0000000..839da02 --- /dev/null +++ b/ocb_encrypt_authenticate_memory.c @@ -0,0 +1,50 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* OCB Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef OCB_MODE + +int ocb_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen) +{ + int err; + ocb_state ocb; + + _ARGCHK(key != NULL); + _ARGCHK(nonce != NULL); + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + _ARGCHK(tag != NULL); + _ARGCHK(taglen != NULL); + + if ((err = ocb_init(&ocb, cipher, key, keylen, nonce)) != CRYPT_OK) { + return err; + } + + while (ptlen > (unsigned long)ocb.block_len) { + if ((err = ocb_encrypt(&ocb, pt, ct)) != CRYPT_OK) { + return err; + } + ptlen -= ocb.block_len; + pt += ocb.block_len; + ct += ocb.block_len; + } + + return ocb_done_encrypt(&ocb, pt, ptlen, ct, tag, taglen); +} + +#endif diff --git a/ocb_init.c b/ocb_init.c new file mode 100644 index 0000000..bfb5a87 --- /dev/null +++ b/ocb_init.c @@ -0,0 +1,117 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* OCB Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef OCB_MODE + +static const struct { + int len; + unsigned char poly_div[MAXBLOCKSIZE], + poly_mul[MAXBLOCKSIZE]; +} polys[] = { +{ + 8, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } +}, { + 16, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 } +} +}; + +int ocb_init(ocb_state *ocb, int cipher, + const unsigned char *key, unsigned long keylen, const unsigned char *nonce) +{ + int poly, x, y, m, err; + + _ARGCHK(ocb != NULL); + _ARGCHK(key != NULL); + _ARGCHK(nonce != NULL); + + /* valid cipher? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* determine which polys to use */ + ocb->block_len = cipher_descriptor[cipher].block_length; + for (poly = 0; poly < (int)(sizeof(polys)/sizeof(polys[0])); poly++) { + if (polys[poly].len == ocb->block_len) { + break; + } + } + if (polys[poly].len != ocb->block_len) { + return CRYPT_INVALID_ARG; + } + + /* schedule the key */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &ocb->key)) != CRYPT_OK) { + return err; + } + + /* find L = E[0] */ + zeromem(ocb->L, ocb->block_len); + cipher_descriptor[cipher].ecb_encrypt(ocb->L, ocb->L, &ocb->key); + + /* find R = E[N xor L] */ + for (x = 0; x < ocb->block_len; x++) { + ocb->R[x] = ocb->L[x] ^ nonce[x]; + } + cipher_descriptor[cipher].ecb_encrypt(ocb->R, ocb->R, &ocb->key); + + /* find Ls[i] = L << i for i == 0..31 */ + memcpy(ocb->Ls[0], ocb->L, ocb->block_len); + for (x = 1; x < 32; x++) { + m = ocb->Ls[x-1][0] >> 7; + for (y = 0; y < ocb->block_len-1; y++) { + ocb->Ls[x][y] = ((ocb->Ls[x-1][y] << 1) | (ocb->Ls[x-1][y+1] >> 7)) & 255; + } + ocb->Ls[x][ocb->block_len-1] = (ocb->Ls[x-1][ocb->block_len-1] << 1) & 255; + + if (m == 1) { + for (y = 0; y < ocb->block_len; y++) { + ocb->Ls[x][y] ^= polys[poly].poly_mul[y]; + } + } + } + + /* find Lr = L / x */ + m = ocb->L[ocb->block_len-1] & 1; + + /* shift right */ + for (x = ocb->block_len - 1; x > 0; x--) { + ocb->Lr[x] = ((ocb->L[x] >> 1) | (ocb->L[x-1] << 7)) & 255; + } + ocb->Lr[0] = ocb->L[0] >> 1; + + if (m == 1) { + for (x = 0; x < ocb->block_len; x++) { + ocb->Lr[x] ^= polys[poly].poly_div[x]; + } + } + + /* set Li, checksum */ + zeromem(ocb->Li, ocb->block_len); + zeromem(ocb->checksum, ocb->block_len); + + /* set other params */ + ocb->block_index = 1; + ocb->cipher = cipher; + + return CRYPT_OK; +} + +#endif diff --git a/ocb_ntz.c b/ocb_ntz.c new file mode 100644 index 0000000..fbf6bb6 --- /dev/null +++ b/ocb_ntz.c @@ -0,0 +1,29 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* OCB Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef OCB_MODE + +int ocb_ntz(unsigned long x) +{ + int c; + x &= 0xFFFFFFFFUL; + c = 0; + while ((x & 1) == 0) { + ++c; + x >>= 1; + } + return c; +} + +#endif diff --git a/ocb_shift_xor.c b/ocb_shift_xor.c new file mode 100644 index 0000000..ce93138 --- /dev/null +++ b/ocb_shift_xor.c @@ -0,0 +1,27 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* OCB Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef OCB_MODE + +void ocb_shift_xor(ocb_state *ocb, unsigned char *Z) +{ + int x, y; + y = ocb_ntz(ocb->block_index++); + for (x = 0; x < ocb->block_len; x++) { + ocb->Li[x] ^= ocb->Ls[y][x]; + Z[x] = ocb->Li[x] ^ ocb->R[x]; + } +} + +#endif diff --git a/ocb_test.c b/ocb_test.c new file mode 100644 index 0000000..0b5dafd --- /dev/null +++ b/ocb_test.c @@ -0,0 +1,226 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* OCB Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef OCB_MODE + +int ocb_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + int ptlen; + unsigned char key[16], nonce[16], pt[34], ct[34], tag[16]; + } tests[] = { + + /* OCB-AES-128-0B */ +{ + 0, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0 }, + /* ct */ + { 0 }, + /* tag */ + { 0x15, 0xd3, 0x7d, 0xd7, 0xc8, 0x90, 0xd5, 0xd6, + 0xac, 0xab, 0x92, 0x7b, 0xc0, 0xdc, 0x60, 0xee }, +}, + + + /* OCB-AES-128-3B */ +{ + 3, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0x00, 0x01, 0x02 }, + /* ct */ + { 0xfc, 0xd3, 0x7d }, + /* tag */ + { 0x02, 0x25, 0x47, 0x39, 0xa5, 0xe3, 0x56, 0x5a, + 0xe2, 0xdc, 0xd6, 0x2c, 0x65, 0x97, 0x46, 0xba }, +}, + + /* OCB-AES-128-16B */ +{ + 16, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* ct */ + { 0x37, 0xdf, 0x8c, 0xe1, 0x5b, 0x48, 0x9b, 0xf3, + 0x1d, 0x0f, 0xc4, 0x4d, 0xa1, 0xfa, 0xf6, 0xd6 }, + /* tag */ + { 0xdf, 0xb7, 0x63, 0xeb, 0xdb, 0x5f, 0x0e, 0x71, + 0x9c, 0x7b, 0x41, 0x61, 0x80, 0x80, 0x04, 0xdf }, +}, + + /* OCB-AES-128-20B */ +{ + 20, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 }, + /* ct */ + { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, + 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, + 0x70, 0x03, 0xeb, 0x55}, + /* tag */ + { 0x75, 0x30, 0x84, 0x14, 0x4e, 0xb6, 0x3b, 0x77, + 0x0b, 0x06, 0x3c, 0x2e, 0x23, 0xcd, 0xa0, 0xbb }, +}, + + /* OCB-AES-128-32B */ +{ + 32, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + /* ct */ + { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, + 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, + 0x4a, 0xfc, 0xbb, 0x7f, 0xed, 0xc0, 0x8c, 0xa8, + 0x65, 0x4c, 0x6d, 0x30, 0x4d, 0x16, 0x12, 0xfa }, + + /* tag */ + { 0xc1, 0x4c, 0xbf, 0x2c, 0x1a, 0x1f, 0x1c, 0x3c, + 0x13, 0x7e, 0xad, 0xea, 0x1f, 0x2f, 0x2f, 0xcf }, +}, + + /* OCB-AES-128-34B */ +{ + 34, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21 }, + /* ct */ + { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, + 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, + 0xd4, 0x90, 0x3d, 0xd0, 0x02, 0x5b, 0xa4, 0xaa, + 0x83, 0x7c, 0x74, 0xf1, 0x21, 0xb0, 0x26, 0x0f, + 0xa9, 0x5d }, + + /* tag */ + { 0xcf, 0x83, 0x41, 0xbb, 0x10, 0x82, 0x0c, 0xcf, + 0x14, 0xbd, 0xec, 0x56, 0xb8, 0xd7, 0xd6, 0xab }, +}, + +}; + + int err, x, idx, res; + unsigned long len; + unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE]; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + len = sizeof(outtag); + if ((err = ocb_encrypt_authenticate_memory(idx, tests[x].key, 16, + tests[x].nonce, tests[x].pt, tests[x].ptlen, outct, outtag, &len)) != CRYPT_OK) { + return err; + } + + if (memcmp(outtag, tests[x].tag, len) || memcmp(outct, tests[x].ct, tests[x].ptlen)) { +#if 0 + unsigned long y; + printf("\n\nFailure: \nCT:\n"); + for (y = 0; y < (unsigned long)tests[x].ptlen; ) { + printf("0x%02x", outct[y]); + if (y < (unsigned long)(tests[x].ptlen-1)) printf(", "); + if (!(++y % 8)) printf("\n"); + } + printf("\nTAG:\n"); + for (y = 0; y < len; ) { + printf("0x%02x", outtag[y]); + if (y < len-1) printf(", "); + if (!(++y % 8)) printf("\n"); + } +#endif + return CRYPT_FAIL_TESTVECTOR; + } + + if ((err = ocb_decrypt_verify_memory(idx, tests[x].key, 16, tests[x].nonce, outct, tests[x].ptlen, + outct, tests[x].tag, len, &res)) != CRYPT_OK) { + return err; + } + if ((res != 1) || memcmp(tests[x].pt, outct, tests[x].ptlen)) { +#if 0 + unsigned long y; + printf("\n\nFailure-decrypt: \nPT:\n"); + for (y = 0; y < (unsigned long)tests[x].ptlen; ) { + printf("0x%02x", outct[y]); + if (y < (unsigned long)(tests[x].ptlen-1)) printf(", "); + if (!(++y % 8)) printf("\n"); + } + printf("\nres = %d\n\n", res); +#endif + } + } + return CRYPT_OK; +#endif /* LTC_TEST */ +} + +#endif /* OCB_MODE */ + + +/* some comments + + -- it's hard to seek + -- hard to stream [you can't emit ciphertext until full block] + -- The setup is somewhat complicated... +*/ diff --git a/ofb_decrypt.c b/ofb_decrypt.c new file mode 100644 index 0000000..9531969 --- /dev/null +++ b/ofb_decrypt.c @@ -0,0 +1,26 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef OFB + +int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb) +{ + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + _ARGCHK(ofb != NULL); + return ofb_encrypt(ct, pt, len, ofb); +} + + +#endif + + diff --git a/ofb.c b/ofb_encrypt.c similarity index 55% rename from ofb.c rename to ofb_encrypt.c index cb902b2..d5d06f3 100644 --- a/ofb.c +++ b/ofb_encrypt.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -12,31 +12,6 @@ #ifdef OFB -int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, - int keylen, int num_rounds, symmetric_OFB *ofb) -{ - int x, err; - - _ARGCHK(IV != NULL); - _ARGCHK(key != NULL); - _ARGCHK(ofb != NULL); - - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - /* copy details */ - ofb->cipher = cipher; - ofb->blocklen = cipher_descriptor[cipher].block_length; - for (x = 0; x < ofb->blocklen; x++) { - ofb->IV[x] = IV[x]; - } - - /* init the cipher */ - ofb->padlen = ofb->blocklen; - return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ofb->key); -} - int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb) { int err; @@ -63,15 +38,4 @@ int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s return CRYPT_OK; } -int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb) -{ - _ARGCHK(pt != NULL); - _ARGCHK(ct != NULL); - _ARGCHK(ofb != NULL); - return ofb_encrypt(ct, pt, len, ofb); -} - - #endif - - diff --git a/ofb_start.c b/ofb_start.c new file mode 100644 index 0000000..45fcc70 --- /dev/null +++ b/ofb_start.c @@ -0,0 +1,40 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef OFB + +int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_OFB *ofb) +{ + int x, err; + + _ARGCHK(IV != NULL); + _ARGCHK(key != NULL); + _ARGCHK(ofb != NULL); + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* copy details */ + ofb->cipher = cipher; + ofb->blocklen = cipher_descriptor[cipher].block_length; + for (x = 0; x < ofb->blocklen; x++) { + ofb->IV[x] = IV[x]; + } + + /* init the cipher */ + ofb->padlen = ofb->blocklen; + return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ofb->key); +} + +#endif diff --git a/omac.c b/omac.c deleted file mode 100644 index 5688bb5..0000000 --- a/omac.c +++ /dev/null @@ -1,318 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * gurantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org - */ -/* OMAC1 Support by Tom St Denis (for 64 and 128 bit block ciphers only) */ -#include "mycrypt.h" - -#ifdef OMAC - -int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen) -{ - int err, x, y, mask, msb, len; - - _ARGCHK(omac != NULL); - _ARGCHK(key != NULL); - - /* schedule the key */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - /* now setup the system */ - switch (cipher_descriptor[cipher].block_length) { - case 8: mask = 0x1B; - len = 8; - break; - case 16: mask = 0x87; - len = 16; - break; - default: return CRYPT_INVALID_ARG; - } - - if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &omac->key)) != CRYPT_OK) { - return err; - } - - /* ok now we need Lu and Lu^2 [calc one from the other] */ - - /* first calc L which is Ek(0) */ - zeromem(omac->Lu[0], cipher_descriptor[cipher].block_length); - cipher_descriptor[cipher].ecb_encrypt(omac->Lu[0], omac->Lu[0], &omac->key); - - /* now do the mults, whoopy! */ - for (x = 0; x < 2; x++) { - /* if msb(L * u^(x+1)) = 0 then just shift, otherwise shift and xor constant mask */ - msb = omac->Lu[x][0] >> 7; - - /* shift left */ - for (y = 0; y < (len - 1); y++) { - omac->Lu[x][y] = ((omac->Lu[x][y] << 1) | (omac->Lu[x][y+1] >> 7)) & 255; - } - omac->Lu[x][len - 1] = ((omac->Lu[x][len - 1] << 1) ^ (msb ? mask : 0)) & 255; - - /* copy up as require */ - if (x == 0) { - memcpy(omac->Lu[1], omac->Lu[0], sizeof(omac->Lu[0])); - } - } - - /* setup state */ - omac->cipher_idx = cipher; - omac->buflen = 0; - omac->blklen = len; - zeromem(omac->prev, sizeof(omac->prev)); - zeromem(omac->block, sizeof(omac->block)); - - return CRYPT_OK; -} - -int omac_process(omac_state *state, const unsigned char *buf, unsigned long len) -{ - int err, n, x; - - _ARGCHK(state != NULL); - _ARGCHK(buf != NULL); - if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) { - return err; - } - - if ((state->buflen > (int)sizeof(state->block)) || (state->buflen < 0) || - (state->blklen > (int)sizeof(state->block)) || (state->buflen > state->blklen)) { - return CRYPT_INVALID_ARG; - } - - while (len != 0) { - /* ok if the block is full we xor in prev, encrypt and replace prev */ - if (state->buflen == state->blklen) { - for (x = 0; x < state->blklen; x++) { - state->block[x] ^= state->prev[x]; - } - cipher_descriptor[state->cipher_idx].ecb_encrypt(state->block, state->prev, &state->key); - state->buflen = 0; - } - - /* add bytes */ - n = MIN(len, (unsigned long)(state->blklen - state->buflen)); - memcpy(state->block + state->buflen, buf, n); - state->buflen += n; - len -= n; - buf += n; - } - - return CRYPT_OK; -} - -int omac_done(omac_state *state, unsigned char *out, unsigned long *outlen) -{ - int err, mode, x; - - _ARGCHK(state != NULL); - _ARGCHK(out != NULL); - if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) { - return err; - } - - if ((state->buflen > (int)sizeof(state->block)) || (state->buflen < 0) || - (state->blklen > (int)sizeof(state->block)) || (state->buflen > state->blklen)) { - return CRYPT_INVALID_ARG; - } - - /* figure out mode */ - if (state->buflen != state->blklen) { - /* add the 0x80 byte */ - state->block[state->buflen++] = 0x80; - - /* pad with 0x00 */ - while (state->buflen < state->blklen) { - state->block[state->buflen++] = 0x00; - } - mode = 1; - } else { - mode = 0; - } - - /* now xor prev + Lu[mode] */ - for (x = 0; x < state->blklen; x++) { - state->block[x] ^= state->prev[x] ^ state->Lu[mode][x]; - } - - /* encrypt it */ - cipher_descriptor[state->cipher_idx].ecb_encrypt(state->block, state->block, &state->key); - - /* output it */ - for (x = 0; x < state->blklen && (unsigned long)x < *outlen; x++) { - out[x] = state->block[x]; - } - *outlen = x; - -#ifdef CLEAN_STACK - zeromem(state, sizeof(*state)); -#endif - return CRYPT_OK; -} - -int omac_memory(int cipher, const unsigned char *key, unsigned long keylen, - const unsigned char *msg, unsigned long msglen, - unsigned char *out, unsigned long *outlen) -{ - int err; - omac_state omac; - - _ARGCHK(key != NULL); - _ARGCHK(msg != NULL); - _ARGCHK(out != NULL); - _ARGCHK(outlen != NULL); - - if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) { - return err; - } - if ((err = omac_process(&omac, msg, msglen)) != CRYPT_OK) { - return err; - } - if ((err = omac_done(&omac, out, outlen)) != CRYPT_OK) { - return err; - } - -#ifdef CLEAN_STACK - zeromem(&omac, sizeof(omac)); -#endif - - return CRYPT_OK; -} - -int omac_file(int cipher, const unsigned char *key, unsigned long keylen, - const char *filename, unsigned char *out, unsigned long *outlen) -{ -#ifdef NO_FILE - return CRYPT_NOP; -#else - int err, x; - omac_state omac; - FILE *in; - unsigned char buf[512]; - - - _ARGCHK(key != NULL); - _ARGCHK(filename != NULL); - _ARGCHK(out != NULL); - _ARGCHK(outlen != NULL); - - - in = fopen(filename, "rb"); - if (in == NULL) { - return CRYPT_FILE_NOTFOUND; - } - - if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) { - fclose(in); - return err; - } - - do { - x = fread(buf, 1, sizeof(buf), in); - if ((err = omac_process(&omac, buf, x)) != CRYPT_OK) { - fclose(in); - return err; - } - } while (x == sizeof(buf)); - fclose(in); - - if ((err = omac_done(&omac, out, outlen)) != CRYPT_OK) { - return err; - } - -#ifdef CLEAN_STACK - zeromem(buf, sizeof(buf)); -#endif - - return CRYPT_OK; -#endif -} - -int omac_test(void) -{ -#if !defined(LTC_TEST) - return CRYPT_NOP; -#else - static const struct { - int keylen, msglen; - unsigned char key[16], msg[64], tag[16]; - } tests[] = { - { 16, 0, - { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, - { 0x00 }, - { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, - 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 } - }, - { 16, 16, - { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, - { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a }, - { 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, - 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c } - }, - { 16, 40, - { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, - { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, - 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 }, - { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, - 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 } - }, - { 16, 64, - { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, - { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, - 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, - 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, - 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, - 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }, - { 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, - 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe } - } - - }; - unsigned char out[16]; - int x, y, err, idx; - unsigned long len; - - - /* AES can be under rijndael or aes... try to find it */ - if ((idx = find_cipher("aes")) == -1) { - if ((idx = find_cipher("rijndael")) == -1) { - return CRYPT_NOP; - } - } - - for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { - len = sizeof(out); - if ((err = omac_memory(idx, tests[x].key, tests[x].keylen, tests[x].msg, tests[x].msglen, out, &len)) != CRYPT_OK) { - return err; - } - - if (memcmp(out, tests[x].tag, 16) != 0) { - printf("\n\nTag: "); - for (y = 0; y < 16; y++) printf("%02x", out[y]); printf("\n\n"); - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif -} - -#endif diff --git a/omac_done.c b/omac_done.c new file mode 100644 index 0000000..f065a1d --- /dev/null +++ b/omac_done.c @@ -0,0 +1,66 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +/* OMAC1 Support by Tom St Denis (for 64 and 128 bit block ciphers only) */ +#include "mycrypt.h" + +#ifdef OMAC + +int omac_done(omac_state *state, unsigned char *out, unsigned long *outlen) +{ + int err, mode, x; + + _ARGCHK(state != NULL); + _ARGCHK(out != NULL); + if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) { + return err; + } + + if ((state->buflen > (int)sizeof(state->block)) || (state->buflen < 0) || + (state->blklen > (int)sizeof(state->block)) || (state->buflen > state->blklen)) { + return CRYPT_INVALID_ARG; + } + + /* figure out mode */ + if (state->buflen != state->blklen) { + /* add the 0x80 byte */ + state->block[state->buflen++] = 0x80; + + /* pad with 0x00 */ + while (state->buflen < state->blklen) { + state->block[state->buflen++] = 0x00; + } + mode = 1; + } else { + mode = 0; + } + + /* now xor prev + Lu[mode] */ + for (x = 0; x < state->blklen; x++) { + state->block[x] ^= state->prev[x] ^ state->Lu[mode][x]; + } + + /* encrypt it */ + cipher_descriptor[state->cipher_idx].ecb_encrypt(state->block, state->block, &state->key); + + /* output it */ + for (x = 0; x < state->blklen && (unsigned long)x < *outlen; x++) { + out[x] = state->block[x]; + } + *outlen = x; + +#ifdef CLEAN_STACK + zeromem(state, sizeof(*state)); +#endif + return CRYPT_OK; +} + +#endif + diff --git a/omac_file.c b/omac_file.c new file mode 100644 index 0000000..09d2d4b --- /dev/null +++ b/omac_file.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +/* OMAC1 Support by Tom St Denis (for 64 and 128 bit block ciphers only) */ +#include "mycrypt.h" + +#ifdef OMAC + +int omac_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen) +{ +#ifdef NO_FILE + return CRYPT_NOP; +#else + int err, x; + omac_state omac; + FILE *in; + unsigned char buf[512]; + + _ARGCHK(key != NULL); + _ARGCHK(filename != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + in = fopen(filename, "rb"); + if (in == NULL) { + return CRYPT_FILE_NOTFOUND; + } + + if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) { + fclose(in); + return err; + } + + do { + x = fread(buf, 1, sizeof(buf), in); + if ((err = omac_process(&omac, buf, x)) != CRYPT_OK) { + fclose(in); + return err; + } + } while (x == sizeof(buf)); + fclose(in); + + if ((err = omac_done(&omac, out, outlen)) != CRYPT_OK) { + return err; + } + +#ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + + return CRYPT_OK; +#endif +} + +#endif diff --git a/omac_init.c b/omac_init.c new file mode 100644 index 0000000..3945630 --- /dev/null +++ b/omac_init.c @@ -0,0 +1,76 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +/* OMAC1 Support by Tom St Denis (for 64 and 128 bit block ciphers only) */ +#include "mycrypt.h" + +#ifdef OMAC + +int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen) +{ + int err, x, y, mask, msb, len; + + _ARGCHK(omac != NULL); + _ARGCHK(key != NULL); + + /* schedule the key */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* now setup the system */ + switch (cipher_descriptor[cipher].block_length) { + case 8: mask = 0x1B; + len = 8; + break; + case 16: mask = 0x87; + len = 16; + break; + default: return CRYPT_INVALID_ARG; + } + + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &omac->key)) != CRYPT_OK) { + return err; + } + + /* ok now we need Lu and Lu^2 [calc one from the other] */ + + /* first calc L which is Ek(0) */ + zeromem(omac->Lu[0], cipher_descriptor[cipher].block_length); + cipher_descriptor[cipher].ecb_encrypt(omac->Lu[0], omac->Lu[0], &omac->key); + + /* now do the mults, whoopy! */ + for (x = 0; x < 2; x++) { + /* if msb(L * u^(x+1)) = 0 then just shift, otherwise shift and xor constant mask */ + msb = omac->Lu[x][0] >> 7; + + /* shift left */ + for (y = 0; y < (len - 1); y++) { + omac->Lu[x][y] = ((omac->Lu[x][y] << 1) | (omac->Lu[x][y+1] >> 7)) & 255; + } + omac->Lu[x][len - 1] = ((omac->Lu[x][len - 1] << 1) ^ (msb ? mask : 0)) & 255; + + /* copy up as require */ + if (x == 0) { + memcpy(omac->Lu[1], omac->Lu[0], sizeof(omac->Lu[0])); + } + } + + /* setup state */ + omac->cipher_idx = cipher; + omac->buflen = 0; + omac->blklen = len; + zeromem(omac->prev, sizeof(omac->prev)); + zeromem(omac->block, sizeof(omac->block)); + + return CRYPT_OK; +} + +#endif diff --git a/omac_memory.c b/omac_memory.c new file mode 100644 index 0000000..1cca891 --- /dev/null +++ b/omac_memory.c @@ -0,0 +1,42 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +/* OMAC1 Support by Tom St Denis (for 64 and 128 bit block ciphers only) */ +#include "mycrypt.h" + +#ifdef OMAC + +int omac_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *msg, unsigned long msglen, + unsigned char *out, unsigned long *outlen) +{ + int err; + omac_state omac; + + _ARGCHK(key != NULL); + _ARGCHK(msg != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) { + return err; + } + if ((err = omac_process(&omac, msg, msglen)) != CRYPT_OK) { + return err; + } + if ((err = omac_done(&omac, out, outlen)) != CRYPT_OK) { + return err; + } + + return CRYPT_OK; +} + +#endif diff --git a/omac_process.c b/omac_process.c new file mode 100644 index 0000000..8da1527 --- /dev/null +++ b/omac_process.c @@ -0,0 +1,53 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +/* OMAC1 Support by Tom St Denis (for 64 and 128 bit block ciphers only) */ +#include "mycrypt.h" + +#ifdef OMAC + +int omac_process(omac_state *state, const unsigned char *buf, unsigned long len) +{ + int err, n, x; + + _ARGCHK(state != NULL); + _ARGCHK(buf != NULL); + if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) { + return err; + } + + if ((state->buflen > (int)sizeof(state->block)) || (state->buflen < 0) || + (state->blklen > (int)sizeof(state->block)) || (state->buflen > state->blklen)) { + return CRYPT_INVALID_ARG; + } + + while (len != 0) { + /* ok if the block is full we xor in prev, encrypt and replace prev */ + if (state->buflen == state->blklen) { + for (x = 0; x < state->blklen; x++) { + state->block[x] ^= state->prev[x]; + } + cipher_descriptor[state->cipher_idx].ecb_encrypt(state->block, state->prev, &state->key); + state->buflen = 0; + } + + /* add bytes */ + n = MIN(len, (unsigned long)(state->blklen - state->buflen)); + memcpy(state->block + state->buflen, buf, n); + state->buflen += n; + len -= n; + buf += n; + } + + return CRYPT_OK; +} + +#endif + diff --git a/omac_test.c b/omac_test.c new file mode 100644 index 0000000..2d50d9a --- /dev/null +++ b/omac_test.c @@ -0,0 +1,95 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +/* OMAC1 Support by Tom St Denis (for 64 and 128 bit block ciphers only) */ +#include "mycrypt.h" + +#ifdef OMAC + +int omac_test(void) +{ +#if !defined(LTC_TEST) + return CRYPT_NOP; +#else + static const struct { + int keylen, msglen; + unsigned char key[16], msg[64], tag[16]; + } tests[] = { + { 16, 0, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x00 }, + { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 } + }, + { 16, 16, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a }, + { 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c } + }, + { 16, 40, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 }, + { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, + 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 } + }, + { 16, 64, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }, + { 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe } + } + + }; + unsigned char out[16]; + int x, y, err, idx; + unsigned long len; + + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + len = sizeof(out); + if ((err = omac_memory(idx, tests[x].key, tests[x].keylen, tests[x].msg, tests[x].msglen, out, &len)) != CRYPT_OK) { + return err; + } + + if (memcmp(out, tests[x].tag, 16) != 0) { + printf("\n\nTag: "); + for (y = 0; y < 16; y++) printf("%02x", out[y]); printf("\n\n"); + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/packet_store_header.c b/packet_store_header.c new file mode 100644 index 0000000..d750718 --- /dev/null +++ b/packet_store_header.c @@ -0,0 +1,29 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +#ifdef PACKET + +void packet_store_header(unsigned char *dst, int section, int subsection) +{ + _ARGCHK(dst != NULL); + + /* store version number */ + dst[0] = (unsigned char)(CRYPT&255); + dst[1] = (unsigned char)((CRYPT>>8)&255); + + /* store section and subsection */ + dst[2] = (unsigned char)(section & 255); + dst[3] = (unsigned char)(subsection & 255); + +} + +#endif diff --git a/packet.c b/packet_valid_header.c similarity index 68% rename from packet.c rename to packet_valid_header.c index 8a6c1f4..7fda507 100644 --- a/packet.c +++ b/packet_valid_header.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -12,20 +12,6 @@ #ifdef PACKET -void packet_store_header(unsigned char *dst, int section, int subsection) -{ - _ARGCHK(dst != NULL); - - /* store version number */ - dst[0] = (unsigned char)(CRYPT&255); - dst[1] = (unsigned char)((CRYPT>>8)&255); - - /* store section and subsection */ - dst[2] = (unsigned char)(section & 255); - dst[3] = (unsigned char)(subsection & 255); - -} - int packet_valid_header(unsigned char *src, int section, int subsection) { unsigned long ver; diff --git a/pkcs_1_i2osp.c b/pkcs_1_i2osp.c new file mode 100644 index 0000000..1a7fadd --- /dev/null +++ b/pkcs_1_i2osp.c @@ -0,0 +1,40 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +/* Integer to Octet I2OSP -- Tom St Denis */ + +#ifdef PKCS_1 + +/* always stores the same # of bytes, pads with leading zero bytes + as required + */ +int pkcs_1_i2osp(mp_int *n, unsigned long modulus_len, unsigned char *out) +{ + int err; + unsigned long size; + + size = mp_unsigned_bin_size(n); + + if (size > modulus_len) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* store it */ + zeromem(out, modulus_len); + if ((err = mp_to_unsigned_bin(n, out+(modulus_len-size))) != MP_OKAY) { + return mpi_to_ltc_error(err); + } + return CRYPT_OK; +} + +#endif /* PKCS_1 */ + diff --git a/pkcs_1_mgf1.c b/pkcs_1_mgf1.c new file mode 100644 index 0000000..b21d928 --- /dev/null +++ b/pkcs_1_mgf1.c @@ -0,0 +1,66 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +/* The Mask Generation Function (MGF1) for PKCS #1 -- Tom St Denis */ + +#ifdef PKCS_1 + +int pkcs_1_mgf1(const unsigned char *seed, unsigned long seedlen, + int hash_idx, + unsigned char *mask, unsigned long masklen) +{ + unsigned long hLen, counter, x; + int err; + hash_state md; + unsigned char buf[MAXBLOCKSIZE]; + + _ARGCHK(seed != NULL); + _ARGCHK(mask != NULL); + + /* ensure valid hash */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + /* get hash output size */ + hLen = hash_descriptor[hash_idx].hashsize; + + /* start counter */ + counter = 0; + + while (masklen > 0) { + /* handle counter */ + STORE32H(counter, buf); + ++counter; + + /* get hash of seed || counter */ + hash_descriptor[hash_idx].init(&md); + if ((err = hash_descriptor[hash_idx].process(&md, seed, seedlen)) != CRYPT_OK) { + return err; + } + if ((err = hash_descriptor[hash_idx].process(&md, buf, 4)) != CRYPT_OK) { + return err; + } + if ((err = hash_descriptor[hash_idx].done(&md, buf)) != CRYPT_OK) { + return err; + } + + /* store it */ + for (x = 0; x < hLen && masklen > 0; x++, masklen--) { + *mask++ = buf[x]; + } + } + + return CRYPT_OK; +} + +#endif /* PKCS_1 */ diff --git a/pkcs_1_oaep_decode.c b/pkcs_1_oaep_decode.c new file mode 100644 index 0000000..d9430dc --- /dev/null +++ b/pkcs_1_oaep_decode.c @@ -0,0 +1,135 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +/* OAEP Padding for PKCS #1 -- Tom St Denis */ + +#ifdef PKCS_1 + +int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + unsigned char DB[1024], seed[MAXBLOCKSIZE], mask[sizeof(DB)]; + unsigned long hLen, x, y, modulus_len; + int err; + + _ARGCHK(msg != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + /* test valid hash */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + hLen = hash_descriptor[hash_idx].hashsize; + modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); + + /* test message size */ + if (modulus_len >= sizeof(DB) || msglen != modulus_len) { + return CRYPT_PK_INVALID_SIZE; + } + + /* ok so it's now in the form + + 0x00 || maskedseed || maskedDB + + 1 || hLen || modulus_len - hLen - 1 + + */ + + /* must have leading 0x00 byte */ + if (msg[0] != 0x00) { + return CRYPT_INVALID_PACKET; + } + + /* now read the masked seed */ + for (x = 1, y = 0; y < hLen; y++) { + seed[y] = msg[x++]; + } + + /* now read the masked DB */ + for (y = 0; y < modulus_len - hLen - 1; y++) { + DB[y] = msg[x++]; + } + + /* compute MGF1 of maskedDB (hLen) */ + if ((err = pkcs_1_mgf1(DB, modulus_len - hLen - 1, hash_idx, mask, hLen)) != CRYPT_OK) { + return err; + } + + /* XOR against seed */ + for (y = 0; y < hLen; y++) { + seed[y] ^= mask[y]; + } + + /* compute MGF1 of seed (k - hlen - 1) */ + if ((err = pkcs_1_mgf1(seed, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + return err; + } + + /* xor against DB */ + for (y = 0; y < (modulus_len - hLen - 1); y++) { + DB[y] ^= mask[y]; + } + + /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ + + /* compute lhash and store it in seed [reuse temps!] */ + x = sizeof(seed); + if (lparam != NULL) { + if ((err = hash_memory(hash_idx, lparam, lparamlen, seed, &x)) != CRYPT_OK) { + return err; + } + } else { + /* can't pass hash_memory a NULL so use DB with zero length */ + if ((err = hash_memory(hash_idx, DB, 0, seed, &x)) != CRYPT_OK) { + return err; + } + } + + /* compare the lhash'es */ + if (memcmp(seed, DB, hLen) != 0) { + return CRYPT_INVALID_PACKET; + } + + /* now zeroes before a 0x01 */ + for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) { + /* step... */ + } + + /* error out if wasn't 0x01 */ + if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) { + return CRYPT_INVALID_PACKET; + } + + /* rest is the message (and skip 0x01) */ + if (msglen - ++x > *outlen) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* copy message */ + *outlen = (modulus_len - hLen - 1) - x; + for (y = 0; x != (modulus_len - hLen - 1); ) { + out[y++] = DB[x++]; + } + +#ifdef CLEAN_STACK + zeromem(DB, sizeof(DB)); + zeromem(seed, sizeof(seed)); + zeromem(mask, sizeof(mask)); +#endif + + return CRYPT_OK; +} + +#endif /* PKCS_1 */ diff --git a/pkcs_1_oaep_encode.c b/pkcs_1_oaep_encode.c new file mode 100644 index 0000000..2c8f5c0 --- /dev/null +++ b/pkcs_1_oaep_encode.c @@ -0,0 +1,128 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +/* OAEP Padding for PKCS #1 -- Tom St Denis */ + +#ifdef PKCS_1 + +int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, int hash_idx, + int prng_idx, prng_state *prng, + unsigned char *out, unsigned long *outlen) +{ + unsigned char DB[1024], seed[MAXBLOCKSIZE], mask[sizeof(DB)]; + unsigned long hLen, x, y, modulus_len; + int err; + + _ARGCHK(msg != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + /* test valid hash */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + /* valid prng */ + if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { + return err; + } + + hLen = hash_descriptor[hash_idx].hashsize; + modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); + + /* test message size */ + if (modulus_len >= sizeof(DB) || msglen > (modulus_len - 2*hLen - 2)) { + return CRYPT_PK_INVALID_SIZE; + } + + /* get lhash */ +// DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes + x = sizeof(DB); + if (lparam != NULL) { + if ((err = hash_memory(hash_idx, lparam, lparamlen, DB, &x)) != CRYPT_OK) { + return err; + } + } else { + /* can't pass hash_memory a NULL so use DB with zero length */ + if ((err = hash_memory(hash_idx, DB, 0, DB, &x)) != CRYPT_OK) { + return err; + } + } + + /* append PS then 0x01 (to lhash) */ + x = hLen; + y = modulus_len - msglen - 2*hLen - 2; + while (y--) { + DB[x++] = 0x00; + } + DB[x++] = 0x01; + + /* message */ + y = msglen; + while (y--) { + DB[x++] = *msg++; + } + + /* now choose a random seed */ + if (prng_descriptor[prng_idx].read(seed, hLen, prng) != hLen) { + return CRYPT_ERROR_READPRNG; + } + + /* compute MGF1 of seed (k - hlen - 1) */ + if ((err = pkcs_1_mgf1(seed, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + return err; + } + + /* xor against DB */ + for (y = 0; y < (modulus_len - hLen - 1); y++) { + DB[y] ^= mask[y]; + } + + /* compute MGF1 of maskedDB (hLen) */ + if ((err = pkcs_1_mgf1(DB, modulus_len - hLen - 1, hash_idx, mask, hLen)) != CRYPT_OK) { + return err; + } + + /* XOR against seed */ + for (y = 0; y < hLen; y++) { + seed[y] ^= mask[y]; + } + + /* create string of length modulus_len */ + if (*outlen < modulus_len) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* start output which is 0x00 || maskedSeed || maskedDB */ + x = 0; + out[x++] = 0x00; + for (y = 0; y < hLen; y++) { + out[x++] = seed[y]; + } + for (y = 0; y < modulus_len - hLen - 1; y++) { + out[x++] = DB[y]; + } + *outlen = x; + +#ifdef CLEAN_STACK + zeromem(DB, sizeof(DB)); + zeromem(seed, sizeof(seed)); + zeromem(mask, sizeof(mask)); +#endif + + return CRYPT_OK; +} + +#endif /* PKCS_1 */ + diff --git a/pkcs_1_os2ip.c b/pkcs_1_os2ip.c new file mode 100644 index 0000000..cff881e --- /dev/null +++ b/pkcs_1_os2ip.c @@ -0,0 +1,27 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +/* Octet to Integer OS2IP -- Tom St Denis */ +#ifdef PKCS_1 + +int pkcs_1_os2ip(mp_int *n, unsigned char *in, unsigned long inlen) +{ + int err; + /* read it */ + if ((err = mp_read_unsigned_bin(n, in, inlen)) != MP_OKAY) { + return mpi_to_ltc_error(err); + } + return CRYPT_OK; +} + +#endif /* PKCS_1 */ + diff --git a/pkcs_1_pss_decode.c b/pkcs_1_pss_decode.c new file mode 100644 index 0000000..313677c --- /dev/null +++ b/pkcs_1_pss_decode.c @@ -0,0 +1,121 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +/* PKCS #1 PSS Signature Padding -- Tom St Denis */ + +#ifdef PKCS_1 + +int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, + const unsigned char *sig, unsigned long siglen, + unsigned long saltlen, int hash_idx, + unsigned long modulus_bitlen, int *res) +{ + unsigned char DB[1024], mask[sizeof(DB)], salt[sizeof(DB)], hash[sizeof(DB)]; + unsigned long x, y, hLen, modulus_len; + int err; + hash_state md; + + _ARGCHK(msghash != NULL); + _ARGCHK(res != NULL); + + /* default to invalid */ + *res = 0; + + /* ensure hash is valid */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + hLen = hash_descriptor[hash_idx].hashsize; + modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); + + /* check sizes */ + if ((saltlen > sizeof(salt)) || (modulus_len > sizeof(DB)) || + (modulus_len < hLen + saltlen + 2) || (siglen != modulus_len)) { + return CRYPT_INVALID_ARG; + } + + /* ensure the 0xBC byte */ + if (sig[siglen-1] != 0xBC) { + return CRYPT_OK; + } + + /* copy out the DB */ + for (x = 0; x < modulus_len - hLen - 1; x++) { + DB[x] = sig[x]; + } + + /* copy out the hash */ + for (y = 0; y < hLen; y++) { + hash[y] = sig[x++]; + } + + /* check the MSB */ + if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - modulus_bitlen))) != 0) { + return CRYPT_OK; + } + + /* generate mask of length modulus_len - hLen - 1 from hash */ + if ((err = pkcs_1_mgf1(hash, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + return err; + } + + /* xor against DB */ + for (y = 0; y < (modulus_len - hLen - 1); y++) { + DB[y] ^= mask[y]; + } + + /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ + + /* check for zeroes and 0x01 */ + for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) { + if (DB[x] != 0x00) { + return CRYPT_OK; + } + } + + if (DB[x++] != 0x01) { + return CRYPT_OK; + } + + /* M = (eight) 0x00 || msghash || salt, mask = H(M) */ + hash_descriptor[hash_idx].init(&md); + zeromem(mask, 8); + if ((err = hash_descriptor[hash_idx].process(&md, mask, 8)) != CRYPT_OK) { + return err; + } + if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { + return err; + } + if ((err = hash_descriptor[hash_idx].process(&md, DB+x, saltlen)) != CRYPT_OK) { + return err; + } + if ((err = hash_descriptor[hash_idx].done(&md, mask)) != CRYPT_OK) { + return err; + } + + /* mask == hash means valid signature */ + if (memcmp(mask, hash, hLen) == 0) { + *res = 1; + } + +#ifdef CLEAN_STACK + zeromem(DB, sizeof(DB)); + zeromem(mask, sizeof(mask)); + zeromem(salt, sizeof(salt)); + zeromem(hash, sizeof(hash)); +#endif + + return CRYPT_OK; +} + +#endif /* PKCS_1 */ diff --git a/pkcs_1_pss_encode.c b/pkcs_1_pss_encode.c new file mode 100644 index 0000000..01d219a --- /dev/null +++ b/pkcs_1_pss_encode.c @@ -0,0 +1,122 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +/* PKCS #1 PSS Signature Padding -- Tom St Denis */ + +#ifdef PKCS_1 + +int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, + unsigned long saltlen, int hash_idx, + int prng_idx, prng_state *prng, + unsigned long modulus_bitlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned char DB[1024], mask[sizeof(DB)], salt[sizeof(DB)], hash[sizeof(DB)]; + unsigned long x, y, hLen, modulus_len; + int err; + hash_state md; + + _ARGCHK(msghash != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + /* ensure hash and PRNG are valid */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { + return err; + } + + hLen = hash_descriptor[hash_idx].hashsize; + modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); + + /* check sizes */ + if ((saltlen > sizeof(salt)) || (modulus_len > sizeof(DB)) || (modulus_len < hLen + saltlen + 2)) { + return CRYPT_INVALID_ARG; + } + + /* generate random salt */ + if (saltlen > 0) { + if (prng_descriptor[prng_idx].read(salt, saltlen, prng) != saltlen) { + return CRYPT_ERROR_READPRNG; + } + } + + /* M = (eight) 0x00 || msghash || salt, hash = H(M) */ + hash_descriptor[hash_idx].init(&md); + zeromem(DB, 8); + if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) { + return err; + } + if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { + return err; + } + if ((err = hash_descriptor[hash_idx].process(&md, salt, saltlen)) != CRYPT_OK) { + return err; + } + if ((err = hash_descriptor[hash_idx].done(&md, hash)) != CRYPT_OK) { + return err; + } + + /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ + for (x = 0; x < (modulus_len - saltlen - hLen - 2); x++) { + DB[x] = 0x00; + } + DB[x++] = 0x01; + for (y = 0; y < saltlen; y++) { + DB[x++] = salt[y]; + } + + /* generate mask of length modulus_len - hLen - 1 from hash */ + if ((err = pkcs_1_mgf1(hash, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + return err; + } + + /* xor against DB */ + for (y = 0; y < (modulus_len - hLen - 1); y++) { + DB[y] ^= mask[y]; + } + + /* output is DB || hash || 0xBC */ + if (*outlen < modulus_len) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* DB */ + for (y = x = 0; x < modulus_len - hLen - 1; x++) { + out[y++] = DB[x]; + } + /* hash */ + for (x = 0; x < hLen; x++) { + out[y++] = hash[x]; + } + /* 0xBC */ + out[y] = 0xBC; + + /* now clear the 8*modulus_len - modulus_bitlen most significant bits */ + out[0] &= 0xFF >> ((modulus_len<<3) - modulus_bitlen); + + /* store output size */ + *outlen = modulus_len; + +#ifdef CLEAN_STACK + zeromem(DB, sizeof(DB)); + zeromem(mask, sizeof(mask)); + zeromem(salt, sizeof(salt)); + zeromem(hash, sizeof(hash)); +#endif + + return CRYPT_OK; +} + +#endif /* PKCS_1 */ diff --git a/pkcs_5_1.c b/pkcs_5_1.c new file mode 100644 index 0000000..d7ae0e1 --- /dev/null +++ b/pkcs_5_1.c @@ -0,0 +1,63 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include + +/* PKCS #5, Algorithm #1 */ +#ifdef PKCS_5 + +int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + int err; + unsigned long x; + hash_state md; + unsigned char buf[MAXBLOCKSIZE]; + + _ARGCHK(password != NULL); + _ARGCHK(salt != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + /* test hash IDX */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + /* hash initial password + salt */ + hash_descriptor[hash_idx].init(&md); + hash_descriptor[hash_idx].process(&md, password, password_len); + hash_descriptor[hash_idx].process(&md, salt, 8); + hash_descriptor[hash_idx].done(&md, buf); + + while (--iteration_count) { + // code goes here. + x = sizeof(buf); + if ((err = hash_memory(hash_idx, buf, hash_descriptor[hash_idx].hashsize, buf, &x)) != CRYPT_OK) { + return err; + } + } + + /* copy upto outlen bytes */ + for (x = 0; x < hash_descriptor[hash_idx].hashsize && x < *outlen; x++) { + out[x] = buf[x]; + } + *outlen = x; + +#ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + + return CRYPT_OK; +} + +#endif diff --git a/pkcs_5_2.c b/pkcs_5_2.c new file mode 100644 index 0000000..46bf75b --- /dev/null +++ b/pkcs_5_2.c @@ -0,0 +1,88 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include + +/* PKCS #5, Algorithm #2 */ +#ifdef PKCS_5 + +int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, unsigned long salt_len, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + int err, itts; + unsigned long stored, left, x, y, blkno; + unsigned char buf[2][MAXBLOCKSIZE]; + hmac_state hmac; + + _ARGCHK(password != NULL); + _ARGCHK(salt != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + /* test hash IDX */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + left = *outlen; + blkno = 1; + stored = 0; + while (left != 0) { + /* process block number blkno */ + zeromem(buf, sizeof(buf)); + + /* store current block number and increment for next pass */ + STORE32H(blkno, buf[1]); + ++blkno; + + /* get PRF(P, S||int(blkno)) */ + if ((err = hmac_init(&hmac, hash_idx, password, password_len)) != CRYPT_OK) { + return err; + } + if ((err = hmac_process(&hmac, salt, salt_len)) != CRYPT_OK) { + return err; + } + if ((err = hmac_process(&hmac, buf[1], 4)) != CRYPT_OK) { + return err; + } + x = sizeof(buf[0]); + if ((err = hmac_done(&hmac, buf[0], &x)) != CRYPT_OK) { + return err; + } + + /* now compute repeated and XOR it in buf[1] */ + memcpy(buf[1], buf[0], x); + for (itts = 2; itts < iteration_count; ++itts) { + if ((err = hmac_memory(hash_idx, password, password_len, buf[0], x, buf[0], &x)) != CRYPT_OK) { + return err; + } + for (y = 0; y < x; y++) { + buf[1][y] ^= buf[0][y]; + } + } + + /* now emit upto x bytes of buf[1] to output */ + for (y = 0; y < x && left != 0; ++y) { + out[stored++] = buf[1][y]; + --left; + } + } + *outlen = stored; + +#ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + return CRYPT_OK; +} + +#endif + diff --git a/pmac.c b/pmac.c deleted file mode 100644 index 09d46ce..0000000 --- a/pmac.c +++ /dev/null @@ -1,437 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * gurantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org - */ - -/* PMAC implementation by Tom St Denis */ -#include "mycrypt.h" - -#ifdef PMAC - -static const struct { - int len; - unsigned char poly_div[MAXBLOCKSIZE], - poly_mul[MAXBLOCKSIZE]; -} polys[] = { -{ - 8, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } -}, { - 16, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 } -} -}; - -int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen) -{ - int poly, x, y, m, err; - unsigned char L[MAXBLOCKSIZE]; - - _ARGCHK(pmac != NULL); - _ARGCHK(key != NULL); - - /* valid cipher? */ - if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { - return err; - } - - /* determine which polys to use */ - pmac->block_len = cipher_descriptor[cipher].block_length; - for (poly = 0; poly < (int)(sizeof(polys)/sizeof(polys[0])); poly++) { - if (polys[poly].len == pmac->block_len) { - break; - } - } - if (polys[poly].len != pmac->block_len) { - return CRYPT_INVALID_ARG; - } - - /* schedule the key */ - if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &pmac->key)) != CRYPT_OK) { - return err; - } - - /* find L = E[0] */ - zeromem(L, pmac->block_len); - cipher_descriptor[cipher].ecb_encrypt(L, L, &pmac->key); - - /* find Ls[i] = L << i for i == 0..31 */ - memcpy(pmac->Ls[0], L, pmac->block_len); - for (x = 1; x < 32; x++) { - m = pmac->Ls[x-1][0] >> 7; - for (y = 0; y < pmac->block_len-1; y++) { - pmac->Ls[x][y] = ((pmac->Ls[x-1][y] << 1) | (pmac->Ls[x-1][y+1] >> 7)) & 255; - } - pmac->Ls[x][pmac->block_len-1] = (pmac->Ls[x-1][pmac->block_len-1] << 1) & 255; - - if (m == 1) { - for (y = 0; y < pmac->block_len; y++) { - pmac->Ls[x][y] ^= polys[poly].poly_mul[y]; - } - } - } - - /* find Lr = L / x */ - m = L[pmac->block_len-1] & 1; - - /* shift right */ - for (x = pmac->block_len - 1; x > 0; x--) { - pmac->Lr[x] = ((L[x] >> 1) | (L[x-1] << 7)) & 255; - } - pmac->Lr[0] = L[0] >> 1; - - if (m == 1) { - for (x = 0; x < pmac->block_len; x++) { - pmac->Lr[x] ^= polys[poly].poly_div[x]; - } - } - - /* zero buffer, counters, etc... */ - pmac->block_index = 1; - pmac->cipher_idx = cipher; - pmac->buflen = 0; - zeromem(pmac->block, sizeof(pmac->block)); - zeromem(pmac->Li, sizeof(pmac->Li)); - zeromem(pmac->checksum, sizeof(pmac->checksum)); - -#ifdef CLEAN_STACK - zeromem(L, sizeof(L)); -#endif - - return CRYPT_OK; -} - -static int ntz(unsigned long x) -{ - int c; - x &= 0xFFFFFFFFUL; - c = 0; - while ((x & 1) == 0) { - ++c; - x >>= 1; - } - return c; -} - -static void shift_xor(pmac_state *pmac) -{ - int x, y; - y = ntz(pmac->block_index++); - for (x = 0; x < pmac->block_len; x++) { - pmac->Li[x] ^= pmac->Ls[y][x]; - } -} - -int pmac_process(pmac_state *state, const unsigned char *buf, unsigned long len) -{ - int err, n, x; - unsigned char Z[MAXBLOCKSIZE]; - - _ARGCHK(state != NULL); - _ARGCHK(buf != NULL); - if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) { - return err; - } - - if ((state->buflen > (int)sizeof(state->block)) || (state->buflen < 0) || - (state->block_len > (int)sizeof(state->block)) || (state->buflen > state->block_len)) { - return CRYPT_INVALID_ARG; - } - - while (len != 0) { - /* ok if the block is full we xor in prev, encrypt and replace prev */ - if (state->buflen == state->block_len) { - shift_xor(state); - for (x = 0; x < state->block_len; x++) { - Z[x] = state->Li[x] ^ state->block[x]; - } - cipher_descriptor[state->cipher_idx].ecb_encrypt(Z, Z, &state->key); - for (x = 0; x < state->block_len; x++) { - state->checksum[x] ^= Z[x]; - } - state->buflen = 0; - } - - /* add bytes */ - n = MIN(len, (unsigned long)(state->block_len - state->buflen)); - memcpy(state->block + state->buflen, buf, n); - state->buflen += n; - len -= n; - buf += n; - } - -#ifdef CLEAN_STACK - zeromem(Z, sizeof(Z)); -#endif - - return CRYPT_OK; -} - -int pmac_done(pmac_state *state, unsigned char *out, unsigned long *outlen) -{ - int err, x; - - _ARGCHK(state != NULL); - _ARGCHK(out != NULL); - if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) { - return err; - } - - if ((state->buflen > (int)sizeof(state->block)) || (state->buflen < 0) || - (state->block_len > (int)sizeof(state->block)) || (state->buflen > state->block_len)) { - return CRYPT_INVALID_ARG; - } - - - /* handle padding. If multiple xor in L/x */ - - if (state->buflen == state->block_len) { - /* xor Lr against the checksum */ - for (x = 0; x < state->block_len; x++) { - state->checksum[x] ^= state->block[x] ^ state->Lr[x]; - } - } else { - /* otherwise xor message bytes then the 0x80 byte */ - for (x = 0; x < state->buflen; x++) { - state->checksum[x] ^= state->block[x]; - } - state->checksum[x] ^= 0x80; - } - - /* encrypt it */ - cipher_descriptor[state->cipher_idx].ecb_encrypt(state->checksum, state->checksum, &state->key); - - /* store it */ - for (x = 0; x < state->block_len && x <= (int)*outlen; x++) { - out[x] = state->checksum[x]; - } - *outlen = x; - -#ifdef CLEAN_STACK - zeromem(state, sizeof(*state)); -#endif - return CRYPT_OK; -} - -int pmac_memory(int cipher, const unsigned char *key, unsigned long keylen, - const unsigned char *msg, unsigned long msglen, - unsigned char *out, unsigned long *outlen) -{ - int err; - pmac_state pmac; - - _ARGCHK(key != NULL); - _ARGCHK(msg != NULL); - _ARGCHK(out != NULL); - _ARGCHK(outlen != NULL); - - - if ((err = pmac_init(&pmac, cipher, key, keylen)) != CRYPT_OK) { - return err; - } - if ((err = pmac_process(&pmac, msg, msglen)) != CRYPT_OK) { - return err; - } - if ((err = pmac_done(&pmac, out, outlen)) != CRYPT_OK) { - return err; - } - - return CRYPT_OK; -} - -int pmac_file(int cipher, const unsigned char *key, unsigned long keylen, - const char *filename, unsigned char *out, unsigned long *outlen) -{ -#ifdef NO_FILE - return CRYPT_NOP; -#else - int err, x; - pmac_state pmac; - FILE *in; - unsigned char buf[512]; - - - _ARGCHK(key != NULL); - _ARGCHK(filename != NULL); - _ARGCHK(out != NULL); - _ARGCHK(outlen != NULL); - - - in = fopen(filename, "rb"); - if (in == NULL) { - return CRYPT_FILE_NOTFOUND; - } - - if ((err = pmac_init(&pmac, cipher, key, keylen)) != CRYPT_OK) { - fclose(in); - return err; - } - - do { - x = fread(buf, 1, sizeof(buf), in); - if ((err = pmac_process(&pmac, buf, x)) != CRYPT_OK) { - fclose(in); - return err; - } - } while (x == sizeof(buf)); - fclose(in); - - if ((err = pmac_done(&pmac, out, outlen)) != CRYPT_OK) { - return err; - } - -#ifdef CLEAN_STACK - zeromem(buf, sizeof(buf)); -#endif - - return CRYPT_OK; -#endif -} - -int pmac_test(void) -{ -#if !defined(LTC_TEST) - return CRYPT_NOP; -#else - static const struct { - int msglen; - unsigned char key[16], msg[34], tag[16]; - } tests[] = { - - /* PMAC-AES-128-0B */ -{ - 0, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* msg */ - { 0x00 }, - /* tag */ - { 0x43, 0x99, 0x57, 0x2c, 0xd6, 0xea, 0x53, 0x41, - 0xb8, 0xd3, 0x58, 0x76, 0xa7, 0x09, 0x8a, 0xf7 } -}, - - /* PMAC-AES-128-3B */ -{ - 3, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* msg */ - { 0x00, 0x01, 0x02 }, - /* tag */ - { 0x25, 0x6b, 0xa5, 0x19, 0x3c, 0x1b, 0x99, 0x1b, - 0x4d, 0xf0, 0xc5, 0x1f, 0x38, 0x8a, 0x9e, 0x27 } -}, - - /* PMAC-AES-128-16B */ -{ - 16, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* msg */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* tag */ - { 0xeb, 0xbd, 0x82, 0x2f, 0xa4, 0x58, 0xda, 0xf6, - 0xdf, 0xda, 0xd7, 0xc2, 0x7d, 0xa7, 0x63, 0x38 } -}, - - /* PMAC-AES-128-20B */ -{ - 20, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* msg */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13 }, - /* tag */ - { 0x04, 0x12, 0xca, 0x15, 0x0b, 0xbf, 0x79, 0x05, - 0x8d, 0x8c, 0x75, 0xa5, 0x8c, 0x99, 0x3f, 0x55 } -}, - - /* PMAC-AES-128-32B */ -{ - 32, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* msg */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, - /* tag */ - { 0xe9, 0x7a, 0xc0, 0x4e, 0x9e, 0x5e, 0x33, 0x99, - 0xce, 0x53, 0x55, 0xcd, 0x74, 0x07, 0xbc, 0x75 } -}, - - /* PMAC-AES-128-34B */ -{ - 34, - /* key */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, - /* msg */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21 }, - /* tag */ - { 0x5c, 0xba, 0x7d, 0x5e, 0xb2, 0x4f, 0x7c, 0x86, - 0xcc, 0xc5, 0x46, 0x04, 0xe5, 0x3d, 0x55, 0x12 } -} - -}; - int err, x, idx; - unsigned long len; - unsigned char outtag[MAXBLOCKSIZE]; - - /* AES can be under rijndael or aes... try to find it */ - if ((idx = find_cipher("aes")) == -1) { - if ((idx = find_cipher("rijndael")) == -1) { - return CRYPT_NOP; - } - } - - for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { - len = sizeof(outtag); - if ((err = pmac_memory(idx, tests[x].key, 16, tests[x].msg, tests[x].msglen, outtag, &len)) != CRYPT_OK) { - return err; - } - - if (memcmp(outtag, tests[x].tag, len)) { -#if 0 - unsigned long y; - printf("\nTAG:\n"); - for (y = 0; y < len; ) { - printf("0x%02x", outtag[y]); - if (y < len-1) printf(", "); - if (!(++y % 8)) printf("\n"); - } -#endif - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; -#endif /* LTC_TEST */ -} - -#endif /* PMAC_MODE */ - - - diff --git a/pmac_done.c b/pmac_done.c new file mode 100644 index 0000000..8051da7 --- /dev/null +++ b/pmac_done.c @@ -0,0 +1,64 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* PMAC implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef PMAC + +int pmac_done(pmac_state *state, unsigned char *out, unsigned long *outlen) +{ + int err, x; + + _ARGCHK(state != NULL); + _ARGCHK(out != NULL); + if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) { + return err; + } + + if ((state->buflen > (int)sizeof(state->block)) || (state->buflen < 0) || + (state->block_len > (int)sizeof(state->block)) || (state->buflen > state->block_len)) { + return CRYPT_INVALID_ARG; + } + + + /* handle padding. If multiple xor in L/x */ + + if (state->buflen == state->block_len) { + /* xor Lr against the checksum */ + for (x = 0; x < state->block_len; x++) { + state->checksum[x] ^= state->block[x] ^ state->Lr[x]; + } + } else { + /* otherwise xor message bytes then the 0x80 byte */ + for (x = 0; x < state->buflen; x++) { + state->checksum[x] ^= state->block[x]; + } + state->checksum[x] ^= 0x80; + } + + /* encrypt it */ + cipher_descriptor[state->cipher_idx].ecb_encrypt(state->checksum, state->checksum, &state->key); + + /* store it */ + for (x = 0; x < state->block_len && x <= (int)*outlen; x++) { + out[x] = state->checksum[x]; + } + *outlen = x; + +#ifdef CLEAN_STACK + zeromem(state, sizeof(*state)); +#endif + return CRYPT_OK; +} + +#endif + diff --git a/pmac_file.c b/pmac_file.c new file mode 100644 index 0000000..c664a09 --- /dev/null +++ b/pmac_file.c @@ -0,0 +1,67 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* PMAC implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef PMAC + +int pmac_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen) +{ +#ifdef NO_FILE + return CRYPT_NOP; +#else + int err, x; + pmac_state pmac; + FILE *in; + unsigned char buf[512]; + + + _ARGCHK(key != NULL); + _ARGCHK(filename != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + in = fopen(filename, "rb"); + if (in == NULL) { + return CRYPT_FILE_NOTFOUND; + } + + if ((err = pmac_init(&pmac, cipher, key, keylen)) != CRYPT_OK) { + fclose(in); + return err; + } + + do { + x = fread(buf, 1, sizeof(buf), in); + if ((err = pmac_process(&pmac, buf, x)) != CRYPT_OK) { + fclose(in); + return err; + } + } while (x == sizeof(buf)); + fclose(in); + + if ((err = pmac_done(&pmac, out, outlen)) != CRYPT_OK) { + return err; + } + +#ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + + return CRYPT_OK; +#endif +} + +#endif diff --git a/pmac_init.c b/pmac_init.c new file mode 100644 index 0000000..b4ef111 --- /dev/null +++ b/pmac_init.c @@ -0,0 +1,114 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* PMAC implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef PMAC + +static const struct { + int len; + unsigned char poly_div[MAXBLOCKSIZE], + poly_mul[MAXBLOCKSIZE]; +} polys[] = { +{ + 8, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } +}, { + 16, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 } +} +}; + +int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen) +{ + int poly, x, y, m, err; + unsigned char L[MAXBLOCKSIZE]; + + _ARGCHK(pmac != NULL); + _ARGCHK(key != NULL); + + /* valid cipher? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* determine which polys to use */ + pmac->block_len = cipher_descriptor[cipher].block_length; + for (poly = 0; poly < (int)(sizeof(polys)/sizeof(polys[0])); poly++) { + if (polys[poly].len == pmac->block_len) { + break; + } + } + if (polys[poly].len != pmac->block_len) { + return CRYPT_INVALID_ARG; + } + + /* schedule the key */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &pmac->key)) != CRYPT_OK) { + return err; + } + + /* find L = E[0] */ + zeromem(L, pmac->block_len); + cipher_descriptor[cipher].ecb_encrypt(L, L, &pmac->key); + + /* find Ls[i] = L << i for i == 0..31 */ + memcpy(pmac->Ls[0], L, pmac->block_len); + for (x = 1; x < 32; x++) { + m = pmac->Ls[x-1][0] >> 7; + for (y = 0; y < pmac->block_len-1; y++) { + pmac->Ls[x][y] = ((pmac->Ls[x-1][y] << 1) | (pmac->Ls[x-1][y+1] >> 7)) & 255; + } + pmac->Ls[x][pmac->block_len-1] = (pmac->Ls[x-1][pmac->block_len-1] << 1) & 255; + + if (m == 1) { + for (y = 0; y < pmac->block_len; y++) { + pmac->Ls[x][y] ^= polys[poly].poly_mul[y]; + } + } + } + + /* find Lr = L / x */ + m = L[pmac->block_len-1] & 1; + + /* shift right */ + for (x = pmac->block_len - 1; x > 0; x--) { + pmac->Lr[x] = ((L[x] >> 1) | (L[x-1] << 7)) & 255; + } + pmac->Lr[0] = L[0] >> 1; + + if (m == 1) { + for (x = 0; x < pmac->block_len; x++) { + pmac->Lr[x] ^= polys[poly].poly_div[x]; + } + } + + /* zero buffer, counters, etc... */ + pmac->block_index = 1; + pmac->cipher_idx = cipher; + pmac->buflen = 0; + zeromem(pmac->block, sizeof(pmac->block)); + zeromem(pmac->Li, sizeof(pmac->Li)); + zeromem(pmac->checksum, sizeof(pmac->checksum)); + +#ifdef CLEAN_STACK + zeromem(L, sizeof(L)); +#endif + + return CRYPT_OK; +} + +#endif diff --git a/pmac_memory.c b/pmac_memory.c new file mode 100644 index 0000000..c279d71 --- /dev/null +++ b/pmac_memory.c @@ -0,0 +1,44 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* PMAC implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef PMAC + +int pmac_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *msg, unsigned long msglen, + unsigned char *out, unsigned long *outlen) +{ + int err; + pmac_state pmac; + + _ARGCHK(key != NULL); + _ARGCHK(msg != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + + if ((err = pmac_init(&pmac, cipher, key, keylen)) != CRYPT_OK) { + return err; + } + if ((err = pmac_process(&pmac, msg, msglen)) != CRYPT_OK) { + return err; + } + if ((err = pmac_done(&pmac, out, outlen)) != CRYPT_OK) { + return err; + } + + return CRYPT_OK; +} + +#endif diff --git a/pmac_ntz.c b/pmac_ntz.c new file mode 100644 index 0000000..98ec430 --- /dev/null +++ b/pmac_ntz.c @@ -0,0 +1,29 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* PMAC implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef PMAC + +int pmac_ntz(unsigned long x) +{ + int c; + x &= 0xFFFFFFFFUL; + c = 0; + while ((x & 1) == 0) { + ++c; + x >>= 1; + } + return c; +} + +#endif diff --git a/pmac_process.c b/pmac_process.c new file mode 100644 index 0000000..ff2c3fe --- /dev/null +++ b/pmac_process.c @@ -0,0 +1,62 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* PMAC implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef PMAC + +int pmac_process(pmac_state *state, const unsigned char *buf, unsigned long len) +{ + int err, n, x; + unsigned char Z[MAXBLOCKSIZE]; + + _ARGCHK(state != NULL); + _ARGCHK(buf != NULL); + if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) { + return err; + } + + if ((state->buflen > (int)sizeof(state->block)) || (state->buflen < 0) || + (state->block_len > (int)sizeof(state->block)) || (state->buflen > state->block_len)) { + return CRYPT_INVALID_ARG; + } + + while (len != 0) { + /* ok if the block is full we xor in prev, encrypt and replace prev */ + if (state->buflen == state->block_len) { + pmac_shift_xor(state); + for (x = 0; x < state->block_len; x++) { + Z[x] = state->Li[x] ^ state->block[x]; + } + cipher_descriptor[state->cipher_idx].ecb_encrypt(Z, Z, &state->key); + for (x = 0; x < state->block_len; x++) { + state->checksum[x] ^= Z[x]; + } + state->buflen = 0; + } + + /* add bytes */ + n = MIN(len, (unsigned long)(state->block_len - state->buflen)); + memcpy(state->block + state->buflen, buf, n); + state->buflen += n; + len -= n; + buf += n; + } + +#ifdef CLEAN_STACK + zeromem(Z, sizeof(Z)); +#endif + + return CRYPT_OK; +} + +#endif diff --git a/pmac_shift_xor.c b/pmac_shift_xor.c new file mode 100644 index 0000000..46159fb --- /dev/null +++ b/pmac_shift_xor.c @@ -0,0 +1,26 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* PMAC implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef PMAC + +void pmac_shift_xor(pmac_state *pmac) +{ + int x, y; + y = pmac_ntz(pmac->block_index++); + for (x = 0; x < pmac->block_len; x++) { + pmac->Li[x] ^= pmac->Ls[y][x]; + } +} + +#endif diff --git a/pmac_test.c b/pmac_test.c new file mode 100644 index 0000000..e813eb5 --- /dev/null +++ b/pmac_test.c @@ -0,0 +1,153 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* PMAC implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef PMAC + +int pmac_test(void) +{ +#if !defined(LTC_TEST) + return CRYPT_NOP; +#else + static const struct { + int msglen; + unsigned char key[16], msg[34], tag[16]; + } tests[] = { + + /* PMAC-AES-128-0B */ +{ + 0, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00 }, + /* tag */ + { 0x43, 0x99, 0x57, 0x2c, 0xd6, 0xea, 0x53, 0x41, + 0xb8, 0xd3, 0x58, 0x76, 0xa7, 0x09, 0x8a, 0xf7 } +}, + + /* PMAC-AES-128-3B */ +{ + 3, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00, 0x01, 0x02 }, + /* tag */ + { 0x25, 0x6b, 0xa5, 0x19, 0x3c, 0x1b, 0x99, 0x1b, + 0x4d, 0xf0, 0xc5, 0x1f, 0x38, 0x8a, 0x9e, 0x27 } +}, + + /* PMAC-AES-128-16B */ +{ + 16, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* tag */ + { 0xeb, 0xbd, 0x82, 0x2f, 0xa4, 0x58, 0xda, 0xf6, + 0xdf, 0xda, 0xd7, 0xc2, 0x7d, 0xa7, 0x63, 0x38 } +}, + + /* PMAC-AES-128-20B */ +{ + 20, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 }, + /* tag */ + { 0x04, 0x12, 0xca, 0x15, 0x0b, 0xbf, 0x79, 0x05, + 0x8d, 0x8c, 0x75, 0xa5, 0x8c, 0x99, 0x3f, 0x55 } +}, + + /* PMAC-AES-128-32B */ +{ + 32, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + /* tag */ + { 0xe9, 0x7a, 0xc0, 0x4e, 0x9e, 0x5e, 0x33, 0x99, + 0xce, 0x53, 0x55, 0xcd, 0x74, 0x07, 0xbc, 0x75 } +}, + + /* PMAC-AES-128-34B */ +{ + 34, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21 }, + /* tag */ + { 0x5c, 0xba, 0x7d, 0x5e, 0xb2, 0x4f, 0x7c, 0x86, + 0xcc, 0xc5, 0x46, 0x04, 0xe5, 0x3d, 0x55, 0x12 } +} + +}; + int err, x, idx; + unsigned long len; + unsigned char outtag[MAXBLOCKSIZE]; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + len = sizeof(outtag); + if ((err = pmac_memory(idx, tests[x].key, 16, tests[x].msg, tests[x].msglen, outtag, &len)) != CRYPT_OK) { + return err; + } + + if (memcmp(outtag, tests[x].tag, len)) { +#if 0 + unsigned long y; + printf("\nTAG:\n"); + for (y = 0; y < len; ) { + printf("0x%02x", outtag[y]); + if (y < len-1) printf(", "); + if (!(++y % 8)) printf("\n"); + } +#endif + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif /* LTC_TEST */ +} + +#endif /* PMAC_MODE */ + + + diff --git a/prime.c b/rand_prime.c similarity index 71% rename from prime.c rename to rand_prime.c index 64d6eb9..2834c6a 100644 --- a/prime.c +++ b/rand_prime.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -17,21 +17,6 @@ struct rng_data { int wprng; }; - -#define UPPER_LIMIT PRIME_SIZE - -/* figures out if a number is prime (MR test) */ -int is_prime(mp_int *N, int *result) -{ - int err; - _ARGCHK(N != NULL); - _ARGCHK(result != NULL); - if ((err = mp_prime_is_prime(N, mp_prime_rabin_miller_trials(mp_count_bits(N)), result)) != MP_OKAY) { - return mpi_to_ltc_error(err); - } - return CRYPT_OK; -} - static int rand_prime_helper(unsigned char *dst, int len, void *dat) { return (int)prng_descriptor[((struct rng_data *)dat)->wprng].read(dst, len, ((struct rng_data *)dat)->prng); @@ -45,7 +30,7 @@ int rand_prime(mp_int *N, long len, prng_state *prng, int wprng) _ARGCHK(N != NULL); /* allow sizes between 2 and 256 bytes for a prime size */ - if (len < 2 || len > 256) { + if (len < 16 || len > 4096) { return CRYPT_INVALID_PRIME_SIZE; } @@ -60,7 +45,7 @@ int rand_prime(mp_int *N, long len, prng_state *prng, int wprng) /* get type */ if (len < 0) { - type = 1; + type = LTM_PRIME_BBS; len = -len; } else { type = 0; @@ -69,7 +54,7 @@ int rand_prime(mp_int *N, long len, prng_state *prng, int wprng) /* New prime generation makes the code even more cryptoish-insane. Do you know what this means!!! -- Gir: Yeah, oh wait, er, no. */ - if ((err = mp_prime_random(N, mp_prime_rabin_miller_trials(len*8), len, type, rand_prime_helper, &rng)) != MP_OKAY) { + if ((err = mp_prime_random_ex(N, mp_prime_rabin_miller_trials(len), len, type, rand_prime_helper, &rng)) != MP_OKAY) { return mpi_to_ltc_error(err); } diff --git a/rc2.c b/rc2.c index fbb4bc1..a8f1d2d 100644 --- a/rc2.c +++ b/rc2.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -69,7 +69,7 @@ int rc2_setup(const unsigned char *key, int keylen, int rounds, symmetric_key *s unsigned T8, TM; int i, bits; - _ARGCHK(key != NULL); + _ARGCHK(key != NULL); _ARGCHK(skey != NULL); if (keylen < 8 || keylen > 128) { diff --git a/rc4.c b/rc4.c index 2521cfb..9d2f6b7 100644 --- a/rc4.c +++ b/rc4.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/rc5.c b/rc5.c index 2f97e28..ab79535 100644 --- a/rc5.c +++ b/rc5.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -46,9 +46,8 @@ int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_ke ulong32 L[64], *S, A, B, i, j, v, s, t, l; _ARGCHK(skey != NULL); - _ARGCHK(key != NULL); + _ARGCHK(key != NULL); - /* test parameters */ if (num_rounds == 0) { num_rounds = rc5_desc.default_rounds; diff --git a/rc6.c b/rc6.c index adb631c..8cc165c 100644 --- a/rc6.c +++ b/rc6.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -252,6 +252,23 @@ int rc6_test(void) /* compare */ if (memcmp(tmp[0], tests[x].ct, 16) || memcmp(tmp[1], tests[x].pt, 16)) { +#if 0 + printf("\n\nFailed test %d\n", x); + if (memcmp(tmp[0], tests[x].ct, 16)) { + printf("Ciphertext: "); + for (y = 0; y < 16; y++) printf("%02x ", tmp[0][y]); + printf("\nExpected : "); + for (y = 0; y < 16; y++) printf("%02x ", tests[x].ct[y]); + printf("\n"); + } + if (memcmp(tmp[1], tests[x].pt, 16)) { + printf("Plaintext: "); + for (y = 0; y < 16; y++) printf("%02x ", tmp[0][y]); + printf("\nExpected : "); + for (y = 0; y < 16; y++) printf("%02x ", tests[x].pt[y]); + printf("\n"); + } +#endif return CRYPT_FAIL_TESTVECTOR; } diff --git a/rmd128.c b/rmd128.c index aff0c62..4aaf8d5 100644 --- a/rmd128.c +++ b/rmd128.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -77,7 +77,7 @@ static void rmd128_compress(hash_state *md, unsigned char *buf) { ulong32 aa,bb,cc,dd,aaa,bbb,ccc,ddd,X[16]; int i; - + /* load words X */ for (i = 0; i < 16; i++){ LOAD32L(X[i], buf + (4 * i)); @@ -313,6 +313,9 @@ int rmd128_done(hash_state * md, unsigned char *hash) int rmd128_test(void) { +#ifndef LTC_TEST + return CRYPT_NOP; +#else static const struct { char *msg; unsigned char md[16]; @@ -358,6 +361,7 @@ int rmd128_test(void) } } return CRYPT_OK; +#endif } #endif diff --git a/rmd160.c b/rmd160.c index ef917fa..93a2cab 100644 --- a/rmd160.c +++ b/rmd160.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -372,6 +372,9 @@ int rmd160_done(hash_state * md, unsigned char *hash) int rmd160_test(void) { +#ifndef LTC_TEST + return CRYPT_NOP; +#else static const struct { char *msg; unsigned char md[20]; @@ -417,6 +420,7 @@ int rmd160_test(void) } } return CRYPT_OK; +#endif } #endif diff --git a/bits.c b/rng_get_bytes.c similarity index 77% rename from bits.c rename to rng_get_bytes.c index b3e14fd..f3027cd 100644 --- a/bits.c +++ b/rng_get_bytes.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -127,44 +127,3 @@ unsigned long rng_get_bytes(unsigned char *buf, unsigned long len, #endif return 0; } - -int rng_make_prng(int bits, int wprng, prng_state *prng, - void (*callback)(void)) -{ - unsigned char buf[256]; - int err; - - _ARGCHK(prng != NULL); - - /* check parameter */ - if ((err = prng_is_valid(wprng)) != CRYPT_OK) { - return err; - } - - if (bits < 64 || bits > 1024) { - return CRYPT_INVALID_PRNGSIZE; - } - - if ((err = prng_descriptor[wprng].start(prng)) != CRYPT_OK) { - return err; - } - - bits = ((bits/8)+((bits&7)!=0?1:0)) * 2; - if (rng_get_bytes(buf, (unsigned long)bits, callback) != (unsigned long)bits) { - return CRYPT_ERROR_READPRNG; - } - - if ((err = prng_descriptor[wprng].add_entropy(buf, (unsigned long)bits, prng)) != CRYPT_OK) { - return err; - } - - if ((err = prng_descriptor[wprng].ready(prng)) != CRYPT_OK) { - return err; - } - - #ifdef CLEAN_STACK - zeromem(buf, sizeof(buf)); - #endif - return CRYPT_OK; -} - diff --git a/rng_make_prng.c b/rng_make_prng.c new file mode 100644 index 0000000..4c30e69 --- /dev/null +++ b/rng_make_prng.c @@ -0,0 +1,53 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +/* portable way to get secure random bits to feed a PRNG */ +#include "mycrypt.h" + +int rng_make_prng(int bits, int wprng, prng_state *prng, + void (*callback)(void)) +{ + unsigned char buf[256]; + int err; + + _ARGCHK(prng != NULL); + + /* check parameter */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + if (bits < 64 || bits > 1024) { + return CRYPT_INVALID_PRNGSIZE; + } + + if ((err = prng_descriptor[wprng].start(prng)) != CRYPT_OK) { + return err; + } + + bits = ((bits/8)+((bits&7)!=0?1:0)) * 2; + if (rng_get_bytes(buf, (unsigned long)bits, callback) != (unsigned long)bits) { + return CRYPT_ERROR_READPRNG; + } + + if ((err = prng_descriptor[wprng].add_entropy(buf, (unsigned long)bits, prng)) != CRYPT_OK) { + return err; + } + + if ((err = prng_descriptor[wprng].ready(prng)) != CRYPT_OK) { + return err; + } + + #ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); + #endif + return CRYPT_OK; +} + diff --git a/rsa.c b/rsa.c index 6b97c7f..05190fd 100644 --- a/rsa.c +++ b/rsa.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -12,188 +12,8 @@ /* RSA Code by Tom St Denis */ #include "mycrypt.h" -/* Min and Max RSA key sizes (in bits) */ -#define MIN_RSA_SIZE 1024 -#define MAX_RSA_SIZE 4096 - -/* Stack required for temps (plus padding) */ -#define RSA_STACK (8 + (MAX_RSA_SIZE/8)) - #ifdef MRSA -int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) -{ - mp_int p, q, tmp1, tmp2, tmp3; - int err; - - _ARGCHK(key != NULL); - - if ((size < (MIN_RSA_SIZE/8)) || (size > (MAX_RSA_SIZE/8))) { - return CRYPT_INVALID_KEYSIZE; - } - - if ((e < 3) || ((e & 1) == 0)) { - return CRYPT_INVALID_ARG; - } - - if ((err = prng_is_valid(wprng)) != CRYPT_OK) { - return err; - } - - if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY) { - return mpi_to_ltc_error(err); - } - - /* make primes p and q (optimization provided by Wayne Scott) */ - if ((err = mp_set_int(&tmp3, e)) != MP_OKAY) { goto error; } /* tmp3 = e */ - - /* make prime "p" */ - do { - if ((err = rand_prime(&p, size/2, prng, wprng)) != CRYPT_OK) { goto done; } - if ((err = mp_sub_d(&p, 1, &tmp1)) != MP_OKAY) { goto error; } /* tmp1 = p-1 */ - if ((err = mp_gcd(&tmp1, &tmp3, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = gcd(p-1, e) */ - } while (mp_cmp_d(&tmp2, 1) != 0); /* while e divides p-1 */ - - /* make prime "q" */ - do { - if ((err = rand_prime(&q, size/2, prng, wprng)) != CRYPT_OK) { goto done; } - if ((err = mp_sub_d(&q, 1, &tmp1)) != MP_OKAY) { goto error; } /* tmp1 = q-1 */ - if ((err = mp_gcd(&tmp1, &tmp3, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = gcd(q-1, e) */ - } while (mp_cmp_d(&tmp2, 1) != 0); /* while e divides q-1 */ - - /* tmp1 = lcm(p-1, q-1) */ - if ((err = mp_sub_d(&p, 1, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = p-1 */ - /* tmp1 = q-1 (previous do/while loop) */ - if ((err = mp_lcm(&tmp1, &tmp2, &tmp1)) != MP_OKAY) { goto error; } /* tmp1 = lcm(p-1, q-1) */ - - /* make key */ - if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, - &key->qP, &key->pQ, &key->p, &key->q, NULL)) != MP_OKAY) { - goto error; - } - - if ((err = mp_set_int(&key->e, e)) != MP_OKAY) { goto error2; } /* key->e = e */ - if ((err = mp_invmod(&key->e, &tmp1, &key->d)) != MP_OKAY) { goto error2; } /* key->d = 1/e mod lcm(p-1,q-1) */ - if ((err = mp_mul(&p, &q, &key->N)) != MP_OKAY) { goto error2; } /* key->N = pq */ - -/* optimize for CRT now */ - /* find d mod q-1 and d mod p-1 */ - if ((err = mp_sub_d(&p, 1, &tmp1)) != MP_OKAY) { goto error2; } /* tmp1 = q-1 */ - if ((err = mp_sub_d(&q, 1, &tmp2)) != MP_OKAY) { goto error2; } /* tmp2 = p-1 */ - - if ((err = mp_mod(&key->d, &tmp1, &key->dP)) != MP_OKAY) { goto error2; } /* dP = d mod p-1 */ - if ((err = mp_mod(&key->d, &tmp2, &key->dQ)) != MP_OKAY) { goto error2; } /* dQ = d mod q-1 */ - - if ((err = mp_invmod(&q, &p, &key->qP)) != MP_OKAY) { goto error2; } /* qP = 1/q mod p */ - if ((err = mp_mulmod(&key->qP, &q, &key->N, &key->qP)) != MP_OKAY) { goto error2; } /* qP = q * (1/q mod p) mod N */ - - if ((err = mp_invmod(&p, &q, &key->pQ)) != MP_OKAY) { goto error2; } /* pQ = 1/p mod q */ - if ((err = mp_mulmod(&key->pQ, &p, &key->N, &key->pQ)) != MP_OKAY) { goto error2; } /* pQ = p * (1/p mod q) mod N */ - - if ((err = mp_copy(&p, &key->p)) != MP_OKAY) { goto error2; } - if ((err = mp_copy(&q, &key->q)) != MP_OKAY) { goto error2; } - - /* shrink ram required */ - if ((err = mp_shrink(&key->e)) != MP_OKAY) { goto error2; } - if ((err = mp_shrink(&key->d)) != MP_OKAY) { goto error2; } - if ((err = mp_shrink(&key->N)) != MP_OKAY) { goto error2; } - if ((err = mp_shrink(&key->dQ)) != MP_OKAY) { goto error2; } - if ((err = mp_shrink(&key->dP)) != MP_OKAY) { goto error2; } - if ((err = mp_shrink(&key->qP)) != MP_OKAY) { goto error2; } - if ((err = mp_shrink(&key->pQ)) != MP_OKAY) { goto error2; } - if ((err = mp_shrink(&key->p)) != MP_OKAY) { goto error2; } - if ((err = mp_shrink(&key->q)) != MP_OKAY) { goto error2; } - - err = CRYPT_OK; - key->type = PK_PRIVATE_OPTIMIZED; - goto done; -error2: - mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP, - &key->qP, &key->pQ, &key->p, &key->q, NULL); -error: - err = mpi_to_ltc_error(err); -done: - mp_clear_multi(&tmp3, &tmp2, &tmp1, &p, &q, NULL); - return err; -} - -void rsa_free(rsa_key *key) -{ - _ARGCHK(key != NULL); - mp_clear_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, - &key->qP, &key->pQ, &key->p, &key->q, NULL); -} - -int rsa_exptmod(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, int which, - rsa_key *key) -{ - mp_int tmp, tmpa, tmpb; - unsigned long x; - int err; - - _ARGCHK(in != NULL); - _ARGCHK(out != NULL); - _ARGCHK(outlen != NULL); - _ARGCHK(key != NULL); - - if (which == PK_PRIVATE && (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED)) { - return CRYPT_PK_NOT_PRIVATE; - } - - /* must be a private or public operation */ - if (which != PK_PRIVATE && which != PK_PUBLIC) { - return CRYPT_PK_INVALID_TYPE; - } - - /* init and copy into tmp */ - if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != MP_OKAY) { goto error; } - if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, (int)inlen)) != MP_OKAY) { goto error; } - - /* sanity check on the input */ - if (mp_cmp(&key->N, &tmp) == MP_LT) { - err = CRYPT_PK_INVALID_SIZE; - goto done; - } - - /* are we using the private exponent and is the key optimized? */ - if (which == PK_PRIVATE && key->type == PK_PRIVATE_OPTIMIZED) { - /* tmpa = tmp^dP mod p */ - if ((err = mp_exptmod(&tmp, &key->dP, &key->p, &tmpa)) != MP_OKAY) { goto error; } - - /* tmpb = tmp^dQ mod q */ - if ((err = mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb)) != MP_OKAY) { goto error; } - - /* tmp = tmpa*qP + tmpb*pQ mod N */ - if ((err = mp_mul(&tmpa, &key->qP, &tmpa)) != MP_OKAY) { goto error; } - if ((err = mp_mul(&tmpb, &key->pQ, &tmpb)) != MP_OKAY) { goto error; } - if ((err = mp_addmod(&tmpa, &tmpb, &key->N, &tmp)) != MP_OKAY) { goto error; } - } else { - /* exptmod it */ - if ((err = mp_exptmod(&tmp, which==PK_PRIVATE?&key->d:&key->e, &key->N, &tmp)) != MP_OKAY) { goto error; } - } - - /* read it back */ - x = (unsigned long)mp_unsigned_bin_size(&tmp); - if (x > *outlen) { - err = CRYPT_BUFFER_OVERFLOW; - goto done; - } - *outlen = x; - - /* convert it */ - if ((err = mp_to_unsigned_bin(&tmp, out)) != MP_OKAY) { goto error; } - - /* clean up and return */ - err = CRYPT_OK; - goto done; -error: - err = mpi_to_ltc_error(err); -done: - mp_clear_multi(&tmp, &tmpa, &tmpb, NULL); - return err; -} - int rsa_signpad(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { @@ -208,7 +28,7 @@ int rsa_signpad(const unsigned char *in, unsigned long inlen, } /* check inlen */ - if (inlen > 512) { + if (inlen > MAX_RSA_SIZE/8) { return CRYPT_PK_INVALID_SIZE; } @@ -411,24 +231,24 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) key->type = (int)in[y++]; /* load the modulus */ - INPUT_BIGNUM(&key->N, in, x, y); + INPUT_BIGNUM(&key->N, in, x, y, inlen); /* load public exponent */ - INPUT_BIGNUM(&key->e, in, x, y); + INPUT_BIGNUM(&key->e, in, x, y, inlen); /* get private exponent */ if (key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) { - INPUT_BIGNUM(&key->d, in, x, y); + INPUT_BIGNUM(&key->d, in, x, y, inlen); } /* get CRT private data if required */ if (key->type == PK_PRIVATE_OPTIMIZED) { - INPUT_BIGNUM(&key->dQ, in, x, y); - INPUT_BIGNUM(&key->dP, in, x, y); - INPUT_BIGNUM(&key->pQ, in, x, y); - INPUT_BIGNUM(&key->qP, in, x, y); - INPUT_BIGNUM(&key->p, in, x, y); - INPUT_BIGNUM(&key->q, in, x, y); + INPUT_BIGNUM(&key->dQ, in, x, y, inlen); + INPUT_BIGNUM(&key->dP, in, x, y, inlen); + INPUT_BIGNUM(&key->pQ, in, x, y, inlen); + INPUT_BIGNUM(&key->qP, in, x, y, inlen); + INPUT_BIGNUM(&key->p, in, x, y, inlen); + INPUT_BIGNUM(&key->q, in, x, y, inlen); } /* free up ram not required */ diff --git a/rsa_exptmod.c b/rsa_exptmod.c new file mode 100644 index 0000000..b794718 --- /dev/null +++ b/rsa_exptmod.c @@ -0,0 +1,87 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* RSA Code by Tom St Denis */ +#include "mycrypt.h" + +#ifdef MRSA + +int rsa_exptmod(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + rsa_key *key) +{ + mp_int tmp, tmpa, tmpb; + unsigned long x; + int err; + + _ARGCHK(in != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + _ARGCHK(key != NULL); + + if (which == PK_PRIVATE && (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED)) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* must be a private or public operation */ + if (which != PK_PRIVATE && which != PK_PUBLIC) { + return CRYPT_PK_INVALID_TYPE; + } + + /* init and copy into tmp */ + if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != MP_OKAY) { goto error; } + if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, (int)inlen)) != MP_OKAY) { goto error; } + + /* sanity check on the input */ + if (mp_cmp(&key->N, &tmp) == MP_LT) { + err = CRYPT_PK_INVALID_SIZE; + goto done; + } + + /* are we using the private exponent and is the key optimized? */ + if (which == PK_PRIVATE && key->type == PK_PRIVATE_OPTIMIZED) { + /* tmpa = tmp^dP mod p */ + if ((err = mp_exptmod(&tmp, &key->dP, &key->p, &tmpa)) != MP_OKAY) { goto error; } + + /* tmpb = tmp^dQ mod q */ + if ((err = mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb)) != MP_OKAY) { goto error; } + + /* tmp = tmpa*qP + tmpb*pQ mod N */ + if ((err = mp_mul(&tmpa, &key->qP, &tmpa)) != MP_OKAY) { goto error; } + if ((err = mp_mul(&tmpb, &key->pQ, &tmpb)) != MP_OKAY) { goto error; } + if ((err = mp_addmod(&tmpa, &tmpb, &key->N, &tmp)) != MP_OKAY) { goto error; } + } else { + /* exptmod it */ + if ((err = mp_exptmod(&tmp, which==PK_PRIVATE?&key->d:&key->e, &key->N, &tmp)) != MP_OKAY) { goto error; } + } + + /* read it back */ + x = (unsigned long)mp_unsigned_bin_size(&tmp); + if (x > *outlen) { + err = CRYPT_BUFFER_OVERFLOW; + goto done; + } + *outlen = x; + + /* convert it */ + if ((err = mp_to_unsigned_bin(&tmp, out)) != MP_OKAY) { goto error; } + + /* clean up and return */ + err = CRYPT_OK; + goto done; +error: + err = mpi_to_ltc_error(err); +done: + mp_clear_multi(&tmp, &tmpa, &tmpb, NULL); + return err; +} + +#endif diff --git a/rsa_free.c b/rsa_free.c new file mode 100644 index 0000000..c97242b --- /dev/null +++ b/rsa_free.c @@ -0,0 +1,24 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* RSA Code by Tom St Denis */ +#include "mycrypt.h" + +#ifdef MRSA + +void rsa_free(rsa_key *key) +{ + _ARGCHK(key != NULL); + mp_clear_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, + &key->qP, &key->pQ, &key->p, &key->q, NULL); +} + +#endif diff --git a/rsa_make_key.c b/rsa_make_key.c new file mode 100644 index 0000000..56773ff --- /dev/null +++ b/rsa_make_key.c @@ -0,0 +1,113 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* RSA Code by Tom St Denis */ +#include "mycrypt.h" + +#ifdef MRSA + +int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) +{ + mp_int p, q, tmp1, tmp2, tmp3; + int err; + + _ARGCHK(key != NULL); + + if ((size < (MIN_RSA_SIZE/8)) || (size > (MAX_RSA_SIZE/8))) { + return CRYPT_INVALID_KEYSIZE; + } + + if ((e < 3) || ((e & 1) == 0)) { + return CRYPT_INVALID_ARG; + } + + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY) { + return mpi_to_ltc_error(err); + } + + /* make primes p and q (optimization provided by Wayne Scott) */ + if ((err = mp_set_int(&tmp3, e)) != MP_OKAY) { goto error; } /* tmp3 = e */ + + /* make prime "p" */ + do { + if ((err = rand_prime(&p, size*4, prng, wprng)) != CRYPT_OK) { goto done; } + if ((err = mp_sub_d(&p, 1, &tmp1)) != MP_OKAY) { goto error; } /* tmp1 = p-1 */ + if ((err = mp_gcd(&tmp1, &tmp3, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = gcd(p-1, e) */ + } while (mp_cmp_d(&tmp2, 1) != 0); /* while e divides p-1 */ + + /* make prime "q" */ + do { + if ((err = rand_prime(&q, size*4, prng, wprng)) != CRYPT_OK) { goto done; } + if ((err = mp_sub_d(&q, 1, &tmp1)) != MP_OKAY) { goto error; } /* tmp1 = q-1 */ + if ((err = mp_gcd(&tmp1, &tmp3, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = gcd(q-1, e) */ + } while (mp_cmp_d(&tmp2, 1) != 0); /* while e divides q-1 */ + + /* tmp1 = lcm(p-1, q-1) */ + if ((err = mp_sub_d(&p, 1, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = p-1 */ + /* tmp1 = q-1 (previous do/while loop) */ + if ((err = mp_lcm(&tmp1, &tmp2, &tmp1)) != MP_OKAY) { goto error; } /* tmp1 = lcm(p-1, q-1) */ + + /* make key */ + if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, + &key->qP, &key->pQ, &key->p, &key->q, NULL)) != MP_OKAY) { + goto error; + } + + if ((err = mp_set_int(&key->e, e)) != MP_OKAY) { goto error2; } /* key->e = e */ + if ((err = mp_invmod(&key->e, &tmp1, &key->d)) != MP_OKAY) { goto error2; } /* key->d = 1/e mod lcm(p-1,q-1) */ + if ((err = mp_mul(&p, &q, &key->N)) != MP_OKAY) { goto error2; } /* key->N = pq */ + +/* optimize for CRT now */ + /* find d mod q-1 and d mod p-1 */ + if ((err = mp_sub_d(&p, 1, &tmp1)) != MP_OKAY) { goto error2; } /* tmp1 = q-1 */ + if ((err = mp_sub_d(&q, 1, &tmp2)) != MP_OKAY) { goto error2; } /* tmp2 = p-1 */ + + if ((err = mp_mod(&key->d, &tmp1, &key->dP)) != MP_OKAY) { goto error2; } /* dP = d mod p-1 */ + if ((err = mp_mod(&key->d, &tmp2, &key->dQ)) != MP_OKAY) { goto error2; } /* dQ = d mod q-1 */ + + if ((err = mp_invmod(&q, &p, &key->qP)) != MP_OKAY) { goto error2; } /* qP = 1/q mod p */ + if ((err = mp_mulmod(&key->qP, &q, &key->N, &key->qP)) != MP_OKAY) { goto error2; } /* qP = q * (1/q mod p) mod N */ + + if ((err = mp_invmod(&p, &q, &key->pQ)) != MP_OKAY) { goto error2; } /* pQ = 1/p mod q */ + if ((err = mp_mulmod(&key->pQ, &p, &key->N, &key->pQ)) != MP_OKAY) { goto error2; } /* pQ = p * (1/p mod q) mod N */ + + if ((err = mp_copy(&p, &key->p)) != MP_OKAY) { goto error2; } + if ((err = mp_copy(&q, &key->q)) != MP_OKAY) { goto error2; } + + /* shrink ram required */ + if ((err = mp_shrink(&key->e)) != MP_OKAY) { goto error2; } + if ((err = mp_shrink(&key->d)) != MP_OKAY) { goto error2; } + if ((err = mp_shrink(&key->N)) != MP_OKAY) { goto error2; } + if ((err = mp_shrink(&key->dQ)) != MP_OKAY) { goto error2; } + if ((err = mp_shrink(&key->dP)) != MP_OKAY) { goto error2; } + if ((err = mp_shrink(&key->qP)) != MP_OKAY) { goto error2; } + if ((err = mp_shrink(&key->pQ)) != MP_OKAY) { goto error2; } + if ((err = mp_shrink(&key->p)) != MP_OKAY) { goto error2; } + if ((err = mp_shrink(&key->q)) != MP_OKAY) { goto error2; } + + err = CRYPT_OK; + key->type = PK_PRIVATE_OPTIMIZED; + goto done; +error2: + mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP, + &key->qP, &key->pQ, &key->p, &key->q, NULL); +error: + err = mpi_to_ltc_error(err); +done: + mp_clear_multi(&tmp3, &tmp2, &tmp1, &p, &q, NULL); + return err; +} + +#endif diff --git a/rsa_sys.c b/rsa_sys.c index 37d381f..fd3aa0a 100644 --- a/rsa_sys.c +++ b/rsa_sys.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/s_ocb_done.c b/s_ocb_done.c new file mode 100644 index 0000000..90ed65c --- /dev/null +++ b/s_ocb_done.c @@ -0,0 +1,102 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* OCB Implementation by Tom St Denis */ +#include "mycrypt.h" + +#ifdef OCB_MODE + +/* Since the last block is encrypted in CTR mode the same code can + * be used to finish a decrypt or encrypt stream. The only difference + * is we XOR the final ciphertext into the checksum so we have to xor it + * before we CTR [decrypt] or after [encrypt] + * + * the names pt/ptlen/ct really just mean in/inlen/out but this is the way I wrote it... + */ +int __ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode) + +{ + unsigned char Z[MAXBLOCKSIZE], Y[MAXBLOCKSIZE], X[MAXBLOCKSIZE]; + int err, x; + + _ARGCHK(ocb != NULL); + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + _ARGCHK(tag != NULL); + _ARGCHK(taglen != NULL); + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + return err; + } + if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length || + (int)ptlen > ocb->block_len || (int)ptlen < 0) { + return CRYPT_INVALID_ARG; + } + + /* compute X[m] = len(pt[m]) XOR Lr XOR Z[m] */ + ocb_shift_xor(ocb, X); + memcpy(Z, X, ocb->block_len); + + X[ocb->block_len-1] ^= (ptlen*8)&255; + X[ocb->block_len-2] ^= ((ptlen*8)>>8)&255; + for (x = 0; x < ocb->block_len; x++) { + X[x] ^= ocb->Lr[x]; + } + + /* Y[m] = E(X[m])) */ + cipher_descriptor[ocb->cipher].ecb_encrypt(X, Y, &ocb->key); + + if (mode == 1) { + /* decrypt mode, so let's xor it first */ + /* xor C[m] into checksum */ + for (x = 0; x < (int)ptlen; x++) { + ocb->checksum[x] ^= ct[x]; + } + } + + /* C[m] = P[m] xor Y[m] */ + for (x = 0; x < (int)ptlen; x++) { + ct[x] = pt[x] ^ Y[x]; + } + + if (mode == 0) { + /* encrypt mode */ + /* xor C[m] into checksum */ + for (x = 0; x < (int)ptlen; x++) { + ocb->checksum[x] ^= ct[x]; + } + } + + /* xor Y[m] and Z[m] into checksum */ + for (x = 0; x < ocb->block_len; x++) { + ocb->checksum[x] ^= Y[x] ^ Z[x]; + } + + /* encrypt checksum, er... tag!! */ + cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->checksum, X, &ocb->key); + + /* now store it */ + for (x = 0; x < ocb->block_len && x < (int)*taglen; x++) { + tag[x] = X[x]; + } + *taglen = x; + +#ifdef CLEAN_STACK + zeromem(X, sizeof(X)); + zeromem(Y, sizeof(Y)); + zeromem(Z, sizeof(Z)); + zeromem(ocb, sizeof(*ocb)); +#endif + return CRYPT_OK; +} + +#endif + diff --git a/safer.c b/safer.c index 1866967..580872a 100644 --- a/safer.c +++ b/safer.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/safer_tab.c b/safer_tab.c index 18dfa33..06859db 100644 --- a/safer_tab.c +++ b/safer_tab.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/saferp.c b/saferp.c index 798015d..8415deb 100644 --- a/saferp.c +++ b/saferp.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/sha1.c b/sha1.c index ff8976e..98d2a49 100644 --- a/sha1.c +++ b/sha1.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -39,8 +39,6 @@ static void sha1_compress(hash_state *md, unsigned char *buf) { ulong32 a,b,c,d,e,W[80],i; - _ARGCHK(md != NULL); - /* copy the state into 512-bits into W[0..15] */ for (i = 0; i < 16; i++) { LOAD32H(W[i], buf + (4*i)); diff --git a/sha224.c b/sha224.c index efee67c..d564159 100644 --- a/sha224.c +++ b/sha224.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/sha256.c b/sha256.c index 105ba49..10eb663 100644 --- a/sha256.c +++ b/sha256.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -65,8 +65,6 @@ static void sha256_compress(hash_state * md, unsigned char *buf) ulong32 S[8], W[64], t0, t1; int i; - _ARGCHK(md != NULL); - /* copy state into S */ for (i = 0; i < 8; i++) { S[i] = md->sha256.state[i]; diff --git a/sha384.c b/sha384.c index 3f29cfc..98fb07d 100644 --- a/sha384.c +++ b/sha384.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/sha512.c b/sha512.c index 7978a9a..fa83a72 100644 --- a/sha512.c +++ b/sha512.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -91,8 +91,6 @@ static void sha512_compress(hash_state * md, unsigned char *buf) ulong64 S[8], W[80], t0, t1; int i; - _ARGCHK(md != NULL); - /* copy state into S */ for (i = 0; i < 8; i++) { S[i] = md->sha512.state[i]; diff --git a/skipjack.c b/skipjack.c index aee2db9..a66efa1 100644 --- a/skipjack.c +++ b/skipjack.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/sprng.c b/sprng.c index 4d93bc3..db6e338 100644 --- a/sprng.c +++ b/sprng.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/strings.c b/strings.c index e156037..b00cb63 100644 --- a/strings.c +++ b/strings.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -50,6 +50,7 @@ static const char *err_2_str[] = }; +#ifdef MPI static const struct { int mpi_code, ltc_code; } mpi_to_ltc_codes[] = { @@ -57,6 +58,7 @@ static const struct { { MP_MEM , CRYPT_MEM}, { MP_VAL , CRYPT_INVALID_ARG}, }; +#endif const char *error_to_string(int err) { @@ -67,6 +69,7 @@ const char *error_to_string(int err) } } +#ifdef MPI /* convert a MPI error to a LTC error (Possibly the most powerful function ever! Oh wait... no) */ int mpi_to_ltc_error(int err) { @@ -79,5 +82,5 @@ int mpi_to_ltc_error(int err) } return CRYPT_ERROR; } - +#endif diff --git a/tiger.c b/tiger.c index 465b861..6184fa3 100644 --- a/tiger.c +++ b/tiger.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -578,7 +578,8 @@ static void pass(ulong64 *a, ulong64 *b, ulong64 *c, ulong64 *x, int mul) } /* The key mixing schedule */ -static void key_schedule(ulong64 *x) { +static void key_schedule(ulong64 *x) +{ x[0] -= x[7] ^ CONST64(0xA5A5A5A5A5A5A5A5); x[1] ^= x[0]; x[2] += x[1]; @@ -606,8 +607,6 @@ static void tiger_compress(hash_state *md, unsigned char *buf) ulong64 a, b, c, x[8]; unsigned long i; - _ARGCHK(md != NULL); - /* load words */ for (i = 0; i < 8; i++) { LOAD64L(x[i],&buf[8*i]); @@ -650,7 +649,7 @@ HASH_PROCESS(tiger_process, tiger_compress, tiger, 64) int tiger_done(hash_state * md, unsigned char *hash) { - _ARGCHK(md != NULL); + _ARGCHK(md != NULL); _ARGCHK(hash != NULL); if (md->tiger.curlen >= sizeof(md->tiger.buf)) { diff --git a/tommath.h b/tommath.h index 6cc9bb0..0029994 100644 --- a/tommath.h +++ b/tommath.h @@ -30,12 +30,12 @@ extern "C" { /* C++ compilers don't like assigning void * to mp_digit * */ -#define OPT_CAST (mp_digit *) +#define OPT_CAST(x) (x *) #else /* C on the other hand doesn't care */ -#define OPT_CAST +#define OPT_CAST(x) #endif @@ -99,13 +99,13 @@ extern "C" { #define XFREE free #define XREALLOC realloc #define XCALLOC calloc + #else + /* prototypes for our heap functions */ + extern void *XMALLOC(size_t n); + extern void *REALLOC(void *p, size_t n); + extern void *XCALLOC(size_t n, size_t s); + extern void XFREE(void *p); #endif - - /* prototypes for our heap functions */ - extern void *XMALLOC(size_t n); - extern void *REALLOC(void *p, size_t n); - extern void *XCALLOC(size_t n, size_t s); - extern void XFREE(void *p); #endif @@ -134,6 +134,12 @@ extern "C" { #define MP_YES 1 /* yes response */ #define MP_NO 0 /* no response */ +/* Primality generation flags */ +#define LTM_PRIME_BBS 0x0001 /* BBS style prime */ +#define LTM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */ +#define LTM_PRIME_2MSB_OFF 0x0004 /* force 2nd MSB to 0 */ +#define LTM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */ + typedef int mp_err; /* you'll have to tune these... */ @@ -142,12 +148,18 @@ extern int KARATSUBA_MUL_CUTOFF, TOOM_MUL_CUTOFF, TOOM_SQR_CUTOFF; -/* various build options */ -#define MP_PREC 64 /* default digits of precision */ - /* define this to use lower memory usage routines (exptmods mostly) */ /* #define MP_LOW_MEM */ +/* default precision */ +#ifndef MP_PREC + #ifdef MP_LOW_MEM + #define MP_PREC 64 /* default digits of precision */ + #else + #define MP_PREC 8 /* default digits of precision */ + #endif +#endif + /* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */ #define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) @@ -207,6 +219,15 @@ void mp_set(mp_int *a, mp_digit b); /* set a 32-bit const */ int mp_set_int(mp_int *a, unsigned long b); +/* get a 32-bit value */ +unsigned long mp_get_int(mp_int * a); + +/* initialize and set a digit */ +int mp_init_set (mp_int * a, mp_digit b); + +/* initialize and set 32-bit value */ +int mp_init_set_int (mp_int * a, unsigned long b); + /* copy, b = a */ int mp_copy(mp_int *a, mp_int *b); @@ -350,8 +371,11 @@ int mp_lcm(mp_int *a, mp_int *b, mp_int *c); */ int mp_n_root(mp_int *a, mp_digit b, mp_int *c); -/* shortcut for square root */ -#define mp_sqrt(a, b) mp_n_root(a, 2, b) +/* special sqrt algo */ +int mp_sqrt(mp_int *arg, mp_int *ret); + +/* is number a square? */ +int mp_is_square(mp_int *arg, int *ret); /* computes the jacobi c = (a | n) (or Legendre if b is prime) */ int mp_jacobi(mp_int *a, mp_int *n, int *c); @@ -393,7 +417,7 @@ int mp_reduce_is_2k(mp_int *a); int mp_reduce_2k_setup(mp_int *a, mp_digit *d); /* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ -int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit k); +int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d); /* d = a**b (mod c) */ int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); @@ -453,8 +477,23 @@ int mp_prime_next_prime(mp_int *a, int t, int bbs_style); * * The prime generated will be larger than 2^(8*size). */ -int mp_prime_random(mp_int *a, int t, int size, int bbs, ltm_prime_callback cb, void *dat); +#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat) +/* makes a truly random prime of a given size (bits), + * + * Flags are as follows: + * + * LTM_PRIME_BBS - make prime congruent to 3 mod 4 + * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS) + * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero + * LTM_PRIME_2MSB_ON - make the 2nd highest bit one + * + * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can + * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself + * so it can be NULL + * + */ +int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat); /* ---> radix conversion <--- */ int mp_count_bits(mp_int *a); @@ -469,6 +508,7 @@ int mp_to_signed_bin(mp_int *a, unsigned char *b); int mp_read_radix(mp_int *a, char *str, int radix); int mp_toradix(mp_int *a, char *str, int radix); +int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen); int mp_radix_size(mp_int *a, int radix, int *size); int mp_fread(mp_int *a, int radix, FILE *stream); diff --git a/twofish.c b/twofish.c index bd0fc1b..b618b98 100644 --- a/twofish.c +++ b/twofish.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/twofish_tab.c b/twofish_tab.c index 3995085..5a2bb5b 100644 --- a/twofish_tab.c +++ b/twofish_tab.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/whirl.c b/whirl.c index 8d447d4..72b81cc 100644 --- a/whirl.c +++ b/whirl.c @@ -1,275 +1,275 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * gurantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org - */ - -/* WHIRLPOOL (using their new sbox) hash function by Tom St Denis */ - -#include "mycrypt.h" - -#ifdef WHIRLPOOL - -const struct _hash_descriptor whirlpool_desc = -{ - "whirlpool", - 11, - 64, - 64, - &whirlpool_init, - &whirlpool_process, - &whirlpool_done, - &whirlpool_test -}; - -/* the sboxes */ -#include "whirltab.c" - -/* get a_{i,j} */ -#define GB(a,i,j) ((a[(i) & 7] >> (8 * (j))) & 255) - -/* shortcut macro to perform three functions at once */ -#define theta_pi_gamma(a, i) \ - sbox0[GB(a, i-0, 7)] ^ \ - sbox1[GB(a, i-1, 6)] ^ \ - sbox2[GB(a, i-2, 5)] ^ \ - sbox3[GB(a, i-3, 4)] ^ \ - sbox4[GB(a, i-4, 3)] ^ \ - sbox5[GB(a, i-5, 2)] ^ \ - sbox6[GB(a, i-6, 1)] ^ \ - sbox7[GB(a, i-7, 0)] - -#ifdef CLEAN_STACK -static void _whirlpool_compress(hash_state *md, unsigned char *buf) -#else -static void whirlpool_compress(hash_state *md, unsigned char *buf) -#endif -{ - ulong64 K[2][8], T[3][8]; - int x, y; - - /* load the block/state */ - for (x = 0; x < 8; x++) { - K[0][x] = md->whirlpool.state[x]; - - LOAD64H(T[0][x], buf + (8 * x)); - T[2][x] = T[0][x]; - T[0][x] ^= K[0][x]; - } - - /* do rounds 1..10 */ - for (x = 0; x < 10; x += 2) { - /* odd round */ - /* apply main transform to K[0] into K[1] */ - for (y = 0; y < 8; y++) { - K[1][y] = theta_pi_gamma(K[0], y); - } - /* xor the constant */ - K[1][0] ^= cont[x]; - - /* apply main transform to T[0] into T[1] */ - for (y = 0; y < 8; y++) { - T[1][y] = theta_pi_gamma(T[0], y) ^ K[1][y]; - } - - /* even round */ - /* apply main transform to K[1] into K[0] */ - for (y = 0; y < 8; y++) { - K[0][y] = theta_pi_gamma(K[1], y); - } - /* xor the constant */ - K[0][0] ^= cont[x+1]; - - /* apply main transform to T[0] into T[1] */ - for (y = 0; y < 8; y++) { - T[0][y] = theta_pi_gamma(T[1], y) ^ K[0][y]; - } - } - - /* store state */ - for (x = 0; x < 8; x++) { - md->whirlpool.state[x] ^= T[0][x] ^ T[2][x]; - } +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ + +/* WHIRLPOOL (using their new sbox) hash function by Tom St Denis */ + +#include "mycrypt.h" + +#ifdef WHIRLPOOL + +const struct _hash_descriptor whirlpool_desc = +{ + "whirlpool", + 11, + 64, + 64, + &whirlpool_init, + &whirlpool_process, + &whirlpool_done, + &whirlpool_test +}; + +/* the sboxes */ +#include "whirltab.c" + +/* get a_{i,j} */ +#define GB(a,i,j) ((a[(i) & 7] >> (8 * (j))) & 255) + +/* shortcut macro to perform three functions at once */ +#define theta_pi_gamma(a, i) \ + SB0(GB(a, i-0, 7)) ^ \ + SB1(GB(a, i-1, 6)) ^ \ + SB2(GB(a, i-2, 5)) ^ \ + SB3(GB(a, i-3, 4)) ^ \ + SB4(GB(a, i-4, 3)) ^ \ + SB5(GB(a, i-5, 2)) ^ \ + SB6(GB(a, i-6, 1)) ^ \ + SB7(GB(a, i-7, 0)) + +#ifdef CLEAN_STACK +static void _whirlpool_compress(hash_state *md, unsigned char *buf) +#else +static void whirlpool_compress(hash_state *md, unsigned char *buf) +#endif +{ + ulong64 K[2][8], T[3][8]; + int x, y; + + /* load the block/state */ + for (x = 0; x < 8; x++) { + K[0][x] = md->whirlpool.state[x]; + + LOAD64H(T[0][x], buf + (8 * x)); + T[2][x] = T[0][x]; + T[0][x] ^= K[0][x]; + } + + /* do rounds 1..10 */ + for (x = 0; x < 10; x += 2) { + /* odd round */ + /* apply main transform to K[0] into K[1] */ + for (y = 0; y < 8; y++) { + K[1][y] = theta_pi_gamma(K[0], y); + } + /* xor the constant */ + K[1][0] ^= cont[x]; + + /* apply main transform to T[0] into T[1] */ + for (y = 0; y < 8; y++) { + T[1][y] = theta_pi_gamma(T[0], y) ^ K[1][y]; + } + + /* even round */ + /* apply main transform to K[1] into K[0] */ + for (y = 0; y < 8; y++) { + K[0][y] = theta_pi_gamma(K[1], y); + } + /* xor the constant */ + K[0][0] ^= cont[x+1]; + + /* apply main transform to T[0] into T[1] */ + for (y = 0; y < 8; y++) { + T[0][y] = theta_pi_gamma(T[1], y) ^ K[0][y]; + } + } + + /* store state */ + for (x = 0; x < 8; x++) { + md->whirlpool.state[x] ^= T[0][x] ^ T[2][x]; + } } - -#ifdef CLEAN_STACK -static void whirlpool_compress(hash_state *md, unsigned char *buf) -{ - _whirlpool_compress(md, buf); - burn_stack((5 * 8 * sizeof(ulong64)) + (2 * sizeof(int))); -} -#endif - - -void whirlpool_init(hash_state * md) -{ - _ARGCHK(md != NULL); - zeromem(&md->whirlpool, sizeof(md->whirlpool)); -} - -HASH_PROCESS(whirlpool_process, whirlpool_compress, whirlpool, 64) - -int whirlpool_done(hash_state * md, unsigned char *hash) -{ - int i; - - _ARGCHK(md != NULL); - _ARGCHK(hash != NULL); - - if (md->whirlpool.curlen >= sizeof(md->whirlpool.buf)) { - return CRYPT_INVALID_ARG; - } - - /* increase the length of the message */ - md->whirlpool.length += md->whirlpool.curlen * 8; - - /* append the '1' bit */ - md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0x80; - - /* if the length is currently above 32 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->whirlpool.curlen > 32) { - while (md->whirlpool.curlen < 64) { - md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0; - } - whirlpool_compress(md, md->whirlpool.buf); - md->whirlpool.curlen = 0; - } - - /* pad upto 56 bytes of zeroes (should be 32 but we only support 64-bit lengths) */ - while (md->whirlpool.curlen < 56) { - md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64H(md->whirlpool.length, md->whirlpool.buf+56); - whirlpool_compress(md, md->whirlpool.buf); - - /* copy output */ - for (i = 0; i < 8; i++) { - STORE64H(md->whirlpool.state[i], hash+(8*i)); - } -#ifdef CLEAN_STACK - zeromem(md, sizeof(*md)); -#endif - return CRYPT_OK; -} - - -int whirlpool_test(void) -{ - #ifndef LTC_TEST - return CRYPT_NOP; - #else - static const struct { - int len; - unsigned char msg[128], hash[64]; - } tests[] = { - - /* NULL Message */ -{ - 0, - { 0x00 }, - { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66, 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26, - 0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8, 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7, - 0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB, 0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57, - 0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37, 0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 } + +#ifdef CLEAN_STACK +static void whirlpool_compress(hash_state *md, unsigned char *buf) +{ + _whirlpool_compress(md, buf); + burn_stack((5 * 8 * sizeof(ulong64)) + (2 * sizeof(int))); +} +#endif + + +void whirlpool_init(hash_state * md) +{ + _ARGCHK(md != NULL); + zeromem(&md->whirlpool, sizeof(md->whirlpool)); +} + +HASH_PROCESS(whirlpool_process, whirlpool_compress, whirlpool, 64) + +int whirlpool_done(hash_state * md, unsigned char *hash) +{ + int i; + + _ARGCHK(md != NULL); + _ARGCHK(hash != NULL); + + if (md->whirlpool.curlen >= sizeof(md->whirlpool.buf)) { + return CRYPT_INVALID_ARG; + } + + /* increase the length of the message */ + md->whirlpool.length += md->whirlpool.curlen * 8; + + /* append the '1' bit */ + md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 32 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->whirlpool.curlen > 32) { + while (md->whirlpool.curlen < 64) { + md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0; + } + whirlpool_compress(md, md->whirlpool.buf); + md->whirlpool.curlen = 0; + } + + /* pad upto 56 bytes of zeroes (should be 32 but we only support 64-bit lengths) */ + while (md->whirlpool.curlen < 56) { + md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->whirlpool.length, md->whirlpool.buf+56); + whirlpool_compress(md, md->whirlpool.buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE64H(md->whirlpool.state[i], hash+(8*i)); + } +#ifdef CLEAN_STACK + zeromem(md, sizeof(*md)); +#endif + return CRYPT_OK; +} + + +int whirlpool_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + int len; + unsigned char msg[128], hash[64]; + } tests[] = { + + /* NULL Message */ +{ + 0, + { 0x00 }, + { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66, 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26, + 0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8, 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7, + 0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB, 0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57, + 0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37, 0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 } }, - - /* 448-bits of 0 bits */ + + /* 448-bits of 0 bits */ { - 56, - { 0x00 }, - { 0x0B, 0x3F, 0x53, 0x78, 0xEB, 0xED, 0x2B, 0xF4, 0xD7, 0xBE, 0x3C, 0xFD, 0x81, 0x8C, 0x1B, 0x03, - 0xB6, 0xBB, 0x03, 0xD3, 0x46, 0x94, 0x8B, 0x04, 0xF4, 0xF4, 0x0C, 0x72, 0x6F, 0x07, 0x58, 0x70, - 0x2A, 0x0F, 0x1E, 0x22, 0x58, 0x80, 0xE3, 0x8D, 0xD5, 0xF6, 0xED, 0x6D, 0xE9, 0xB1, 0xE9, 0x61, - 0xE4, 0x9F, 0xC1, 0x31, 0x8D, 0x7C, 0xB7, 0x48, 0x22, 0xF3, 0xD0, 0xE2, 0xE9, 0xA7, 0xE7, 0xB0 } -}, - - /* 520-bits of 0 bits */ -{ - 65, - { 0x00 }, - { 0x85, 0xE1, 0x24, 0xC4, 0x41, 0x5B, 0xCF, 0x43, 0x19, 0x54, 0x3E, 0x3A, 0x63, 0xFF, 0x57, 0x1D, - 0x09, 0x35, 0x4C, 0xEE, 0xBE, 0xE1, 0xE3, 0x25, 0x30, 0x8C, 0x90, 0x69, 0xF4, 0x3E, 0x2A, 0xE4, - 0xD0, 0xE5, 0x1D, 0x4E, 0xB1, 0xE8, 0x64, 0x28, 0x70, 0x19, 0x4E, 0x95, 0x30, 0xD8, 0xD8, 0xAF, - 0x65, 0x89, 0xD1, 0xBF, 0x69, 0x49, 0xDD, 0xF9, 0x0A, 0x7F, 0x12, 0x08, 0x62, 0x37, 0x95, 0xB9 } -}, - - /* 512-bits, leading set */ -{ - 64, - { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x10, 0x3E, 0x00, 0x55, 0xA9, 0xB0, 0x90, 0xE1, 0x1C, 0x8F, 0xDD, 0xEB, 0xBA, 0x06, 0xC0, 0x5A, - 0xCE, 0x8B, 0x64, 0xB8, 0x96, 0x12, 0x8F, 0x6E, 0xED, 0x30, 0x71, 0xFC, 0xF3, 0xDC, 0x16, 0x94, - 0x67, 0x78, 0xE0, 0x72, 0x23, 0x23, 0x3F, 0xD1, 0x80, 0xFC, 0x40, 0xCC, 0xDB, 0x84, 0x30, 0xA6, - 0x40, 0xE3, 0x76, 0x34, 0x27, 0x1E, 0x65, 0x5C, 0xA1, 0x67, 0x4E, 0xBF, 0xF5, 0x07, 0xF8, 0xCB } -}, - - /* 512-bits, leading set of second byte */ -{ - 64, - { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x35, 0x7B, 0x42, 0xEA, 0x79, 0xBC, 0x97, 0x86, 0x97, 0x5A, 0x3C, 0x44, 0x70, 0xAA, 0xB2, 0x3E, - 0x62, 0x29, 0x79, 0x7B, 0xAD, 0xBD, 0x54, 0x36, 0x5B, 0x54, 0x96, 0xE5, 0x5D, 0x9D, 0xD7, 0x9F, - 0xE9, 0x62, 0x4F, 0xB4, 0x22, 0x66, 0x93, 0x0A, 0x62, 0x8E, 0xD4, 0xDB, 0x08, 0xF9, 0xDD, 0x35, - 0xEF, 0x1B, 0xE1, 0x04, 0x53, 0xFC, 0x18, 0xF4, 0x2C, 0x7F, 0x5E, 0x1F, 0x9B, 0xAE, 0x55, 0xE0 } -}, - - /* 512-bits, leading set of last byte */ -{ - 64, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }, - { 0x8B, 0x39, 0x04, 0xDD, 0x19, 0x81, 0x41, 0x26, 0xFD, 0x02, 0x74, 0xAB, 0x49, 0xC5, 0x97, 0xF6, - 0xD7, 0x75, 0x33, 0x52, 0xA2, 0xDD, 0x91, 0xFD, 0x8F, 0x9F, 0x54, 0x05, 0x4C, 0x54, 0xBF, 0x0F, - 0x06, 0xDB, 0x4F, 0xF7, 0x08, 0xA3, 0xA2, 0x8B, 0xC3, 0x7A, 0x92, 0x1E, 0xEE, 0x11, 0xED, 0x7B, - 0x6A, 0x53, 0x79, 0x32, 0xCC, 0x5E, 0x94, 0xEE, 0x1E, 0xA6, 0x57, 0x60, 0x7E, 0x36, 0xC9, 0xF7 } -}, - -}; - - int i; - unsigned char tmp[64]; - hash_state md; - - for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { - whirlpool_init(&md); - whirlpool_process(&md, (unsigned char *)tests[i].msg, tests[i].len); - whirlpool_done(&md, tmp); - if (memcmp(tmp, tests[i].hash, 64) != 0) { -#if 0 - printf("\nFailed test %d\n", i); - for (i = 0; i < 64; ) { - printf("%02x ", tmp[i]); - if (!(++i & 15)) printf("\n"); - } -#endif - return CRYPT_FAIL_TESTVECTOR; - } - } - return CRYPT_OK; - #endif -} - - -#endif - + 56, + { 0x00 }, + { 0x0B, 0x3F, 0x53, 0x78, 0xEB, 0xED, 0x2B, 0xF4, 0xD7, 0xBE, 0x3C, 0xFD, 0x81, 0x8C, 0x1B, 0x03, + 0xB6, 0xBB, 0x03, 0xD3, 0x46, 0x94, 0x8B, 0x04, 0xF4, 0xF4, 0x0C, 0x72, 0x6F, 0x07, 0x58, 0x70, + 0x2A, 0x0F, 0x1E, 0x22, 0x58, 0x80, 0xE3, 0x8D, 0xD5, 0xF6, 0xED, 0x6D, 0xE9, 0xB1, 0xE9, 0x61, + 0xE4, 0x9F, 0xC1, 0x31, 0x8D, 0x7C, 0xB7, 0x48, 0x22, 0xF3, 0xD0, 0xE2, 0xE9, 0xA7, 0xE7, 0xB0 } +}, + + /* 520-bits of 0 bits */ +{ + 65, + { 0x00 }, + { 0x85, 0xE1, 0x24, 0xC4, 0x41, 0x5B, 0xCF, 0x43, 0x19, 0x54, 0x3E, 0x3A, 0x63, 0xFF, 0x57, 0x1D, + 0x09, 0x35, 0x4C, 0xEE, 0xBE, 0xE1, 0xE3, 0x25, 0x30, 0x8C, 0x90, 0x69, 0xF4, 0x3E, 0x2A, 0xE4, + 0xD0, 0xE5, 0x1D, 0x4E, 0xB1, 0xE8, 0x64, 0x28, 0x70, 0x19, 0x4E, 0x95, 0x30, 0xD8, 0xD8, 0xAF, + 0x65, 0x89, 0xD1, 0xBF, 0x69, 0x49, 0xDD, 0xF9, 0x0A, 0x7F, 0x12, 0x08, 0x62, 0x37, 0x95, 0xB9 } +}, + + /* 512-bits, leading set */ +{ + 64, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x10, 0x3E, 0x00, 0x55, 0xA9, 0xB0, 0x90, 0xE1, 0x1C, 0x8F, 0xDD, 0xEB, 0xBA, 0x06, 0xC0, 0x5A, + 0xCE, 0x8B, 0x64, 0xB8, 0x96, 0x12, 0x8F, 0x6E, 0xED, 0x30, 0x71, 0xFC, 0xF3, 0xDC, 0x16, 0x94, + 0x67, 0x78, 0xE0, 0x72, 0x23, 0x23, 0x3F, 0xD1, 0x80, 0xFC, 0x40, 0xCC, 0xDB, 0x84, 0x30, 0xA6, + 0x40, 0xE3, 0x76, 0x34, 0x27, 0x1E, 0x65, 0x5C, 0xA1, 0x67, 0x4E, 0xBF, 0xF5, 0x07, 0xF8, 0xCB } +}, + + /* 512-bits, leading set of second byte */ +{ + 64, + { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x35, 0x7B, 0x42, 0xEA, 0x79, 0xBC, 0x97, 0x86, 0x97, 0x5A, 0x3C, 0x44, 0x70, 0xAA, 0xB2, 0x3E, + 0x62, 0x29, 0x79, 0x7B, 0xAD, 0xBD, 0x54, 0x36, 0x5B, 0x54, 0x96, 0xE5, 0x5D, 0x9D, 0xD7, 0x9F, + 0xE9, 0x62, 0x4F, 0xB4, 0x22, 0x66, 0x93, 0x0A, 0x62, 0x8E, 0xD4, 0xDB, 0x08, 0xF9, 0xDD, 0x35, + 0xEF, 0x1B, 0xE1, 0x04, 0x53, 0xFC, 0x18, 0xF4, 0x2C, 0x7F, 0x5E, 0x1F, 0x9B, 0xAE, 0x55, 0xE0 } +}, + + /* 512-bits, leading set of last byte */ +{ + 64, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }, + { 0x8B, 0x39, 0x04, 0xDD, 0x19, 0x81, 0x41, 0x26, 0xFD, 0x02, 0x74, 0xAB, 0x49, 0xC5, 0x97, 0xF6, + 0xD7, 0x75, 0x33, 0x52, 0xA2, 0xDD, 0x91, 0xFD, 0x8F, 0x9F, 0x54, 0x05, 0x4C, 0x54, 0xBF, 0x0F, + 0x06, 0xDB, 0x4F, 0xF7, 0x08, 0xA3, 0xA2, 0x8B, 0xC3, 0x7A, 0x92, 0x1E, 0xEE, 0x11, 0xED, 0x7B, + 0x6A, 0x53, 0x79, 0x32, 0xCC, 0x5E, 0x94, 0xEE, 0x1E, 0xA6, 0x57, 0x60, 0x7E, 0x36, 0xC9, 0xF7 } +}, + +}; + + int i; + unsigned char tmp[64]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + whirlpool_init(&md); + whirlpool_process(&md, (unsigned char *)tests[i].msg, tests[i].len); + whirlpool_done(&md, tmp); + if (memcmp(tmp, tests[i].hash, 64) != 0) { +#if 0 + printf("\nFailed test %d\n", i); + for (i = 0; i < 64; ) { + printf("%02x ", tmp[i]); + if (!(++i & 15)) printf("\n"); + } +#endif + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + + +#endif + diff --git a/whirltab.c b/whirltab.c index 0ce779b..031c643 100644 --- a/whirltab.c +++ b/whirltab.c @@ -65,6 +65,29 @@ CONST64(0xcccc17cc2edb85e2), CONST64(0x424215422a578468), CONST64(0x98985a98b4c2 CONST64(0x2828a0285d885075), CONST64(0x5c5c6d5cda31b886), CONST64(0xf8f8c7f8933fed6b), CONST64(0x8686228644a411c2) }; +#ifdef SMALL_CODE + +#define SB0(x) sbox0[x] +#define SB1(x) ROR64(sbox0[x], 8) +#define SB2(x) ROR64(sbox0[x], 16) +#define SB3(x) ROR64(sbox0[x], 24) +#define SB4(x) ROR64(sbox0[x], 32) +#define SB5(x) ROR64(sbox0[x], 40) +#define SB6(x) ROR64(sbox0[x], 48) +#define SB7(x) ROR64(sbox0[x], 56) + +#else + +#define SB0(x) sbox0[x] +#define SB1(x) sbox1[x] +#define SB2(x) sbox2[x] +#define SB3(x) sbox3[x] +#define SB4(x) sbox4[x] +#define SB5(x) sbox5[x] +#define SB6(x) sbox6[x] +#define SB7(x) sbox7[x] + + static const ulong64 sbox1[] = { CONST64(0xd818186018c07830), CONST64(0x2623238c2305af46), CONST64(0xb8c6c63fc67ef991), CONST64(0xfbe8e887e8136fcd), CONST64(0xcb878726874ca113), CONST64(0x11b8b8dab8a9626d), CONST64(0x0901010401080502), CONST64(0x0d4f4f214f426e9e), @@ -534,6 +557,8 @@ CONST64(0xcc17cc2edb85e2cc), CONST64(0x4215422a57846842), CONST64(0x985a98b4c22d CONST64(0x28a0285d88507528), CONST64(0x5c6d5cda31b8865c), CONST64(0xf8c7f8933fed6bf8), CONST64(0x86228644a411c286) }; +#endif + static const ulong64 cont[] = { CONST64(0x1823c6e887b8014f), CONST64(0x36a6d2f5796f9152), diff --git a/xtea.c b/xtea.c index 895907c..1434149 100644 --- a/xtea.c +++ b/xtea.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ diff --git a/yarrow.c b/yarrow.c index 2410ce2..0cc0ad5 100644 --- a/yarrow.c +++ b/yarrow.c @@ -4,7 +4,7 @@ * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express - * gurantee it works. + * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org */ @@ -96,7 +96,7 @@ int yarrow_add_entropy(const unsigned char *buf, unsigned long len, prng_state * hash_state md; int err; - _ARGCHK(buf != NULL); + _ARGCHK(buf != NULL); _ARGCHK(prng != NULL); if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { @@ -150,7 +150,7 @@ int yarrow_ready(prng_state *prng) unsigned long yarrow_read(unsigned char *buf, unsigned long len, prng_state *prng) { - _ARGCHK(buf != NULL); + _ARGCHK(buf != NULL); _ARGCHK(prng != NULL); /* put buf in predictable state first */ diff --git a/zeromem.c b/zeromem.c new file mode 100644 index 0000000..15181ac --- /dev/null +++ b/zeromem.c @@ -0,0 +1,19 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org + */ +#include "mycrypt.h" + +void zeromem(void *dst, size_t len) +{ + unsigned char *mem = (unsigned char *)dst; + _ARGCHK(dst != NULL); + while (len-- > 0) + *mem++ = 0; +}