From 40c5578ac3fdd649a76229f3c86420bec4f0b412 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Wed, 12 May 2004 20:42:16 +0000 Subject: [PATCH] added libtomcrypt-0.95 --- LICENSE | 16 +- PLAN | 38 + aes.c | 162 +-- aes_tab.c | 711 ++++++----- base64.c | 2 +- blowfish.c | 2 +- mem.c => burn_stack.c | 10 +- cast5.c | 2 +- cbc.c | 121 -- cbc_decrypt.c | 56 + cbc_encrypt.c | 52 + cbc_start.c | 43 + cfb.c | 111 -- cfb_decrypt.c | 48 + cfb_encrypt.c | 46 + cfb_start.c | 47 + changes | 19 + config.pl | 173 --- crypt.c | 379 +----- crypt.pdf | Bin 430814 -> 404940 bytes crypt.tex | 194 ++- crypt_argchk.c | 21 + crypt_cipher_descriptor.c | 46 + crypt_cipher_is_valid.c | 19 + crypt_find_cipher.c | 24 + crypt_find_cipher_any.c | 32 + crypt_find_cipher_id.c | 22 + crypt_find_hash.c | 23 + crypt_find_hash_any.c | 34 + crypt_find_hash_id.c | 22 + crypt_find_prng.c | 24 + crypt_hash_descriptor.c | 45 + crypt_hash_is_valid.c | 19 + crypt_prng_descriptor.c | 46 + crypt_prng_is_valid.c | 19 + crypt_register_cipher.c | 36 + crypt_register_hash.c | 36 + crypt_register_prng.c | 36 + crypt_unregister_cipher.c | 28 + crypt_unregister_hash.c | 27 + crypt_unregister_prng.c | 27 + ctr_decrypt.c | 25 + ctr.c => ctr_encrypt.c | 43 +- ctr_start.c | 46 + demos/encrypt.c | 63 +- demos/test.c | 143 ++- demos/test.c~ | 1985 +++++++++++++++++++++++++++++ des.c | 4 +- dh.c | 12 +- dh_sys.c | 49 +- dsa.c | 477 ------- dsa_export.c | 62 + dsa_free.c | 21 + dsa_import.c | 59 + dsa_make_key.c | 117 ++ dsa_sign_hash.c | 125 ++ dsa_verify_hash.c | 97 ++ dsa_verify_key.c | 86 ++ eax_addheader.c | 25 + eax_decrypt.c | 34 + eax_decrypt_verify_memory.c | 60 + eax_done.c | 56 + eax_encrypt.c | 35 + eax_encrypt_authenticate_memory.c | 43 + eax_init.c | 106 ++ eax.c => eax_test.c | 782 ++++-------- ecb_decrypt.c | 31 + ecb_encrypt.c | 29 + ecb.c => ecb_start.c | 32 +- ecc.c | 13 +- ecc_sys.c | 2 +- gf.c | 2 +- hash.c | 102 -- hash_file.c | 41 + hash_filehandle.c | 49 + hash_memory.c | 35 + hmac_done.c | 84 ++ hmac_file.c | 96 ++ hmac_init.c | 87 ++ hmac_memory.c | 67 + hmac_process.c | 48 + hmac.c => hmac_test.c | 201 +-- is_prime.c | 27 + keyring.c | 2 +- makefile | 102 +- makefile.cygwin_dll | 65 +- makefile.icc | 213 ++++ makefile.msvc | 66 +- makefile.out | 28 - md2.c | 4 +- md4.c | 4 +- md5.c | 4 +- mpi.c | 668 ++++++++-- mycrypt.h | 10 +- mycrypt_cfg.h | 2 +- mycrypt_custom.h | 4 + mycrypt_hash.h | 10 + mycrypt_macros.h | 4 +- mycrypt_pk.h | 13 +- mycrypt_pkcs.h | 53 + noekeon.c | 2 +- notes/etc/whirlgen.c | 182 +-- notes/etc/whirltest.c | 30 +- notes/tech0001.txt | 146 +-- ocb.c | 636 --------- ocb_decrypt.c | 58 + ocb_decrypt_verify_memory.c | 52 + ocb_done_decrypt.c | 51 + ocb_done_encrypt.c | 29 + ocb_encrypt.c | 56 + ocb_encrypt_authenticate_memory.c | 50 + ocb_init.c | 117 ++ ocb_ntz.c | 29 + ocb_shift_xor.c | 27 + ocb_test.c | 226 ++++ ofb_decrypt.c | 26 + ofb.c => ofb_encrypt.c | 38 +- ofb_start.c | 40 + omac.c | 318 ----- omac_done.c | 66 + omac_file.c | 65 + omac_init.c | 76 ++ omac_memory.c | 42 + omac_process.c | 53 + omac_test.c | 95 ++ packet_store_header.c | 29 + packet.c => packet_valid_header.c | 16 +- pkcs_1_i2osp.c | 40 + pkcs_1_mgf1.c | 66 + pkcs_1_oaep_decode.c | 135 ++ pkcs_1_oaep_encode.c | 128 ++ pkcs_1_os2ip.c | 27 + pkcs_1_pss_decode.c | 121 ++ pkcs_1_pss_encode.c | 122 ++ pkcs_5_1.c | 63 + pkcs_5_2.c | 88 ++ pmac.c | 437 ------- pmac_done.c | 64 + pmac_file.c | 67 + pmac_init.c | 114 ++ pmac_memory.c | 44 + pmac_ntz.c | 29 + pmac_process.c | 62 + pmac_shift_xor.c | 26 + pmac_test.c | 153 +++ prime.c => rand_prime.c | 23 +- rc2.c | 4 +- rc4.c | 2 +- rc5.c | 5 +- rc6.c | 19 +- rmd128.c | 8 +- rmd160.c | 6 +- bits.c => rng_get_bytes.c | 43 +- rng_make_prng.c | 53 + rsa.c | 202 +-- rsa_exptmod.c | 87 ++ rsa_free.c | 24 + rsa_make_key.c | 113 ++ rsa_sys.c | 2 +- s_ocb_done.c | 102 ++ safer.c | 2 +- safer_tab.c | 2 +- saferp.c | 2 +- sha1.c | 4 +- sha224.c | 2 +- sha256.c | 4 +- sha384.c | 2 +- sha512.c | 4 +- skipjack.c | 2 +- sprng.c | 2 +- strings.c | 7 +- tiger.c | 9 +- tommath.h | 70 +- twofish.c | 2 +- twofish_tab.c | 2 +- whirl.c | 538 ++++---- whirltab.c | 25 + xtea.c | 2 +- yarrow.c | 6 +- zeromem.c | 19 + 180 files changed, 10226 insertions(+), 5085 deletions(-) create mode 100644 PLAN rename mem.c => burn_stack.c (75%) delete mode 100644 cbc.c create mode 100644 cbc_decrypt.c create mode 100644 cbc_encrypt.c create mode 100644 cbc_start.c delete mode 100644 cfb.c create mode 100644 cfb_decrypt.c create mode 100644 cfb_encrypt.c create mode 100644 cfb_start.c delete mode 100644 config.pl create mode 100644 crypt_argchk.c create mode 100644 crypt_cipher_descriptor.c create mode 100644 crypt_cipher_is_valid.c create mode 100644 crypt_find_cipher.c create mode 100644 crypt_find_cipher_any.c create mode 100644 crypt_find_cipher_id.c create mode 100644 crypt_find_hash.c create mode 100644 crypt_find_hash_any.c create mode 100644 crypt_find_hash_id.c create mode 100644 crypt_find_prng.c create mode 100644 crypt_hash_descriptor.c create mode 100644 crypt_hash_is_valid.c create mode 100644 crypt_prng_descriptor.c create mode 100644 crypt_prng_is_valid.c create mode 100644 crypt_register_cipher.c create mode 100644 crypt_register_hash.c create mode 100644 crypt_register_prng.c create mode 100644 crypt_unregister_cipher.c create mode 100644 crypt_unregister_hash.c create mode 100644 crypt_unregister_prng.c create mode 100644 ctr_decrypt.c rename ctr.c => ctr_encrypt.c (63%) create mode 100644 ctr_start.c create mode 100644 demos/test.c~ delete mode 100644 dsa.c create mode 100644 dsa_export.c create mode 100644 dsa_free.c create mode 100644 dsa_import.c create mode 100644 dsa_make_key.c create mode 100644 dsa_sign_hash.c create mode 100644 dsa_verify_hash.c create mode 100644 dsa_verify_key.c create mode 100644 eax_addheader.c create mode 100644 eax_decrypt.c create mode 100644 eax_decrypt_verify_memory.c create mode 100644 eax_done.c create mode 100644 eax_encrypt.c create mode 100644 eax_encrypt_authenticate_memory.c create mode 100644 eax_init.c rename eax.c => eax_test.c (55%) create mode 100644 ecb_decrypt.c create mode 100644 ecb_encrypt.c rename ecb.c => ecb_start.c (52%) delete mode 100644 hash.c create mode 100644 hash_file.c create mode 100644 hash_filehandle.c create mode 100644 hash_memory.c create mode 100644 hmac_done.c create mode 100644 hmac_file.c create mode 100644 hmac_init.c create mode 100644 hmac_memory.c create mode 100644 hmac_process.c rename hmac.c => hmac_test.c (71%) create mode 100644 is_prime.c create mode 100644 makefile.icc delete mode 100644 makefile.out create mode 100644 mycrypt_pkcs.h delete mode 100644 ocb.c create mode 100644 ocb_decrypt.c create mode 100644 ocb_decrypt_verify_memory.c create mode 100644 ocb_done_decrypt.c create mode 100644 ocb_done_encrypt.c create mode 100644 ocb_encrypt.c create mode 100644 ocb_encrypt_authenticate_memory.c create mode 100644 ocb_init.c create mode 100644 ocb_ntz.c create mode 100644 ocb_shift_xor.c create mode 100644 ocb_test.c create mode 100644 ofb_decrypt.c rename ofb.c => ofb_encrypt.c (55%) create mode 100644 ofb_start.c delete mode 100644 omac.c create mode 100644 omac_done.c create mode 100644 omac_file.c create mode 100644 omac_init.c create mode 100644 omac_memory.c create mode 100644 omac_process.c create mode 100644 omac_test.c create mode 100644 packet_store_header.c rename packet.c => packet_valid_header.c (68%) create mode 100644 pkcs_1_i2osp.c create mode 100644 pkcs_1_mgf1.c create mode 100644 pkcs_1_oaep_decode.c create mode 100644 pkcs_1_oaep_encode.c create mode 100644 pkcs_1_os2ip.c create mode 100644 pkcs_1_pss_decode.c create mode 100644 pkcs_1_pss_encode.c create mode 100644 pkcs_5_1.c create mode 100644 pkcs_5_2.c delete mode 100644 pmac.c create mode 100644 pmac_done.c create mode 100644 pmac_file.c create mode 100644 pmac_init.c create mode 100644 pmac_memory.c create mode 100644 pmac_ntz.c create mode 100644 pmac_process.c create mode 100644 pmac_shift_xor.c create mode 100644 pmac_test.c rename prime.c => rand_prime.c (71%) rename bits.c => rng_get_bytes.c (77%) create mode 100644 rng_make_prng.c create mode 100644 rsa_exptmod.c create mode 100644 rsa_free.c create mode 100644 rsa_make_key.c create mode 100644 s_ocb_done.c create mode 100644 zeromem.c 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 a459ff2c2c62bd9dd57357ba171ef5000242f956..749b9da772d279a3fe0ebe9c3e06c195c49f24fa 100644 GIT binary patch literal 404940 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

^Hgqnya3crJzj>Q=2W5!P}8e$<`h6t@p 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 ZF8jYYau%$;uTf2K?|1C)R?&w z;PI_I?d5{vpJn>YpKh`C;QU!%<3n+p$NRm~7Q_#QJ@HfuQ*5~HLV}42#C)=~2OSE+ zHf9zAC*_$TtQDvq9%#gBqn z3(&CMUCffeSf^lJPbe?Zs%Uu#F74HbB(eX((fU-D$CE}*D&Y(T6QL;j<(PO_FG0{8 zKvRyjalT|OYgxhfL1Uu}aTd0C3ca|fFkm{!*v|Q zD$6>LoKecR3h2LK{2`4wx5*fFPBzO96Y(lF=P2XIB~OyQO#BlkTq;WLhVpRyI<^uX z7wyy?Qh-P>4?{(5<8bNKab?$O)QWJR6fz8g7nvE@z0sx!hCnkgC@4A7KNF)e&d&gA zp)tT2+peNFo>`4mEJ+K1YF-f2J)`fHw`rG?kVp^i`lL(-upRBu-cmL$gES(U(BQqV z!V~n6e<==ZF7!tq_R04lR<}QRO6UTlt&b(uw5RW|98yZBt6GsXDT zIhG?%p31c8sXe8|PU#T^j%55KwTg|@GL=^Pb4Q|+5R@v|a;g>>%BaRoXpHTJ#JB8Y zV~OxrR42LuL6!nkix}nM2KmFhyE;SkK1hV%w@fSf3$Y)mGGgE@469^^|f-TdY&r zHR^|^CKfhc5NghUYQ1YB?0ofWzixE5w7nglYEpdD6!S%za;;%0uF}<#~Z}1gf^pn&{ox&c)yE z`%qlbkK&Hn*sIFDs8Wt61m?KFaEskY4ngetgAAV_8!yt)cP(eM@RqAR$4#c2)S znosN7Y3}60@XfiG&P!*6YAAn(1pc7;_c*X}28PUr<#N%z)wp@dvQQX6#gd45+p=Mw z;1UeL*`DyCVZNT2Bu`v&8OGl3_yY9w)(rjk3B!NR4gO=X%1qDkUz=6t|G{y~{J(PC zPH9>@Zv4lDp@}cxK(2Wtz|XViS?SWFIGwqSis}k|+L#;(Ng)9Q)=xD_Z-?i1n#?a) zzu(C8&y4T{Wb^83qG5)2^h6^YwSoJyFK6Ov?WAF*Az!ZmZ{q6m>S=8#Ns%eXohT|@ zXD53IJt8fRiAp9pW9{krvS`Nm`TSkaOwhC+O6xpZBKP(kdek2#c}#ynF&9<2v_nRZI5^6+QZSs;9-71~@^^)2Uf!7v27uFV zaIoeQbKq5!o?n6`{e}0U+WSyyV@;j5^9~l7u+N2}n&98WM*?;1m0B|y#G?P<7K*jZ z`L{V`PjgTkaa$9t&RwYg#VwDI-cH_VKcfTnS1fC+$LQKsqY!*#!~%B1DZmH6tD$&< zu0B_p!t7(SCGGc$fm6H>|18gtQ%{}$LmB*0u4NR0Wi+J_CIsskR>SKPI;IbT>FBxo zOM`AdvAL$Tg!nXQTe12IUjkxa_|3TQ0sNoU+l0D9z|lv6Og!bw!5h>I9yY$WuXl0i;9LRKp1Y;U zbailfcduKIx6ZVU=4l#}FA@Hh&sYUqUb7{Lh=bq#6AiXrt?bwIlb?Wy*S==%`1H}C zS+OkzLRHg;7%EY3gtAdVNhGf^aQ;4*Q{n;Zr{3)m%oHJIxL84)Cb;+00@do_Pi0A? zU=JjR%p*qX-1Y;vQ-Lpcl9H1Y+itf$_fY|G;PkNLt#P4a-&t#b07F9f*QbvNt#_^* zZO5J*ytKJKzE!R{2;}Ew8kRxbi<)lXXrr|hoerEhq{J2~+N|T`7Ae$ym6dbUnV`FxV`xqcyxf-N0`nPJ&zms6G*v z)mV*wfAZuA8VG&Nrk8f>2LEkr3HmWmInyB$$9)cRrmLo+&N*lx-c_lFF@y(F4wn^2 zAvj=#0c96-Dlc^=FHCp0q3ytotSXheD!4jK2f#zrCbU<6XFpu^?O<1^?O2Ia$alVk z)RT`D^ZZ*Rq)WYwyNx;V_wDYm6Q7`^2~X!yludOd86PYs;MNk=$}vQK_9fR5A5ha6 zO*4ybYRr7W_hESEpE_T;KSlT*Kts(>?f1xPFIrN}&{Oy(+mGe5e`Cs2Gj%>mJ}<69 zU2hNWXBu|0x_T~M(~Eb-LhwP+(cWodt=YlZ&1MGpJ|CZJQf`W8p>LP8Xptsw=KjIa z3_*$qbIIC-#h*}T_Egq08WCE=v{Ecu#DTgy)@W~Ras^7XbP#V2oUef{@oGOtZDY&5*cM`yV)m?*4=4{nR zXOT{qKuXtn0#ixkvK9KpM$yM2`r&)x+&#y0Rv|@SZY|-ot1{$mkL2}P(kX6-qK(4F z)^zAqs;V6F?K0DO_kD}3oI3efR>{K1JNe?XqfM#G@MOG z)d3LunewlEi33~bA%AZx7C3Jv;_dGZXq5A2cCROg0VCP@xi334jDGk=@OC5t(~k|+ za9wuy_br*VnXqjUobs=rOeXC%x*=c`XL@+x!b>5LW;|p&;+NJL1E2=&_T8j~RFh^# zy#Y*NLTyB=dv@(GSvfSXSO6d6SNs(T5h0Mg;f9J3nh zr`y5Fgd-RPeV#k_Rh0P(>FAe#EJ8oaFgJ~0v-ViA!dt;7nB+t87+PxTjI@g92uBEc z`dQonN-el82N(|jBRhwb$lvx7z;>oiPh`#+02$vV?|`HF(hgyVLyaqobKclSFh;u% ztAz4X82$v+DJLKG!}s}86fG*Vt=C5Hs^ibGng(&J;}CZ0Ze_GVlf<>-l@*|e3*b4K zpGN>;61kxOZZT0f0zQse#x|ve3d3~=h$KW$RwyUForDFRN2TwzMAva+OyLj@!#9OJ zz8P79IF+)PJ==gWl4^P zvmSb=k*LFyA3eTcS>j@b9hY@;>8sLJ#bzMN_9 zvN-^+a=eom_~A8ivOj$h7^`@W5`oHbuMprhP&_&q*R_$Pr8H6e-LRnLtQrH>zmpXg zY5<67{AWSlGD%)JJ5a1`eSy@V>>dF}8tt6GOtl@t)_R446TF=>j`WJq*08w!23r?b zz7`xG;st&vY_`vpy%gm0i$-NGuhmqs!gYVooOny%4^$o!0BrfyFv|DGBPE=eM;|w` zvZhKj)a)g~-ovFcTW|PCW=ntxjcyD%;5(vZgq!S!1N}TsxOcYQ*x#jBE}CS?i|?g zg9Sy#?{w2Ut310#rwM^t4Ul(am1jEf*a&{uX@o;Kk$HHA5(19>ymglC#p53YVc1{S%-I z?!*PBml-$35MV=ABKhfqJl%p_!|?u={$1}_S%JJOwi{<_28nTFQf0wRq3%l!v?uu+f z0Uzdro99N&^rD~m_vc+z}$K0(b9c>KDGW8k|C&o zD)*^Om(pbgW?aBpNn2iV?6dK-LDH#tcNQMdQ{v9;(X# zx)&t!Pvr|U5lwlpp+iQUQSz*ISy@L(&Gm}`pWHy9E=dieBy-~R)4E4oCGTIjgKheI zv2MzQ9nq9BN_m%F)#iq$dkM_tSXs6-1sCPLx4b_q_K^C^dpX**njq@3=Ax}DRwGe( z^hZXsQ{+j*SWhoqo9k#9`DBnL;4=fVNs<#^pR=A$W>@R0`#ej>`Q?x=>Eq>4%yo{M zt=>RPC^T*HknVUF(Vw;nh`Gg;m%he+ z!_udaCQxVJ{(0*)4?H_HA-)~$P$O~y+cUgu2M7f~0E8?%l_qQV1y7b1&_Sg{%63jG zwN|$-4O%vXH0b_0#1%FH2r4&}sb9lWlCu3-f)-GfWb};9XBGgyd8c=58EnKc+Chy~ zr+hp8ylChSYla`V^jNE#8eO@Ft%#YE&;gd|x28U-jBz9CB@J+`zy4e~?j^R5xWRBT zSOtCKV=u^jF61?QRr?ytHrV8vygw{J*rY$Ebf2iHI`|ww{r;7U^&)VX!MtkEBtE)4 zNM6{CZq}|lwi5U|ja1865!|B*5Px7dHjglHZ+@pNrieIsP&5-1_w}qZ6yH|7(p@|B z4U3;XWUr4S+4u1_i?7F#Qlvd^0FZOv{<41gYSoqyBq^$CX2nK5IaQ5BMpS6Qla*#%JAVu;}mnmLClE;aqWE-A$ z4nn=~6n5tKUUG@|%>nAVXNP_pc)O{fwe@6#v1|m&tAe>wuXKE~Wtc{J6IyV4dl3Vn2#Quh?*S)GzzZ zzzKD)E*-v`(CcV;Xc8t!4i8~xKKMynY)%utwla*18JRdu-l;?g97TW$@Cu{4AA5|- zQ5!F-Dw)D~rpOQo<>rwp5O}srUr_*}r#``sO!U$7DiIbUbMyi*q0 zCtHT-4viPLs0p$SzVDdqc?AD`p@KQ#I2wwC(TB?bQ)kKIap48`{Z1?|K{zP@fsh61 z?@t^qY{>xQU%%lF2H%)%fwiMhjoz04ItT{Eu*jv4h*yt67vboX_acI+astduWQ8{+ zZlL6!=*_*Wfp}k?0R5lxrJy1&GXYF@z#;OC@* zi>97tGwjij{jKm8A?}x_m|R-ZW&Vd=Bd7g-R9*={KXyHT;>0W0l^YO1w$_+D#krA! z%v{OIWK{XCm7Ior-m(%(p#E5C%VS86;Dm84R0nY|^$n!&g-Rl2N0GH$ZNsf6s4b(| zQ{k%{7GkCh`;(Ad1G&(t4Nke)dNw41nC-6JBm*YMf|_#_-=vy#$~#POd^T(6rW?`+ zctUhIlgC#Rl}#iz+=1%3O91{}x8=?hWQB;eXlla}H9zCelx(NILJQvUj9`RmFjX}2 zGfj#we5IrISsNqb^XDPvbxT@2;3E8ZHaMxbJmaf02klL_%@i{^P(5{5$Bt^6;|Q_N znwNDE0lMOM?m859s~Uj(NR@w32nOP>j30|Re4nSl($<(BnCv9?MUd&(f`2;`jJfe-DJ`f%t=N9U_6KOZ3jNB1LsP2+I!{v~%wPFdwr@_17i418IKi(^p`Jjc z12Dz#qip@(EJ9WJdR<5^E%{L0-%J0%4Plt(ju$CCUVqsrQp-bfqkwwr^A0AD>-9D(owBs9Y5+~o%iALuF!1-BOd6WIQSwDU-~$vFh6)T zJJGn2Q1xnn5vmad)LICALZpPh%^s^(9Udw_h)D4uC4$kR{M*lxiStcr`EW7vf(IV1 zsrfY-l&0vGqXr$O_#cuciw{3?Nbq0rdl%Flhof z7xWbWRvSRW_-D~ZQ1^#O%8)ZOI9XH?;|yiE5D^Qeb4R{_%L@A93wYv=%}iT*9jvm!Qn6E=X8JJjUdPLmfnc6C7KkdFts>HDNT=xYH|} zu1PM=P`rx}TM2Aa%-m>X?Ug8Ovw45XpE@IRg1kJ=j^b_F3IwOkT5aKqZV|sI8~x2b z6x>iqe)i`LTfZR4=az|j*&K!4<#SiO`B+0@G0Bh}GJ#WwtaYlQ9R2`%*dczQatb6} zSY9RjBx}ocd>RxBYkCwmsL*|XLJA*aLLk2pIr2Rj_5Ap(UDPZ#($gUIK6r1P7%!a7 z^|%ngSzM39>VHl#O7Yz^?rw}2zGNz*=NuR?L!bC0xV5V^uGV&B#R;nl48#;6-~W0b z0fmydt1<`)5oJYUj0ehOm<1JM0Pkb(^mkxGH>7Dbk-d;VpLB7I&LeHOPz zDDfJc8F;Rd{^+V+WcWG8syt@fK28pPeesPJSdaa81^=JA{67>tBL@TX|JC&@{{uk9 z^1lM8x-|Z?oatJlCqV2Z_o*9iq>$kck=;5ckjGtcvqfY$ZnHRvy{~uZ2Zkb=g@~v+ zMy=nG!%K#3cbd*Lw`pQ+6szyuiz$bDCb#KiOi@mT$+HbBM^_@FK_GGtoE50@pD3fVRLc&BtWJ?Mj9~-QXyiD%n(+UZJ6w-`kp>y!d89C@Tu1MMDq+xOO*%cX%AOk4xXOT^Qq?4%tHQR&+#~#@pF;|^9?(rlNF#LXA{K(;op>xxRM|r(0?XJ7+q!4uj zq<;KxA}Y3$GooH1f8un<@Nm&g6hO_`;1CEi7;!u6HMvFL)n$hqo3lik zZ67#eu>Jd>M2t3b~MO8e5Oy&x9G5w%oi--pFY*P=Gy2{36$JEBrtk=|ofI%5xZ%Cfnt1LAi&KM=NaIdu*-~hLG{VN=X zCdExb!UqK}O5N0)$5;A>il213sUXUdt_I%G+dHU7@3bBm`4sM7`K9Hb+j3~p@&)np z+bJ)xCZFsi{I>D4OJmMqE?^(UtDfbNzZW_LLBMT6v`!KbArY_s^3V(9TyfpU4p8h#dH3fgGhay3QmQ6t-g5d_c>wrf8v``4h1tRH(9 z4wLKKJ2pmoI;!R1VfY*$A|oIb=iAafujl{|&|Crm0ohLyjtIayBOldXbXsEI@x2O! z1r)B*;y49&mcCFMaCAIw19@4ZzN}i}3c}_;m!ub0E`rM582})Tgo>B4N@9N7cPZ6@C%CEh7Rhfq- zMMSCS`AAS~_kuVH)OI}7y$(`DLxNbz+TCdnx?>VC{OQslwKDx02}h%J)-HH1b4#uJCF?pbg~L4k73GwTWSJNP zyQ&+EVdg){<0kQT)G1xYm4}8ckiGm-Kp%p2n_gHIk&+e6T+P@nQI>}qWGe=kR{@0TYI+vpWw?xADqm0z2VhOE zIliQ?=X!*u33oP2hQVx8E+0wtmxOQXmBLvOhMKKMnUhWrDMn)#b4#k*lf=p(n{f>f zfT}J3aB%z%%4eGaI0K6cfCt^9@l(k&0%^Q@BmKhXq z4)QUmkWNoc*^*l15lQ%o0&a9DF9d!il5o8Ri4R*Fz>7pw6q z|F0ltxgytqe!a8{W7nG^tOXIzLq863w9(TLXk=HzH8Z)rklSi`CDL$>b%f(Ouub~! zq{-4VsVN4Av`;4Z4D+1X`uDNjcWB`nu8WMktETsFDJEwzx#RzE+WtRiF6)1tw*Ld0 z%ksZsb5$Za;QHlZggtZmP0XXd9#UFi$dQ<-!#M;HKoui4dk8`b`IVv`kEf!f11>c@ zGxb9-k0zS`ka1&NdRoX!IF2G-f%XLELRs`Gn(ari3aGf5-H628$*qJ04LH=1DUT?5 zHdMPZEF~)6bCPo;2-n#))ccs@grqx!VL2*>Nr`8;c(1>E{|8lI{U1;T*8df%F!dW)kJW}a)le%Q%V&N#1})5dgMMf+a-k0{>NkjiPv>(M zx2|aB?AT)L`Rx-aQ@={1aL?|7<_{Y)XBjtC{#yu!dLkqOSyB3f>`U9+0N((Qij`f2 z7isPMLht#e`VgU%&$6;K@S*VvRMF_ylZm0hV`WCCTXiu|cjn{uIy0$YNZoWhKj82j zpzw2fq}4}By9Ye*N%-(MudR^(dV4%`g_rS0H)YyT<@(JvNon{m{G!t$`*XnEgYzU> zoy+U-{h{BN*ub51;p4)i#j<~ST~!*1U=Q2p;&EGBgV2OIzP2?;rFBq;r*eWNPxn_af)r zr~xPWsJ2qYV$H@E1Fc9u!)Yw4TO)q2j!<*0aa4$T4Ur^?qH2=8dK1p9c^A`So&fi+ zx?5PApGc|V682;i10PO&0?c(Qd@Z6d79}0_2|4FfuBNOsi0=xM9I}3%|BmTHsSk`eWWtBmyxr8*&xSZkT>5Z zqTag&hD4v%kB~YABHER1Tda{w9PO}Rq58|tk`Tx4U)~RfAGrJE!ur!OiY&yLDANSU z#q<|vESaWORGOT~Uy^rc@wGP4eO8-VF42dQL^N?Q?}pQKBkrzUy<=5<&IoEH!*=x> z_C&xa@dpn2OhWmVSW8!eH!vWyv0TDtmOY{3WLu&|mLMHv3eyZ#EpIH&#?&b)7ng&V+5RfpD^W>YJ*Iy zFv6a<9+F4^O9Gg}DBP48^~}CF+8d~MYx1ehNRqfWkF{sqyF6M!`Xo`-wVLy4p6V9h ztiZ%TW{GJ{)(&rClDzQwW9dZ%e#Q*HN@D;pJuIDi$y#s~pB zka=2Y|7W8~?#Qz(V^sg??Hg9PA)x;7T=LEAae_VhUgY;5O<9#*U`js~1x-OvQo)J` zOHY5bS3YMwe?+8Jap+es%FW`{*6b~ydzglfw@k`*E_}nL+}J2Ga9&UR5yuMCY-@mo1+Rs4Sk8K(N~&ayR(hNV4KdPOm21wNOPvKXQcv zVsi0U?@6wiA{RofkKzj>C4wv&sn5i75Fw0VfIt~PuS;=7MsnjGxmX_t3rrTavDTQ+ zX@3(XhaU3cxD|8{s|}7bOdvFV@)HsrU}H;>Pw&Z|;oDZmJdq=2q4&H;aIQP{7dC}%LH zX1Jt{s6qao>W zD)TWKtsJz^fSs z?AcrDj->Z^c0&)V7vCGlSz^D!IW4_|0L6}B@3}~(^c|sKfB#-gk3~%sQJ^x@w_y}B z;SpzqsldyrAslCRa?&IDP__<{7bo#w?-{1iYOVv-PsU!*mN&+~f7`SB63j}%j6F!5b8bI95y$OEFCKb+Z{$;uFc^~tD~D?U~O zy?<%-5ltUH^Oz-|nW2TJ=5^)r^8Bj<4DxnH$|);ZmB`?>Rq#9IvyMd39#bb}f3$7k zGe~QzL5B1d7&70**Se;Ze&C}lf33!0sUKNwodh@T0`W+EtB9L;8(P!E9>@#riD2#H=O?_)4LxZ;wmMOGb_j=jl>MwD}-^>W~C+1T7Cilhx6! z`O~i^IF=I+Bauch-w; z7zF^&Ttr(;gFisr0RwVW@OMUi1Q2w1RLj+A=q6{!`8HFZjW$A56_v~hx6C5#0Sj}= zp1xrNuRtW?*mEMbr#7-a)uSZ=hCVso%B#o-MD=q-X??6TlQP2x?+(r`N1HId^e8t$ zd`3Vlctaj8*ohhZ6e&d^_@MbN)-AW27{XqZn_UPg14qMF^<%GKmmIoWLJy!nhT!3~ z>ibEMfVGIyf`7sCmi}`R_25b9sb(!y(!+P&^4g5FpM7?H_EM9?%UjdR%=M)q<>jX| zdaEq0>(h0}l+O3=XY=a;^|SS-?S0_#>8n=ut%YRT(%x<8MhLs670{wIbSL$6{9Zd^ zQwZmP1`7h%+;@ps&o;W+0#^sU4Myn{=oFtHyI6Tn*q4MT)<+!Qk>QX2$=h9PY0TbU z4eTp|xFZ*ILW#x7j9PNf(K=23m1ddmR&-pGgL12&1B{JsF z_yZ&Z%btkGu)sJ3m$-RlnxanzC{s(+Z1tpU^+P+gZcQO9?>@#;ynGu<5T%@_(lAP!rbaCoO+Y*esT;ivPQw{ZE}3(x)MyT*OH$f!ti={{(d>sV%zifcD|4Pl7E;qt2~59 zUbZPDN-0tL55A|v>*4r*|MO}Hp6~N@O77ZqbrGWK;O3|EHReZLbZ>!cClycH?=0HJdx32O{2@Y*@sO*!X%#m<)Qd*e}8;3 zG?Nk}<^12R)$Ml0^oK(Kyw!;19g!?*$!zv z<|XS{q8jp+vn!9fTOj{o4hi^{iC2t8vS9J@_A;}t_6M^)i>)R;-l8Nl$}^(_Yjq0? z4bCdQlG4T^w`tE8aTQgEcwVdiePz|eTjQ~(f4-uWQk6Iyxr%PRGAp!Q!!sN#Nr?%L z0vB-#=xs`=dS6E8NN#(UtJV+XI(`X%%1!>hkmm-o1v6%*$l1JN_; zBN&nf-J9E=P5lb|)er;CI-%ZogLywsitC%z9dMt)c{E+L6P#BHattS}TpP^)7R|;S zk2O(CiB*1dKie{*k5GF1wEWXUCK>X7mW~Fu4LK#f#RhKE)fwRr87P_BHo7g9bc{Q+ zQd4l&P8U)_&7fI-(b?j8-P$!rQ=zXZ*s+U<{$g+=-2*Wwf#f`94c+(<`ms*8!wu6; z((SOB4y>^U0z=am=f_88-rBBCzc@umFDMa)Wj|pq^*75&-$mL*NS|#ydbt|GfSHed zv`JVbbYe~MEbQB&Few5R%@gASjOS!Mm{qDy1dKsmd~5Hp;S5r1#1t(@aoI5~N1_g0 zx&C^yZrOhO3a;euZrrhMuxxLKA4dkTN+#t{I%UWfs)^-!6WZDmg#iFTxpju3SBBc9 zBP$J3>9RtDSI{s7vM+3llSRh%0*GG~24K~UEmclqJj#ewXdL2yBkUXii==S1Ng6D? zPKvA;>(Mqv?LV1vR7itNn&+fb92W?;Uwe5v`YoHqBlB+gJFWZ0nP*nB-Tu?{{igNm z__lQz*$_EVJ8K?+i%V2wUTzNRUsf2Pf6tNrk0THok97}KElA$?p3*#1Gt%vcb{~oz z_&C@df~tV25=P%Y0tWh*7az0saBI=T^Z5CqHH=Em^BtUsKH8b1aqt2R%>TF(p|XM7|9jgt zuo!#M4-}fNdOtJw*zsh#&3dxKwpDMV=Hq;YZyF}NLHUaI$`nh72bQgese>2`N7&?W zjn;}A8E1<>KpNc)2YwO@4Qu+rHaC==rM4YY7cS%k2q4Uvl{At~wPW`vW z6%anl2Rri7%pUt<*tJNr+z!*qF@&I?Vi?X69J z9~q-i8`fAh{KlzIe>$?UE%lwtToyUQSmBlB#-z*I>Ns&1O~!>w3rsXIHXwq;b_D{U zz6z8VTiiLzZHtO9)-9sJqtS4CGzA8G*jgmIP8~L#PDANOY{s6o5QsxitcX{+Ft*kC zl~7}gF^45G19KY2bu)!EAl5?hU?Pkx^FqiIfr%G zN6xNnbj+Lt!aYaWR5Mb=Kf9Q|qWyR^V+1FDTokL|<8TK|-=$DFVgZuW{Wo8oSt375 zY41h^KqNqv;Iq~lgJc-G91`|MvVOS1Ru8G}-d}N42P%(rSrb9#EcBW#8!U$T9>f++Kh9h#G9j6w?yHXA1;R;@*Rg!~Cd z4!bF_=;5M;07f*vcFrFe=o9@T ztAnQ(qXvmnV77#>T7hY|QZHX>x(~8{CN&DMb`B=|W?~P7WnbxqP7PxP7 zB+_QAK`tf4#PTqe`Aid4rQ9TH#^$&rkxyErv$iJ0A?i_aKL76>lRKxp7QgSzv3%v-diJ#Z8zQV~>|fDqNK zemLP3piMe!ehX{{EN)0HTECmF>~J^LhXQ~$3arLrCZX%BJLqdyf1ot3F;#dQ) z8Zq#0=)wT_?1d7n>8=i=3tFzJ>9FL!WBf@fRLeey*nrV5j4+Npf*Uru(7d4DH!sDE zzVeI1yJNCp=(u?O0~2@>F5>V|Exm^17HG>Mh_O+@&b$G2F=|~27LlwnWNaEK`+G0jn1>ev7e@1o^nf*$i?)N80Oxt2t=C0q;B%V9B~yGHI}QS^7FCFV09GK z0uLGtv=gpk|3v}RY3~m>R0uaMiaQW_)JCw!Gk<3WK^6nh4^M2H0jR2!%>iTIo_WdO z;avRoJVUOxYmk?$*cReUNh85q87Y;g0KZmT zynZB|t88=2y6trVpPkZg3#YYRj-X}(L~TC?V^W3oo+E=pGj;}S+^m!O-?a1@+#yH^ zpGYP+R(v#>C9`{JXn5C~Ji;6(!!;Z6Fz?oAsmcpvDmyio!>svH)A1=EZdYL%)f{P< zFq}>zi}+{^nt0R)&Q%flmynK^CpGSF_0|`2ez@;8eDF4)t4gMB9SEHtjck{u=@2P} z;|^=heM>;4yj7EHJAEu*5h!ct7sR_97(k47D%Bz2^`1if@tHn)Q6~#`dG+&) zi&+?d6L{Fk)spM9Z$Ap<&tk2wjuu{t64wgZ$Z=Fpc~9@TFjiniWq0~9O7J652i23UjUYE9gR?~_}`!k(?Ib(&I&T>@bFP?dr-Ca@>#U0xrj8dE_il3rgeitc4IEn7 z!)cOD$HD4C`4)z<=M7WBfAUfjJmpXdmsuiUO(vGjsP)cs4aVj^2p89hNguU6+cHGe zqAw*-qr7ldudd?!$yL3q@?3lROGE;UKZGjkGeqE6>AId%#rYwq1;)#TfRs5s9Fe5( z$+v1z`|?_)C`EL#kr=s)vvMZ%hP!rqdH$04vOvy-4D)KDq4xZ!&&Xb$M1;-2H;TaAc1lTJnubwjGuT_M+svrV+q9=!dfF($7H%E+!<2;8{1O9ev z)Y4}h;oVDnd506^@TZJ7KV{k3AxfX|UQu?Qb55^Log5o%60qK_-q6T4bq9iiFj$Z~ zu5&IDt0mmq;s?n}3@dxP$Kz=OA7c#e=0<&{Rew3F4g8k2)tDlnLefXC!y1Hp zMd5bqJ{lcCprLvw?h!w1-`^hRm`#U#35VgUN$!n2b_n`ztOe=SQD?c^^e=+AO|6?{ zvn@pSBcjVb{O-5y-XEY#G);wnH>>|;LH~=;W@Tmg|2j@=|8!dZdHO%i>OaiK|87<_ z{&rtR5vQ4Y1LhJ*!@9kDN#s_B?}+NFttl`7(GVycUB<&wQOzjaAD=mRwsn}aXB1P6 zB>dVeUy3{aW(6yC&nQA7TqBt$lhdUmQY18iJ5Iw|UxOghjHI$ucy{<_8j z9M@^%r2e=H_dpsl{dzM!gi=R)9t+}@lW?Nx@^Y9lrY9%nC;YA)r8V5thq}2Q2G3~=+tfSi zE^=~y_*m}H)VE9&y*Fm~>|pfIY$O}qy~CU3XX^arq)V;=22N;sAHU^nlEo}w3K0q~ zjNA3MM30+&#~*WNim zUSI1u@jA}$dKn(nK-`0v!=1n6x>Sl>nq?8Y-~SlC(Y{}De&6L=A};~rYNA&04W2zO z_QDo_f%xlV@x98veV3GPaQodBQ@G!`9Skn&EcKG*^Eio?A4FcXc4m2POyKQRh_nQQ z7es3e)ZO&!_jFFKu*Q7W)r0egP_j9LXq;&lVj^ZSxp{U@G>lQHaXaE2hDlA$ud2<_=9?xlVn){s z+C{X2Z5VfPjToPGFPltw>&alDp*7K;nBZNC!7SCCd4WuZ$YiOw(okC~q&!~RH2gSK zS!7H~nsRZyok*BdPI1B5K1DeVxbrD{EaPuiV*bPKE>7O( zSPb}Td$ze(-)MvxQ1Li;R+LTYfXeYXle=<%egF;#L*03XmUnPS)FvEz#fgA#eGi& z{N=#W!2EuzvV=!#l@ly<&U@)Hs|sw57X?Cb$gtbyUlH^`k~`Shhq@Pnf#`a`xmk=D zcE+lb8g7Yv6{b16=KoYb>Y`ssPMt__R+D9~(YFu8BH8%-uKeyT8^DJlVx?3C1iZeW zA;VA}x$M=ttM+KRJt8foelip&MGS+hi`G~|Gl@iiz|5k<%E|tR{z!kZy;}DM?oxSx zAy>(b|hL#zVhF>`pjrl=kMrwDv zQDY{9o2u9??Y2(@z1Jm2FiW~LUbeqcN&*+;JBv8I10nZ;M84-jLm)h75A$yoF^@mX zBk#=i!Yj0Kovd9_i0|zn$>VvqrW;l;r-b_3F8Ow#`K(gVA&T0ZiE{kg1PHK9X!4FA z0txwCRS0j_SD!Q}0OhW!4817MNfXbX22G;$oN!;6dKahV(X`pht~ie-n}={HN1;{4 zUH{DDN1#~SYt6+Rq*Z$yB=B+IP!#syjDhmnhzSwD-(JOARci3vb-tzrl@E1s5a~_Z zDW)8#qmG=kl%wa2G>iN~XwzZMZj)}##UlUP?=r+MHJ(m~!s<3t`Bpz&Ni)~sV{blF z(JLzdju!4xD0|)pB)nDC$ee7i52*H-R_*5x6^i-dJ~shtK*C3XxIa0y1xiZ5{uH~a z^PSZQAQZAoL~K6qexA1vYP&HJ)^J{>CDW#_`7O$a**0a|LUurYWbV#N448>6sx!|B}KJr zK^aUvJ(1oq7boeN;K#@36woyltV%4QZRiMzl!R!&8MQwY@vM$%F!m%ZfP@NQeDQH{Z zHBFDVKR%f{d8jPA%XW>^+ng-b_J*ZmFP)p8E;YpX6G{lr>?S>%MP@ET(}};}wJ3_G zh})`HQ}{C-clrxYCtMJf$xc*z-BvnL*p-ud9b>L6ZBFZ43u@Wx%>PcOgS(0} zGn4{Q*RT?NiiX=0U#2vk_g`8n9wS{)ghCz~kKp%+JER3#wiOVId)W8+nlC|RT^l(_ zyLkr^2N?XB$F5oku$b|Fb9{SCCJ=DLnuJ#-pLB7$cy;o!+!HnXkAZ_1zbc#W!7ZC7&pvSc1m30`uhzy_eEumEdN_{VRUte~P+)(4zlU z)LpA?+G4XIc(1Bi>nTpwosp(aLTjRnYm+iuk;UWz!FB}ii6>QUY$UrD50%IJ!qZ7b zSS^%$0%nA2!h^9l4yHTJOx=-507@%9Tm8tXb!YC#06nLFvFVV`j&u(q8bg9-5dTvvMJUse_G;xj8+GF7A|rNi8pn`&wTLa0sOup6s6@*#a<%!VlZc zwYo4e9titE(&31CL)y1GjndPHN6 z&@11`f64}7^k)G5=`r~s6sw{yJG7;Z0kQM*L;X(HLN?Vzzf3{^Mx(&Tk!}*c^0Fd( zdcaNErPIbe6-hx&daUYGyF5yLo0D8O-)h;9k6Hs+wG!H`i(xSjT}#x(0YlRDt_D|i z)Q*X|ZeIFKqvLrx(Tc<6ic=IMzZ?swR|+^Fgd#g)vS_8ybB_EN13vE>C&P;xjspot zM=uIZ+9nrI6sfH&Hb9en6=&uq-t2dsgDUNu9Y{BZ#4nIGYlLPkwL+I`E{{J{r7=N4 zidW`Lcb<3nn3V~E+@QGRX9l66-xAw`x1EZ}0mdG5jKh;FgaK8rIB=O@95aaZ8W6V# z3=wT}%+n%!=H1kIcX5IRIq%{GD%`MteY3>&K_=?OKO_7SAA z(zsvz-iw%6l5#90d%M9i+jP{P$)d21=_D6LkW*TBCeqnphs`NfgkoKeJh2;=kjO{7 zxhzwB!z^{nTxj2I$R~}JIeu!mVW{7UrdgA*LyBAixh*_<0|(#Ek3LV$%*aRM?;mH6 z^212|x#Os3Yc*pM=*uBOWa*&5OTgjv6RwwQ&sa_l|k+c z<8qdiH$?iCGm!ld&!2j+WpWxjD;HBOgoRYxzQ7T|tc5wCfoD>k8zHS68zUy_92h+E zp>ey`u053sP1YiAW?!e_SZmYL@@(-(&?j2eLvEupLW_^sBI3{OnLT(M69S4lH+dx7 zhq*-+T{PV>>4c3#FJ#bqf_j>io;*(OvlsTu>9yFl)Df928N6?uHr#2;!Nrf-Phgpq zpPBG@H$NtZ3@BhzDvj4;P{jV3#u&RvRB0oa+hgurmMv)}z zj$LL1bg?*uIbj-bLNP@&TeJmks|yi}$fv96_4ddN7$7Rdo4)(W_0?1+TW8NBaL^Y& z-wDrT_ur7C(dOwM)Ak?67g3{;PY96!h?7yLS`9yM0dEOVs381PU3l=YJfF{HVnQOs zcz|%FT2~JS-bGbOgnj?!o^LN7tloC^pCX+?2Dr`p@FIxNEq+oqjDb%C{(ulH<|05b zYKSkwc>U`9T^7eM%z*)X!ziE@7UU?wKVGNL4emcf@HE2}7YM05*$-S>nfaU?z zt+!?`raQv3V|u;9$kFYvxsl~5oB!B3Hw(+70BBTuNU1Ex3!>OA?kGVjdo2w4Wq^WH z<%c4cd#epsl%3~=1#gukqDhHluqYGt_swe>xvy*kDdj@lSyNXQBv0hfT&o`Acp4(WI)wFnyk!iYhO|4|j}gnC~u zx>1-j)TG(UTc1e6MQA8Q(pR$IQh<~`wL=XZ4nG%z2It^_DYfL)*=3dt?g8^JW~O1{d@|M1UD%kIy% z03Kd*zr+)f%VLuhNcwTzGe@xzv)wJ4=BJWs6}sHy5!5QNeXu{Oo-FpP;LF(|+|oLr zd`%&3D~~`FmPm!rd2q@sIdelxbT3z4=!ukj`C(ad-L5TIBJY4S__Vj>DQf^2CX2p{ z;qH%5TF5!ez8tl+BdiA5P{`PYfki@eIE=F;h(0&3Tncr#vzW0jhYL(m^XHI zw0!zIV!rP{`4P({k#>xun?5BctEboH#mCY608b@QWWeduPjMfag(Q+58EHqm+tbaB zub1`nv^e{hSlJ!SSH(i^{ki{qy&)B8V`8iolBT2GKj{Q2;JMHH#6orvii|~9L z+2SB-!;EeREKH=yvj1sf9>Pj->7h~+@m~EsVl_azW7&8U(Z1VxBr9=}Y(sCeJ8xtP>Yy6E$48?6;-KIn<^XPsG!ARS9)W3CBr}4xx{XCT zqL6-dbp!G%s<@c1V-tajVy9$tY9Ik&yien`gg8X9YmXa;N}nr-+G63WjUZy*u?-)% z^x?^6S@^Lij`g}t13XuPs7RbQGY3tkQAg!+69Z93rJ+Zi)~HUT=NP@Wh;Sf)%nYQ~ z|0~MsDMK${J4*2;o-K9qyzxwDdcJe-p(3WmF{Z_*ygy`!1Js)%6z-g%x*8wDFj`7L3VkgFxzysRjL=%U4X)9`bH zCEEAoOnG<;#1z}|?!-N) z@nQwUTA_ZOB)vPfzF~92c*eEIifX1a(^wSFj*I@EG$%ou*Uw|lfl>No+V=9(ezcl! z`mup9=5i)%fH}hx%j1}I74@m`!AkSBtn#O88Rjlv_8|ZBqky>IIqKCybE(fA>Y|cn zf+d^q^z$V>z;IWegnfr8#agm*QjStYmz;^OqKBv=hqsrODy;ri1U;H=4F-4>I!Lvr z;XM?b`yJ*JWN`$q0`{!<2oeYt>7q!&mZf0j-QwJRacG`+sW7iwPPxICc^|4GW$Xx2 zB8VHqz@)G>rWB)`3N-#A6TZUq3NG?yglhRUfK?E!45~Is#H#bZSG?}Wv3YpDjFhHJ zXTLchWR7?Jj?QgZH9%7RGBLz+4D!T-*{Ua9w8)Qyl5cHpiErl?Yqim(`xU4mFRz1o|r9F4V zGiO@ z{mbi0Ir+DR%JXpQqnyu@2{QpM=a-|DQkC+{zk!?L7)4xzvZ}bXY^PEC z%pxyb?&Vn-%7|dA>F_c ztYhR!ISMQ_mRip({18Te@hbQ^&qTJ;gH_5mMn7O0cMdS`F4+WOgweN#?gm;WKw;mG zZ{=@-4HC{LiJo)HJH$wMhG|_+I9WZ$+4`MGU&ykFXZ{Z4UV*iv<;>()63?{uz)uA7 zV6nC`Rk)KfQ{Fw@gM=GEZl0pgDiZ_B3oq8a6>1LHkpBy*a3X|i zj&F}m?M)U$6RG`qVI2M{p|dI?P_DFK_(LEUKbKUdO!&KsH(5jwjfrEq~p(9m^1?&wk(K1`~Zjre<@{F z6!&}8G6y$Rh*B4NHaf*8*RAi`UQ+2)C+)&xAb@b$b@J7L7OwT__~p8|MyN#qnaE#f zyWq*)+p5F1e9g%Z+%|n2ltU9yq~a;;sakFD6C*|XxK!2KG4B`%cVh$6Nj>S@iU@&s z_*Sep(z9MO-QtZ0Sd3!iyHL@XBct1a9kk)y-SY)9t+%-^=nfh~Vt>**v`9J$#pS+* z`Sd5XmUj#KvcMc|9uJt=l4S!Juov2IWA|h#lux;qA&`oqs5Xb_?V0dyi2CDZ&)ui% zy_%t7g+qJ~rQ*@+U^WkIzw7mr4cH8R7A~ndci)7Yk5GGb8E`PP{f8l*5dw4kK^dfh zQ86*jT{XxF@w~1E)Z|o5&fOMMOTR2Ez?6N*Zu9r7_6Iy>>c%K08)Htxm|JG1x`+S@ z`E51ZJV5cB-*SoUB3rq2jby+29A%7Q;x9MuQAZ#8lY^1sQWqO#(7Iwl<6Jfw9K-iO zd+SYAg1&-@kcTU-0bTZdZszh2rgrufzfw!wW1b>8Rh!0+At;#O5yPtp1h{o%78dcY zX(~(Szy=~UEC^n2$>MnVF2`cXj`~dVLfcO(?I38ue2y}2JZbe0Ze-G34V;b<{rCA` z&!=Z@jv%5M2;}r}th^k?7cu~WFo7ExBsB}|pp$Y++sU#>*g@nI6~#XJuy#&c6OTk4 z;ds9pD1{~1i~K#VnDf86aJTH(%0ST+wvkkfL}kp0X0U;{n+7xN-_Ke1gXA!{kiP~v zltt(c_0c!D16M-K{hCzvJY4-&F_3evD<)?*sYFFQA{54}+~?6GgrS`FB>Ex*<#y;I zHJ%V&6^8Sr@O%xpxUvO3ekUDePFJaeGqO0K9J9OR&fsUXJBmf4Ki-XhoxWn(I-Yuh zv4c|;)^B6vml}tb)O7vY*xjZFw1EoVdxpUVQOzk8tjijKVT?&3WKD3sHLt1 z5ZOK6H*N|)(Eg)$+n~E449AEBpJ8WaGK9Kn84L9K(eXu%Zb>ou3Wg@~Edjn6Wr7)s zY@bE%7F;kMdmumjI(y#I4slS}?PJ`g!zb=goU4rH8QpjDr+%7Mb$Cb4H1IIHWoMWS zY;2j|c|5|r4D_~*9YxUI;MK^;%cJ)rXy&8r(O(AO)E?{P%4y zExAnke~^s-TH4CU!tmcyXYBt0SmpRX0ju4rHj#hJMK`C#e1`3EsfBn_SltV9-A4o^ zC=2>$sewlIt1qml&NH2|629JIni4*A=K>M^(1r6;#M4Z(XT`>SQYXImTw3UK!&2jc zG~T9{4?dbve3BZR_L}AzvgpHg{;60}fmms@rI!aOOmTOn?`DM55aclJ(x=1Mov%A1 zG-(%MX9tH?F4`(LQPX?cJ7C~Y9Nz`Hk zaV%}DHu!f8_93KRkIPD{)SIO$%hh;xW|@A2ia^Tqh1UzL`425Rm#)iBy+kY~d$cuE zs>`f@to8y(FLf5bkE+K6)~tCV4E@$|j@=h&XA7CHop^>Y9gF~2=)|oBSuCnkF~F9PJ@z7~eD<<2)-sJ0_dip`6;$ zj=ZJeQIw%_WM%Ha>vlEof9ZccYnKiCid+sFw=F&QWlc}5tBu`w-pnYSJ5#eS$06SvLx&67}>nff-(s>iQr-yW)oxEZgA!*F|P^8NJJ1(GkY4?srr5r$V@=+*w z+3pxNq4q?UH0`G>v5wy9vce{GIfs|uwDs709l#fW*6#VP4i3B2Awj$1ys9!;=SRZG zP4}mWFeGnbvRgg`0Vb-EHnqXRj;Jzf>T{R6pfZ7$sl_(+3n68#ubLY|z=|!f&K_{V z;KX`)=CI6Zf%Kc2b<-Jr{5DETqS9asbJQKn*g<}wsli>|r^Zx4XUfOJ2dji!h)l7~ z1A!1uI%^96yavwJZ|NQE0f*6oP%)P_B-}2)C$0!Zn0ETel{7t%IU_>S9cjEro4s4@ z+DaUjN9^gxZ;3))6rYI48ho<0De!kYE^Y4BXa`qh{VhVZ6EVyuCSkT3BR7iAu9-^j zW{6CYMg*7V1dsx#e}0egskg-2nuT7@5i}da z2@};EZd!KFw$n|E+rQtfa3gg5yYXG7kxfT!-97*JjMiRNPqtvszfMa^7U zh@Ccge!O0OuFa@rC)IT7?%381rmIUvyOTp8RBH{boMr30U|;!4-LzASK{6^2mT84o z%f)=OTJ42uIY8p2pTgECm9aVx%VzyMvz~dlW=)11LT{zQ?BH~v_gP^Y7v1uUtlzaQJK3-Bp61N@^Nn%9@o+}!Hx(Hxfb38W<+}^HRDv6Zc>6Zv$Mj-uH%`3fMF$Sz4PzR`m`okvj z%ZRvwQK;EUvPm~8@N*InV+U!J8F zvqSs{S%Lx+t@?}$=24Ib_HH1r@?b~`$fM**wf)Di9JYnE)8XS}nyQgI+eB^Jr26u?pSPr*}+v*0S0LIOgzfGo1Xnrh;{r`9QXHpvN3#mjh-A@j>#j9`mtA%M7E~ zYm};T$@WQcY$MlNbfN+p&b#)1_tx~{lY@ZPQ%6c_wJPwpp}F;zY=~h46@Spchn!IZ z56hH!+l4StWe+VYb=u_=0Gcofd?K-PMan`0!sEGxPzGx}O#V&@Y>X?*EVmbSp~!<} zBs>8lCpsNz*@yykfy1oEDd8sqF-{c~w5~L$8kF&i*I)OczzR{wv0YuAEiD;cV#yk3 zf})kh$&rhv-|uVUSVD$iUd2%{j~aunm`#Fw+SY}bImn|$M6gFV=o;&~_a=0zQ5M3j zj2g-wodmfsMDd#nA?g(z3s#z-4FJ7>E5CGulX5DPnBpUrA$qfs-`w{HicVFLOM&WS-s31^Qe9NIH>uUH7Y0327dSkpP%dmT_Gq>TFB3jNwVLih}I zE#SJrM*>kLw6h}b7Lv!Hgp#)-R*|UBs>3KwYEn>)D%$?5%(TLJqXv7giG> zz^d0%}pmBdHNblk> zhCnKjQ&ioam4Vb$p2nsT=Dseo;vR2s3_8h@NdcMx#)S<2hI|{|Y;!GyyK&gaip7M6 z`7LZ%+KBax3^RY6_Iq}VfD?6bac692SSvA7%rDlH0euoD7FD3idv%`SswVS%+3*R* z%T{mKu=V`6_9(i(O_vYviUEFyBGpCS0>G-4V%-lP^O5(`G4QdWx8Fddei#>0=os)- zYte`IrI(k}b9Um;&8`8vKqO@CZ)+l|lDpPJs^=b(F7kla<{ifTHtqN9J=(TWGy{f* z&x6Ms^l_7PwR`WLUwXQUZNRoe8ec_tLsJ09k&_foAsp7=68XB}LftZytv^depqia~aLw594U5o@G+;)yX0P_=1+4 zRDGzTb>5nWofn|31Dy&~)a;KapG@e*8Fm82thH;>g+usjS36AdNtprCBUGXE-5v)v z{jLiN5nek+GdnM*KFsM&{`CK$ib$4D`n*>#kf#3P=uLKT7yqm`HgTWxUXNfE-|7_B zVN!bwO*l7Ea-dGv-62eJ0T=S`H%sn3UnchgN~ED+oqB5YL+AKGLej#H5Y&B^aqg{^ z@)1PR2!DG41L1eIHdTV|!)XC1#_WvDMts^!IiB#`7+P9wKaY}0bHc3Ez~g6fUtgRG zDutDp=pS8L$CKCH$@WcbTIcRg#be>!x;(J*%fHQEUQy}wjqdK+`-9|G*26}Rg#^=r zUX`BqSsLv)>&TRC%F9>X7^#M|M?fblGLa=G;zK|uEfSJaLR9&U!-`%o@Wq|p^XEJo z4e>&Bd&D`fhbwvntTf5_fPmJqzHm_Rz0L1aeqyQV^_J8suUVb}?SnUdlLo{ zG*@spS-9bk?)N?VK#wJUAYfTAkP-+vfGyM_Jc?Q{M`p$|v^-CKR4xH@9-8F0;U=~d z4r<;cK1NGE?ts7zJQdk<^F&VZ+WK@CjEC5FLnh@+1lwU`ChFQICb6Zr17C5Dt+a0ZqBAu?`x|z z(7YM6Sd9>r&SNZFn!;FRP8-y(0el6Bhil zuzP-R@EW-*)}=GZw>W(Ed_7$Gx)trUA5Cxh`@+0>GC=K*=yTnhQJ0cqBucAX<8r@!R&&QjWlZx$` zJ=vJm&r9!(>!xOl``uN8=uJVULIx%}T8~Iq zM(H7|Zu`oeUpCKcP}NXm;_)w}2w_s;Qqxt^P|%0QnxDrqohN&W=L;JhJFLqMTO z4y<~J&IlaYE&cjyG~?zsUySss1tpT~q*XAbZq>}?!vmJX|anFToES(#1(^QG& zUKN~InI7~xFT`KsA&}dUXiJVjmx!inH~n}>)dXZ#A$`;sy6mb9IMTk{h<0h#2_O~Q z(jkDFfuU+i<0ZBzGOUZ`)hBRs-Oc4)e`m$by1~C|3swav(Q?>_MP5*2Ls^F$0Epi3 z7d_n6Z$;-;uT08aclOAmHMeaxo%SV(@cB2Ne>i;DYLHM zshi3Gw&%CxCd0H#I?^1$x;u!w_(YeA)U>Ft^Ym=msaYIaol+*%ZHq(<5Z5Lc>SOB- z6F&$N!JclHc*M`Upuk@pkKXpwMzJRK0Fp08p$#&$P=KwTWVqMnIF7sm*)(9hJ~88c zNBrJ@)--?W$GZ=HhfdDNJzZhZfw(|dGefje^a2EFr5UKlS}j0I*F=D_M1qv(7Z)C7 z!er!Z9;#044wq*e4LBCH@OJ~;+LyP%RM_Xn^rWhXsU0CD|%Wm^&4zqCwu;fPl3TvY`f1 zIA7enOUN9uxh1f(AsmQdpSy-9m{gyJrV*3atjRzmzM}{!JZVP+`6BBy)(U*Mk!ud_ zV8=|eI^p+@)j{;%p0^xVcCmQ~5ZwSdhFIAb)gV8MC=NFT5){B`^ZZ%nH5G@dNr+_s zD0E)ypz^%CnTC%A5>S#$MR z^7H+HqqsEjGColW;2n^F%MlJt(tYFoW3J*(i)i6kY&*P$vaQIb$aUQo`s!0H) z>r~bQB>>VdywdwmW8PY&uS-T~S@L!qh4kkbRtixhhit8Ne8y)KV-D3@p~>5{YqZ+j zODNK#0B5N~{RD@<*<*9B7#9|DsN;A9r^;TZT3zxqs_K;PQb~=r3q+GF%la*}y;TYD zNr5B4(F0#iL zo@fPXnKV48;a6P{Uunr#&?}vvF&`Ym#>cD)sRsM7vbW&XN1ggaTVG^bezqtBVx6w= z1(rw8gxvrM*JZ|fi{}AQI!7p;%&}nkjfmyX4Kn&}vbAy=Z(Z+#@Gwe4!90Ak@Fp4_ z)rqi>>uTUepLU$79{mDe(9S?eVY2}+N2v^K1T~m|9^(0a+j0 zXNYLYHJ%|Sp_+yjxn&X>8j08Fi6SK#jFfaz@C_SH7{^GcU^UH6oQ|8Djsh|{4d(d( zI|0uI_wr3lZH>*9#^eEmYI{vj<>zlPF)=sQ9lh|cWUk~`l=L?`i)SjEFHksjN>uJ4 zizw|g<3sALHwZJ>)2zOephXnroiHPPd*T)X_}R9NEk;4Yq3Bzo^$b{GFdZG;oWhxp z=FPLZ|K41>Wd3#{l)f+Ve?!0^d`Q13PGwEHUrQw%dF1Dh>G>hW!P7<_DIj^UJ;OsU z;U?K{>Zw|Nm3J(%s03q0{nYn@ocCl$J@YcVIMz6&oK1OjZ?-fv76VL^OTOiSmTe9_e9E}7v3rUQ1NucU6SVPP(>dtnuu)O_trSuRzW_0WC ze`L$#lj9r3Km2$(1h$7qS00CfS4yVLG4?0uP{^GZJ}Wxe(T-L(6;hNRlGaxaThUQ8$FO ze4m^mD4z&)$|ti3SR{uH7f5Rhl;%*n#yfwLyf}t*Y3OZhoNj&J3|;kA6b6wVSgE6C zM8>YD_XoBh^!c)~5~ZGVwkqZa%hbMNRpf<`HVU&(L@Yq0xr*ps5Nc(pZWGkD`9npJ zuLdoV?woth>l;b-)creozFhB+UZ{v4pN|l1kS@yYR7o?2y3gLMC2YcSH+*24AH`>o zxh(hNtd&j-%LBX)VzHgc59^M>7JQO@bC9R(>^|SgDvM#qM#v#hus3a04mkTE4};Eh zxpZA&&uWj!qN5}0EJO(OY#4G!P6M(|fBC!w^Ou0h}kJ8KMizzX|;RSGNCCRb}L0X8G4l8Z-UBGfd3%|0jm&Z?vEtHXBmUY{xf5 zzg`9g%k(SyRw;>Do~Qz|3~UiT2u4I#$_r6-*0u`p>8fiRNoePSW{W4wjXnWToA$&0 z6cf{|{iBH_WTxT|x-WX>cko2tRa)PCkw|9!ST{R5YuAi=3j_Ora28OA98uI za{36>NI33qnq|7ZRNEm~iT1X%u1=TdDy$?COR~dVH@@N!2jy=ZkHb(HgP2C<%WXMy zHJ_(X;Kr}7cGe+AG&2pf6LT(;1c>tXTqm+10@3<&Otw2ywngG6r(zP-aUQ<`#F=XV zf+2)&4$oK4a^jwUxAgCTDonJXug_-JqjMh>t+KV6JzI?d-t;$AJZk~mvyyG!WNu&=|sx% zF}$6(@=P*O^^j9Fl$9n;SjURj?m%1VJn<4W)Cr%quNJrf_F`4}?-+izGH@|NerdI- zn;q6_nIXcW3amv*Dt)BDW?-EgH`xuAh1ps8!NlL<8 zUNmk${SzoTJnGNNncib!V|tMNHTa(u!t%s0y>j;5HcS=NoY%$|9=KtkK$B>OYb+ssQ153cz+`dj z;x896rY#(LzKJLiTY9TbA3c24-W`pZ?37xiW&;ms-BQm?mHSZ-RRg3heil{nTe1J} zL;7GR7YN5zJHvSwjnHT?K1lpSo7pU1UVuj4JC#KQb>7M*p?t%!M|W53$Eg_SfGR_I zJiSj+7r1|-;>?tdHtFUO)mtCJe2{^|2>Hj z?1AtvE8jsmy6~k_b2{||hyJT_Jb9VC&bESJMw0D`7DJ)4dzA~?D!#DUKP?K)?+uP; zfxm}pV@8PpwOj>qOGSN*TroN@v%unHl1Nh>3&c%{HnJpIB?mIy+8>d?5rm++Zym?t z`6K_~>v-@LLW425MSEtF%9_k?Sg{Ux5i)Y@g(c2g5TTzsx`wzvCqWQN-+Y$s(s?Tq z3M2~7!DW|FSI-he1zpd@CJ>MFL zAydHmH{?Vs={h^H12z==Y_J(?px1>MT}?@^pdE>z(r+*i&xz{CduA0FNe&2g^V}WX zzu22^PRnymT9$8C!}we5cW&$LZvX6YZ|P5(wzkV<)T{bnRh9?!SrGvseJ}ie{`^Jx z5u$#8)dgTTGkw4J0GqddVO2(VMmI0vxCT;tRzcJo%x3B@hOqoE|EW2tB>xcvGC>le zsul*%ze^wIS~L5Msj8$tw}Q(6X&r@-^=>Yd{~yNQDY&+F+y0Ji+g`Eltk}tl?X1|g zZQGf#ZQHi(73*8?sXAx>>)X5PoV#%`#?74dRBQd|zur2M%&>EV7Fv7=(wFDiJXgrM zT^e#0&J0xEOak38U4+-=#qtoZT=0h}W6xA3=aS^5f1a9liINyP24j|`V+Sja`#W1Q z-#iMqzzco*1L%wpb5`3{@%aUF*{WuM;8jz~qxX4Pr_O9#-OiC9Sfg}mqsSMqbAQ&< z>j_MU2JCFTv%NIA_H}-SHGm(^alBR)ob=?EGa9T!qe@jL9Nr?^tPJx?lfX|njntO> z1V_e@JxF@P!Xbo$tGv}a?Mo8EA!0&8a}0mHAj{7p(>cPIb))p)JY1<)^S`gh0=5{( z#XCxcL|nC-MKX4uZsM;L5O~&NxDMCSYMH7|hH5l6MPM`R}9H<3RMQey}GE`o=tYEC)$AmJgs> z-c(Wi2=+=5=8NBNnlUK9!yIBZlULc`1K0UQ8LyUM1U3i&`-C3?fK6&QSE%oaZBH@) z&&U~;>=9j|)w5$Nt+F7Wx@g&En4?1Ns3;q*Er3+$cDp+>?{x0#bj4F)jEKtN{-{`M z0b*sgsR@O`NkI)mgQ<`x7iw5c}ynTb7Fm}?o$8ucKGCzW&| zH8c^cetZwO5a|h?4`$C&E8F{r@WSCj+Hk+l_OMMKl59gGHhP;#1KQD;i8vEHG2iRyAUd*(#*d2=#YG0sNJJNCi{ z=;-N*X_8DAN>@L*@hKcj7s7e>wcwlOm7pTD`PNm1*d(+io)$BG3eVlhisW&Hd3zF=HI(Db8Yj4HG=$*2M9WvM zkEW43Px9ud&RFH6LA_B@lf|8N2!E_%WCqAIG-diQR{davC_G4}l$-#T6{%SqIAmt43vXlGY%njbs|>f5Ws>Wb>W~~g6oq97$z048?flW ztrYTfAAz$4z7RM!GFh-SegD$cv7UN~5lR*1S@6i75Ib*`exlpdtNhDIm`%3kg58zQaq`-8;1ch|;Df7y^ zq8Ez=E`h%^XVlL|@rcYhHwPE)A0-dOii{+1qqo3*a6&~v7L3H4U9FtC=qISDa#z_% zHLv`LYnoK(0Rkl=aA?RX5oxFQe#q2fe>ac+==RFVot~!W+b;d%ko1J9rV%s#b1U3= ztxAXQC)ItJ%}RTRHEyFZ@p8=%%%njD{6L-05pgzT9FoQ@X1r4K$-S4tA3Flge$j;F&~N4`_~^ zW!u(Ns!$^>K;Vqt1zz70po49l%HDL?T{Fk?j|5xg+7~B!B`q)}`1nh^Hy|a0^LU-z zn&3hGmB`+lZ;U6f9fawE@n*eWTwEfAxnV*WAbZy(rO>gp9vxe`?MEF9vd6D<#~^doy%{<~KWW8$ zGT++iv_eBQw!lovhfPr@z0(4(ss%0!(l|w}*!t$z>bFW7jRRXaCj$59=!QR9v@-75 ziA;G7?6c^Q4A>+#Ms0yEAZN!AWw#!`KzM-H6&~Nfx9F+h|KvH{P>T8Y9)@CK$Zl;0 z%L1afD>u70Lu9Sg{3X*?8Ly&9U~Z zZZuc0%RxejQb$d<$yHz(C0n-ruGj^)Bno-f>CypT0X-pc?uH2j{y4QYZlZhl)^fIS zDiwQjX65w-_N1LK`S+vuUkB=+N{oZ+UxgUczmqbQ_I(%RA>fzzd)AnY5q~c&&)wr zsJi{#wV8C4U*1nj4DTpcDsHPbVXfSPc+nc_tel@d&uOlY$9kIn=l(`&EtflKlF0e={SAKy4i&lBF zob|=#v0Gali#4ucIHr$LS)1`>$%%rb=-nO5MaKM)q3ceessgQY4|}RK)MGnPUYQg~ z$vqwQQ^BRo?}yX^F@GrW0L;Qn1wb}~(j=$(nv(>LCB*CnI6(UD%^!KLZiZb#$@+ar$_z}GrmpbmMlfEaa}E83ArI#oUx)7$UO zm>={HE~;b&Oj5{gH+Z?;)f@CeFf(MuslpiEqwkhJg6U4HJf_j37kGNbtp2jt)1}-b z&_A`bR*`?fK*StDj!b~sB3h`bNX7hCF5disH(9oz4YhD$xMqde;iM$jp`bFaq_SbE zSS&M2#FS#0Z-rVcgZKoXdA8>E2WQs^R-C|3pp^`}3mUY=hK^*};Dv!cgJ3(Y9=s{Y zL*BxI`IS?s?^%o;pwA#wdyfK!r{tN9Nd(sTsRKq!2;^79lOxi~Pf-BLo{i+)t#gy- z{Z94zlS$_kPfo9BItGAqKM&a?fc`AgPnEY#RSh+>L~@6+A5Y1?bdVpzP>5Gt$chZ2 z8%yLzu@4PwVTB@UqoT_RolWbdd$;=QeeqRhF85D<#D+8>N?d;AIyPH?+ZrioGXF_p z04q|ioTAVa*3B0Z>t>8FC~-5`luHA5iD1?trk~Kz2o)(jaEUvO-CmIga!rg1%NX%$ z`-SQx0z8l$5vRrB1|o-3W#=fLvwh8!G}y(&{2#{QZiL{b;1ZXn9W^7m4th0c3|1Q> zdaY^w2Jdv7A2^__$7CmAbCU0dOjb-8kF~@a&vgq%2Zk|}#jT3~!>po$sh-Dw4+Bj4&@SbTmrE`qvxCE^a2%yYT z=i|@Zn?|0$zQ*-8Zx7BZ-(qEGYpof-8%NI&T^H~LUyth=cP~d;_WkUtg+T#spF*3L z(^c2?*wX_T^{+w;A9^>HXWVOCXtnn8IvRQ#y#fqgfBp>}Q~*^^)f@Gk>qI7v(+tH+ zOIPH3Wj6c~Ll$=)%laVXv0|@=V0oA?vIu=>xchQUMGYg;mdfeYqf^zKN-VIHNzNt{ zar{+_t;SsxCGY<1^VP<7Zw`-nFWd*Ufh zSKUEi%Ux1@n$+!OlrnqW5yT}Il@P=6jn0?e6pWiquer!+gU%BIxT$DpD_)rz8gPv@ zYt>4PtqyA}If5IWIke|JlZX|oD+biNEFmQL-Kuu!kpUS^7d7H`auY>4yUnR7l@<;q zx7fjifXOvBtT){}Q$KOnBFV4NO=&;8w$b<1h)KyCfi7GIBgXziy3EdYl92}xeB*o` zZmds%f`K&+7W`R05qqi40#EKDQ=oXxGo6zx7z&yBp)ilab5A2k-;Z;odoxLhpX2nJ z0VG~);8nA4Bz0LNVf{0{z`rjY)c%8Y_@4|4MkeO}aqUe1&c?Db{h!#_E=?`ljZyUJ zhB}5%NDmoJbKYlIm*>82CMdYk0&_<@Ct331=OdpZxdlAkSR4pwJPU={ z^y{>1b>R$Z)F{|S?yY+R@4MHNyYQywN2`Y1_Vo00O;`?=Fc)7;4wvpv^3q@ zysJac4PyemK$D~b!P%5SurXyhRF&Wf>+7diM{BP~Gl|XHNoFTKvZHIS;_ovXdOiWM z6RwGBW;YC5{O%(B$O2d>3ShHWOo9-@eX3 zUN!Yu{Sx?*f>D7*r0r3?yi%6k7a7 z^~x>g7n~9M*WZC2&4s^^w-JFfHQpts!r;L|S7*9!*h$bfqQUlENH3&Eh(MIrBuFmn zl!R9AsrRgxel9|pBJVxw0F6S$(`s&8odcZfaAb^Cf?nz%X9cOp;hM{`G^xkI`$L|W zGFIfX=%J5E;`g_$o*o1n@X69ZTv-YjuwHbyLNEvZWbO`Gp~V3hmL2drW#SLx|1NB+ z^YSA`74?FJ!)E+N)xZ%VL&}*0xFl~t{3~`o8Dhl^_?P@tH+7cam<&r~ahB?Y!9Hnx! z%KIuP5#iZM+;uYHO4%~qp1vuH3`mwqinBfcyssElcYp>p!!rH^zo{&BU9uP+ER}R# zgmdD)|IcIAc~HQ%HD$Rj(GpcT6&D?5Z6hf|xRBx%+Q(J5cH0-ky5^MO#M^0y3*6{P zw|AF4I%7+ue5QDCo_NgEfolbz?b(~oEo_g3|Fg;RW=qkI^H=#wqcje+kOc4fRt;wU zQ9;sB_{z-&Npfttn0!MJA9)Y;ul!W>jI+j8^&r*Y1-AO2vuao%>BMC)KjdjZ4pYg8TS~$YhVPE zyd~=nes^PNoiIT54y>4a#A%nZtY`CxNr2<68IXfyJJG4c)-SS{Ux{eLJ)p8iz%+r#L@u$s)&ZW_VZ{ zjnqN>A(8Ox+Q#HCX!j3};o0#VmNYH%>F0#7se?T5>*Zytw){{T^%K4e%Y3{iwxVK; z_Nd0a!Po^NG^6Q(d4!da-Es&a;jHSVndGC(LcT5+h2xF{`%F$BROmr{NHm#dhg7Q^0cdn;^=@k9(enAJhup%TxW6*cBmc zndL5)v{0WoWOGj<-R55FgdJn_55a3%V!;jsAy&w%P%;sJKP;ycA+J( z>3mKzD8QC_CQ4XsGbiHY?d#krIpfPXbANKZs`5qE5|g$;gY?gqZYh37?e<*-$hK^; zEm?MDG&?^Q(_n0Cp*6)bC1+)m3i(fq4cZ*eLk9<7Naci`=5{qEKqp6Ba;yAQ_!8?} z_q+}R|=*|Z26^SpTbPtm@FUN*i7lbECx;j}mVZjsg;?Us=SJtv3bE#QWFI$`c zxSUOTA|-*AB#glZW9=3fe7DubF>1%4Qa*tXBUkFS8P9CDGRmhkSv=v!XeSU(^vtq+ zwc@)zKt_9k*K$_{Q$BLM$$PPv zxZIn-`b03P+7ya^;L4fp##J11tY#tAuDu$Wol|P1)skj3s9QQH0Cm>8I$ukLiT1Jo zxAO@HMHkhHZSj=>iMQl#zIn!NFi52Pc%VH*|78nj&hIhZ)gl0Wbfd{ahznW)R6>dr z63jkFO3XqGeal6c>_SK$u-#9CVHUd{1N*H&Obx7{x>@g1Z+iwdxWZDjbO*s>tR=eD z7PT#5MO0?wL#Obm>-G|ceGgTLX@v}l3$Eusuo5B&+g;;-gU5eo0P?L^35Qc|96JOF zr*;MQkiC+0B;<)G7zpN&f9vw|TokL&PcI%Z#N-~IY#vk;FjNP(!-borcwOgslP36`t<|g-uQYqa zHS}KJQI8R#_k$~%>mdzZ+~`oy++I2ks5*gfNNXfN>i^&i|A*dX<>dSyU&#C)=w0Uj z6TQ2nDQmkqioErp&+rNfnrlp2u)4D)@w7XIgG)TxAD>K%1jTrY%r@XADn%w9aetxw zsVY1DN1~Y{wbzeaVe0xEpjM;1H2GOiJ6hlP-9NK*weMr!Lw2q4QP-~X<<`d8vFl|4 zLt1_~F_9VU>rYFrMMDv(M9*N0Ng0IE>E``f1HJ^#rqY)%aWOO&`jG4E{+qC&p0Sd3 z@9t=aVcWYlc7{GI$3_mF0gTij9m8dcy08dIlvchxAo-f1{?-BgZsp&kiDp40_;QwLdips*rwW162F z;I~jHUG121AzX3T)Ujz_K!r_Ad;PiYzN^w_R1Ei0LMwIsRkW#h+)dObqDoA;{599b z*0GS-gPIk&JffPl2k7X8?Ndhqebu=ZzOA52&eC+FF(D3KT(~%8fO=HsUsS;z*M)oh z7SAH?NqdA1r?#`mod|&bH9Yjlh%k)=s>^z3v9f%fPakA@hokC=uO@|hg{@P9(GP`9 z`g|(Sl&H*o1I!d|yM@rPo!t*rB=DxcsbV8vtEo(KXAylpZ@&Wh9tKJxJvyy_;G)*? zt^id$clS7A+5z938X+om2MJ7zm3sGLtpoq%1;w~$e$%RIgdBWO?OBJtm zoJ5xGWbh_v zZV}|lVrVgrt!hLc)Qko^Q6~rzpj*%|pvS<>aN(P(i{|T!IZsQ0w#zN55aa9C#K>5`)IZFvFOSm{9L;u$fu>myLDzodfJ zya`AJd))fjf^N98^qay}9K!-o^AYlU-Y?n_-3`&UOFD!cgm1To_W?}w9apQH)|sko z>;(7<*-~(}^nxAor5D{BTd$l+aiO&2kpk#{a0g8_XP{;YGVW%wQj4m9p}q;P@81Q( zQolx<@XqRqv9`3I0ZRT@j{Mw_VQ^S>dZpxTAC6PKi$fOi`=GOz>p9+jF_v3 zb(*%g!&s{bVK|X~w6;zl)RS&CeZ7ztS$Y)3R75w(cg@t8vjbmXgWC)7me)ObO zhrSWVp;F@9Ewr2A5rqQ0?T42-%&0_=@m=8u+OD90a~PJ(BPW!a|J zK38+Bura42UQbk#3an3@DS&G~EsD~lbKAm9E)ErfE2w@@Q67N;cc!xg4m9ud87h-S zI*S5LX!5YORgX>xmPY4jtS7vv;cY_>M(SxjDhC;e34C2S;&x27w% zUS%c(wJzZpMH~<}?~NpvnQZ%m2L@!C@xs(36m(2k?0FB)%dn(%s$B#lha>^=L)yRmv;C}j<67Z}m;H(xie$)s7Kz+p*Q1c}q;?I6Z*-shhFS5< zNNw+sE*t8lPm8kBtyf=T8zGvG+Dwj%+>Vd_sBz`@I@2Z+8N%_tg11-M`|gX)+oF%%hW$)>N5a~{gEAkZ$k@!*P!u!y48lu z;_h910sc)PRWhF{*vr3SMI)9Fu2MiP;O&N6V8(hpdlzBdp(wML30U*E4!&GLX=9hA z#u^z9u>!F&LC9jSGZ)1N`%LSX6Bx=VwdAuhR0A7LNw{+L>2>DS%ski`xNpSmkES|> z4`PucD+%h{!q`KqQV4LfS~ZoM9hmlYm*e;Z!0NGz-844za8`0hHw>kez~@jUe2Fd48{o!FHZzlNGqU;7%KouZ zxk=xT@%z$`W`@c|ib$q&3GiFZd1raWAkNhVm<=c_#a=W4CVg-{;&7mo$luBGyj z1yKIW*+^zdba1kz7x#u(z*%b~x>sli>s9m9yI^oI42UYZL!TP%;?>Va34_j_Ws;7m zNs0{)8Ot%9ooWG11P36b=9S(sm)5+B1!|J2&Gx_%pK^x~x?Vtx4eulbA8o z(O6+gwq(klknl`gjC_80R1Ws+R`Q{KMSRWD;1s{4bWH~8{;zhN3O`#Kl>~MF0;qJT z$P#aKE0PSnQS0nO_8@&eZX=z{vR7l+myL=%*+!wfP#Wx0X zpvmR&)0{J?tkSk5RK1lxK?$HHU)xpUEnLAznlj>e-c)>Ty!4dsQUoTYjIg!?E9_CK z$jw^5IA-EAkCDqJU3%eV^JuFO6a{>#-ZiwlHWo^H@`lTLuCoo=TN*k_x$<>CCP{Ff z)*ln?5oBt7_{%poCn^3W1v2UDQSb1)t` zPy0~>1S0tPH*o3Tb^r3CW}Y?0qNp<{M04+E>%3#m)8FW!$&HU|hR7mFJtAUs1qaIGZ=*gtmzUt_Do0Jvlr%VW~5SL}xWF*K%m|Wly!&zhc zX69*Q{h+lz+c>M{x&}@*2&yJV?(;+6j2iCm&tzna9-$MZ_r2gxUAas5*y)09MLh2H zy6-Poov;4cfA`7%<$nJQg5_Xm{FhJuZ}MURZyYLd$f7ER!Ph7ptB?OS6`2eKF@47=%oIdrC)^=XLoT zZ%I&e`FE<%$;I5s+zAt`(W_ZEK~Gvt&JH7w%b-Q|k(&ok1nlZ6)BejUlx!J+{7NBg zMXsE0@R`z6DUWQ?F2ZV)ZjunF>R0_@kc-?P1mh|pdejKmM9deEs zs{D~#$fywT9@Y07o6Oiu0MBKAsk9LI++q|1G0ooZmFsgc zyNNzXvzRTzpv)YtTD96x>4GZ0y9ng*(9VJ&?na8sy)78VM7YUP_gqQ4a77YWQO0-- zg$&B;3r=O^X=LzPM>S{pgdg**QNh)+#~M`)o|A|gejtCVkqu7cB=lploD5EGJb7q$ zS2v}GSP51coFz#7pb3SX-<6tdk!DP|ND|~+riH<%uC7!3*L2|uFwfV_Qrbzs=Qj+w(Q&N9~J7=WiB7-OcDVF#l5v4NUN92|f%lTb&av#UzhTtyW zq1{4%@GvE~Z;O^x>>KW3fgCK!tCgQymp96TsyO5pTojF_Z=ZxYR)YrsBIf)pTShxX z&a%}q!Mvx%d)eJ1S9>upm|$2R5QI1=v2qiN|l=eH)M{_Lc>}GkA`#d1a3W> zznXQbG|8~x-gFvX)7lgblWY((-B%hjlVrzZ=Ar8X&mn!D$)->*oXX$T#Tup}y&nlj ziPHExIIX;1gUMcTW>zEkf&H?J-L1MSUB;A$>yW)S2-?k{Lkk*1T5UIf3b$d3R<0ke zt+DqS)O3C5e=AUo|sLD4?xMfDa%Z36mv>^R-wX@IkkS^2AaUm0Mt&ZT`xn5ktVY<*}@we;FdR` zqL$jGOTswzM#PxRNl0=#b8<0nm$@H)#?v~SvRWQ`3CN}J^ys1UAivR`F_l4{o9eZ~FWiF9SyGrPC^ zh@E>RyJYox=VT|_;co@=!Ua8Hj62->y1O>LXK^7wBUGD{wT_zJOV>q2)}q=b0S_qv zDrZ5#JttK}$^(J=d@m#l>S1Urr0Vp&bGdgI6{4b}Fdm*Nm=?8)&|RZd5{x8R10z)BF5pBonl?E`}Db(K4R1%>Fz@Ak7!~l zf%b*Irv*lyx6c40HPxe};P4Fr0zTJ4$V){<93`YMz2TJDJe$G>av*^SvOA$Q3R+(u zt~o0nw|_d&0ar0@w>Lwh`0@ie;9y2l6i^@<Ko3Nj-0{N^D>atXJ06thC8`KHSXNjCLit4EK#9pr1I zm@-?17hRlYM1!?#4UQ)`Mb-+=Jst^)vw`#Jy7Lm-gC)92AqEhqPQChyMRZ*wuWw~N z0mEQWc%4Y&hNG8;+6J1rARJvn$2f06*pWKH1Hdkmwg5J_rLi`){-e+yqQ@%y;SwZW zckc%QyVk+%ide@hg+QD_=hZipe@zn7F`d{@uTg}=QM;z(eY?09ZJe4zECh)`)Xz8X`OK_Y{j< z__DTHV22!MFEib)8WM3sU!$WF|MW>@fe-&n;Qilzci6t}pH+uB%@K6dJDu)($j zW^(&H@&?UQYD=QSX>t{@3=QjTyZYaLXE(HI<5U`0DN-UwAV9|?EP0ODKvzx5Fqw5u z%J$gAPK7BX1=IN`I18CLE2@9ap_Qsa;}!xC!`a#jw@qXY&|VHE4Y6HEA8bXlSB({> zXa$}~$nT&5NL4dcmSjy+9&L^LlG56zKra$tR<)BWX`#_)esrTdBC$lIRCN4G7IB)! z=N6FX!iZ83aZVC&i~l=xGF@1vJ``k6r$Cpxspi~=oDl=E}QXfmP!uaJRaiPw_*$E+?j5vY|`WJ}g@Ll|Lx_%79S=8}^p?YSQuIA7JOkTGjMJ)Vb1 z^#zLKX!L-cS{U?r-N(bMzzP-6}zf0;r5ka%>Ef9 zt+#7q(7e-#LkOp%OC+qIG#QQh^f*JLqGv`Rg_vvUCqcNq#q=F_p#AnSHbjUEf_0Lt zU!uW$5$(_-bb*TH>rg9w1QhPIQ^ET(U!I}`Yg@+1F170_{9eLFG^%99(tz}no;a0x zHOfI%h8XfHGB=zXrY-BFS)CcJQ@8s%i&iJZ-5^ynI#FbdTKrJb2YMI0(saGTS9Zl99FRFQhm&aVUhMT zbAfvoJZ-61_WKp-q#6V%jr(S-|GT7fru;9x5od7rfGKZq{=Q-}b7`kP?ODygSSMv8 zTE2cP2BS!>QCN3+KR+Em9x?39_7*8rS4_`6K9}mceSBz~obIE4;r`t}l6rEY3sp~l zTe(+0?c1~2qQV3YGb?(Js?KN`9c=N14LJrL+ZGCY&M_Kh#kR%eg7nqNLIp)9=m8rUnxm?aa*AHs>FAvOCxjHdR zoq*b*i-0lu?&mdy;4oR57P+v<_1(=-eFw}JcFt*v$4lUHSBKpH{`|lmF(LGX-NUspN^O*#sP;9Z@r}ptfw_j6J)!&C>>Kw| zase!P60^V01;$5T-ki|T6ZJtg%I836@!leB^fsq}Wa=7XENB8wmrN6OBO%-mpwO~Z z6}i-jg>EeXy<-GznLlj5$&-!|_%$#kvg#*f)3!xH1Y5&mvPMxkz6MhDBYe4UFxnMg zJzUtaBqOUcOlQ;>MEg6mp&L-*eVmr1paN+<;^m=}R(Z}(jTHv(n?9;=2&H*;a z42|M(ND`N&WmA4Eg{^#ZH#!w7iyH~Yj=I{Umw^f#BHCDAquoh$RpYNyRKPMFvEj=}kS%9PCU_?@>5u0a>oYfjtl(%&4cSPY$pO*hfGH5PUYV3iJkdhJsg(*=Jfwx?fQrJ z`Cql`pOE>#J)EhA-B_%bu^(=l-aUiz%~pc}_#=0g$h1VgdE!ZflS?9&Cg7tzrEkAv zEz9D;+(1Dq#N>AX73YgwLpP{Wt3hwRf9rSm+t1zipy0X>v*xT$E#CCrZW>4 zA_H6fWdBCY%l{KGKX!J%8{E{B^@Up^&6Q?DwwE=Ku<#IwIdY@t%kTX>B(D-cHRAN< z54{h`Mc&Vx3L)_K2R|6ABTS7l2Wa4Y-(Ej6Q09I;{pO9e=c=>I!&oNdJPLU`pj6)L zzr0Z0(5^mzs70jQ^yjnB9rAF-mO~fSOqSn0^>MU>FGq zeN3@4x?g-0%NQqAsQTD%{8j!SA`s<2lHIE=<{tt2ccYRkn()QrRa5@S9V<$+B3X z?+M>e#2BcdTlWLlPAMVgFat4Gyb=RYX_?JkRu3w$JZ4w=5mv>B#Zfr}q?Ok$b_^GZWwDfX32ZI!7-oH|ESwAD82uXLk=4dW&s$4Tc4sXhZj>mN*s0 zeYYG;kr1XE+~i?^YAZ@$O9B1H+R}ze1EAeaM~pZ^UDs~GNo|i+u2;9~roX}&PS+4` zc*8x5a@V32+jvw3N{mc(7u?58p2B`62e$F7OAWm+1la^xv>L!}tzR_%5^-g{u{3c) z?Tt6!TG^wg7Fiojp$+X7?Hq-Tbqb2z>UY6=vLL|!DtRME`3<&-maqyGsr)Ul2?g25 zI|s*WTm`wpK?x~N>61rpfcim^7Ah;(IGKlcD;uD?``*ZF0wdF~ zepvdUuw#=MR+51#rSY_QF+*v@k-_XnIslpGjPpwb0XCzHkav&RuTEPyLv?{|so+(< zHMmH0Ut{U|(l*kP4UwK5=!70}h?fEu9Zg!9Nl>A`yoo1%J90eoVu?1e$#37NanLT) z_B~$6)84>347L~!Z7LTT^B@@;2CNA1bkdtGqWvPy<7xji@c<^Sa)t+QWbU%Hd_paS zb*Q~#3nU^c!s~ImI7X}^Oj==%knsBV3^Xhf8xgOH`t%J9OnqFYDmvwGLz)x6pMH44 z!S}Lk}`su!YgIHz#jkRZ5A$i4?ew z1R#5_VO8Al%T{0j@zFr+8EG@9t|0s=J5LZV3bd;Td0O{;)!h~tk=pmO$V-NG!VP0I431oORj*G@R8iROVkZelsIM>!*(>vm!tyA`{ zn0MJ;RLd5kP)+a`c?u6g4Ehy;D-H9u81lOa*G-NA+Xm>4mF(Y5!HhehL!%;rhTi1n z1cQ3*Hca;VujyV>-Y{G1ZeKivvK|+WW7=>aKl^b?%Oq+%&@ysSrR@grK3-aBOrc7m zhrlOTl6m(QZkEP6X?~@1G5~$_5^;`*%nh6!NWC4tp%)0kFs3}F>5S9rYs-*^HDjv= z4GM+10){fsq$r*b2&tBlz`gP@ehj*}~s=(?o;k=2JD?-)w1+mU*U zlMUb8EO@%_1Rom$;|jsFPCie9*Uxb}U|o+X;WAg4SGK@LM`dowNS50yk972UpOP$i zbp=BE;IHFR@Wo$pu$F{{Spat(D~wh|l=k#tQqZX~elOi>MdqT5xQXm>JBzet;&P*8 z5FH{@6gHj-6QKjIPQWZ^uLtd5tg@j^&?-!_#r}5|fxVA0NG<+RrzI@JE!tnb+u~e9 zhJk9cUw`jfQaFE-u`_R)z9NcpJkm;SlxrV4iDYXg)<`xf<7_1 zpNO!!RvC8?pO{g3tAhC$L2jDNvBhI12b5a_}> z=d~sV<$gQ)Y-w2V2ch$THfyk416%|1#Z*1L=d;PY{JtVZe*9pzj}xSfyATNF?%b0Z zf7ZlUTk}pl76#n!r_U}IdnvX(-)@~OkZV68-yoe{7pir1Wy>PuA*zzqj)Q~utA!ZU zPv6>^m+jq!&!2`q>jb;m*;A;-3ej0)^?~a9o%+HDBlV6dj7{Y_hZ9!isP7I>23^Vb zh@%Zjp8-uZZ&XXDe%6U$E`)z*v>P@=F~>M<8-12p6gNVSJaVFZ z#~3L8swq)gh#Pyti$lEdmC_x4AG`^p-P|r#OL{{~Cexdze#ou%F13r_D|NQ2m=_mI z?to+kEih-qWvSUGK6~Bo)grJIoOjF%>r@DhxpFFd;?g(*I*zsg?uL$x=X}VvT~JiRo^S zw4KCx2owZGmwku&o>VkEo85?4V#E3#SIkYEt-Tf}k&0&>YsQptm|bD6N<_vZXDIMx zR8QwH3URt~f39G+1o7DDk2~2v8NY3bu~3D($nEVuV}7@0eY{|P`x}ZnP~HY&+EV)5 zek812$7J!4n5P-zPv=+iSkML$g-pz);bK{r9AC7rWuusxGoE#KPWx=3nRq`MJNkO( zzG4rfP>R;x^dWK?f**0-TRDDrYDl6Emk-QcwU67bto8enuvv}wQ%)FqcL@02zj0+4 zsj^b8tzvi15L91;$}Ue5vKT=P>QBCWHHRqRwq);2jelC_qHnZoNHF%pALyBP>6xZi z)#QAYGe!K6ielci5vt@nzxH}m-Q;6fR{i8U;oObk%`)Ja8P-W%$x+*h_4qcE5zyPO@6{_ds@$o^5_2lmS#B%oDJ0%hloHi%;ZPx%*^hXTSUOSX|~1 z_rRvH(yFdajvh?Ig81$%(jTA}>!1M7PQ8La+F%f{Z@cH@j|C3$ml2q-Hh*g?yT6kW zy4~rWIQ@(kz+43k5e}zevlZz}pKy4*gbM}btt0$I3mGp7=Q+0y_Z)**0BxwX$P!OM z#f<-tv3G8+JkGbaW81dXJGO1x?AW$#bZpyB$F}WsY&&^+=BYVns?Jp1^Af)MkNsP< zKG#|+4PzmSn7yevNLk{Y-cmU{30HSN2t>OA!^q1 zbpvw7E!Wd$bpI#TixCp4mgbjy4rlCPu!tj-duJF}JnR=sYs0Z1H z>nay$3pVySW>5Fe+E6xAc`8T2lt=61dVI<<(#h3tk}EG!+lcu5JUM#QK;y_uXQ@2w z45&0Le?oKG;USL3jnL*&K4Cg}pjKA=XbpyhPEBMP`o=X7FXkxNV=ERJQ07x6^7AoU zlg`XFJnbCGY-=ceOP!iVE$LZ*EB`+*@yy!6g5mOuWGX@T{+({&%Ytwk- zWG1|Qq_wt)b{8clWj={sbjbtMFLFIK^G1kl*bw6-Ll2-GE@qAXOBy zqITF&N&CXOh@4gWi4$=%^xAs;Z^Fe!ML`G^_~<3`FBjo-;x7i*8ak)MogM z#;)>|-6EuID%NG+XItNQ&sxpIn`}>jcyV6Pl4vY8dKE#l9buyQE+?Sv&JTi=(cCn#HNsRCtqhuhbH+4m8V?(w8e|)&ZiK`YxZ#0`#K|%0s~eck z0*pJY$E|rbtO2bl5xv-l_{zjUQJTC16yV^au~iw?iP;3|peQw38c2FZ<}0Q&lAg31 ziU6c#J4TfZvAnHGsgpDpFA1W)b&Y-;^S{o)yfN@`o4Ufk7@U_R}o#s=H$qwq_rJQPxL z^CDDL44f>8tyWy6S@=Fs{;#_uSyb*kR4!dLnFLW`?vSdw^6V#4lP;>bo1Eqq0$E|q z&aSc*T_XbK_-K-&qb~2&CO9BZ=$%6`O1842cY&3v7&jbrHr|96wb&Mrn?`q!yZXs< zF6~0@D&vytcD;=U{5?(z`3}D^J1vvFelbiqR-?sMgVKmMHZWO_xj94}383&e3H+52 zc=-w$x@!?3-45f($EgUE&}XFl zoZOG6z2d5!8`(PVz;j*P!fwNN_v0#b>zQ408OsS$q!BEC*yXy;TP58ga_8Iq&39QD zAi1DQffFj_Nbq>S;PvT_xfk=ils(=iC2_w(D0pI`hXH%SqPqqj^>%zrIX=)HFR$(d zgD8B~LKq;%rAn#8^BW~d{QN8 zcb0{U52|6%Pp25luFXshuF5?TdSo4E72fTV^pZ+iB~7aJXeiLQ9)!YwBoO`4?6Q5v z$zNJbw8yyCW8ZL_Sk_8IXgQVFwBm(_ZFOOPeN7n=fL6lf|s2I#u|89@bCO%gJ+MzF0P*13DHUou6{oD{;xY-Qndp$yM z!CIvzm2f2&FAWh;L+?|LSfXRv)C2e?X99E9nzdd|(bo}L8aYy~Dzb>>1$V9fp%VK* z7b|LW@j|goj->1>y~(-Dnjzso;(6W6YgpmS|L`jJR9OTve|*OD&GpAwy+*)3(pg|6 z+yF?JkEYe=<_a-Skz~NneQdZx=bNCQ3b!jJzuI)$>MxH3zU~w`LoYE%NO~x-YUMbe z^})JHV2c+9Vi&z2I1_ z=9l6w%HV=)smxgXuD3kHd+l}Vzt&(SMztf_{(eVPkRJ5^zxw!}s`vk=qgekpUCQ#W z%;~>5&@BI`4g7!VTH-r_C4x34nFpXmB}_E=r^cBoQ3>4K6hZ{dK*HG1qf0`^ihxGg|VznE=r? zkk?OBw=b-h{;>F|WFH6i#Q_B4mlo!H)&`xu4uJ)CM6vSo^C=F%o{pcU+lvM#PwbK_ zlGwMZ;MtV(pe6qMdPB8dPD`A>Rr35Kp)9h$G_%tmh0w5Qli*ra}-F&RnzWiQeS zC>F{NV?C;f{mFRisgdDqf&ZS67n)m6)(Hlz;-I@hK8fa$9C=)_UEzk8y`@x4u*sw} zXHDQ7+US{{KW?Q=QacobI`c}G(wO*zZfWcEPxSseA4C}Je3IUwEQb@LLwNZp@6(Nt zmG%BxAoKu87;$Xb(Dqhn!anekL`$BJowi+nSn!L^zK{Ul5l2oD4Dq7rLtsM2hjK*Q ztRLzbg%~AV$kwLF&to#bD#s0l6i@9|b3i6Inrdj%qS+=}CFnKJ)2pz}xKo6JRpg?` z97>T#j7kM$mdpm2TKz-k^4j36)qb@H@oo7VX2sI5hvd659&VI@(#`vKGzlSaOF0s* zNj8jT+i}1Yn8gukum|+$tXF}qMQ|vnwBxNMgO(bO^MaFKi*cPYL~B^PhB^xeWbt#6 zU)uoU^h1%=48!sCpLmvpVWI^~=yn_+jBzl`w;nOba!c3T>vOQ8vPf{kc=s|7x7ymY zRn4C!2hVyytj?YVV-oXWB7^0$W9O~w+%ij(`ntDlw|>IQT2oGXrFxK@ow1=!JMUE1 zjZR0^ZuJ|*S-Iid7w`FLL=u~!d+7F5m-YydM(9sfMeaWKwXJ&>J{7Wx=YeI_bsQjO z!X8u^B0QN@N{axFr)nPEpA!3ra2g<*9pkbKK~vd!1@Ibd^qCCQcFX4S7$2U*9Da3e zH6L}hoIdm=+yW8EsO*V_%%9dkg1&&(Zp{mux*PLuxquA2WE3wMT#t2OU1)osOosQ$ z=kh+z?)LScE@e)9-Gn*O+O>q&7521_p#VlzNjquHV=cK>&p9$n$jN4D%yPoJsUU-@ zoKAo+?}0d=D1U^i^3l<58By?E)`Wrg0xWw;JW7Mk5{ddBQ#088xb&7%x&SF3j5l*$no9A#(F&c2)fJ5==rOJc7 z*R{-nEd+9vc6PcO@`NJ2UOE21qireR!l;JXH2S}m$j0XHHah3%W{@WpXv-3a2GUMd zGJk5)Ln4`v82=u#lK&=N_5eMH3)OCcXSI(r6g#*P`E0fSDUhfb^vn;kndDa4 zRp#n*J5URJZK3rSIY)A^qvZ(CoM-v1*9P7|?29Ng@eoHA=G@N#Wrtj6<%EQEk6bo; zMC2@(1a&O>ta;sD{cAB!#qajc+udX7{j|-`OgwG-VZe*fn{Si+ffC6RKCsytvZGqG z9$XN*a|mOLsSPRWg&1zV4Gtv0A`R&o)wUXyKr~OY{c%U%<@qb^KYW(|)zQny!NUGO z&@#(^fR;|pT@+>7PZ624zmb}rH6hz zMJ0&Qe!+iXVNCzFZNmB=s4&+5iV9PWsz(SE zKoWWXjHIvEw7ZTCp$|bK#|dh~SjK`yh5719SZD+&%iJAJ1;%3ON?lomf@Azad|zTQ zHm<{O7b8difqV(Q16s&bK0*V#(> z>I%t!0nQRHd(b|A>zkq};yl5~^S6X`TaNp@@C7kPfYSci#aIZXDm{iJ|1|XdobowM zWr8fFLS-+n+^9Jr`23qW)tYO1udxbSLg`ZD;`1(B-s1tN(j>7_LmY%FMHjzZOz`<` zS&r=wJlVR7MI=raJAIIf{xvq*H_GVF)Rtgf=n0|s-x+CRVwQ}xTeAabR1eMVFFAAWpXoD z6Q1^XyCB%|d%tPbRCOOk`N=Ga%Se7jy@C{Q1-EZE=`QWqg$V=Is^odS4_I=5%PdlW zI|9X!_jAUUuZtUJi4ys^fAbwBE7B;VgffRaL>G%A6052xli21=J3`Dlj!auSU0O?rDb5=dm*$XE@$!1mW2an@afiy}sbsNW8& z(#*e6Y~ETrWTX2PjTNyhh*8l3?O{*{AH)JMy2Khah!i6_rUDrv)32a7%+Yi+YP=Pc zW{W$IN6k40>=MqF0R>a{`>0pHaaH{amMZtvUJf3rlGQ?=Y`rl(pZE1?r|uL0`GrMa zXPIe$bYVc2ArHc;Z~*8@2m^W}xt~>h1$sTaqwYvHBG(z8_Lb0?j3rrjtV(RKK+Jr{ z!np$D!Wu^koT!IGe7|53daQxpQ>;TdfZ4;&ag?P>8jIe_mo~Ld7RcBTPYiAW>XVU2 z{3JNJ-vof6f_Z?I5Ie$}`B(XyB)a**-3BxDgFT-nC_T}o>lia#PZXRNBFf|;D*v5^ z!IxgGpM*k%r9^~r=GhgfJpFKtc!dWFD-nqCUjA~KLyQS^GKw}dz6O8bDqbiY(Pc?? zOr8EA93PEJ!ufYz4I++jbMhM@Ll~^S-anQV6T}>%Dgna)GM7ktTX&|W#xMPOD?dy3 z(`njFo&U9G`}305Tj$&2Yv5wwv2LcxmD562u@g!lFljzl*dPQGkVO8>jgm=?&J^<1 z5$C|{AF`mq6jqNXb%-oI#QYIH7HOY>-F#&iL1i-kC%k4Nszj=ZIv_N7csW$m)Ozx7R3`R@z%Hjb& zfWoSCu{tlrB=lQdqg)JpjbQpyOY~FrWW98+KsWKz*Kk6>on$25GoO8)#hw-ObW#c)bm77zb10O z9X_uSQ_0YIM@nL)X{sm-DkIdP(i9J9F06_LQDTw-PEOu-YThUg5(6ej2AuNMHX^{n-2jJ6t~iR)-kpG+ z<(=-Ym>{Ss)l|5+R!r-6N+lda*9}$scz(yyZ__Y{w@0Is(y2Khb0B>DQX?6W%_oa> z6_>%a%lQD8H!CRbE0oYDNceX2Fn?MqfgYBcMZ=q_*f4WS#{m`Yh+E)+6xn6jNy$Y} z#biUCU9FbF9x+4$B zj(~Lxf$E2ukGMoOx8c%W5oIfJ3q)2t%#L6Ths_+2KleB3fHZ;cJRWg1UkF@eJHT8_ zh4X>!0<_(njHr?DQdc#zyoH~U((3bVe8Ko2!A{5VoV=^qudflT)3U_%i#q5Dn|*!r z^XJkPLFyNw>H?y*5jYxCqQmX`DDJpXhgekpmS(8Zsq5<#VmYg}sZ5(J~uxu6P9q@snHRS$n`K_~SoctPFemCVn=_rbqMf8)Kps zqL-CZcJ+?(xQupe;thdMWA%|-x|aa5?wO3T-WhW)(I|0(+;h4N+G#5o&Uy=RGki36 z=*RWlT;|Yxa2cRkS%l>lBHbq_@(pglhnTadh@N{x6s~J0BId1-IK;@Lbef?t0D+|- zAstXRVT<;~;#57+55@qrIzjXwD|kq<1k@A|MXDQFgv+Vr_Z6GhZ_d=yXx%?Da2!%6 z_L%_WMXUNFWyoP!b{Jvv zW}A*X7E1Q?aV&B`{`8=1pbpKoZW@zO+GbjG??9CY^qUr9cSRl^=!Y9(bP3j!HP(Z{WhiaiAq*wiT22Pn(Xz!Qq0jdb;VORNzQ7LKliLg;_ zXySoin*Wo}6-IDJ+)a|F7^4)?9I&tb=lpWeTztT`A9RwAM43j93+sGxf_lGS`3{f* z_pw=GCIaeQN*7;VRv&= z0Fit)Hx%~(3JRlzlHJfA!AJWZbCc2+50ej*K|TQb~rV`Tc?`m_DqMeu^d%TXAj z(TeFJjGFh4ezn2}A~0QVNalwc@m@A#6pP-_uvbxFbT|-|=Ii4Ia~ifk8C7CL8?}0RO`kzYXOFM<)(ux*IN9pgZO{FZ zIjv?w zW%g3WjGP}Yj}iH0_&&|qVM5zT=J|>6n(bic{W6Wn0F1s1{5@9B7f@vJvrHH1dWwEX z@?=br7KZE=FQo+(h7uh%{D|2mNcmVM_+h#W&%!j+!6`_4{XYmV2#|yf(U&Q5w=%@Q zVE0$D=ATq)n)KgR{3u#?{NBc*0$W)Kl?!`&$*`4QY=%5&?nAa@iqTngT>YM08wpei(r_*-g^~9kWuk~OuIR)oMh|CtA{TeHcNucM2D2#>TboD+xQcI(TGIf2O z8z~&_c_gGF1Z6Da(Q?jLLUe7m5lZ-}E|41;?n?PZ=UrCm9&V>n)UDW~N6@;&HIEtD zMBDBCMvvtbBa8kJlM!Adib-MN2r*SNQ3i+vrrRt2-LVi2O^z_yD)wmhzFi&&4x2ih zyc`NoXnUsq!QL!wzer?jB$p<4eSL9ODtTuo(Ni_mX&mb;)DEHPLc*!`gvs5Z7svs3%O8g2GSdNb_%z0+L$dO__&zHMB+C*)A`FWWDL5Ox}2~vVQ3JNE)NN?7XkDFTNx8Iha=1!a~0&cpKuJ*y~USb)}j( z%$pPP%`|SOSv*PLaC84}c_d~ojFQs}{5w7>j(o~Cpims>(0COq+Rq^!pr8b-`e!0J z#228$IY=VTKd^}G!qJk=pzMpf-Uyq~2z@bA?e;-96~?fBcqfdYjBWdj`Yjs5)=m_w z49jLvR-w^+;8yko(Y*qRqfth(V4D!_$XC!BohUFG`ZK)ifq@JpQ1Ee9wUPUqWSt50 z)BZT)(RhJcWl%249jum|*=Oks2ZQ!9-}vrl0?9Pkh0Y4wo{g4V+a`9w+%k=}{}d14 zRe*zu0s38Y3X6{8s*eK?{55yG^*lJ^D+~zxk}tSeG=dN~SV{*FWFP&7Q3>!pe^Y1j zSgGa+91ZF)P%#O^XU$)y(#LEK0Z~a;y&%!aWn%3l86(e!5qs?LbGh-YSQ|Vxj*# zEG!|}e!zo3bm9zuK3nBOQpobQ-l!XRMumkSz2^8j6##+6vLE?maj`dD;N8e(?t-A7 zo4utefVhad90DPZ<|yA2idEE^F6b#IZ{M}?^1H%SHaTAbWKC-W` zg|HALI;b!MmFwMQ$+|toZ1y+6p+WmmgxB^wpA)DU59JuTV0%U%)*tcb+G+I>5P?Hk zqL#rDclp<0{kVEM<|_6wN6zW}R3RloiBrIXLanrQX~a;(6a$j3(TT18L;&(&CWNDk z=I5EyZ=-~XMeapNV^nXBcdi+N>?=6B2~t&rWT?A!>SU+}_SWhjD@4TIL{|QCnTiO{ z24HX}MC4j2IY5>;JTuJ4sw3I?#EA)@d|qTgxYWkf4-yK?DcK(Fo|`N-**kVd^_N)2 zaFbyl0)o>0&b@Ef!pHuFRH&bTY5a^Ib#s$Hgi6h7)HB$Kbq< z9Phl5-b8QW;1Qoy#8Bb!9#@5{H~NJ;U{wlRiCD zy|W@uNoA@uc6XFNa@n}d(%IxU%y=khkcvI0ttb(XiA=Ma!x&=%j%48~rX^KATdQca zjbKhu4Cfw0cMic#rZ9I<%~5>VpQ;6(Re1PyH#tDA|2F(O(B;^K=0|3+z!X$H(wy+x zq`EWK2FhX4nOsBXx_AeykB3Zk`k0dTVUnSE*OD;@gDp(=`Y%P*!i(Jc%WtW8I1s*N zNnEkJxP}u1eHK%E_PdqsF2CBXF~lVl9WdTj2HD_}^G~w@%|Cd&i*Vb7D>4m6vx#Q! zV5W1&3;U!vD6slTRDN20b(CdFFaV&u_r)R3owJ?albzyqyF$ABcbiAhflBA-Apn|Y zLwjq#MWSsMuyK@VBn5Xh6c8WDl>q@F<3tp@1Vovan~NS9GrdH$@pP-D zxz_$-QEAp4<>f+|V@)Ypzz#P*pp@RWxP9$z_LZ^{PZk(v3)<)A{yJ{A@YfT5P3zbzGe=Lx# zN?_z8trt{I=No@)JRA7HL`$^*q?|Od@@*D$*1bStZMg39B!Gch6`kJnn zw$;=3JNwM2ZP+2tR>=B7tr88q^xc})As2k5!f&~xkNFzV;-Ftve!Vi?P@w94cUxG5=KOpqi5Hn(107;W30CFOWK=@+doE_ z_d&oqi#{7339A?Nq@}l+TILyP{Kho4GUMWqu3At9L>Rs`muqEe`VQFkv;T)(1NQ%F z*C0l7!|`Ak*+>1ARKqudUC-#)S2D+Sf>)Olb2c!@&^~L7cZurlC`E^om{m&BS)S-20B1 z$~Y3JGxWrEHaVW0dewjv0s*0TRvz3X_CxgohHne(+h^#M$8&=X8Gx}0e>xEm*{Sz| z)Zon-C|^Xv#i7FlXjzZ@(*fF#%`~>qJp`Id1DoCTTgN&L8%N1Vt0oL%ghMq7R%mKN zMN>VQltP7ze8xgmjATlc;Wzi8{S|AOl;09U$5#;fSW0F=5QM(fp!B z!*3nX&-Pe_^S$4%KGg}kzm7Jpziwx){a#k$_&?!P7hYvFS#IxAp~_I;f|_0)Tf>tj z^S?iL7GnH9D06LfYD#cPhvJrN?AR9KCgK)ia$7o2hbwYyH+SS#GFmcyz1uQvyS{e@ zoDaU&oJlbqI}}e(#f(d>ru{fSU#2w46F``>9$2T$KIa9-I^c_(({J{Rvw}T;h9_N? z@L8|aU(g8W0;K~?t47eQ5#N1eKq|>m+H5;U&-G%c;-n{Kt0Pw2Oc(I)Y-H?mCHw5( z3(KwF(WOke^?zwN#Sr6ef8Bj`YP9?w7%~+7IgO(f{*-?iiC+$lUhpp4-rr!6C>E@e zgn>}J{;SD9pg*=L&pq5#Q~J21qZZ$=6V6rh5}W~@DnV(#RE0k84@?DyLS%XJ-gFIc z)KdbKjIv8$FPs;=LTq8SOJ3MxR$-=F9|1)=5w?YqVgt>q(zWa3ZY)Sh%h=N^!;jWl z(z0#ORGzX(hVhd9Q020fVAf{T9R>`3@HW9W&qG=F+KGW0c=9#>SsJ?VpVD^{l_Did zYD+6~q-70XX->WAgY6?=&iDr>WHrsY%6~@5Q^&o{iTuZiDxro(grkhCvJ1(C%l8+t zZKOvRym5n0d7z!NHwk)M`i#N#%+KPdJ)Ye8fUE z!Mkd!p28TSBg89Wo}g zu>3ZAiMU$sASMj!fO16iyr{cT&~eI!jQwK^Z0I<;I`gii3M9zzMRB~1`ee4#9^~`V z1rH6}`q|U5O_qL^3T<0f2pB3enpzmD$A6_i>kqv-!(_ZXn~{K&j2ZY({)Euu_qGC? z`%HlMBxj@Mj$drUt$45TE)Nyo!D5Ya>vj9D5yKE2DZ>!G9_zcqmT;q5c=YX6AyDRd zv^M%m60QS_wvNC5pV3f3zbUtSiH4?`rzwW#bQ9-vb6p&!JeB@b1XF(#cfjuPTM!D! zwsV)S{N^k2{1iUfY4T*|&U7dI@E zsxMDO<*8LWOT4H+`Fi674;6vmFO9~@Cmf4L5^L7^8qN?u2xReIQY0rWHQ02KlqZ25 z6sKkendhD+rmurAHm)7ob0kI9h6|^7O)`&D!=CFKPPR4_3}2pe;-ufa$=gsKwPS3X z*3!JNOz$_2oIhz>)}$$E=d_Eh?jrAA*=;-G-Jj+nw=9w(7I%iNM*3RZ3ttC7mP!%{ z3ktW4_ChPck3}>H@=uO|Mvd8gpWdKvC|eLLFz$L~D@Tje5mpE^Zr3C$M`k5ssJ{)n z1Sqb`@`7Ap*SZF{(EupBxvp4jayZjP6wemcm)I5en|dgdvA z)fpC0L0_ZC>oA7&EM2gXKcn?H3rY9K+wOI3?+dA|4ngf;4zY+apV}B>5YCOakJf1v zlxv)x*&LpU2PC{>f`;7RAi%=3i>!9T3s#y5$r}$^0KCtg?Ex1DbfhK)+j$MNT=qEe zBLrz#95h5#?QNBO8+A5g232+_AvAUdteUUpD!sx#j9NY)$u{_NTwLJmrF+Tk2JxW& zaHrERM0qtH(|DsDD~wW1(Dw%;S*@k~5Y`=@kIz`CNyiqjs5vbMbsw=?ygJrpb8Q_o zl{3bz)JlW(!@}ShO)}z#N8v6qxj*q2%KySpqw~S;F5uJNa_#4GA!gQtq|D=*8w9y2 za9I}N?&WjH3WICZ5XRXXcK52tddP-3m$dq40yz~Kq_P|NNNscP#MAc_s`D+qnDnM- z{I?5F4Z*(KA&y`>Fg%Pq1a&F5Ks)8(;fv>pyP!!BABJD*(O}*?$@yz23Kl~a${^?@ zto}YBz5GqRs~}oJ5F={K!aWkmBmCwDfBDi3B$KA!7x7S9Ct!#KJZDSwJ-ZNZ6Ki-l zsYtl|T^l|clfK<2eqUhMkk%0YK`Z@>sbgaLH`0#%Uq;ryTUP(oj>C|qjos!j^3_jb z{{3B$@;`5C?_cvx;3h+&V5{Z0mErt&ND6MrvEUv&_wH(o1>e6LH@Aq(55`=93K@}r zD-SO&CYfh=8s7kg!Bb^_=Xe<^lMpEh&8oDe`F|~496pY{%1=(?Ib>LIc6ReZ6V|00 z58kH#BaPBoBPW;5*ZGBMo$A=MBQ^D?yaj0TV15-Te+c<#y)6FHf%jQ19tbj$#1DZ z!sL?7?b`b*(3-spnzfS)rncWo=5ClPEF73CYL66%0gfUXw)=O@`tu@Gg0~&MV<=Ww zdIl*!I#rLt)k^d)m%$vODG3_~;@-<9!IQxD`NMWzcP`dTRySSbH2ZZM>L67|t1Nmj#DSHydCbk_I(1mY*_p9a_iKbx&CF zqTID=8Yx0^95U2$F*7m4DoJTW6{6I}xwh5boAxaUswO$nMFdPIc^5D2?xA|`Nl4Og zW%_=$Ka9e)HFLZ(6bWu%i%3aK31h&KilwjN8PvE}2yJVo#zRJ&z^Lv|NM;5PvcEUb zx0pWT!tdtu7{1yh{fN>R0~6390@KH2mtE#@mdVd= zat3+Yf0){+99kp8hl-;j^g^gl6+Si;lt{5vc^c0DC92Ol(J|iHfSUY};-?QLv=?Y@ zD<--Rb^pD0yx}fLD%!Ctyh`bb5v>9i-Iox#+r3f_)+GCLaVe87>ryhX2xh$*E( z4f^%mKG6_iAe?L;D^bEZ3-+NC=20%7w=VMSL1;f_iTd}3q33ZRO@Eaj6O;)DTL|`1 z{L7c^0GWLo9>rca^*UR8QM?FKXz*-4uvCA9p>=?)%nl1msg*qrC+|k|G?Xv5u?L<_{Rp3lG6voq48Y^xU zCk2J!y1iyF1O3ychq_BxfG9O$YZwjY>F!X$8C!Qp&L^mI1r&%2f{i5w*&o<5A&YV% zVZHJ0E-ua`{?Yf@7?d`yG!zqwm09W&Lnm9?Cc+No&D^hWyTzkB8`|` zNvt;)bxfFf_1zIZ+8PpQmPJ(fK7?YYtIJC~MAOEQ>)Ux(w7X~xdRYl+I547tvRq^% z;+sZ;kRDhP-8(s9)IgiHjch2vs0`R$KS*{3#3G$7bD}|z8?Nx$ z1{}Nzm|&yP7!`YiEgYnfMe5;spe`})6`N+uBK_RhcC90L=_XlrX`)%ENq1N}^Q?h4 z>;r;db6PlUr~Ia9kch;^pdeJKI0>hbdVa7?I1&!0*N=ZWJ=R@hJipau|Lq^~hdKT5 z;8|A?!M?gK+md(f>alkly}C)Z)Q)Fy6T&B(40DsXfSHz_|(9x%=14!U4ah!mQ39PHUC1f5rkDn$()3TLw!H%wDYU0$G@<%_!swNjth`;rX6(vh}uA^`JAYJE3za>vJM zdAGLkOZuw%mYae>X0Ht(x1IUgrJmxz`#rD3c4Y3&?;sPu3xOQC2?ijv$M+TPyqW&dECX@9k5xI z4LQ-0@kS^>-vY)ROk(bCHp&e_C7jV~;Tji6J09T?PF*uEl^{X?nsGh(LIUJ4p=Hx* zl@y4CKnNy3*ctJJI=(oE3*oi|cw1_7hEVY@sU7=U$4#(VsU!vO;IwN+S0YO zXm6O6;`+Rk*)?$q_rQR(DhI^jDsGXDSC(a& zCfE8t5V>0HtY#^mOlNZxtRYq$G|;CB_*&rM@F?|va@`#cH`GdYCn`Y^;u#b5$UD_O z9YA->yA_dsdM|ua7g5i1*hZlJE$Sb_Y`h6izVO6H4f9z&wf`*_7#kV!x7v|kZQINO zC-LQM9nI~$Ey;1Qe2)_aZyx0SyVajfqtAoC1tBenRVrkaOHU-WM9q+2uCOk?%D1`E6(y6Itx^=d1M5&>>`-x zgIQbM?rY~8h(He_>_5o4f3cWMER6p<>B;dQ<`+2r0UiFogA;#exo}6&<@A=mp!yL5 zvNO)x^|c;|T@S^|vfCop^MC>jL>Y=@B^Z8pM(=;T<+NvOCen@vSVIA(_AVyVo&GL! zO<%l2Q=bI4^}KNE=l%^)gCQhswV$SB@QhlC zFL+y00qbjYWhATqHVCK82qv)20gfF{4~M7y{mUXdx23fxLdu7Wq1LP1)N8%Iks*Ex z{j6;Lmy}_A`|pP_;Pku@!1|@K!rt$??Ysz4F4gbBxN;$j#K|vxb`w~sX1Q^OjgBro z)vYvI8Em{B??*d4g>Z~09f!w03gZ;?%@e~vZ0oY1(u^8Rf1Z} zU#me=MzGCkowxA`&iGRYo4)hU0=wVR3k} zMPtcjp)r)$f^B1|s)MqKtaQx0T951&Q82fLB8@%R(a2{K+%s4$Ey&G5RA<%4a%$-jKrcs)l83f!;O`x;aV!} z(E_UJT+GIwd%H-~Xme+>K0Yb&lIdh(jlSAXtpqAWPb?L++mq^@qEIBgdK5P6y%V4c z7UWkR$A}PyQ$8JfXY);#J!yE6@N}f>LmMM_lkfy!S)g2~j0Z+vVg)Y> zbu2!vDgA=bL0-R1dbt=&CPyo&8W9j0#HV$q_zQ@}*N-~=_5o1@;x~FC(gtB{2(tDF z@`w~`!yHtWMC~zVO?%XceiTQRAU3VU+6A^c*=Bz;p8lv+h zoa)BDL;!^IDc2Qo1Cy*$(S#RAi&*7o46`&Iqc*^=F=~G=5!byU387?Non@F5H4fxP z7`$768R#@~=x{;k#)Jm|v3*4YtV z2~=XmH}%O1bG-)|%3zulZZ*UijcJ=(I=`f0`cZ}nr*xL<1}p(uP;^><1!j+rVN!;k zhclT_dok|Q6v^B==t%1%kRD)>_v6*S-091hl4Z7d-9}+CPO$W6Q*4@n%!ghx{QS9~ z#*oQmd~R%ttL_%0EsXCdYs$0TJ+wQp4EIqe$?>;rV|vK~kPM8_YQ%wcMJ5x>HH?Me zQ!r$|L6i(80jZCa8k0J5?SRNo@$~N!DA{OY7T{RUI3I!laH$Yu92w?1=cRXiwB{wB zloVRcW}IcpV3B6?z}vsR!YvkIy12-uSq}^f5sJaOed>fItapbHLQZ8oA3CE#MW(Vi zu4(R)>>vw~6g=!j@g=qV%Khs3@!JDs`JWx`9 zQ+*0gep(5&AM}Zd>5)@^^!Q0t9DS7d7}SMWUbM50n2XjRBXqMg&8m)9R`6Aig&$K( zqN}Vj8Zu}wicWULu|P$xHon%S@)1hK_!iYpxnd2vZ$;s}kWg$9?Q^U6y0TX``)Eg+ z`WqYL&y{m|n6B?VL{dULU!V0s{Mt9$vrU|JX)zdDU}&6gKj zj?r#iTYXVb=`~p3m!SnbTt~QdP)D(*Y`!VT=@{q5QUw6^l^uRL9Q8x{hHRktJP{Rp zFt9(+1eF}Z_q-0zh`iIRC}V;VlOfV@%@VAKc7h#zjzEp@E1;)CKinj0^Qr1a9^MS6 z(P8dqAEk_9m15W6sy@M3!v}HfIKugq#`TPXM(l+8u5nK}d^<+iGcFeR>`;vf3 z8kE_6X|tvpU>#(`as2-=c8;;RJ?gfvZQHhOx2v{o+qT_R+qP}nTD9G-TDSjwv(LH7 z*~vX0-(-GzGxN*`V~pQf*s9BU5+nuTT;rW#qSEWx%%7DbstqurNcpDeg0JRlN4H!@ z2l*0M#8Zwq-X(w~%=zETIy}Ivju=Ri+$%aDMeF>^4`l8gRw?SQ37`0Z)ftN$4i>a} zw8b^aU?5`J*T}UAOcq@>uJz0NdcJkw?C{sIe{;YNbi?i%K%BFBK+A&)f1RAZP>lr5 z?_a}n7)~pbrF)Shikv zxT6C?V|o=VS-%x&m)v?Tfs0PTDLd7h=}M$;_=0!7>wWYkW0GtU0(@)0`O z#I7DQuFvVR!6aULlmfo*aG3n8XFZTHYD)#prB=hr7CxcIEnYhNJhZnnK3%lW#g$(u zk&mM|h7kR=x7;;W5U~iBk>O!a%Ma3C#pC1Q&l`9vFRULg<_et&3KGzB=FHJqp@0@I zD+Fg@a4>{lcz$!mBRlmzu^nZ7JSD|llzHW4f;Bn@ziD^09LHXWzf zrf?n`SfX%|mh(r8<_Oi$8D}r4GM(4ujWMmuqn!_`m!y4x_T*s} z$E!PaC)#nIe4NBExJ0w03hMOHB3EzbQ2RJK!CnudG7#&s06AT9FdK5JJ!_kx-U+sE?^Ca`FagW*KC-Fp}=eSNd_~p_z%oW^=(P8UuvYY9z11Ci6uX#65lKo?!6?y=-g*RUAPta411$ zg6D1YT0az1e;H)FnB*mLSACl~QCSH7?R9^>Uw@|eeYvZ~ z_wMVNU+r4at?{qz6 z+Gqra>_>*Bs|CSW2Yb9Ih>DMAO~l|$b)A|EeJo3u^vw(uu60i(+8_hb@q$L%j21qh z8?d>MT@>(BT<>tYzIsGLVG-1$kUbM^J3aVmOLQP{bY%jR3O+EnU^kqj>}QX0DJ(Yy zyTV!0VSvdiLUjR1B=nA|4W%1?E5KX4u3BM|nu>X?1eD@F2X>vle1L@rg-$IuKxqW+ zkGAfxjap?ikq2Na>=^1t?R}mZ|6(LT=`<Pb9Fnwpkuujc4vCpR?Sc8k#w>_n z5Vf6HuOper{VS}<;G@hKrbx)KA0p5DWr7D6w zdEj?%{rZTmtOujMR}r_Og~Ky!LDOXf;=atJsqX0r1&SyMCTj$ccVUfZM-+(Gc84k~ zDFRu^L@4RRgcI*C09opJ@)JCa8XzPLozICyQe!gOCs9;Tih?q!rD`QYR}wSZ)oCQ8 z^aB_Qc>y>=&Ubha0|~#u>-)c0fp*w`N^lbF5kU(ZJecXYphkd^1A(X@>20}nIBu>mrKhnc9y&a))5rAC*(Kf@*SRihpd;mNrSMu{0ST7y+76~87Z z!X^B@^X!?;)DkX0$s({Cip++9T?2sD^%usGx<$>2-srfa7mFR?Pu~Y2`qyw^1?0)v zKL-^hDSPC$;-8Qmyez@)l=oLEA8X*^f0v6NEA{u&N&RX*=9AX4q%d(_d^hce+X!fY z$j)+qwv1^+Ig^KV<6TnCS5bz_yp69^@`2?v@12@!0S!4CL{P+~m2w8CfmV%;x9w!~ zu912TXx<2wa71$r-oh!PEyN+h3i39u(OQby7kKN-bchJZ3}h;f7#B!}S#DM%BZw#y zD)kuV&8^d{H5ybaKAzm%cEv`6dBmnODr?jY+oGQvTSovm53mMC;n~ZHo~R%iPH&PU zZ`{%Z;6ifq5TOqk4DZpSpGF=5R=dle1IlcWGzYE8p(PWmGSwbt_uGc84}noZU2sd5 zlfY_kyUbi#4uO>iA$aP6m>p}94DqRI4j>E50I1k%gOHyEMZ<+r6oYAr6NX+2fJr$6 zPP^U_PYZ2ax{f}UT_hlvQiS$)C5iD7)bwbVb(I~WEaZds-%rJkm>D%iyjyd>UC ziZtBufzg?c#ydvoMDc4rP0q7OymaWvwu+Ej&T`dv>^*H-_Ke{6%R9Y%NVFN0SQj!3*Ass4g zW6+7T%w3WLuk+|_TQV5p(k#PnO%KL$upkS zS{S==Wb*i)hXRb^wf?!=1GQs43x%}bXu!p3U9IP8Tp$|ZaBfm(%6n+{x6!flW-`-IRe&<;nAOCpj?d2CC_*3U^&#RYQ$v9C{zm zhpzn}CV@&6u4qdXw~4ypit>O$6j}z0Kb~k8hkGobR4@ z>*G<(>@%ZVG5{3)!k`apzcV|tY*lFbdZVLd+Ha zet)0P)8GOeliao3(BI<& zgX1q-%8D%|8G1rLn$l36K3#&xa8PGa*Nf}yc_c5dqx)@3I|N6Hn8ZBt=fVK0w!-T~ zZWv?{-V%4JcGb9wU6>5zq0dHHPRTeH*7d65OAEVmLly79V0Ccqu_q|M9AM1;;<6)A zzVSi|UsQhga)7OuPek5zKsb^KClA$ZoN1}1nKs0qw(QG!Vk(<|7cfTkw|h-<%_jLC zWxfg2#M4`<0Sr2RFfW}L=UwsVog@n=`S@(QO;;;DzL8j29xbZ0%^h;EYZrr1f+HQB zetMkH6I%4_V>#+zIpyywr*$jlQ_mrnc!A<>dq;`DB%|3wQ2OxSa+!__34lV?{n>AqU0L|;l&Pd+=?KwbddL?iYHjIrA?rb^$ zd!kWBrO|y>7PBaYIuPOAS+?8eC4i5cL`M6y0=59lx=(zFwc_i(uE_bY&VdY>k|Fi= zEz@YSF-Ype?&Q=YI+b8T*V3Ae@HHOiHLHmEU`tQ z-i>hYVewG)M~jbV9TrFtdALHcs9dZH)(E0cGPoyewu~S}k(#y(ta%VH zXqW#TbZdub%wa3P9t?^d=M9L8y1@sPzfCr5Fx7HZfR+vSsLF7M5?rvLs1QrH{V=U; zf8)X_hqxs%jr0J9+C*VAD&35hK{z2GPgW9Rft&*0F70^6ijf7Ep(BZkIDu4p8ligo z)2B(OSmvDS`yEY%`2;+s^rX2w^xTK_w8C?!uHNY6)71kb+8Ox#i$KTC4>J;adH4?mhRZDkU%@EQgQ?Nv;oDw#C<8n-hO z1b-ogaAwZ={dsy4##e(~P>t&GDeUBZ3U8oeMTC)+y|Odypde8YeBg1%7b;hzpnOye z0@-(xMHSz5C(h4uaoeBq3+{aziilukB(BtV?1xk4I0X1(j>jYd9BL!jLL0iye81)l zr34Vytl_=#89=xXs*m=!UL1Z`H_gfU!imFB0w8 zWqq@0^dTr%CMbVUZx33SO#O~`z$RAZYEmt!SL{!p;z2tC!hcRdUuqL}vbYpCdvK^E zgh3*oyt~1OUy$5Xn}7Q?*vU>}NWY7P)6ihb<9n~gef7?%tH~sUNuPQacZMTghIVwT zGqs<*PKB$05&=*&ZgH}KdY&En^XNw)sbY9y(7YWu|1d&cNtWqR5j~^gesbT|lT)fJ zcvU;{uj}lSA##{zgaYFl-k~i)8w@iB@`E*@9Ab(AAzXuH8zg@m`~8X`#upKtH855f zR`iB+h*u9=aKBr|T%fYaY@X6U6sXzsr|D!lx5RYls{B}5!%s(hX-ETvA&b~O2iU*+ zCLWvcz`Hq`p)uMbzXa6r3V=fdFv!65U1d{;3Y? z<&p_T5UMH_qoR->;^W>xptG+n0;NaUAPTaCbFCbDhyL{q&=VXd8xSgV%uf$>kD%Nm zuc+%BKag{3AB#>pa#2cOV81!{kmFz3R{Gkp-+q)b}?KK|EAjq8=?%`DYN-bwyUhiecK!LrWdEx)z7^JKgU+i zP)y1LQt6dCTJslxWKEW}olwo~4E1jj>A-!bOl|L5xQWW35~bG>j0e6{KD9dyjP>Gw z^LApWPzTas2Bd^DaxE9q!%S@~qf@UtmQ9$e_(g_?6dwTjo7kjNdY0f8h}DaN%NB85 zSb;Q3#!I$i1mzGqb4(FW@cJ-?2P|+C>XzeOF+Wl76j!-GB&~;^&)5!y!nA(gPitP% zydyc4H1QOSrZ3sf5j{i};9S0d>rfGo~y3q)hG5>zmyatDDjSZ+dFOM0O@P}p~TuP4}hJzln81?(bc z*z37HE#O(I9(OBueiBhQ_24NJRAp!^Z7oONfiAAM(0jL z^n zlFUyDs6(*07qgtYJUxyfVCai}=Z3LrFA)`^{W;wEF zD&SBG3KM#ehUSw|=$9$Wkj`IinNJYGqO>4Tcy34Ap(~-^ZFz8I{Co3%Tsc?VY^Fr^={U zux$YHs^ zAZJ%g_ouh_<96kHSiT@#(yRA#^vKQ5x9j8fSgFp)`Z-I>U9;|ATKJvQ6%#*yLg|er z8LdwwRoZ%-E3Z=-vLCAEfuc|N3Z}S;_9nW`=6ip5{?f>Dg&wd`GRt_Y$u`ST!+YcR zQXc1{OfQ&V3LS1% z){2Ou^V@Nqma9tl1#C)|eP|B5iJQ4=H*G9N031rEJKp4Vs*Do*XWZ3v9c>;iWeIbd$L8T6LCR=fio*j5$bh&niLPUWvYeOM`an98Sl^nkVCt1g4=U*7(^w+O z@sY}Z5hE7M6C`NG2p3dk(h;CaBtQlmr$TL;xd)5ndB;jv8(O|&NKgP|Mo){>up+%S zYzQN4^n&FHt)weJEV<0rOtPUdxC!BjE&{q4u<+~pxMSypz&r%+mA>UoH7Q;Rbt@X^ zXkJX%!vt%~!*IS?v%cZ{S__*uw5}Z-2TNn5O<{LY8X40ZzO-wsx57i(C-M5tN+4_v z_w{?IWQ@dd+z?kEkWb1ML(Hh1vr6djBoJu6LHZzJm?FS>JRf|HQhG(GT=*F?ppU8Q z=G~<^`fO3Nc-cit0B#jUZW!+8{Z*J!e!|GAgGe0HmCuF962VMJEHVM}(N)pi1*rxC zDJd2@t<8M1?~L7Dh&9vz?=2R%_b;Q(wA=|11C-Im4szDkwv$2%I)AUhr7XixrF7r0 zRzt&$r26X$r2Z%(3%Ax2oh;W!np#}1{yRSscsIC|BL%9$$N&6~SSa&W$)gDU#5myT zoG&5c!fddYWvYO6yAE1q#032}tal?d8=_^j2~4!+5Kh_Zvu-$-NMEc>u&WiKdTDx3 z6fO9`6sK)KyDExPH{I{@W{K#t)FmKFAbRY|!{qw8aMHmfi83YVd?~~izC(5Bkkhz@ zayv92W;OQ+wDnvd3W{0JySkmxH6dc@lI3)(nD>~)8RJ`7JzC^UNEk1~HAo7iq%OLQ zWglhRnM20H{yCG=rgwRqP|0+t5^Yt#^Tz&SagF=gR>mqiH|1S|%2K*v=NB9c|8Av>7 zS;re4gPxbYSh{1sWeCkvWR3x&f0vLET!o!;Wys)o)Hf}GzLzt@#Fs*NtKTqG<4yTf zaikvPFO4w*mw8$OOfX_(WA6$h2eIJBJB(l>GmYry;-IURtBm|FEFk@aJU#Gr99a%L zZvrYbMfT@`ly4|pU`_KJ<1p}nIZ09(K)qvN!R5jDtUr<)(C1cp-5ZP3?4nMYn1sI? zBE%7&Rk_(i^Ay^{d!^-{g^`eWoSugu-yva_TT~XzfFjviv&_Wk)k2$Xl<9WshRAk7Y6RgaIT-rB+K zY|p1lVv8WxXMh+wzzvGRhsvGJKrKnYu39>xB*(H8N^tsKs$&_r6^rGz;5}4=o`udYO3`l7X{PPS!_hxZL4qBcl=@v7U!Ivj zxp^$z|977nBDoQdZ}ey?$`+n}C-3t!Ct7r5U$&4u_&Yg3>Uy(WCQr?<2?w1Kq3&)s zy@%K!^ozq~!9H`^_ME^^hd@Ex$CuHDzAlVoVxoRA)@1$ftBJc-TVK7_rtuDLBWNo=2ZG@PWhkkpb7*#3cNLsS^Pk zf~xFikKngX(zC>yKN>A?$Er*P&8NGpe3<1YCOV_LtI%c&RF3BMgg@;BhJm&4c%AUy+e zfIa4&;Pqc~FV5Jnwry##9cY&z;)NZ<$#|e;np`UA zxd9yK(9xAplAJqOVFe-VQx~%CQQVLc4mP&sjeJWuf@W|Io|+ zmxYs!?Y|OsSsDH(OpKM`e+3hp*3yXE97CLGOvKL@r;k57dmqcJ)xpjLh~Vuf^4H_Q znhCFuWfYBJ{(3C$iChX!R{c8%0aI0P)9~uz^Aj6+HkpOQR{ACP=2f5LlkSt=Soix| zv+AU_#xxbbD2scaW!2Hwg*%GAt{u(kpDxz7`KOD`ptxUL?ls#&x^4>)udy|yuleKS z{(c{$mm11YqOJM;a(~jQ_I-bmil266JDWnVb^MHJ@|EAJ_TUG=Gm}in<^3&$#BH`E zUvRa>@GGL}3#InYEZxqx&7Y-rN7vWQtZBNP*YB>kcdM6+&&*eRQ@fq8?vHl^;*mWT zZD8x(g!!SIR)yXvIQSHk5sOCVw5)!e%hot#( zD^oR8WkWb$cUw)yc4;n`BNqpDs+h-~v=5tH))~$fJ3PdfIHM8rlFjEjJ(FQFacTt3#OaS$>m< zM#=F6L_{G@bUYL9D2hmwl%UsK@NmDhB>JpJCB5Xk%elO2eIHBu+e(z|4tQj*1m>71 z0t`QjbY)>8wdN4WJIa~}Y!T3zIDl3Wf;J#uY2c)|uRlVSn9WHQ*v2Nzy(0U|1qp+6 zltt#1U}F1O$MQ`6YFNu_L8Tri!({YD>;*r#vntWaDRMAY2;`^esH-9u{`>%1B?#Hb zaDwf~6|#A4U*QQA0&Phvpe6+q4MCBOj?@wZp>Z)#5DexV--FN(!lAm|Hp_7450hG# zB<>y}4DO~Hi&XO1NRWkrq7+e%ejVE<2_m+KWrCPrYDe3i%|o%=&?jSp&@*7P-j#y? z!zr;hR2Dygh8C3kE2m`uu@8(BC68?uX$E4X1lEiwEDISK7+i3AJlxq*dCUMh3KBZ~ zk0hKp0QO-#=NAtkY~zzS2n&MWI0mQ0x$I6Ta-k5M)=y+7%bBbr2hbWpm~tm&HY`P{ zBMrE<+N8FRz0KoZ<&Wk|3X!gw900}+zggte6 zy8#9Q6h|vfJ9k|rQ*=FWDvn)2#9u;qC=;!g*s*ZKW>N<^XE9h~e8F&@MO0uIv#4~# z1>QEoDY>!KEE#CF&8kAB%vT!%4rmW(Db^zdTJcY#|#1AZn-vH^iX8d|~L&uxoam#3s!_ zEelpmK8oLDSR7z}zpdSxH^BNeUTAFZn>V&db(kAe^7cJbXh)b*Q{CQO6x4PK(nu*1 zOg(Z}($YkXxX$f@1^trNI$wWAmNHsX&}5VzQv)Z+WL3%&TeipU26Y#0uYUy*(0QYJbA z`&SwQuDo?yVen-PAnOnwt68bl=cU2}v8Ua_`qoh(!6%6ia?r$I7kNfLZQH4j7(v#) zT<3FcZo3HnwbM(mIgGEW8D2UAxs08qy!c+UWyI8+SL_hWaDM8Z#+%=-jUSiSvlw5| zQ;$f)>ylq&V8gsvKlPxkL?qkT9;Sv63^x03bUdy^$ndS-wc`_HhSk*fapHg>orZQP zQ=~&0cZj#@0F;r(S$?V1UMdU^X`KY({iY6`yHBlv3 zWE%q%;w}}?=|Y>^hxa@1^KuUg&_TY%mO0A4>|dd55B1uY7wW`7c0=hCkY`3!)08VK z$G+=mm4c1Wq=tN-fE;1r$coc5h`xP!m}`MAh<_o*eWXMLUKx5zWHg}Ug$&J`iNP$a>;1a)(=GYTr5J{N6u&3-;QcrWSG=T z!aK#Ft`cb?v)hEc)Q_g1J|=jowA4iu1L37HsGpA=t);8R z-wgeZJZ(}=JZ4@?HtanWcxbO}LIxI7XGY1+H@HD#L z5>3ciWCaD>HQIwW1&R!n#gVBeU~KK)S~>pd4Gb1odEP;HUKjRV9x52s_q&sA&2h&% zGkH)l#)6W@G8C>%E1Z28{yxUho19SAGg;5E_ zvS}%e60MiI{f{d9xQl>p$RJ`SiC_OI;IciaGZ`^~WC)9QH?)rRnaQvw?}WE-Nf!FW zea!}IguTRk_CP?&r)dDt-)Wo?28Y-|;wg5NI`;HXacyz`VLD#2GBj}f=%3?)R!Q|X zB%sK^GSS+rQlgm$S{*noAq0>!mFI6!mtL9+xpH>Q6@K=G_RetHqMKH1_WG z#G*&lJk@SH*K$vw^|hO{)c|dY{VrK$$C2(wGapS92MBP!LK-Z!Mw(T~HVf>@)|rrhiZ>mdA)#qd9_d}aYnTt^%!=|zmB;Bydq=?NsE?FkHp|L ziWqvtW@c`mg0}4ykJupQ6}|C1bZxVERCJi3mOF34nU21;);R%&^sB?ND0 z7*>VdAJWKoDp?T0U~9HJiJyX1G*2u}S{P;)pQ zTQbT1!Ve$NF@%R9?zttt9Sl8^(sZ3hV!?88ZOB*t-b3~n*GLF9`QD` z!j`ySvq`p$MjjER=T9L7_*W*?-ITVa`=gCY)9;qMN~FQts1|A661rX#p- z6MMToWP;}w;tnmgs~A)AMyqaQDb!)Yu>C#mh$s~V$9!E9^G#AQ%+?q>w^p*F-x_;^ zu-TUduDrV8Y~D5Np{4AcrQxhJ)>x})G(0Y7aVY%8YMEv;`|fP?vBUb@GGTylU6p;` zrB_(#&hHBvUsm?D65w}t=L;+m87zZTc54F4Vh{#!}T%J9D;qot_I*lmg-bVGk4 zipWyR+dRJ?q?Lpk5lHHYcOMBUHH~L1ERYm0efJD*XBV4L0|McKz?hkt{mEqKjsqpF z%6p*yRO?(mIIq|55A|EFc`<5y`wU$lKrC(lJ$!773ST$CxbJQdOs0&UxqVJs_^~?O zyGwr*!T-;$+Uy52zxj;+N5_uN)>ND{oJG16UOH)gj8Y-F-M9-bRvJNEhUwGA846ip4jH>5C8-qwRjRt7iPK0}k|10kMJ zSw7bHadGbY2ACsO-NL3JSLW-DjEI;cVI}{<{q#M!Mxh;#Uz*ULNY-?0lhM>JjRnK` zZ>OiFBGLjvy|Qadcsb^|BQ{Vqs8KMrS`}uTf3r^Nf@!QD{;(r{7X@OpR5UgRc$A|0 zdTd@xi|e3}qwpR~)qqEeM#m7B@VOFmu_gL3Ey{I38E5B5wNmIxP!X@iRIN<@cv z661jI+(R>snOdq&x~w!%%dKAmnA85UG5AIc2>` zczPQ?A>cM(mp*L)h{Fsi)pGKfspGNB!2`58TkmW2zcC^;SdK2lICB&fhG4EyFl@2} zgpLsM67tZ?*FE?S8&yGZqsyZJzP3d9QPK!6i~9)lMjf@XDy{TnuNW5#w=8fqX0EGxFM8wt!J5 ztK*ztOqp>}UE8uJN-AoBum$j#3vg2l>G804_Y)DX1^+lswAMSRdgiMi=sqb|< zL1+Q=1fPPvfq$JTpG%Tx0{R?gAvH@qXBF&Js~JpByWk<>Swm)kt_2Zx`?~hdx zAMYC1!2a}zJ8;Y$%61H?I-!E+TZ_NjL%kTT=G1!>Q+O9+E^$?A8c72qDUlOwCzh-$P*-nYVUr#U3mmPCP+Y)!87&xbBn#;|ODmF-I2j z*0o!-h>f&1Z&N`m#F_oo&(XF3kwD+Q-h6Slxf@Hm0g7$>$MjqSoS&fMliv zw`0?2^X7>g#DuDhWZ}UIifki&SAaXx)4d)u9SBlL0up<~oJ)&VEoTtktQ@cXJErVi zpK&o5vo!aXI$$vs7@gBK(-SeN8uExo%WEgL5(H3ChOepoWRDCWl8Mv7AeVHD!`o|f zt2D~IJg`TD{SkqAHqUzQ%Rwa$vLTu&2CZs!kEsl6cz&(-K11XqggBp1dt9xet$a83 zWg>ULWEA6gDBN)*EZI56jAiq%Qt?Mefo?R7I<$co#8o7tu9r{6>$wbTCX1Gt1vSL7Wv+~F@0JA@mJri%<3VE=i?sm#C7gC_ggV{`PhziD{pNQm~FV-Y> z>S}MvKja^1ArOQyXIQ6d&VW?{iuH88O%{@bmBH(t_6+Yv$Tw@YOfRrUU!sEy{1f8rVaW8C3ZjBK)q)P8m&=vE;$7+EEXoA{v%9B8guDv3%V_P$vV8H^eCb zNg3KS&VzK?6VvfZselwC%6K7_M`E=!r9341BW*&tENYKmiub`HLAh-O=HiYi)qsEr87tya@U7nR0BPn0T*3$}`|f<<(+8h>u)DVe<+vmIS51N=}rdY7`26 zpt~?59?tRACI8DDg~03g?$`?3(V;8e4Y|vNmHtTxMSMbGmTRgmFPFig0wT3g1K!{! zy|tU^vKKm}(gWi>ubat(DiP9gG+53mgXSdq%K-nbZlto_iqoscDnR--ObmHK0w~Lv z_xzEtZLzX3HTrbJAJS}CUccIytR%C~!8WN#RYib04zl-A>xYJce49!xUD^rvr=Ic?i!89q6piakYe!l5s`EwroJy|5 z!;n6}76!iCV@{{OQlnv`v>`-dYI%$ReRXzMzXcKJ%zcZwU?v!aGRRDi60)qFZ?2=J zPNm*Xwy2P9GL{m|fzr$rK_BiW3jk24*0*GRmQkV^Z|q{wQ_TSTDmyCP6$7-DvILJTTB@@T-7zOW|VZa{XDvH%>2H zC0YP5imCMMWvku2KKIv;GM6B$MKM_>gCKlYur{<12oU$7N>q%YFW~{aqYOrCUAm;> z-4av?uC#2MpnlE6@hX3A1Ce@;&kI~9LD7@*MRVAuSR^@>PuV!EAD&i73i0coP3_> zW1^%imE>Bv$Knb}*kbnt3J4f=fy(vN3a(OFm5YmLRPT|G-oH-mysw`3E+c~&U+T7I zW>G&8NnKg(1DFO&)($>M{JYGf(B!778G-5RhF-cL};N++9i8;TW*5_Q8OIE8h5&Vc>NwGmp`tszkgXl_mjx=YJWH*_Q;El zXUhhqJ~URU8F*-*X-jCIwYoRmsmK=d^QJZ`85pogU!MPwJF2TtXjAEhH|p}Ir^VyQ zDx1r2N(jxkEvGJ80fKj4wPxEpXh1+Bcb$H6b;6e&ht`GSIkH)H8HcJdHo@Ay831b7 zjV&jaU8=ocFoz4Y~;ZI~O`+wZNps4J#0AdQ&h zx51n~#UauhS+i@A&RJX8_I>bL(?;K-&}QC(`8euoH!WrGtLvl?X%RXK>st%jzPPek z+Yv9Q z1579cWGvlv3rGC!AGTdq?&K0XLPTx@%Ij$Zp{TiN`P!TPV?9C1W4b)z-W1XVC-+Fi zkqSJ88qgA(6CX4PE*Gp*Ow}YGyKkiQ_(=5`D98{8tl%F;iE_SomO`gqey1k0ihB-c zv?Cd1=7C#nT2vwsK^Ib-&2*Y7v-q5er32e2t`%ysM*)`F7NX>}=*AeG4lt?(b)fQT zsP-LlDzHa}Zs(WP>v=IskJi`=#6Kx9RSM9L=^uo;t3eE#mG>9LmyO?p^V?&kHSF#1 zsFvCH{+|4MXZ_vjh4I_rsWd6dL;WP~mWLf|Ok#i!%NMMqH;W!E6}{gb%61%rA`Tlq z-fYZ0H7bwnu%F#)dytH$pQt&8?*GD2Rd@W_DWnPa<1 z6oxEB6L0gDQbr08dxoMxCA-S-9#f@eMj41*=h6tygj`s4RPcmP+Gxc0+VhL^x-(?$ z;70Q+Zhny1<-{`6of@P?io*FcorhU2hg?RS=M6n_5&Ppg?0Gi<3$cYGJ|C{jj^jx> zAXPv_44_NX-uHW*Hc*(sBgnJ}{3<03RmCh{+c&xZ6-p^(PM}?PLj*u`MTY-F+XCyP@IL@)j-pR~N$lg0E%3e`MSxHveBr7W^J2NvgL?I)a;(IzcUh4FD zzu&*#r#^ppaE{mOzMuE=x~}`auKT*~*XtrBx&0bpylcoQoY7cQ34)G_&f10JT`htB zgr>`N`5$b?_~p;KyQ~_@`95e2jtzpGziWk(V_kh3O(cS{e{sN;h4pw)_ABeKt+hdw zSYHw{oF}}b)4Hi*w9II5YI!E-({DCX0@6C5NZL*0! zrr9-&qrM>x4xH&&D7`YunyoNNeB4JIKa8@x(wFTeeXLPt94_ta*d-GWZaKDd*V9(E zZ;zbnTv;2Bsq4vZ858^<*iY~M-Da3I_yv^w7FGJmC@sR%Ig^yy=8@F4k;b>rVn$@N zo{Rc$_KLPGRK|_^U-BpmwEzCOf%!F zj3MpeCle_5o-h{mdZ9e9U=T&{5%S2b-vYcs^ zpI`m%*qM3EO5lS&^`i0Im>&zt?81{4@%$&G6!!zEqkN<3wMuhKw_`(TSQTurinhf^ zMcBB>%-{QvD?h3*l#P4MtM*#0*g89bP({V~O?CepVk8p>oQiBMa=Q-P=-4td~16?7~{F@QC{t!CVXiHKM%LUSfA=rm9fcq z9X~Op(oOGb5ku>li&tin(Vhf^EZV22T+Hbx9RA?g$MZcoU-h%0WN-_Q0Bs3A=;8~j z1e?=%H7zHiSQJ!cb*fS{GjW<6P()4KI z`C_1bwcj}Q)pnj$TxOV&x9)S91Y3)4e_P%+L%wlWhJj~dpuTtcVx zpA#EN6W_vH=CS8RF1!_n$*_S()y_AIlVPe=hXHZuM@$tICHLhBTZB=rC(%Gvd=}i z$sL10d^ZY@Vbw5F1M%}xW?XrKd7D5@hgaPrq4vWInQ?>F0eBbR^+yg%H zZAz|U`JV~8(OjbNvMtqwly(BWx+LJMvzDzP#c}8Zh8*elr)_he#fZG{Y1D|hdoRCB zdQt!@QCV(9^1W{~Z(1u@S-xc_YQuN@(&=$qaw=u*V{OU&F2@CgzkWOUloM9gvgWpJ z(45q%xS1eAY%bk5tE`u^R{Lg1*^@{$Ns^ZbbQ`>mG|C&p+kr(V$W8;q( zd}EjbJrgP`dK4EfKB%qfiZo5g@46YmGHcSe>Rc>G8_B0K>nl8c?^^Lx!^}>{6Zg7l zRZPFV=gqC1uC^8p5US(=}@W8 z_w31a@&fjtvWnFmJp0qVs78~*KK(;a%uF2~Q$4a0E)xZ>GI5mMa!%>HukieJy%5BB zM>WXElQh-+&F-dDC2B`lmy>Vxhz-GA=A=5#Pbvc7%8{*;xWy*p_JIm|jdwGH?CFEU z6L@Vmq?x*j&jd6RVq5H9-{Hvclx9Rtp6_~2k77x>_~B4G0n{4d{54m$@RMLc3^>*Y66Qm6iQ2y|C= z1}gQA!O~Kh^&W}#lk+8!8TZsE*ZUUY2FW5*hE8{|AA^22gE~%KtzHm-Y!%U<>Ef+3 z?o^HF-YnlJdhEsey?BJ}S|0l&y;IK${I6UJuAAARz3I(PsArakl|r07T*sqEQn_(s zbrubR_WaW8=pNWN**q~`N`%eYWaxTT+ncLBxVzPB)XZ8O7UPUO`FZ&x`9q7#mZX$( z%}mUG1@>p@IWLX7^O`pqxX^#O-UPi9&^mIhdSgJL`YPKFn)GA}$Ic1)bzHd<%&}T# z*Nu|zEWd8a4xQEzX4_iR)D_${76mN7@J&MiUdim zb}6pw5Z_!qb<|fMg8P)qwWqyzi`1c;GYx#UtVFyci*=FlVx+=LF$%?ZcS!Cq?ye`4 zFK@?+5hO@0+}(E8l)k<&pg?*a=nT`EYbAGPAG{+Qf z-#m};f&!htGVl9Uh1ouX0$xU1oZYDaBT-%hR-7w$y#&-b>fe>R80!@~zgX=RT@029 zv|8(Y)jggvaGkkhJP*|8rAFc>cX8-elYs(`+q1MHj#r(ytGx?S*00Ptt*dgI$GkAG zuP`UwMHeRER7fzgcf%zX-gr^2FY#0+=8LYz8~Pm4C_SfPdkr*Om4doLSbDgd#(jCI z+qxA@{tB8`&itL!`}|n{G}+xiKe~s@(W%=EdG*hATzc}%sSPo5x;}3Nel@Jx{nVh9 z%tXGaw4Oj}f1!vR9X+JK)@a&sP3>lg)(M%Y2bYMsZ|+Xnmu7F3tcA*)PHxz!%)(8` z`cl0-f<{BjO15mH$3~s<(Qj%Djau1!v*W`(EEU74D&`6WA`<_iGn}4_J6qG#Hs1 zO3Ca!B-y36-;YJl4BonG*NDqb%3wy6?58Z?5X6T4^fNTjy2m!Y_ZG^S#n2k~%!1)} zaub4pxn}1nB=X&;A5J>8cb{=Q?a*@_+ayX~1W(D? zL=Nv+N~c>B%g2&63#uN=Ncb8!F0}C#feeTna3=m0Yf@ z@WtT2><+XlRvEwH7`l*99YmCgscxGQBJxZ-Dcawm`S?V~T-GPS7KJs{vEy21M&TB> zG`{p<3i^XLyNAJJ7bhRtbKlkcbaRW8L`O}3KrrqdIu7Yo^nvrmou9g6DMJ#Nn=Efz zu$G$+W(8H~2sX_s5nw&WGwh@_WC>3|dA!hfrB>QNY4;l=OU}$DO1b#wKX@_@t-E1uJ;_-Q&ZQjJHY#Pn!eqv*lkp;1 zMfLvLlBvspCf&(aIvBUmKDRq4JA!VuTrVELLU~u|;|ZBwCy0Q+i91%W6r_4JJxwR$SJ}FXCi@o{v*5-Rlvqa^3C~ zi1Dp*3Yq5+R-NmkzJs~3yZic8EXv4)iEF`?jMFTb(&igqzkF=9@<53sd0SL1JeG{B zEhOQd5_dPrzzZ*6GlCxl@(Ja-gK}I{DChIa)3>p7z15iBmM0J4-;3}|W4dX~e7n|& z*HZJ8_B{e3?Dv{V-`|koSgYh+YMS(Ecb>$<8`f9htikN&cT9=DfQJ|NVq&1T)S4`# zmrIZEisl)b+EAKcyk{Yn8%6J)HXP4j{PeKg&vwyRPKU&5j)zyi8Ng>eK8gRP zoXFolBSJW}hLK$097#n9VlOEbTn_D<92Ww)or5SmsEkUP$J!YueUCiJT0l<9U9}>BNH=MZtUWG+(l=I5WhoF;{xGR9A0ZTEp7Qu*2zvdkP!5gf_XwF&|5Lu)1CrJF}UT z0=cJZ3gu)|NP8zV7LzN+I`rC!cPA_!Dvz8Ba1$BB=lC#N;_qx6xgXp&k?s7=6CGe8ezUofXXvL6fNZdrJrQ@rrJx(7xUp z@tEeed%OpY+FLpZ%CW{v4JW-@s0QC%5H-Hf;c@E0ax3*Ui%&S+nbK-gZPh1gXU3D` z-YQ(7hM<)hr`WBE_~j(z-Q~-{I_Y_-*?`r`%qX&Hydg&Ri;|lUif{0(+bAdar&m^G zrtV#jd>gSTQ<~b2qVY^OG4tt#x#K;L^7&p5U~0ydT$GaWR>#*Zl4WlW9gfkZ4(psh zNhLI7z;->z1ol9%@d<9H*YYPD&QuTZDGYSxE^9nzZxnSog)6(w*faylndQWHP%QJ9 zi^w@?;M?z8NdBf2wJga@j=g>84h6R(to7g;VVB#-6pXOm25y)$>yA^E2x% zq*jR`;Jt#C6JV;B(ume+P#Ey=^ID(6r3;bNI`dh$qmQyiL_e1EkVFvFFT0e-o*R3W z`M&7I6KbFBFE!s4wslf)8h6REu2_f_&xlhI=HvmF za=hpbz4*+l75J$IxI&+;Vjhz28erL;@Z`ADE-QhDqeWX^h>oqs*f@uAopSUO=yv_& zQoHx;eFoRvt2Prt_mkrCn+N^YYsc%}ad;#*aB&BEQpce~TUTC~81)BoUwffraHc*~ z#$$3togkz&o`4(eO+b!tvVs6(p?9`-P|(@ol=BG#ti{vWjE_PmXS4HmgjR3MeW0ql zt&;v$vi#&L{F<6k+$j_HYlQr_n|UMy`&T(-u31f0chC2*n$ftRK2_jyw0U1%b2IWD1ROO0tQzyKUC0bF0(0o0ngQ-&$*-{B-mvVM)cSYXH`R|a+1(T zC)LBh=wN%dIEV5k&3AF#-_*WwWBrA=GrFK)b&cAyRr_Jf_(0qYC%Yz&n^%;ymaiyX zxEt7AjFCYb!f!oKyOqZ;OigXmHXNzqB0gs;d;F~az4mW!QC3hpPL3_>eS;idzg9nV zamn;#{)p!-vT%+Uw1k(BDZ5QEo>(CS8$5bQJ4Nu4058t*XEVptwo3A~$n zO85Ed{P>6n!FCDFiX91$)7gqlWG)4>QxOUlFFAjo-O0=8vORT2A}NhxBSPNhT4iH+ll5`L?eRT0VHtAQN%%{1eGzm`a?gxlu&Ow9cY5hFZ_;n^S0eBmqZBnv2Uo!N(DceUub6}w z-WwrQxQcFBSzmMN6Z>ks7+65CO<)ZFZhK}rUu z#vlb_BXa{WTUQ#LA7?MPVMzrZK2BXMkczF7fs-)}2ka^bV;d(LcwzzewXvhEvxA|r zBdif62U|l`V<#Pul7tiuNX^*Q33i{PtCO@U{8ljh5Hc1>$`*Dz7+%`{Km z59IIh14SY(=+FE>0TJgP;78UPrk`R6#e(z1g$x%w$OXua>;C{3yh`V&K5_kwiyLrK z{}1rBZ-8)~xRK!D-m}L;eL}o)_|MxL55m?D&7TK;unQnJ;0yfz06)m|i5H>M09*)L z+@F_#Z=(4FxPWrwMabw7&)!RK06YO7!TbmCAms_c2>=&DrUyLzz4?g`{vx2G_O|yF zE&xx!Cu962p1>T)fFXo>u+VY**_i;D1i@e=A_T*0u#c?4e|Ql_3Jrpo2@bUjRv7uS zd+-<6V=x5CLIeI~MFvCu{!#;my8&>S0oa24yx4%@%k`gg_mBz_if~x~(4YwE9;iR` zhe7;hXj}+&0zyMb`2ZT%53qk58e)C`K;uG8BnW6f!2WG$$R-WAe|2Qi;QF&OKT=)e zMi2yGjT<551J?eq(}f%w67LKAi~9xsi~bjw2bpF5;(>vA{;XvJT^%so-TQeSt5Y+}APK z$(6runVfqE1dl@FguBy6q5VDe=j1>Tb0|no4uo_M*aH7pn*N-Q0WFequMGGnmcT!& zJtusJ?$1F&Hh*#Ml_dNO?Ps;;ghwlX85$>oAb=p@@z4?7;`~2QdrkyF0BD>)&-$F4 ze^%|03X~I>`g8uG{*XVb{z#!6#%lo94uj1D%Y^(rr-$<}P6I+hNEZR=&(8WsCX2)P z3KspRA5s>~5)E$Z-1_HZ|2A6)Vt~+oDEkpX!Z-QR*P2EX}|P4{VP>`@@L_q-!Lyj05K{DF@C! zoO3v0nY_ro@(!H8Bpx{b4>Av&e8|*)??K=|*5G01pJNRu zNC^CKj&KbJSR_241*$!)MB$HGQLPwhiSJ1 zNboT8Z$Uy30)PY$V2=n89$x-ANJw=HSqTmV9>5-j_Gi`phydXU#-DWx9=INX1P?3! z99u^rA?5*q0O0}aQAmH^sev5U0|B8SCbI)|hliJcjxD6R1y3;kEJ%0&dxSN3mDAsb zh9C&Q8oZL~D6~JT_DESfOgRFe9p+6B1j_Ye+vzW}hAgy&a3Ll)1hhYE21hItSx5`v zLP+-j(jN|KkqVL2BzbweZlp_!tVo&9OHF%i$x1k}~bb=h_O%c$3 z%*cNZ+7TV&K@bCA>o9M600|ym{v}9#!+a?M(huAGbC8g#Jufn~Kg^dRp#2}H z{b9-x$QnYr2hiZ*<)35ih;ALG8Uc_F^Q8z#e^K2JQ;a}J2&wKvf&$+X@R#cPpob~O zLuk;$JShU&-&cF+VX6@b4KbM^p#5332kI8|Fx3cz^s~A{fln~{TY^M(5CM9aFFjxj zc$)gJK|>G(VC^tpdH@X`X8yTJ0@>6GJ&el$&<^vZ2xx!S|3V7wFg^o9``HhJ!qa|# znYF_>4FK&h$UI;TUTgZdp&jMD(n4uj1DXz+C4--d=D2ng-x zFa!$yvu1E)sy&R)fRGTvngdhX}=`grNK>GWcH7K&k2znS?9zgp)h>W1f zA|vSGIi3S(e>gHaBFMvHOn@MNiHM-^!##i55|Kql&|e}W=pT-ZkS<8bA|&W95fT)h zc>Bw&A&ZcpzeGq-cmnRvK|7*j$RZ=?VMXbI+W+Cm2&o_sGgScf|0P0#!lRZy#}+bZ zT!$H}Luh+%PXq2Ea{b|RMnFMw9cHY6kPu73z96~a(aK+D>o8*lg!c0q$pw#E{x&oO zK>%onX}1H`;8DxphK3*r2o2!@?L#}<42GT5g`Fy=fgdY(qyfpB8#&VGVC}`B`&E?t zzVH4Cru|*-{pA;aP(uZ4zm{ZwD&L~ zXca8ZeM{inSG&D3TiEyesX)&C{M%l&ChYtD2!?Y%T;SY449>al2y^c9#JTV4aqb^1 z=7eu8!|vzaW7Xp*id3Y79z2x_g-+S>W zWIsBF?1!R|{kRXZUz7^juK*iYaAi_g@us)!{m_t(m4n`fdFfNe;kngaqR6! z!@l3IF@o$L8iwpw&p`G|RUrHIA&~uI49I@v!`{A-3Kn$#P$LxnItAG0eRG2Dr;MTd zd0Oaxk?LM(2)l0o%pdeXJ@*R^_uP5d|M&F=y01S_xR(g~ejo3i9|Zfnk9Ti{|M7Xx zkf8f`_ZAElti9R!$M3xzuD$sO_IZDcLYD?+cg{baoxs5bsNndiSORvDfs=uit?7Z` z{ah6ML-~O-2jT$@pvwl<#vm0aNKFMKYXo~DgSnF%NKr|F1`JYFpy6QW;5;n00al8u zK(XKk1^6$(lUD&lu=W%Nqypx^+OvVfOW|4HeK;zdJXm`&0I6_7u{hza!tUb5+Ow3y zyWkdaa2JFJrXsLGsen`dDdOx@Ey*q@wOd#RnnZh;Q@KXnUI;o-vCbMy}z z0J_b;X#gNQ1c`vQ01yGq0(24BEb_JxV+1tt!;+B527my`T|nOv*e&9&!w&Y&Zy)pk zP!wdE_CvwJFb#(b9i#$#H2dC402n(`@$4PNKIr5(DhB4k0`E<@0NsZD35LSHKd=!JW4!{B!JFp&H1q|hb zc_r}G6*m7KPE7xTSL8~DWaTvP0qlsF6znp4mpy9CGm=Ra2m50tSGXc#!KQ zd{#r!;}Mn+HvD@707&7;%nBg>h`9ezw~ufI7z9A^0Luax_BHHh&sdNN3Ro)*)CK@3 z;Q;*8mdWZXpt0|4V;>Q3JXL^oLxea8DFT*RW~kaH;{|IAVLqNkA?P zz;J<;%fF!)p+vyjfU^!jRgh~R;6`BWFR;J=^)Vv1Q(%4Xk?xV&`XTPUL!bX7oBsuY z>>c4m*3myA{GCV+ZUl@5SdxmA2H>@T?RuE|3Q)x(!v(ki|3Vc3lL3-dh!a=@3dDCr z`2jN#LPdYKwgbiktmXu^ja+q)Gze_vH*5o)H5d=DM)#e911bEjL15YBKf?kbfqVN% z6b8r@(#`??D4;oDLE`^^e}eOOQ3i5}0df3>VBoO+6T$F}6eK(yQRySC1AMyQiS@s! zIwuzw7VPJTMgT?%FO@?A41fjL{cmK6SlECq|0be9uIj)We-}yo*8Kkq5rB?>`5K_s z1IGT3nsOwb1KbFhk&w3mSR!D5{u(H9{)<5GcP%4a0Ki~@IgS4`SO8F9bH5YPZ_ENQ z=K|XJZSV&aG=S41Q~nV(`bPx-_6n$)0uphgK>)Kz$lN0RnW5#A+c&Hqn5->4AWcEWyZkCIC7B-#0%%_g|U=w(&cK zKY#?d7WiZ`6@cIY!~k>-x!D1f0U22^k^PSwa}eMo$bixV!1+fEN3;`w;-9((njC;` zF<_!M1KI7@FI)@m;j+8u0^h~uLFWMW|C_Xts~b5_5d#3MDS)xS>jscPI+$>d@BzH>cf=pu2)q_Z7(i2j zbJFiNYX8I5FwzBPujKe&j}XApZ<_m!C;(Q6d_p_qW3R6Fe}V+O7RWPzyMOEt;5Z;3 z3Gfl6znQy#*U7)PTfj(wPu2Nf=?}`ug$4WB-xB;E7b+-x10D(G|H6V0OA=r#z-QeY z34VX$QX^LhfQW!?|MS9ze8Mv<-av%zu&ru#MlXXa78QKr2Uf@&QvC@}U85 z{9Ua2>%_BHr+6TBfbjq)o`c(dVh;*iBw;^$$_3DOC^rQ5Jv=)MOFD3Kz&^kqmI;t0 z@|6@Ygx@WmzcV*v3nH+&|Ai?6*c@=S21@2POd;$8`80E6(feJ>=3fW|AOpafhSWQO z!VB~cxQQ0qr6%Ae}F-Cu3`Mnjc~ZDVRGtn%kIa zm>W5n(ZK41U=5iWIKbXX!UVGW@!AqAV-u&nzZ`xv4sthkum#!L7=xT#Y(Y+D4#vhH z6WHraKqlrlj6sg(t{^xDkc~O)5>e*8SC>ecTNy)W_G-2Ov;dxlrs{m%>Bsw2e$WFJ z2f=P|GKLXj1$%#rgt4Kmkum6!v5hGVA=h4|+Qo~GP7cNf)>y8v_p5stWvj0fgx2bCM(ECIR>Zov3KdnJyGs)Mz^F zT=nuGeaTYn^SYq|kLLmfzLeGU=Jr04*AuXb)#88dxWj+z;rjR1<%iQ9(J_80=I?nf zu!|L2&$cw1UFo;V$BXG4cL?6_kdn`N`AtxD=F3&~Rvo_u(3{p%c45MG9Zp8wXVV`G z<;W{sZc@%s$y4|93k+nY<>V^wmT-PRtDP8?(xf)+8jme`=U!}96W=#I zXGh5FF@xK$21ik^EP{Ac64O0isDgMovOySN1Os9 zU(reG%ifgE6_E-MG*RX9s8jif>q9Ap#KHyRG*wbsrjCAcC^f&lz&-L+@i>ahivp?{?>c(J(ZoD1%@zd) zj%DX8^OvJSC%$y(n)Jb|WNUMp+6 ztXJVVtOlSM~9+B0*cA%2Z;|SVd;py!eJbr#|C8Rng zh)!a&dE|*&!lP2E9DeRt{HUr6#E%RyeGAQ^uh*nj$ed=>9qwr&QGeQhDoYEWyNQaI zt;i?g`mpz1N3vF$ND!jf}`Vyob*Bj>F zO%R-BSm1wCcQ%c==zC2N#UiKlTO;qO;UQl6zz4fIUGFg&2Od;DdHeSDR?Zi_%%@9k zSEn+eP=Y3*@hD=gv#H~%@9?8&{OD14wR|tSuwUIwiDMKUETikcC07S%0w%`^)E5bnTvA>wC44rXxdDjyR3r*ZgK1XA?&uz+~e%;g@C z0y^qOt#te#s%0>BhnM{2uT6NRxFhC0iiFs;C+^giF2=k&9yTE!mLw{?l0I;wry>46 z9@ZH=y z1-AGJT^C*CZj~=MU0oofqTD37RLCoA7JUMLx1gh#`YKaC-@D$iLb8Vyo8iKvRx_w; zqN5KKk~YObf}!hW&$6Fkjpq-& zWLfHYFIrsLpyF|se86#_mCWbfdQ-gg!r0Ad#o=2VC5Cro;y07Z%WYntz9Hy(kHc>O zuY#}mvyw+()j;PH+qVUaZK3CjZS-Gm@bjqY7A%Ma2r8V9T_bgVq!y!5@Pt#<{*|oR zqKt@Mn-hWj1n7dmX&#{#A=TzHL~b{5Wl;-H%5+Ri)VQYTXU{&K_v^f#5gC>KiQ;bl zaVb=8;WzXIsrT=zvrwAOhCIHL^c>^3?)A!s)E%&tU?>G2iGjrZoHJPtq2Z#Un2I}V zlZFdMbC@ydVx0`v5?B+3^x5rR-^=WKQ(jc4pw!2lbkF*XhMgi^n&{fC98$-q&9>JT zOg8CZktoo$_rjjmhmE#@}P*4K?49L-H_KnB)!u)hp! zjP@?s`#(|-z`zlquD=u3XaA% zVD|w01w&gaTi6%&&IVR66vmED=CF?jP9RZ`7)Tr>0g?nsfuun)AX$(cNFH-gRVOm7+M-T!JU_bA;UlH|6^}>@c+QSHUM1*8G?*J zFlPp23NizkgDgOnAS;kH$OdE!vIE(J96*jBCy+Df2FL~E3UULvgJ6mS8|D!gXRkc^ z(8U2Bf&TX{&R%gfz{SaRM|UFV>s=)^Xzh5_e1f7eh}eCB4*D)Z9Q@>c{cwF1ri%`H zVROXfNGP3)ks$?%J1!gEwcGbjU~nZ@`H6^$&GYsxe0*t05&2E;+KA4=c89i!Y`nt) zpU1-Ub}}uc;R#beFWbhs;SCpwdClF>6t<>9uSN-K z7OzzlwGLc`dBtE>)(80m)pSg}7o1{B6*oG-^7S~0{4Voz$t9?dk}HOEj|aYg5wPug zvMeBqXGi>t?~sdI0PJOm7PAY&PN{ZM{T*SC3}6=u3Gv&M(=pL#63>(Ice6LXhCuJ7 zOzQN#mqIJIE!Lr=ntb-fm;TkG!9KRrOWH44yFJ`u+v|xwRLp5K-{i@C|7E&>zjoAl zIld94lr7XGoTA#WcVpx^BlheB)b#q>A=&dI33HsrGZ~xjqy#QgKewyzzvj8E)vL2& z_4pWhW{oFtRXnS^YPW<1Z*iiwG+X+VN>s*~ZX64t;ydnl<1dA!aVxcCu4giLS9D8R zpmE(NmmE-K$?WWAupr_}Bp2sX%FZO~*0g{W2gJ*UrIsjJW@>f2TCf;Pvpq3UCCISu zM(@VAz~Q>%o-iXRskEHot!8`ScHxsPrQr+_3shtA)pVZ>Q8nQ#0j}5?#Q~M$Oe`T! zc;&>v-Rv`LS?FBR*E1gx3$eLJpxK_6J+CLAjLS+}9$fw+v_9mri{AUH?!tuhYu`%B zV&@g7-^C8R?Ot`QkhZz2=drb3IcRCUU|!X--M{`~fam4toYz+`y|s374!7H0HHzvL zIpH!-4#KWykAEus4EkAEXFdXI*&`4-toF< z(%OGughyp@0$?I26)MEU& z-rRXx~8sx%CmTTb1c>LTgzt({uiZ1RS(zHTS)8-c5Vij+3MiGnBj)JY}QA$ zE}`{u9n|LL(n};e4t}hXR&TJrW}A~*Qr^ICMtZCKQiWb0iV1IWUJr+fyN;P;`n81A z9$DOE?*|xf7?&h+Ri2`xE8G@3;ke`EyK`aA_q(0UyDXEp$}9XqEzy18{x{PFjrgNQ zZ#eBo^(s~cMyV^}<>r?-pQ8;CEWPU#FZnudZ++%og&8Ce8#Tz}?Mh4-ILP1HvQTfnVLqzI79Q|0TH|p! zV;B*!9f`FYtyt`>1ZP#|V>FL2nS(R(po9yXMh5SW3F>n`vAgxHcNrWc>T99A@bIC8 z5`E@6S*Vf#fq zH!N8P;A$N)LAvwvJF({T5hDcFvIlr0TyN<`SPx;JKvmc)*Ts4n- zVaEHlQ0kps;pI#XpXQVJMxE@(ux3~LFf+6(M2KX?UI=)W#(mz-W*W4b8)|H^sQy-h z!Ti3yP?mv6i_Ld>J0?^B^KpvrD|;hpx$ww@zE{f5Rrewz?8@YtdCbhyHl#~eHdfLo z3!2b8)wS8XidLWXmgo_N!ZGi)$9)@;vNu<-=UVH zQ0CFUr+LS6aGS14^mHb-eVm`>r@S)K+~?Rtj2|9VxLgl-Q}nb9lpm?FsCwzxh4mq# zC9lR9N!u_l|Lrlr=_78^OQ2Nm@(Q$e7^!ydVBuq~#oX8IV7+XdiXZM$)E- z)r7yJd9lys&Fo>WS0}zwIGyvkTudk_)kw4?=TF#PCsm0>CEIikRk0MTo<>D?;iCfS zIBMQlnln8%bF#2EtD7>$*V<9d3ATKC?V-mndr^xlslH)6CCPAzPiyq{dXD3>@}h^9 zaF9Dpq4}NJd0BPhjlQ5$uO2gZM`sq12N}JW-^E|5b8^p8k9so3SS0+s?Q(|&r#JKM zw<^rHqVs%SgPN{;LI-=Q$4(78U#uOu=3`h;oRn#)dc$L&0tZ0y5?}DPslt@ z^pKQ%$N7?}jn4RqnyW84sC33JwwMf-dys4Uq}xk%_;?R=3kf~x`Ebf-;hL~lpe7yJ zI;Bg}Lb)pOx%+|@LuijI<3bXcRaAC-S2hOo znG&{Tm+#Vx*AO31ldm#gT{;ve@WQsvN~Cl>G}5(*)Q-q`uyyAlR&c@Tp>;o=la$^q z9W`cQRwv0l@~?w9K#q(0xCYtt;ywnTT}AwB*I34Ji%uIr9Gfn4#?hil*nLUBur~H9 ziEDIdw}uAJS!R_DKcRZsD0;k!yYsXDq^m})&hZb{oDZZfzqxVZoTE%9(JJq#p85dy zQ?bUOwwM%d#T7qEc2_~!4vWfTifw<`z zSvRB0OR@70#;vaUjK&FRX>#mnkD$FpublMHsJ1@0&DfTjK-wx!N$%U58s^FoA3`Fx zq_a!fe1kvMGcjaC?Aw{E5mb8Rw>;M_jT;m&IV7&H1&xJKNI9GN=#%p+bL7$1(gcZ} zVeTm1+#%7d9M6wzNQ&ruq{>R)o;5MdUM)-tdEM}#bm_KfDxPDp@vSh~Ea@HAvr@i# zYWG-KFSddD&&1YI3)0EXIj_!}>Xo$hvog(eU-rywv*#jT_pbU=wTxIv<3z9*lhiwd{u|OXPYkwfc?4{woITKzUQ~&7a~Hif4H%dG z5V}O`b2cFl-_TV;xMekgK39Z3c|6Wx*M3MXns%PmB!^VNFH1pEvso?3_ukvW@81$W zl8x4kL43qdr7IOxSoMC?z&$C4lOoBZ1r3hQ57aZ75lNj;iw`=1Vc>J;*^|hS%JoO{crV>bpkiMmPFiO1#o9QUxRaTfwlFz^c}Gd+bq&*4q(J%9aaZR>rQr+CzrBHu{8ZpaXmph>!L=c=YDLmPd;J_^}BW3?6{$Q6h*)LETW;}UbFhRUdHdv#g$S;#glWgjZs^@?nW<6z>ySdFIbk_akBEQ z+-{erE3Wq0zfZHmcVVFJl20FfCpI8^MO;kqsR{!F^OZ+EHhA)j@B19ns}z-$?qAZT zP|4kZhPzFC5t#FB2lN=7Tty zl*{oQnAfqXX-*ej-S|4#>>X)F7=G;;)7=2h@yu1ea&iuoWejJHahI6Ds=x*ry*JO> zn{BV%PIz0Yc@y{U)Z*xl1j^1Q>hcpP#vPG{LBu3y2y|asCh>sTSPZzzN?l7_lho%> zr%aX-XRsUT)A^Vs&tG9(4aV~Sa_^?#y!p47UgemQKI;oab2oN<)7BWtlrrLO^;t{45>3vXJYqm-{*s{6_ocZPO3t{r9`G$Xxl~ zyMAwJcJx5=zPzb@xp~>_I2LCr-^tKzjgH4yX9|hv-2KSzidc%*#lJumZ@54<;CWSi z!b_2WJnxEL#hXOTVTr+$uI{;h4RvW}iuBRA&-jaZUehYB)|SedRxP@-d%I2?P4ni% zT$)-#_ry8vFU-1p;IP%irfcb!Y$N5W6(`o86(`rz+|sg>DPVqcRo5Wr%M3W!GhW3S z?f$u#4#pVns3ARR;l*B7uNEtfPxe@C@2?6ue_(JQ^_%83wbMppa;U(&`;fmjBBhfq z&F&(_af>1CClPi*CW_SD)05)~uez>&T=L8AyfbNjrTI~`1;|haXUXnum$keJI{PKz z^0+}eIcM2-kDFvq_E=uzzp)5b&2DL(6v^)EON1_zPkz6*_^csjG}#8EJ{)KLX^x~* z+N7w|kl21aImmY6mVQM%^|QOp4|rV_HCMKu9S?6{R1*9i)9|gL)*q`A^Xf)l!?!%G z0;}Tkfq`P_ufDd=RL!AZ6`qQOV5cm78pUdGaIX(13N>ZHO&aU?o@Z<0V-ZhyH+A|o zA@sxR<2}?pc8SigC?=$O>NP(Ks^aBuMe!ozB$MmM^1G?H|A$@59;$9dU zu_jEnFFfIF#v>#oI#c-Z^#ZunKdj%BsP7c>kCHk0U>J6xCF zw2R>O&lQe;k14jD;x`ye3ng|Bky5bXl@N>6&WwH;`aH+pMJ>CL@oV1mOe-IJ+Ow$S z9?l!Kj)|f7o;0pYp9dGV1-(n362F*c{Pd%fmN>p(`AL5~=a;NvtrunLM`Ka z@{4!rJwLC68RV|v855A@-l3DeV%h%rj?!_ic=8WSpnKlavdR8*(bWB-iQLaQ>O&2d z7VQ@l?cNBnbV!9$FWPE$1=hdD^JVM6lMr?fc~kdr1ZAM(?c-S|DoVmFF56a|RrW=1 zD*gqY@8rRub$t$TpIK+x78o!^hdcYxX`RT!3>a;nkLGBinpV9aaPzo8;e#z&sB14^ zouBKm@p?5oXc{SC(R zKb_NYc>7Qf| zuW3+@2|ORhkeqqA;UsAzVlsK@p@k4CnaZ*sYW?hlKxeXFtG4Zj4a0j+o0rAaH%w<& zcs&bm^U&+X z-i}RaZEV+E{S?%MWi#jMW1{!s8dwScyfkjL{=1>Zq5-s;YmU8up+)zZD5@m4<9u}dy{=I&JQF~^lV4bV&y=7F!d zS;kq#sG&FfZM+lTdbEpyu3hZDSr#oX>e%18;zwWcu(YCwT430nq_uVIL@e200A^m4;AWvgvaZ(PLZteZ?Hb=}=j-wj;3v3e`*!ktOe=VtVUt- zu$4E@9P@ZB)!)M>_ZB0NE=cwg-OY+SikhjGyDeDH{G_mF0@Mu*rBrSR()FKky?0S7 zmJG}HlY4(37?MV%@1kAfJ(^Zq`1}=vSVYbIK+Tl$OS^u+?a96VqQAasOP3 z9<3!j@duPiSp^BULc7~^23b)C$Nl{W0>US_vb(_r6qLoUj^X6{s5`n2JHFKx$U9y< zQBOtDo9%LZGeyO;R~_Hp>`Kfj&B)KHUz71JaXFJ*%w1}XXLj=$dUglnO2$%Cg(j*CTb;ciqdVVr z6Kq|2tzLLj4}ixi+{o^aP%-g^5HERZI<4Z8e=G9owRnz|g#(G~U##u5PCD%+)IzpR z89H6TD^(}6S{5W}0~O8WF3tG-`kmHCJ3Ml+W+9g06^d7{=A&)-C&$ z>3a|2r~N4h2Xj_sx8B^Ox%2i?i?rjWljX`a52@)u?!=@U%8E8(LYF>8en?q-IYyDe zk}-yrBD3t0PuaY^~){j;fcETh+pMhxpe&Vj}ns? z^{d%kHz6Snry@>23ho=TcjX`P?mLeI5(#HyHzvLosc!OkWL4?SWSR(ej0AgDfLagh zx~u_#Y5x`K2a6nxx5Z(Vpi4ItXUHK{8gM)!kg1(y{%Y>=u8c( z);db?y-!2Fv&GWa=P1%PBi=+wfhDdQ_hbyZnB`)guCzpJcZpS=6z|Gg#%T z>Bfm6rMAVfPCgw{PDmS*G1}9xNtU%j7)Gv^*%g%bUakeOe#QJ%;gv^#d;VPQ&0rPJAhu!wJBGt=c9eH^&?c#Ow}!WdKAKg-qz zZRfG%F@f&pEru=2+Q+*YQ!=N$#T}&$R>JCdn)Zz>C{{B>3C-3dV#UGyhBm|Gz+}rQ zLzQkkvRZ%10X}~zq7<}V|0TX9@K?W$H#gsYHlm#0Wn$M*;I$<W`VDLo0Jd}qNG z&GHMJvTE}cH-Oi8}w$$CwnEFmdYFFGM6iQq18aj?MD_ZOb!7j)A#j3aEAOF4u! z;)oLIS%YK9J5w}>N8>tZqc9XEsSBoGDzX`}sDt(MF57z8cr7rsFr z%*${HSI*5(OkuIO`UyVD@q#LKh39lympqgr%eeJ=>8pAjI|0coPTS7MXHQau1{9`U z&c^wU*7|}&#nU473Q)oFNwl3jw-~2opLm8!vQ(DL2aPF#zVTHMA8TX5O2v5{<2S}* zsV8`W|HKWGyf>#xA|KsAw+dau(VUjJ>Q3T6McVnw#Hmr=o1G_gBbX^(vUuD_g@cs# z+~p8U<-{@+x%0F%oZ+vX%fiD${em!5aMOb-2^vJxUZJF;z4W+kcA1-I%fPp3rq{S= zEx3b)QrtzB#GMH;q7c%u(|mQ2mRyIv&a6?mK$$?K0rmWgP!C%9rDgP1>M!Op*gSSN z7Ls^xII8b2r5hVddbC+v6es$5Sl1C#67L$+Y?!);@bEk6PYPE@NUsfT2M6I!={+0p zDdptUWUluVP0VLC7OSi74|Ag0N|_7Ybc-Y72~NF!uR`-I1Xri==F{<4)tXof_zry3 z{3p;I%O;=?dz0Gu@2jgXj@3x(GMo}{y1hi<^M*(=M?E`OhhXK^W$8>Y(Hj|aD3?ca zb%Lr1d&hUkEhXK^wD|J37d1-5ZnB>1XF2n}n>!-+6gws+X86~S@$X&C42zrG^rMb% zIa!0>`8_ST)vH-`8B2wHl8SkW0n@EsUPf$(U*(&yxvhWtWJzSkQn z>T}=Q$M00OvaZo*dTiAtw-;v9WX8*@)YFM!NEp`i{BzkX*E>y79g10X>D#jhy8Vm!8c% z4U<-^F`jBFf~ZQpG!Iv03f_*{$a{LT=K@TY-h zNpeGnUMM70cVOnzYgFlP+2?W5YtZj}Nnvv|W#9ZXKk#0D9rx6W0!Piey@~X?62TZf zkDceVt`>@l;5Xx+1z(V?#5aESz3$giVO52>n~^pG!7y1F4nZ4zXg zqMmy>Nt!=uD9y_4&V_4v<0G%BwZ~U?x3cZ*V?qe!B1-$I6bs*+s(WVZXB^;q(WWQk z3g+XY2vf$7#GjWPSBI=ulIgW~pXz-$_erP3(0W!NZ_T}hDZ{ew=IHJV>zm7p3}-5_ zX2V|gpQ5*Z9Hciq)%YYT57X&RfiJJ|^^}m;w|1w;yIocCd#G5LWLla!UC`pDufcr2 zJlV2zAssT^k5p%3GL-Ddi)qa7kYjaOK!mF{BA|+RltNK)@eeK}J;z(Wsxe>rvN|nG zMbrCjx5@C5AKPqRkc()a)&}RQd{XO`GMtXX~gph3EqA2XLfcxpy-7aM=rSYN+qP{hGi=+ol@S@XZQHzAYt`CSwX60ycb~^OAI8IYm|vfNZ-49BodMdX!X$IL z;_F)d%9C=(Qr&^3x3A>|bT zndag`^f`Se(?cl7i)`zdpLCt0Uy3Gqm}`Yd%aHQVX;2cUXQyYntn~5yTK{Ypy&P?K zVi4PgZgm%Z^0#;rrm?y<}Nh%n3t0Rk@mgfZoyGG?R%90eriV48m+?_N-bl zPeB41&%8D(vAwckcgeR>8WG)wAQ%x=SVOuec?*TQ*!l#s{KV=^^BKr^?D-0{AsA$v zmgDo0!+w%8KQcmeaE)4#cd+Ciog7?F+*iRTa&;_vUXWr2bvTmigT^AxekHk#qOl>9 zYv2QW-F@v$9xav3F=jDW)?OJd!JGoRbN}*k+S+2ZOUOd8>+g2lF@rH+<)*m|Jg|}? z7PS2;!b6H)u(EeUuZa9Y+8R{*)aR?-}I}$KH!Hep7y;* z_9{6&R{{Fun&ZRfv)pM9=`J3@Z0J*V8b>tbxSJV!f$eR~OqP+6w}V)rfL*SWLM@kA z3@%f`*GR|@5Eh-KO)(Q>aO3wbaTrqPHul(-O%WM7@-BQRGetf(!VH8BFz|KYD&f`% zp_bno{_fY>@OTJ8w8Y`%SA}IJa*Qi$06G&+`xE#_65c9+IbrV5+qB_4JnYETYJp;n zcxF40)S{D?LkkEsVbY0-3ErPTASR3|-ppySa!Ice4F!DmaC zA*NY6!$f~)YWxbbrBkX3n4e(gCX?-3y+#ZsErt)(^{tEs&5qNkyX<$r8bYcDd(?ZO zzCSQ1C@9RTNEs(c!tol;B3wip+hy>V6PPWYAu+2Cf}2WM+Q_NPl+mQD^*aq6~hr!0{jTlISoxW^iikc zO{R!yF&dpImV^I`Vf?Vo;TFH%tr; z?|rUh5ti5MV(IE$x!5rv=JBMjSGso`P5Q%Z6Wrq?V|aZ~t;aBqCQIF7 z&{tPYcJ~YqYb11y8;dotDdDAn^rIg-z?GjByqZhfz&AaXEUFqg*z#TOc?kmq!1~VA z`1vgvPhUG7uJyCKW`?gaudX+*r*;@@V_m=wt#hXhe~hT1jIhrfyTg@>#U9ivl_6!v zh|?d$*CET%=1TRFsr6$Rjo?vVtB47sJ=4JzkqY|N=p6?$huLbL4m=%GtoN4&qn8_R zk$G--k*|Iq3?hsF0aN;~&MZ4C2ghHB9RKYK!2g6PiL0wfsww?}DKY*Nru4hg@*7iP zz~}hw+53N?lzy{F|Cumm{x`yyk@cS_rT;xV^bf-LPgv+T9rPy~^d}GW4;ttnM9-f* z&p%k6zepaBe?@oxn|JP?O{V_~bm#9+`7b)TN!?9Zd8wUmZzL1hiz`C(io@L~T3?_x z_osR$6<56u%{CAGim>1{~jRYI^dKS4b}MO@#Wug!DP zaEd~7U&x6)wM zoevw;vCun-(B1}xxqle6%cgmKub7P(yye)22Gj@4lN7DYtHJrae;a! zAgs&rtfY2cuHbUI=Mp%NCD;YoKCG(E8&?h{Di(E6R}0?H4+pmo>)gdn1(T02Kr0j1 z`F(EKh=5XRG7LsMOI{ZmQ&tRoEDIl@bL4lb6X-gUc=$q;uqm*oLmI?Q!oZ0?GKPWv zC60P6pP{OSnf478hXB!Q!K)>UYt^$ZlT2*ai#1S|PlD+9oF5lQ@Pjn5zn`cSrUH@e zeEb?%>00wgYl^}yTDor`UmIm9Jlo z%9tfTZNxR-0|u>Ae}InOM*}6!G8uYXUct`rdx?;Y+Kp^DU&AK;Nb<6<(s1ResVO{z zH`d!@=Cme-0uLc%K#KC>!;>4`+&6*YbXEyUA6em?af1&T_Drs~>z$xSG{jr?@?1N` z;%5Htm*4IQX-mH~anXNe?~eKzFCzK+<96EtE(Y;Koo&kDVi8n*L~h_|h1Z`DXO*9i z$E3|TZo?5-5utBy9ABbtQ_zUqMWsakD$undoaF_B$$dHcS18aIJ5I#(k4rOim@qdZ zvqh{-=%FfsiAcFT$k<-9g^8r$*l&x1z|0~l?y6TnSl6T@EwGyytww5v-{?Pbtx|THhfi$e$OKUpZx#;^+M@6-&4_MLgc3Bo;7D~2(<~hx-#$rgh!x^o8CzY}C z&KTw(x8rylwU>?7?+_~joh9l8X(bLb(YSK7bgW>JuRW~=c&nFzCx#kkG#j@OJ>g+T z1ESp{1k(q}wmDKYETG0E&!>aa6_8im-&e=*sB6nY)qVz0e@pdd&&AkA*vuC)#rzmI z1pW@i6(Sz{t^UKhHeZE6jE4>|==j@4xQLM%??502myM$Fy9wqUn4(Wy+Li66xzWTQoj9C+4kq~oyYEoDjO95uyC3)ZBJ zU%D!gJ^WzVnWtu@)^hDu!V*)vhC(JjxR74W`FQI40cQBn)*`*;fk%dH=YhpWPR22+ z1s3LTt3x|l&wy{dxL+tH1RT2^xO`&BM+Ov=0}12OunS(EbvFJ5E%$bOD6Cy^;Kyc& zuLxaH(s4A7gUE3hx`TTyes5lU;}0?)#O@TQfm1xO)i%0-N`1iCC`=bASFUT@wku(y zKv65fPBKNM1GV2c-^9ZQ!|9KS5IxUQwCLJpdWMlb-nW~mJ2$nJ%R7Zu6+qo`@8Mm? z;?hM-KCt-E@?QL7v^M~vYKsEQ8IG>tj!%d5Y$1QG7_D6X3}a(T$`#*3QhFp2LLj1z zpqn?pr7RDm)H#ZpAWYx@MT)%cu$x|yJkY531NG*}rBl7lYzO2uVxw{7e#=6mXbK!q zi+flIRh`voOy=3yg5c=oZuLGe71@pBVeuB)gA@;A9{8>uPng8djhum_mRcrBr#hti zYWuK`j64RK_9Dgr5p%(@)*SK{Sr&lq?!V+HP7L7e&VT{D)6 zM2>CgVRMpQn1?>N1VT}=F+!`yoD$=^_AdJ-nT!)n# z4*SFQv?8Eok;)#LP$T{k;1(#~$z~MrCuHSh7SJ3{zy&nq-Hneh$bk+IP9C+)T$hNA zZ+I63Fsz(_87pshxRt7GJp4g08s3w%Eq4Xj0i@vyD?Y7Dzz*KvV>#iu7l&S%pzae& zb3S~kE*Cz(G){9X+SG^|LC%htk1K6q`aI_f%vRlgUM|rIeqTN!VWaDpDaOKb*`dJZ z{Q&Dsx!=(N*YR^@N)-9d6M(J&JU^@kg8LWAO6P>F&CaN&ld4>bciHLZ;rHyTP<9;j`#v2vbr8o&uF z2AJFDa`NH%0uToK(jJuH2)VTH^xeE6bh41@l-N{*VV2iCUi|$ zlMc7@4(5}@v+1hl`C%I-E~>*m4Uw0QgjA|1b92TIh49MzE^7~A34MEaVR?QFV~eKp z&eQ?yW};7L3aYf)>T~$TEMk?B09STv^6U1*doW$T)XOU-28=r>z{Ucr3&H)eoMGEB zCtlE$RJuu>cT5`cpLaS;?1m^5E5OJ6lZ}84^(f0ZgBQ(f4hA;W&~*emgi%j!C~fmz z*G<_?kb0sEq}eeOa=eJD7Z7mc^)ysy>}!YEPP?pGvTeoeg(K3$tZe?8N4)c1pY79QQM&;X=D%6qVX&5gMK+7YJn2xg4&$B}qdAc;>4W`@k8Y;xxn#EIK zZsYy_4ZRS`;QutxttrTpPE$!uE}KV0CLU|>zO4gQqV`-^#x3~ST}^wYG29&|n>4DL zpQ&OGMX5Jufe&FJ-`IXW>0y|xNB9&wX_)tEQ)mF0g{gz-ZIyYad z=wohJ`K=Mv{!CK?xniSQ_R@uH#=ViaMfMj4^+Nr{cLJmQ&3GDe>ry&ue(YB*lLH!) zEp-I&Ndy=yg7F`>O;9R8!9voCg6<%;!(_t+vh6J3-6VJXrQQVLzaZ*s?LhK+CIA(~ z6jv#5sU>hePYoJPxEnF+AswJFS9Z%A_Zx|eoC6t2RG@xI=fa<#Y2Be}D9Ku?S*hIK9pL;yZw=Q8Ng+3 zB9~x1xNa>uaEvv#lG-=C+{4|@UY<_;`p(Kyez(=Ly*A@!^zRzj!BjK!YaQa($B>>_ zGN~?Kz)>4gKqTCl5jC}}2==rB8S=CiA#|x)E>n1!3m$K%_92_KINAnS>|&lF=hqRB z^n)D0A9V$2G-qhuHHi6D6z3t~U~&$|?)E=8JInEp^gY4cw)rUwfeM1vPhPiSX*-@# z(gfisqM3Elvll#YX4Wgl?xTsnSqRXGg&Z5*V|kVDR-ip6x0!itTCa+!Hhk27P=2&# zew0PhWlCqY)BsYM-bOX?5$qIj(fQTeejXEtk@4t1nRz4%QO!9V93NPvG;6N4vD>T; zRIT=_3hTI5g;RdFy#ePkJ&CWvn`~*Het01J##IipR^tdSm@x?fZ~&=5u{xOD=Mj7F z-|hmPs}*joxe`fl6Yg%OF3zuEEFn_Ye4A9`LiDSb>9y|bjlkRPIs*-paS!mK1`Z_j zbw;pDtO=ut+;%0vedLDC?mVASgh3Pqac-gGQrlk#e-XPad zX`Q7No?2Pd2#}kjyabSLF8i+Qx%@FaH9R6AQ?FD{-E1DnZxsfx)G;klgF)7WJ_Z1u z!XB6|!z@6|m*ogJ7X~Xx;u~WjU^Y+LK*CRw;o4a=W}YgI->Gfkj_A--$UAlrUbsV` z@9|EZI)Xj18dG7v{mMsXlX@f}Sw?0tsjVu_-*1pQC^83Q zz=T~q7&h2hzQ0_*4ArYwJhU_)dS4%=_tNGJjb8BL6%tQ~cH8J9G7!&Tvv~YwJwZGzXgLYq{w4vGLiZbr17{a>S?Qw_!E05R*}@Op z4Dz5>VYr-=2L_~q{*}fSZNmjTIJ*ZQiQAMKPTcNknWClBu!gPy2Phsw!LO1ql)#rZ8hW=4~|1+5Sd!6l%%KIPv_CH(gzq@GCzx!sYbbrg3On!I8{%VQ+nJoQl zuJkvd%Rh-c|H<$2zett-)|CJKkbk5~$zIARPpHFY+RGSm=z9)|6GpBHMtfK+L-{{J zXhicNZWW0LYfOMgjPTBPZTWR8&i5|+Z%sAaRzT4Zl@S!^5s3*c4XaiM&5y_}x#XF+I8YZC!OeIfW6w7b6f$@S-(cER3YuMD-IIrG!1} zhPRbST&7X1Hw139-s07Gj=g{9MZVT2Rpbfi#}kt>Lja0jM~FipO|VMRz(}LKd9MZC zJ*ZF(312#pOwx#-=XNkIr&LPMDBs0%9CTomNLDU_MXDM5g*g05cso=#>s?mQpZ-a1 zkxH#rttyeUE3VP5oF;}an2@n#ac6AcSjMQAgqqV%!)7zIt0FK4VF-D{9mj7?kRQ<| z3{w{nPP7|QHArd*dP7AR98TCDP8Km7UJ^bWK^C5Ka|;pap4BRH_`|K(I-QYPo$mM^ z`u^<3Ya4Hek31SFRzdTWwW?saxH^Y2%kzk!ZT~U)1imDgw-pNaiW&apmkHofSUEVKz4|#yc!n11hYf5BxML}W#Cxu zGq9X6^0vSVuB{1l1g_^mS|q8F2}WYTjJ!fL6Ipj=)e0rW1PJfC0SBC{dDz~xX(5kt zzKI?ivtZVcWf`sjv}u9q4(NMi6G(J!4v`!nY(*|7jae=*1i>({=1?jmU!O2;zLlxy! zEpe)nJ+ZKJ;S-s!6jIPENIpD*jCcx!XsG>i{5Ft+!jRW~Q4x{*2={&fWf_Hz`Gx^6 z7K%tjs?Yflz>z@+ z+|MnS<1j}L0c1De*u${qSYP59$Mcq6NnS~UzNZDFgXxp)8O zA>P_|&;rp}_(by4fbnW6Lz?7mdH+YSTg!bXkdr;RZsfNe=FHgS-4JscO-Fd1m{QMD z%B6t3b>dlrn@-eJfY&4TeV_SYYx9RDy11`rAZo`*YHzH0zzqPjF!Nc3&W#||-O_4id&0aFp!Fpc&*gJ_|i|wF!S% zZJ(~ia-y(M|Ih7yM(V--@LU#*6Y$MZRMd_<%=1pidIF7VCwvzs&99MNA8(5seiCUF zRQ25KPtP+PYH!+o(06v<+s%BtxUJrn>hur&bu-4~V+|K~??qSffJD|8{z>}GuoiPC zCZ(Xm&2wHjwQc2KjJFrZ!U(UPvn&H)9mL#_(!`hiuRC}vOX*NdwD~ubm&y7=QMZY{ z%k$*Q>5VhSF=0|+D29&&9GA$H707|-V7p=>i(Sh~w=4%~hogiKC$-tuN_)svq1iVh3U`5+CbZ=Z8pNd*jnm9?usyuh z!#wGqx<-@)UWT7J`W~%gHf6C_3VW+l<`JLFcbg#YzGil9`@3>B6?+#7HLYkH=wOva z*(6$_$i-Y`TT+lTq~riokSl8SHPDg3U9p;rr|GjPf>q%qocSXi8z4K+nJj`k1$2{Q zlVyC+WhX;@=L&%}Z=qQh1q5#MUNd11fFw7c?6nj|=tNSr7@^w+moX=Fj^5aFP1wtL zUQ!6y&k_&R*4$ZnA)V_*yb&b*F8$hamEhgB_@Z=r^Y(Mtdrn8#f~duvj#QoqIAzD& zatkX=>9oOL7a6PVCPwJzY4PG}&_#ME+XE_Tg22A#70$3iZrCJgSa`e#sF zHr|>6Ta_k!Ko#GsHj}uu!bbUq=K7J{Y!>QC4Su;d62UFSh7J2!bmUZ*$E0=wM zWK%;0c;yb}tb_ZPNECCk(2CC+*Q*p46O>9-bx_B}kLlHLGC`s$jcRD#E-Nit?+0*( z^4nu>-@3E&e~lo?z!7a83ZDJ^h2;w9IWws~+6NF)Ya-`;8XF1adxd4;lhj@Qddfn~ zUg^iCP(`6go+)zqlhjIx=B=yW2+!B(DBF%?2Z~V}Ik%@^4knonTCXCq;#{c?w`&gU z!a1zn)~-!E2i2GN$VWJ@%$zj70Pft4*7HG62>P!vwlYBD5{ zmwjmJ(BqhoUEj$gHX1Mn2*56}a?02C#tle6GuQ!8b7QLUs_xr41-UY%7L*PRt=HSr zQ-jwL_bMFAJCJTfHIx0!eapPuW-Ho8H;$`dq9!J(Mg@Fe3c(`wI;yARwA-|{VRm|+&H8^@mhJD#d{@qhSHgC2lk>gQ$vHG3WHIj8;iex@C zJx0~eS55IM&e&g5x)(>e>X)i|G({E|3}Lc3)}zE6k%xM zY(Qsb@HdNty}1R$Uk-;qCtzz6C#S#b9L#?Emi{JX`cua6r;6b(34{C};)Vada{bQ& zg+Js8|FU}h^Ni0wtO(dhJiuKjF-@x zk;A)$oZCYBnbrZ!?xopCoT=Gnw(z1Qmx-+)Fk|{XB3PJMv(Z~h+tAY4Rn|dQQ?lIK zQThHO!E7@9VSoQ6O~S(h@gc(f&d|-7Q&- z?5Nx*m9!+bkG-?2scZl@g`K0ctD&NNt+Xt$Uz6Pph}DgKGcJR8W$Y z2&#Oict@jehegz*ayry=;}h%1=qzYNs^Hi203>*40-A@!wJw3<|1SU zp$OBT;de!MNeu}dz6nH)6C%_NI%~7;dJ^KN)4UF+ZtQkcd+ApiTXztPIPSkHJ0f9V zx0tMNKeyg|b?)2--(wALJPQc-%hYG^rncJdim|C}C_0ZF@R{4Wh=1E?er{%J0k{29 z7actu%dDr0yNUbi+`D(nPj#t7+={Vi;s(kiP!LDK#rsq|J*{`=1+1TdY|=$VpEYCn zA#2tTBt`mzlLVzqTYhXI@R!_Ds7I22Ra6Qm%qUuUB~{CBsre z)DR>HD}t#i_sIg%$JcvNlAz!2fLh#gKpz!j>?17(q1_3#6@)}!*flXcho;q)04hlk zG@wMYbY*TMcZw7nA$4qz=)T81%if>ta`N&ndlj*vXCtC?`K&UL!=(hawH0JSMJ^}K<8jb*7FpLVq}0@l+Nc+K4# z`=*OtfK5&~F0hurBxE2VO4jNUua{}@V2r?iV<+Rjy<^y=L_Hg{^~SUnf;npU-Y;L_5tQYrl^kPA3>A}JZR zKD48WDPVDIKvLen>rjOEo{hP5X=mvz4WM9>7m1o%vi_+*-FAkh16z%+v$hrWvlqaF zwwlcI@X+KIY1H0Y%$&*^R3yK>mAQ%=Eqed>WFjn* zs4TGbPEt-DBt?Ev#lhXtJ--npr>nEGaanR+UfY^((L8;Z01Yp_cXre z)Gey?^&YcS?RE@HnxHB-5wR=Vc4pcq=b6-d9&Uu6JsN~Ah5N%ZfWY<|c69-i7Bl8( z?FFS<+>SouA#`NoEQfAmL^)b;8OBmiD-2XnneE)5T@>+HwSiP~;Br3~w7jCctD6py z!0K$dp{06<&!cL*+;Ae5Qd2}CU%_NCH7{7%vv<`|Kwpq36UG1h+HkjAK#I;lCOJNP zu;O>E`?gPw_8n(qdUJNQw!>h0*GR{Ir!TOBkSQx5OPP^aL-G2MDp%ah2-|ek1TGC9 zYg7eQGe$mIN$DsCZEsC%K+hmzd%Xr&;|eoR8ggQcxJ@6d$WWcxTlUfU8AZu1P&<78 zDxO?9SAO^E#d6$~PRFL6DYv~C-4DHaY#x#XLyn;^uV1^ej%o5y2kkhQD=+E;R${uq zoE!6NDXJotZ#%E2`s0n{IkB_xo|!LTmoJfgzK0~bFz2X{j%cwds^L6HoH$9lENbI( zd2j9oB3*AlFYZ(EZL+`>LzCpC($!acz5xDu4|HEI^*a1ClPSDY;D`e;vXh#}v$Ls= z3gmq3Lq{h^7Zw+UDx%G7mVq=TV02wkJstifx03RX>QoBognx4FRX(pT->r>3Bdfql zkA0Fe56;r%VKti(o>@S0Jz*wtR%UJdaIkPlN>R;-5>ngQF>_dU;mXp=c9_QA3bWxo zgr%s8-`4^ABX7mD(Sn7vD>m<7ibknW2oYrs8pooW(Tadqg~A*i26raRr(B`0FZ04% z23uB0X13;AcG|D406nE=3WXyyU6HtBS>Ze{3f^8diM{5qP0sn?@W*c_19ouAO#mL9 zHe;iM`4kdUGi4Qv#WtXwm+1A>uEsiv>r{biLk3&ZOp1VWCUY#sNRm+);Hbo4dJ6)w zCB>=vNuBMjTooQzV2A9!gnoE_SJ5fS-Kgx=J}y68e_l!QL3HGHceihB9dJQna}b)C z8gU3EajRi>0FPi7Q%v`ARQh^q6wS-S6xYXJSh*#d0=JdD7x9Fx&B#2^P3Ix|Z1C`B zmt__$W!#$r+h)6$6PhLR2uVM?ly#Jl-p7VCdaP&~w49U$_7w}1lYD@`*v|r+$`POd z7*R4Yy}Jxl7<=2cs%jaT9=JdKRwpnQxHn`0!P2;2k;f4}P&NpfF@461+rn1lt2wOV zgH$6*pxGvBJm}Y#A+o)9k1H55wDkh(BaT0HFqFI+LJJBp2@*aM-5_u^N?ZOulN`NL zsi**bWJ%f5JsEW)d;0>!n?ko|W>AEjhk@5Qb0^5>^Pux3rcbb8NpH}!kWMa>{JtVm zfmWrVTMsyr=7uNm9cDg{>@)P|44K}?{&g6?uZJP694Wmzk_F2m6P`T_tF;OtbK3S& z*z`T(eejYV%F_*^qD{I)3ywGmX)79DQ=1CDJGe6xgT64+ynHt#Hmx0<=j@F5TfL^D z9tcw0@o!IP`&Gh%S03oC0@Pd9sntX3-t55`ClYRUz+J=zt7-WkNXGKT;&*1#v>ty}nv zq%x&Vh}8N{JG4zRvb@Bl+-gVow>x;=UNJc?hNGIE9eFvc&-F_aAr&$UFZp(GnXmG4 z$PwTP4GX0gzJ9nJ4Z7l?4|S3N2&{n_MJl7EG9;vW$CjD zwU&~+im1iH;yX7+Oq=G#)}PX<`jE)nCn=bfp|dot*>IDSZRXjc358TKcCYZwgmFD7 za5|i`9csOAN}L~>ycrC$CM#CSRec~h?XY8~m!!^6d)dA9o-kP{`E5wdpfh>}XPerd z5j|OlTkmRcH*?Z2U705&vE9zV^mk>`9VxTGS(vEF>W(tNg zdl3}(#Wqw;=p64GNHEv%rsdb4U_zw@O3aOjNm3jcLje}wIm!mpi`f*WZWMk=J)2#_ zUw$M7zd~8Y`w)1*L)|&&&YR4V2Bq~OFseV$mJF$y6oJVPsdw}h4@6O5lwYSAz6=O1 z;s|>#(Jr>*dG&1|q0A(+P~l1c#Kycg#ep*bi<&$zxM;#g<-enu02>J!F_2Ysp3raC z%3X#a6=GoB*eTBO#Q7w{sZO2;9^)(rUEx7PEh!fw|@J2$i12>&LK6dxijB*42LUxW)P>g%&q9o-x=WwVu8mD}h;aWVA;clwU7 z{u%6Oul?BlJ?~y&eh3vxk zxElcs&TX5{@{PBA9k5uufRyIcR-T_T0LYx^8YCDlcp5s3 zFnX?~Fh@$)E!p&AT3y>g(TZ(#L%*;89%-}@Vj!9%o~do#l6xGztiR-7NDkm7e4p9T zdrLPBgiG*Mn*%)!dsR6Aaq!*Ki^^Bbi{Vj=P9qnUYQrQTjTZYZ)010a2F41A;}NP8 zEycv3(j92K*R~3Y{#uhSIq#E-{Im&JU?vA_`U80PI&0@<*4jw{5aoxvBqSKtyVvXP zBk#aie2IeqfVv^}B?x;EVQgic$w`jLo#*Vu~lU6BBex6|T5D9#0+k z#`02;xw2Nw>?!dpiY zQW`0PQMYQ-nr(n@$2G7dCTC39I&X7%g`RqN?SQcfW=Nh#G+XsfR*ajC&&eLb0uV`I z{d2x0A3ULh?+?cjA3oLPw6FHL&DEsaqgIlxMt}#@)DsSu8_n&jY$mEb6Lt??uj;n` zBsRFsiw3op2X!zbCt25xCS*S_2>{p$Mw$c5vTY5mVc_C17g${!S@}YHWRjrvgOtFg zqkmvcymGb2@V<^7k@Y;=0Lx?~294oi2+jb`Y$_Qx5_x~WN0#X2$v+*sH;Sia9zp|n zg8)ynb}A2*+{eS>5&|d`JP8Ky5kZ=8!;-R(TD*|ud_C}&m!&~xF%>n*-7T)3k^`=n zzc@pO6@8AwVmT7y@?8td{|5d98>#R#t!|OqshORSkWo-dZBc4hVONlik&XY*Y&c== z3TB<;j)@4ijUmy)0`Tn=D#lVXqa%h)YHz*`^+aBrcPq^k;mIxiZ1@w6PEN1xM$_*i z>46N?aVqYq!Z&kvMs2t-8>hqZ=|gpyO0Pg2o6oa2_sQSs+r_D)TU$G|%H_r)rB;_0 zTXi!1CYIxbg{EYkJ{Mk zSd-LtKK;n$7Irmu?8{&M-9q}{XzUG3!8!_4X?^2q&GhNQ^0DrsN>=uA8J$L2kE$2v z=9DxP3#;KRraM?p%|hjvjP_TryphDoS48m zzU8JZPtQ|G?SyDpVx)~~thKCKRnt!qxEZHm;>@(z1URr?`(M28;2b4pd>1DN>(v{d zbBn9xfMU>#nr9GRw_{LH=$ROuUyJ6ol!tFxU|#H!md)rP&V7r@o|)vB8x(K*@3>YO zLloMq^AKugtAX5Lw`C~eD2FaPoVL!o@afuMS4-oZwt{~d+;_8c&%%0z{)I6O)sN>TdOk*Tj zJP#JD0(ixj%1 zm@Z7lll*!&Zf7QC@#Q+Mvp{>rwCUrtww?f;tRL@OkFE-fdd#_K*Kd*E+^-%K!0*B2 zpA`j!!Awvv%bz2on;h2QtZVE-enS8g8f-BV6+rtu{jyI>E*V=iogIw{B@{TB@RVt< z6HjopN&3-Mw;`c|J0N?wYIO5Z04dIF=~l7lAu;2rnP8{GGaEHXPjBdU$7-vW zBc0|WZRRSZs}o8CZ`yxoLgF~U@4eQ1HK1cDa$XbCaax`e+%XA$>YF(L9(S6LZt<0* ze8OxIDrkxJ)$Ev1hoVSS@-(b1xHlt%&h_No`1yWb#Z~WWswm=A^oVayJC(=e(?2q| zklA*=+MCpEY$Zwf!{THj#WJt?HIcvYa{V)~J+FfyZn2y0^YQcA!eZ|;v|5Sv+Zozr zd!=X?D_=$cHzjPm7^%%TK+>3X3D$T=;}1y6AXTl&C3v%u_yJC*-uZh>tdn8h6VN%88T=!71%~J;#0}K)dRPK47u&lEeeW|K}63@TjI8ha;m+@c= ztSflOE$cbj?a=FnDw~lA8JfV5*L3vFgXHoP1kx?A)un-foK z(hg<$EYgj%vz?xLPZ!dZ{)OU@6e^0 zG0OT*Se~fDehnF*Y{5(!BcoSVFd&eP^Yh9vO8`DS4o8#S{uzV_$7`F1w}96BHXp)g zlYBD@+da4&H$ol$$FTrB9*jP;AW)30;f+E8}9qlVYj z9`=~aE049E2e1$;R+dzBo?~>&f&1V$q)V2taXVt)Y(K`GX+mpSHoENFpN`rfG6r^0=o1G=k};^J$fj-rRhu@@nx_tUSw5l<=_cod^2uD_r5k zTZX(DBrB(DKp%ZUoH;^lye^vI0eN(LY@qp4(;W~!hXr@>=!#vRolWlv-0RdbhFh!m zkCzP6yw52%%oGlHAdB1WsYiv>uV_wJy-g#lRKyPI4y`5Raa~)DR$#m-VIALfdFh5E z?59J4^?d4xoU*zExv*Jk?sPeK3R z66L?;&@8O%^nV5Y%zu6PeHn z{hY(UD53vJ_WU2c&j0Fg{=eRN_&0m=e;J$qUDy2Ap5Pz#tbdX<|LZQ`@2Javz3#u3 zEx%v)|6&*L$3f+P+66SJTc|57wQn+*c4XO0%V^34+EfWu=r_4k6E5cY<4>9k@FSpr z5JUq7M0*{rK^lNz4B#UnD4%LKEk?RnihQq9)v6LYvsh4)3u~H7^72v(U(G&x%)ZOS zd-|1tx3XeY^YqsJ2(hi(_Z z`URDP8R=~V@kB^r4WZE$A)PrDDM}dned(2y*pzt4Hd?_W_5tUJ!{YV6ESvX6L82~h zM~fS{Uxh*8W{2{YXwpeT(AYYW(kQ<~PCL`A)=H$_%wE}1SsX~psQR%PWmSZTESkE9#xh@HrBHe;wg((Fh zatx9Z?$V<&0cAT&2$n=lQP`4K#q7kyQ?VE#i@aBPir@bGEoxBuqUSa-I&}Ca(DE{Wbu;1G)f*!E~O~nN61qJb}@ndpleQ5oidNhZVzocrJGu zh=tYQZqjCvUbt6p+2#AA3gE&)F5?h(Km>OfhJhqWCLFU%+w_0jcBCt!rZ!qPOAO4wz^#EB}hj-l|wG7gw2-3aZ-^h+oT9=6s2xm0m^ z_d1j<4T08fD9aTo)=2NEffzrK8C~syy;5Ukf;h%;$DX>y)IZ30$Cuavo3m{L@zUqR zX1v&YHk1O@8?-L)380#}GOW#!$L9&Dk+6@%QjmL(g{niK;U*Jlm{~1fogDB3=YX6; znY01&Ag&A&k8-GhQQuS^yqMF7=ZCfo(oG2aZI3gl$g%ckl7++L5PlX*BoXk<9jW-cvTRDm2LV$UKfNr z+e8eQSE)oSgDOAnmDBfGo8yB}j{D@)$(TqRPThq#v7jyV!xJFsrp;lHKHiTnE0L8V zllbP>dm!A>=#IPtc~IDq-K3rf8eGWqoKg180X}kXt77Jky!N^!xzV=bJ|{ngN)-Zu zj)zrh#5^bN`n!_+@MQy+>m;8gJxkAo`*hV#_FBc22nPog?^Lt#&1=Rbrxy25nI*Af zY@Rt9_4MFWw+|-7awQC!hHH5dKyTS0whJcqKds~~*KwnC2cAq;bhTBBzm=FO&B9WI zvM=vPmIldt(YsBb@8MQg$ zNL{imT^X>a3Nq5DNuTEL?XF{R{A+uaKad+JY)^$9_>F)A*MIZ5bM5mpY}AWw6c=zR z@z@=>0u;7nddTiB4G+DQlidlGKH=Iw!Q25fH*G7oZi&ncBen~0?LdYCs2tvrV*#h@dUy% zn|nOUwLGiG@-7-oe$1&#z67EF_`5>YAV~q8h+O|C$g6U?v*FfUkWxDK9Hz*1Q0+tB z@(g}-LVk!lK4y5A1F^1bHzoJChk>9O6qHES0))god&HxIQ&$87Wm$7+U5i_k{g)-!rG(?U}jHdC= zs|Ep~i!LYiai`(C^s#Xaq?Dn z?G$ue*%Ob_vz<-ozL~*V8LsfF`ytP-sfj9ONqe>f@3I#+McumCtSrh}70I=z!n8${ zw0IdJ7vB1~)u$BUh3B2#FjZ2%;B7XnIft&-ZM@52!@UqF$Ia%>FJ+uY;?^wve%LV% zfOr5dpO-n_KV=ahRNJqJH*&6@^)RL)qr;Akm$n5Hy2*nyD_v#3GBPFxlr-As>JF?M z7cc9vmiya`EE`&|d1oxA@IzX_Dcs7n3D;`n4 z9}T&LV&8&sZ2B+lv9QC^2`kR7G1=*Exl{^iq|ah%NG1miDW06JtI=!ifq<& zF&>cTkKI+|Nh?TVD^&mb@r%;XfxLv^XF$>!O=!MgHXVf`_Gx_?T;*Fxt>vH*Gx|ft zL97Ul;?JuUZIo7?a^Ymt4dqHEyYlcg(BagI4K+KWn>Qy>lk`#j3_|!u6ErHjX7Y8{ z%V?YnM>$Nf)a!7b?^6v&m?WAj9*B?#^=pjtR&+Ha-unx&4Z0mPlTQsjzgS!Cb z@wrCM=+&R_Xl*4Z%b=YZg9kKdw-Va6lc*UPdFcqbc4CLA!nA1{l9+Wr7sA8gE-_%= z;?#cWGJ`e?@t~xhvQtSNHY`@PyD$!zvYMgLD}V?WyZ|r9 zy;GQ^ftsaTY1_7K+qP}nc4noWm9}l$wr$(asom3irn^tinbULTGX9IWh$rGA)>_~D zW^6=Qb020%L4YbyV~EOiz9}=b(|!s&TG4huNDIXRzpPVx(1Bm>m24Py`6wx59zqa5{}f5dF*RrrB1wIS)R8&GoRhOz@U5$r zNF^0fFrPlEPW0xHJ5L-PMi8Rg0jCllf4XDzt+9|2ZPu(%IWKAg0 zJ=~SISVA^NszAVkJcAU{ZfXOvW8t=5Zd~->ikH8AF3t>rNaE2!sxuvH#&sSp^_$Z30A>WHJjaaHY>cOAxNYGfnuoW znC^!S$>3nP+#qgNSDy)MD{O$0T+6q4Tdx<%C5UA{b#iERV$?{N#m>j5{4qT9AP?)G zy~+BCOKX^1cf6m_G^7zg?W63t2A1NK%dFq@iNAwiO)_1)Ah>VIL(of306H{EdQV0# zf-o!WSmJ8c{L|FoRFkhh;)D$*8tv$^&bbAOXy`6rUbQ}s0I~>Ja#X*vTTqWHz|1IY zAO+>&q>z{Ivr~sd=Fedr>&+z-`62v4(bA2D*aa9!V6S$Krdqvf407Bx{@kwFWb>eS zJK^~?*>5*zPfSvX^FV()ytC#{4u{$Rc&_D?G!xLAL2qN$L2P-%2mw4;&DTL zJgk&u_iKtWmI6nC%0a@RqNXGd)&#vU=T4%lQ6QazasWoCPO*!4V|3~=foqJD4xPJL zd7b>N+p=i(kdRb6yHZakgqx_4z3yF`yO2^->e-6)w%vL|8({=r!T%tC}OsXP8=5%~Nma!Ek^oLd#_pn2Ofk$04XANaLZY^`YJP_V=`EUry zjE2kiu7PRg+L@BuQ`aoFSBa2+%5X87ouazO&cca5fb{*Q zp^SxxuR@!Oz^Bij3-iwtKgH8{WUy8R+B1saDT0RZUC8&_dUbPnRVh2Nd;{a3_yBi( z<8;DL8I)|;8~Se)ckFcguVsP7m)3pYbG<-QL8Kt9%!;Cn&vN-2sjSlWC#R!ruaj{% zz=neaOsQiLeb)=EadB!7t*qGrAI3hn4Y;_?Ji4KN^AY;8wp8Vn{v<2@s?-~{aOAD4 z>5N_SOw08B%6N?Z)=Y@r!KdH%Hv7CsS@s_}*JW1wnta(rL= z3A5aeqr1))zH4cs1#`yqb+y^i#3RvfjaKzM-JNzX;R7Wz18mTUJ-*(6xEw%mI@oKr z)$!sBaEMl~DfkqoHP6U6-+#bXfm^nldjIMxladWIIx?V9MzQaS5Rwr}m z!knOzu}yP>n}vL>Rgc5R9ZE{RAH1Ls5sl=vvw5sPiufZIJ*42DXy7o0g~PPr-Tq1C zPcb?}XWy1rF&O{lT>z`|d92i*)03BbVc4kIJ3kx)r#S=kpdjY?J3y-@Myb5T*rdYg z>yORjlxBt0m?pG^v~D~F-%h{QBxFO{Nfpfyo-!{#-S*ERf1gAtktu8s;Fx=B&dYgJ z{bE)Jm6p|uEirW4!6*NEigsSaMm-5_5oKDVDUpQ?TGi}>E5T+_*~C!b_}*KR+Mwfw zlT7iYc8HU|Qx@r;sX%IuIlKbNFVvESBHINpfJE8Srj`5nNX?I3b_ZX%?e(GssYQ_H z&vCC~#-kmbo4(;$%)A=r-ZiyAj`y7Th;s?u9wbnyz1%y^&p!&WXxURBqIUW&#-+%X z$$v_&d%J#l{Zb7+kP7C6a&(j?)yL4`)slDkPMRv_hf8U;OzcZ&Skbp9PZt)L%2RvHuVD6Vty@a{s?Bk0sOv z6xHSb29kp6|1OYZVf|+y$;$kHH;`oeYm@yCe%XKLsQZVR&f-7U%>MWJ@xMlr|Me{L zzr&&aPZP<1IqduQI=FwkW&S5X>VK%<{#}B}^ev}~Uvj}d0ZG};Hx58n@tC>Ph9GmF@N#7&6`FZ+2FQV>hD?z26w)L^h{`hsEWk8nGG=B2ssoOIN*@A_uO|;Mk)=q^>q!0nXJ-CCY?COu6# z4kkPMp^YljaH3$C;_6JO)AlC8O~H+ZN>lTs`G#Wy-V?lJ@!f#TsYI*NxaQCDb{2b6yarRAaYTkjPZT!ej@XPGfA7Z15MR@GdgHUC9o zV)?oTfBlX_a1$ks?R@BbdAPE)dMeOE4!2U%{GKmq>jo4)%P!>y6+0kNSTl(R1D0cT zQ2q|1DH<#V# zhpN=4L-2|mdt_K(n+2V+M@v67LgKh@LZ-%-I;RoGmTI|vawoZCmO>K-!7oXYp8rMA zF`D$nI(rkfcr`1=5A2R%1l>tyW*sK{)ot9RE5x2pMp;?UPF26*tn}pBE<#s;=W}WU ztL7XVv5wxw;C?4qy9L83R8GNGP!68{IuO64B_y=}$s^n&)k3Sy;m0qtvg5=Sj{9-f z#^12SVmt@-cWCU@LGJDd2JonactJs$vj<&Jch z9ywjIab0k#fpuKozgo2jnJgO7o;CCY4Fg(+bi+~!6&tu)*4U>Bs~7CkfEHL0-@fP( zT}HxF$1`14%KCQ$j0eDqmN#L&@A}v-NQMC?@Z1TmBf0=B0-a)dLg@mCm5q@L!@K&f z5cis@64})QLo0|W2JGEqN6)JM?LLz1~(1DThB&DFq1?^>F$%rA_#ReS_2A-HpmhBMyA*_9O@E>h?saH0fz zTFeA|iolYlOx9iKA<+&DDPgK{YAf!@0*J7KN)^OqsTm0MK&jS|q6W69tyb%N&^2Iy zw0bw%KAP`}GrV|=^J@_vWFwWG3F-&4yCu0B-cQ$Im3!@KQ&0~r{OZ-1Yio|*v!_n0 zXsSYpIpD_R7zNiLP|Q+3Q;>0)N%NW(m2ru7%!0Ifby)jLTav8t?0<0!%ZZ*3NV|MS z5<+Z=3Ba7tgtGQBlN<(drG*8 zX@@8yb%QC;-CVGG18X^a!vdBGLfRntfX2LbVM-*?>GecaC|QlWRa{g-l+FE^tD|yY z{qRdlq(y0NzZ2%8DyB8YsEie}nMTzs5DUZdYpv<97sPj*29MZOD-V>jMwV+P)>#8r zV|~M;2wC-HhVTB!DX%PAvD&vXPXtmA;Q<@&KM#IX<@F0u1AyuB0hn3ETAXVRb$YVH zP4y)ceBR{6#@ZLwQ)#}7jM9t;NGgTbEy@FWhm6`T+s%h4npcO?FkV*d{#qoxcm@FB z)ewMPhqvRlxJ!fn2tVc@u>= z<2nVO0Qne--oE$x^A|kDLDBV**eM*;jcyIcZ<{RIJ|bgmE-lZtm>4xO_*w z?eg%VD3W3zYA`?=zk3kvOpbXUvawfSH2H>w_);POxXY9dLl%^_C5(fK6Js}%p5Fosbo!YL!8Y?u)lkve2p z-fBq(dY}hN-jp60g{38Px*YiXJYymp1>>mRcFb0e{h~;M5*R4yZiQT{w4e55Jurr> z2Gfp@mv@rrlgx?TDCDd&*0)OTnJy?y(S2lf*xiyYXrXUG(kD3p z<-;z&&wBI|8H?8Bby1}GLa`j4P-xsPK>)D(z||5vYgC5*tmW(lo!kkY(ae!hBA;2Hn*4vX+8MQ+&GNm=Po zX~zSF-vYUx)9mxPNn?Q-=CEt***7x_LSvjURyJ6&To)p)fics zqL-|h1kH}s%{gLY-X8Xx;(dmhTcppN;)V1?tH>3Eru%Jp6xY`_Y>U-l1=&NB^c1bp} z$VX@Iz|2tv9-P+CsO#~KkB7dCtll0 z;rc9}3_2twAY5LB-ozLZ(TYHvqf|}%8~{4%5oF&!mtj7`exkZd&NJ?&vE(Xvirp=J z1G>XZ&OVUYvH{Q|veao<`yzp!)peOjMJM>n2p|r%NGZ3g5WnR@LFms@^jv%Hd~y3rY>{} z7Ry~5cSkFF8i*|qfI z((dv?(|x%QT+y3{pD@lNx=*SO6?C6$+gKU;JiOnhS$hqbx)90MGQ4 zn4EK)&)s|8VvDYwat&`QAgKVmb)a*Qo9ny+c}Qo}mj=ftO1)~YuQiWmZ$1A{lQB9* zZC=5_yp}w%+tJsT<41*XrT2O=1tG5-meB%>*6H`PMzlo<-hjg?uyU_M+Y(XjIq{3l zb&Zc?k&k9CcM^lE{ z7E{UAW`pDFCj~qY<)^4tK4%v>jw=uzgoOfT{_Z}05%UK42i2mp>m?foSD>5_$L-TA zVXlvswbHCWw4aXsa;D&S+KvxrK~A_s?Aezt;eanw9c~3+{*q_s%(ty(1+H_>C)CDA z&xheSPYp5Y7&d`n7siFxS{McU94t;Zw?)-@xap@xujl2=9`r%xQNwoZ9o8 z!=2F{+EDT$@5pK5%PGrQHo+X1K1gBbpY8Gqxvt`wO&=ebF1fl+wX4?=2}6C5_ee#* zIZ4%(aCT3jk|s;Fl~N`_pVgvU>)ps)`yNm>A7V#=^)qMSn*91^)oCT8OO9l5HMqN2 z$Q_hSRA?rB(XCJ_-jnA}Fg?I$njZVYhPT5iqMiO&Kim}b$uD0x{;;7CXCI{yMre0 z-JLOj>FbBn7hY>VKOvvtg&-|#Y>alu?dk-X(3#*qWtYy3+oUedr7lmAHCr++!G14kb{8eZe9TaUS1gio2ujC1Gy}G7o49hQxKdC z+}$QHr;REVHexS}bpGLGyJ?**@IN*iu(}?Pa|cz%#>t#Sh|V+Q0a9KOapfyyWMy5Q zYA)1cTjG)QYaa8bBw=hS!d9GY%-13!#5L`HY}LYA7!7`EFe*U4Mz8s3$MIuF>;x)R zbRmLgLb2Kf3|wMcb9dLF9~LzFkqy9n?0~l+@W}JMt)BaFOy7Q*?BPTDZE}V zPDzc2J_fL1v>K>{D@K_rSBNl4QhrJ|OPkbiZY6E&=?#{j?{GPn$Ctb@-(puE_8met zYfFM>z8`^sxDIqYT9hbVrPXQuGfbp5-8aUajdFfl`Am>*WYO^)5JapmC^ zz(e%406mI3A-mn;b&cv`P+!JUb@jn=6Xn&C6IFB$m86gLb75e;w3Bi&d{C@KXr-|P#N^Sb8ALHW6@w)*5+zmR zAz0^&cSbU<6O)J+2eBD`i!xycAn{CU5P!s%Hd`eT#(E-Q9Et7mIlTgLSl%OJ z{SIWmn0=RNV*a8t;7B8CMs9)JjIzy9@M99+!h+6r&8-mB_41F?NR4+=xaLo?4dYG7 zo?bww$)Rmg$|+nbK5I&!BmPtCzPc|H53^jeaFvVoz;azUqkTxZys%jo=5z1VFou~i zmrBQXT=KB+(dT;0YJ24Yjnn>NMrKUB;%@_Ed}#9L(;tMDFD{U;bA&IERglXGp|xP8WWl;tltdYWXEp z6ERmv6b>&0*ofYTxV1%p8Mhv2vybely92Xu0SR{9Tj3k%?1@Q`HG2eXvtW zqXhLg4;aN99mO49X$dY&7z(P1i60>ng?Ni>j_g?XHaewH6*#0bh}X-U-A;>LanKa- zA$7V4tM*MfRH(k>^IrkT3p;0#b~p>hA9yryXI6PQD{dJLEg&@KBhR;U3R`_g zp8{66zqK7SBrF^-YAmIu&a}PkfMwn1krHsaNsY3W!v;ky>%nC>F*XB=kz7tnwOW7~ zXNQoMgFmbUKUqmYf}mb=WVYq7R$7jyKTB?L*4QN97Bs@aHAp~>y2>`y0fy?OgU^DT zb&)kDJmXb>$Z~1JCvS9ZgtUq2BJE6oxgPP|UEu<6>}d){#qYm*K9FC&D@WJgDqxLK z3K9?hE~K`u{oK`HDI{$El!aj%eFK6irNj9hLCa(pSn$V3*eCjLUVa#R|L$O2Rf=Za z?0fXqA>yg{QZrXbteTKpR7{hcZx!h%dF$o2r-Pc2VK{@)+;tP0mxZx7IVCTpW;Q)E zu84KXoGQ4!!|i-b7kx@ZiXs9c)M1+WD4!Z`w>00IdA*F?Y@#)Jn`qG+?qmPjLo+YC zUc=>O$m#8C8acgQY{d>+-4nM`VQb%K6T|=;RsCyfu0fqir(1ZPFRhAzl#Yc9!ueb- zpEVjOw~E!h^O2%ms>C2xs(OboJ?UPq7tee#ICSxZooewL*)uou3xbZ)g?aF1*-2~( zc7b=LZgMvR+Voe%4a-EC@d0`mSsMWS*r{&K`Hh!b9%X7xi6S-k4&s6P?QFc-b4m`g zTH~~&0bfYq_t7venaEyGA04C1b80=tuDbLU_wi^a)>B>~zN1tmD-I>)Kh^1{)A}Z^ zBQs%f(;|V#m>P9Q_O*Cm4ofCiD!p*8EUv*`n5!KS=)JN*yM=at-v=(keP>YMA2qR= zg^-vxvvhQqZ4EzGOiFSy(Em4y^Iaa17nGt8i;j(n43Etge&F zY6re^j+4)eOQ6lRf)@t$=@xSpOoI7mEwNKd$Ih!l<;B$Y&Q*&(6IysU2-oX<#H|jF zk!c79Y{_`rFpokPnycl@eJ~z zCpg}hd)+t>hmcZjv}kr!r`79f+6*HwXTFSFI8JgZ^%KH+V7hnqP+)U$F)NG3*+wGNxwVLTDV2)%5R9+MdGaAg7}ryn@&VW%%4cp zeIK{7(`SKRD-Y#m9hTu#543B51^TF!pd(!uu05yiUSOl10%FGL?wNqLguEq#cpXWC zB!?knXZm&#p4A)ZzX5oc8!~A^okAl`yxkDy+#N?``1r|uzGl6U^vTe$&BJF7N(=5? z&e64lElE@|!TS=IhKs4Uy4WaecrSso?*+MC+pE6l>vOtk`q{W0>Ad+x;{#wPimSQn zD%$hf?hh??_H{7M+s_N$Om}absk3{?_3I`CVb+AbUx*c{P^_@%Xil#jfH-r9>R#^N z3LGVu5f8e+rs@t{3~m2o`ZMwX01;cH8#+6_>|6wVKc1CpZs z*q^=qk^F?b2CU`_QKDE*{&>NHjvG56%TPq}ZXq752q#KI6w$Wm8I2n#jC~#N2>!T# zV%&AQmwroIho&DzV@nT!9$I{Y+>8ynFv*3sK-wt~?*nCqx;^|pDo8#8A%pGJ;)XOv zuqH@Hsg`2HUDH^Q*IOfeM?Qx>U$6gr@3q^*`0C|Zavc@DM6HF$iI#E;pv_#UrXr-; z^iHkuXg2u#3k)UyP|-GohCSF*?;I9as$y2b9bY!dv<}QUEsw$Tt6G@lt@;B7O3pe@ zx3k7Nv-|RmZ)PUvJE!EF_e)1C;8&!-oyKRL_31r-xL&?QuGmJX4>z9&5XVS`LvIPG zRpPvWTD?+`s)NkwXzqETOx%RJ0rty=tXWUn1pC% zNqjEcdc94{*V25=jthU!iR{HIcrc0LI3b8m6Gh)YO1xv^A~ldH*5k*6-=n-G*E?>e zZ~nehYe1m*UiQ8G1HYs~-|$SuO{@O1hVUP?(Lc&2R#rB)e{SfR=>PTM|L$Z#MnzLb z6&7*IdHF6Yf?TBBh`cjvuZMRZtQlb$hca@yz3^2HcVYn0$a(+CBpZtG#cFW76&}lja+5a_f|VjL7>iPXQ!up9-mwHHkRpOSj+THbj z{-N4sad!;r8?`!ctrmHXhfW_3CsPlLjem1k8}Xu0*lJCdIO@HNJs4(gr&zfx9f(qk z@EcI@DYLxbBCkM_dt&{I@@0|TA0kV7zaKKKwb}_ZN3nP;CK!CSuxJobXJr9^VnYBa z1tC5jcCL4*9NFtJM-XSRU!`>3o|F~ylc18G3GeZ}QuUJU7fi&%;Fx8ma$kc4fbm1a`qjvpwX9?}fYWM$bm!X;n%n@A z$Ii-Y@<9{hLQ5uKLz()q40St~@xtGWt%B&mfndQ(1yI!OZZJ}jI~eJxb~U;!YbLmb zLfpiMr!G$-vx68!Fa&+^=eaClKD=E|V@(4nk{z;C5t-2n%b|?gWLXAu*#|ujJhIfs ztzg}Fg^T$ifs@kBigh_BfjRuN9i^+3Unr|mYAqkM=!1k#1yB6|LWk5OWjy=JCk=jD(Rmgtb6UYu8nW8Q2r;$Bvu;TCz_OcR+ST*dY7-1GH+(033U}d;>7JJp ziO6>Y#6pOrec8Zst$K?5jjCALxE0}Z!+>Z-ippm{ro7iXQzOxaB$Gr;LJf_arH6w` zoTygq*`{QN#3_M36o<&hXofx|L%*_w2}G*CAudZUAQtEGxFX=Vq=|p42q6-eag5XM zMFrGf7!j#TJYI(UgajReab>-oKx>cfM`gV9{MdS8)lH$iQ1u7NkKGB)12b;LncWkBBDp!X^Aooi>xZqE*ql9 z0+D@+lO|XwZIgb9|2#XeBb01?A$*XBXS?4Q;^jV772G;_6v%s=il;$L^B<(l*GBxh z1+=r}l#lZWCn^(dXQJgZ*yawK2gZ}2nM zI6qlv2pQx?5D`%pQ3b-IY_?c*(Fi}~B9rVmvUAl{|4c7QnM&|S+@g^?}2mWpuFdSG(zeitCNGj35!94#; zfHBaq%P1oAxc6HwV4zQ~XLzp^+b;+DQ5~bfBgj61q`_~&UTwPq(FGyn4QNDD3KsBX zhy#w%A3CGKF>u5IF9aGk#2K2rZcN;4hLh z!auJeyUjB{Q7=o4c4bOACfl~(_qRt>EGN69-sR<5ZoLhoIHJ9y!DkiPgn=n#rh$*$ zE>3#0&>s;&rHmQ6lun?L6ZXU^m!!&xb*qu?;DZN$zPV}03f4O8IZpl6vh3b0@wwqI zaC8H#09U4Wm=)GlkC!Ab5O|pk3Kd+h#(WMB(FtJ>6buM?aH+DjsTokuo6@n5Vg?Is za*tV=2d~Slsd+cCXBk(*N53FSuvxWSqPdwy&N!nLah~$i=RG3^1xSmcuXQ(rtB#!x z6e5t8_cU;Kly>#H+aA!<>fA=5^Q^2}$Raqul*|h+C>A9sB8FN9!?7Vf>A496gqQGnMBV5 zNKOlT9rU%;rQNGV5F)}=b$)W~?A(-HH0P>J&|Gajbj`B4Q+96$%(qh`6X!JBmvWG#EP{T)6`?4gLb9Bs$y z@MsTXLvlh5DZ!7*dUSaa*3tFw7n7CElFymu&1qr}7CTz5*BUxD<#9H43+`1$%9Fd7 zeBY?bGR94Arl4qVZ6FYvZK7dNvU;Umj41^Vjkf zoYWXqn-I;xOc540$Nvt~w>|eUAH2?NWQmF`$%zcWyXhsHt9zz;PcNOOnYZ-!GlaoV z05n*uic`$22upxG%DyKG$l=FW&FN>0nEh67Whj=u-NH+1=+sx(0}HW_`q<}1m(OOR z6RcSrI+C!M`jw{AAIU0A$x!1)IG{EI6MuRewEv=Ud6{!A?3>&{2{(wfM9Qr{D5``f z!7p>V+H(Wz5SwHP%8FUjOSV}+&=THJKXJ|m!oxsyinj&X4`jVVv?}BPj=4`Ya1ms# z#hydEgCsx(WM@GY@X>bKcRhbN*;=)p#9kHGOsS3o8i{|T=;&o>HO|tHZc(Guhh$}4 z*s%m&zrO{slAB2 zydWHz6$2YaC4`yEsO>!aTJtCa|G2e~j4?UwlY+UJXDoJFpG~{Ob6reJezi82_j`K% z(nzEZJR;^NfOdJlO}e#bU=r>S65pPDI@}@p8pX+9M&QE(4D9{O4%(vkY-^2%#Bl;h z;{f{$*ICP4iWi+Wz0{5l_JHE@U_n)88}s;PFs)+WS3TNvC;HNh9m zxHOCTM9u>=k9znE1;+Xyagn72bI0AH7^^>d74yB`4RbD)ur!E}hHM*X1vO z_$6?OlQOx*eJdt;|1d!pnA>WuXp8lZC$sBjFcm=-bWg#zM;R7 zY{kngqug&mrSMK+Z(xX#$;ACpYsJrbi}WnH~(9aOhHEbJj?&3*aUmsE?3%mp%1$YEqbf=9mQ zcae+I#AF2f7P#57%p7dhaz3lx8!2n)0=RvAK~}y3uQ{)M`lT1S%n$2kW<)?j-fZ;k z3

kob#c>ijG6$Y09U?|H`gb%z^9Upj!}CE-&6B_w8vKd1ln?>PSR}Iw&V*Q`lif zWs1d?9m5%FmC6h&p3utnAXZ^$=A+th4Dkh8n3#B&4A@q-e!G5bpOLNKw-u$enUU-W zu{b0#b;Fy1#!m6UIxN0C3LAj0iKtuGa}t>#z@5KKzSpZP9%E;uW#arvPD;~+hp@;U z6Q47kB+Lc^4?0S4LC&IYnXNp4AuzSVUU?F=wN{lRSw)+-PEeZ*FahEem+)~@_kPl{ZANztL#2GI8lq6Fpb*n5gDt%!-nstdaL|^t zo-cl59$a2t!AKuh8gE9SjDA~cTzAxC{g{Dgt##hb>C7I@ii@=PxVTFhKHk!#1eo;+}UG*Sh=E{ zoavww`2ZTPaDfM8A`t9vMl5ggLgb*?FcGR&-@D=~U6Z*y@H&;le8kYOh_lV9#mu*8 z#CqJ}M_L?cF{N&Tc_0R*e?B;ivNFn*f$WA*gy2eY~pTW%v)D~}oTshhVgM`LZ_Vc{V$ z6pm7Y2rDsVFk*up`qw*&AH=h4y>&@t?Dc?$%cZd_nDYcW@7Bkuj@YIE{;ZqWilJ?A zP?wd=OrN5ORYELe2A6ob#(Ss6+ajIgq@}n^iJ3&gOg;^7F%9veUxLbfCIRTtVg=!V z5>(aAM8Rq`9K;7aVBRoi)0{?cY>y_SeR^P5lujQ}Z_X6O!gR$NDbZukvB5|(rQmaP zoRr&e%Jl2R`R&k}ZHFf8vU1aLdQ)_-AyKWaL?E4eHdgW`zBNjYObD-zIiD3I3=)f= zSQjG`9Sve{b9jC9Yq(2Arerw_M;6)G8oo{i){n#UGm`fXW7^2du`vL!?fYHHf!m7g zxwq{~xuweS6Y%8zs?Y^+V~aVCdZ57sg)uj=07l}N0P0a|;x~zAxjn7;O8EhMatc62 zK4BJYeQUnExYWEqr?x~W;&O5;KpNa&Rdnk^@%IOU+G>!g_9al}ae_mAukf#Y1xnnLRW7ok-TS2r(PpiW>Roy7sbhP(7|B)`SHL zPu0uG%Vl_dd3JMqwk!05oDq$R#ebHp{c~o|%u1_8-!>Dh)SpWs~-7gV95IR!I!~ zU>-1d6y;WC0cBMN(FlD(82nh_oI zt&Vfw#IO2`FVX-Nw=FN1o3AN4zeDNcNw@94S=)=pcC7{yS?#K|YwxyB9+$4)Q(3P~ z2WyS`bqC`P*Pp8_w!RN3SwPm$H7>==le7`-oETaep>Vi76u1U<>*ors9dK!+Lo?!G zGUF*d>{jFN2$zfH>76*ljCgdMG)_M)V^u+GNn_ME5|8ic#?!&o%1@IAHe#}woxKm? z<4>Hrv^orqI);NC%+!>>zp99-)E*idQdXkmp@hoKb^<;Y&y5KShJe7;-N)9rsMpD0 z9F1_U1~;2&iS?`u>^Dta$welsVp^S+%ef;eRa)Jy;H_y%gSwP@)cWU!K#iK(lsa6K zklH}?Nc9bkn);Lm*IL$k)mqnj);iZZ)&|u&*M{a=)rRNVYy+M#ND~{ADuXK%8>6mC z&-A9)Cr+w3mPnS2O?v+)@C$-v;brD!=Vj<+V$@icw5AB;n4_8c`acafvbA#jnNmm# zWZ4giuV2Xz$~u&?s3JEaDL%{C`RZH)g`2#SS zDG7p3VqC`%QR<_6>5}5uY~-ii_4eBZN|@9(`6ZnA&7A#XC=r4*D^*U$&I*$eQu`+Y zJYzDTK_l1nSJE&XQ+BRN%>+JpwqcZjHrb$|(u<*F>H1QyhA8_6}`L?C)gNLVPRsuug=zyLU zZsh80K_;~UQ%af0qn9@?Tc!R+s9vsOK~5O?m8?yWm%tFF7G(Ffr*7NZaw+#jjjh4z zZPk0FbC}Rt@@GeaN6XdmIm&KUoQDpzW&^$(u9Ph}i!@8tY>oj}NdhQIX(=Se+ab!( z%-n5XOV8(dn#yuxzPBQ4ZSO zQcB7~aVpuWMtpO-$d(n8SHmME2vQz@=8#n_W3y;PKyB`@@~X!dsFc@7eY)A6TLgXT zH{#MzoKOhcFy2=u3Jt@W2|ijtvAD!1!DW$HnE-vgR<$W;AI(#rc8G_1DEV z_%zboy;1lS0z6!sMhJz+Tt57)`~lc0X$Xw#o#1tS26B*@2|hmUDZ3pKc3G~GhN&_%vE*s+CeBx)SGO!v3l&~5ea0&HkmJI@fF=y#)4 zIk|Nh9qtSc*;YYMzZV<>&)B^h-{|E>Fb9MP>(NL+n94eyL$AQjy!d4_%?V=Z>Vh6hb!k;9L~@H-j1=ObgLgV1cIwXh(RI-A>T=1yu)1TWqj zkJa$?K$Qa3FH8mDGMCkdm2q*=ufnL7&Z!o!L0y%_fmv2b7T}L$+Y7K|USViR`n$(6 zIeHuO$eAss^@*P~sg{XCBp7;Lg#M=5n0SeA5ZNQnj2?Pj(lnlW( zwlt;FjV0zE2hE>(!X31!-`rf5fPwmx@| z64+i!u$%ZGEf6`Ezz2c{wT*|6lRExeE+pCb6PQ7sKaV?_BWtLkIlJQxRsQQ4M;V9N>0ClV*jO*$v1$6lG_$lA)$GjG3NrgyU+kd4`059$PyllD}&!ag8 zCdbq0#$GhNlYsm2(q-)p?eU22aRM+1nHYG|i0{zdd_^&@XDs#ne%mcEH+6EQDARU9f? zQA-!V;)}uBmcq{L=wbDWz%^6?c-1)z4GCe=qlK(g1^_HW*r>YIn?VJ&CsJMkD25*{ z=Nc8y68pT4%S6VBfD~UPDOgwZ^wx2%=?&rb$R^~6PnGtJOSfGqb%*7ZJ#7Ux#D2@>y59b8;3}(srfj=Y> zf(HVS9-tB$4PzQmwBuQJbd#f_GT;|eXRqa0Lrq%VN>v7vM9#|v54g=Q!!;bIi0%DC zKf@vmbDKYciMDpcn!~$$e)%STB^6m)pzM>*2s%8ULOLvg+o#6AWncKnD`ykh#W zPEKf0ZI_HnNF9pd{SGCB7hnX(rnQn_QI;rXw6`P|UkaX%47iC*2N8D^Xf zir3T8Pl#wRE~E4u{v#tOU^J-Bjqq_WuzFFl zzat{&n(rUrbwO2N?VQfB4cVn^^K_&IgENl~_T?r7ur~5JGnT`EcDq04r5W9f&g>mt zRa)NO*l&;=Hwx(7J$IszJq$pa!)R@VwuzS24tL?RraE^1Qn;nxAJ{q)(8MXM=7h=%qA+ zPPcEtT>B0we79j}a?ejRII?sTuCA5o-76FlDCFF5Pgc~CpCp*ua$v3Sp(UfIPLtU* zUc3Ui;w&(WLSl@+s1!@{9HuGMbNIh8_m0t(zH7F3l8S9rY}>YN+qO{^+jg>I+qRtw zDz>c(-~4y)y-)9c`;6`$=fgSQ*1h*!(265{wxMO7oK|}oKJnKz zFU9PT9nXMZk%-b|RA{sjg-OnlTi%cud0&AgY$Vn^j#4LP=eRvw%l6N2Z9{N_x?0KQ zh(T|@p#`BI4sU*CLwQrFbARkbdK$k`052wM=dI6=Mp3VE5Iy6|Uh#YGSB=J+&s-P$ zK33d((n_N8h-j1`TV!2K#iP0~ShrVCOzjHKD~|A@Zl<%dB+@H*n-2R8zvRznHkhoL zo}l81M=Y6AI9@LTF|+^MC1ut-5=p!>^e&N!C0{o!L-D< zla)_Y(N45Q=wc$w)8zAxLapyr_FjRl9M~rqs8>SX>y8>IRC&W|MG>Kwx+1GWki3m;+t;~#xZ;n7KkUfkh#BcLMsy@ZsXC;IFn?fe2Ovwt(BMg@*KFe z{-?lkFT|xvCt21y*l&v+6XkH7p8XYDQWB?TgFCf^{Y>IKzZ>8CCHYStCHl?XypnSN z&zByv+?`*Chg$7U?llFcZ0m&*eUWog`9Gk2Agq5^rztNCw&W+s!&~VE_D3JGv zVHE|C3icyuwykW5%JYycmtb?)*J!ylXnupfWf_g8YOthK<9%~s-k7bpBr4x_Mq?V? z07nmvDNL((6h5@R@ixyUpDWyQ=v2B=(aT&(%t($;CaoWxa%yMWh!fdoxBy}^`rJt9 z6E4xZWYq!49vs%^u59kJw)Hvu(DEaEVDT~pdN2C$lk0p_JZWt&(dF1v|L2&7pjH0uwCkH^o4-eijd_8e1-= zV=A*A=b_R;u-Y^&aa2@%=MgSJK!8PVYL;+WlW1cCHZkVw-OyOo%-zCnCMROzir=hj zt7XXlfvx`o5i3pB%OjgP;ovB3Jp}f;P{BLz5N@=6oD24jI6~qV~2`E&&5?PEwASh4Kzu#KW0~NVu_`* zfP`d1?gk3zRccPD|JEI&Z5h-1qS)2I9RV(AoP})VjE&@(x;hZlT+!6X#BMui$qwwj z3wzIRpFa#*-~)@X`LG3v=;$J*p=6?6P>bFDmw1`gzvf2n^DrjuyfJo4=u=z8JxG{y{-htLvq{<1GhswLd#~-qxV2-SN}WWo9RJLi>gK>lGV zSj?(XiijI{%Soeqs4vYX%EhVE3R!ekt+BEA^!E2v+8?!SUGcX9QPYGYlTyM+xgQ$B zyBr3P_cBq++6AD5`xvNb5!cHe2Gg=G7e|B_N3Bi`O+zYUjrpQsf*<-j=*~!r8m#=3 zYSgzU>GJh!2;cJp?LyF9QRZYS>Y|RF7*T3avBf z_eG@%;T!##Pexi&3op4^`Q@d)C?57xK&Rmw9&W!dJp|S5jIb}^amg}PRFcuMDL3_T zMkERvsm3ycwViSh$i5MvKxa*$;3mQNo>icgT+%;ue%3B> zgTEx47WZu`i`+pN*vAXxlv9$GHQeK)+v-|8Jexm%Ug!I73~g>+av?U-^Y8?x=t5ON z2O6ySGu%vlmQ-yAK1~0Xa5y=tbG@Mes7eC}QhJ)r_q;8LGJcTlC!yCO= zexy3qzIf$URY5soNz)!r=*a43S7q}zM`M;axDgjz7U0^6Y&o>99Ivs$pWbv2F>|LMMJGT_z$Fd|a15>}PoRM(>xqg*iRGtshHd2l zRIN?BPZ7y&=f2aRzdWb6*nkdhR0nNzC}A9mFz?I+n~cP3bzjbZbO=hD1bT#(7h|W6 zrlXZZN_w@q-|4a>YBaYUpJeW^tMy>1#$k`}aMZcyzfNfDy4tjc!R~jmG1H6qRG%CI zjSKsfd}pG@%v?#4R@%*k^3b!BdHFdSmMvgf(9xM8Z@q=Zaly&sb5GN{6E}`0-<2Pg z08{nnp(;5#JJ39q3L>?ZxyU(vCR20KaYt1gwiQkyt zjbAs9ZX-FKkFieBu9$6Fl>eJFCcl2J*`2o)Qeyum)-mHg|5oTR{{x(-lL*^M_i=#iiMD?nQOcnbjb1!?tF`Ic95O~dnjrWfXB zx0Z_s=}+#-8P{(9*FamR`Zlk*IdjHuj?tu6Z~7jX#hY7pA`s$Q)X!T#g#i0e;#y9M zJ)Rj|jqDT`h64jHQ$gQ~BL!w&Iw22vR<4cU6xV#_?$4#pu^Tr6J_J$6397z>adJL1 z`@KzpiMLtk>IG4{1CY5FPo08|F0aHsShH@~9Ym@m?Bs~yitATDkB!fJGt?Fed?#n> z{3yZSt@OL5ejZ@zY0`9Uy<>TvI-QVDR!LT16wgCu;R`nN-=kTyf;XRp&pyU7o#*sD z_O(ak+G4zWATHxMLE|xIhn#V);?$?llnOM{FrMFlC*g{p=p%c7)+R`SPv(6gcMHDr zy2W39bfQ!R#ZvIFP#uwqw(`9_b8)S?MW3|#^>0W$|IWEx3n5s?yJ1Q6HQ3smg&-0_ z7SDjF)3vc*fxP;erHLjMEL1^@ywIbCN+PdH?VF$`5YJ*j!)<2AEwncVD61z)cj3J@ z-7|3gQP;8s)Fp!tTl#wW>Ou)M&s6;tav{=f7R)CW?5k`!i9!H9FCU7QT0gGMd{<=7 zI2DWSo)DDpnfc!Ns@GD2Oxy9a$|=AD{ilY%4v$_hbf9@ZgZRb%F|RB;dB~P1SgDL) zPOKz<$_M~CsA9Dquso!syf<`40Se}VkHiy+uifS52#HG;HW>vAr$r4#RCx#GAFg-B zF#BtG+>Hs4&)8C($G4RzD@J*XFF?yEr-wuq`8)aivF2R){wJD?2XdNNs% zs!1nX1t>UaoTxryLaGve&8$gN?pr=wqoh=FlTr%}JbgOg*7G}BvT}Z-dNP;Qqzi=C zdSz1p)^jw5^n`2#vJ#wvWV(;%u!f4_Po<}U-8|_)oGX_rKD;bCzFht^N6Ou#I1Ps6 z@nxRKB+k0&cJKh885pdG5hol%RI8@E;(f8E)t_(tLNHfz79d~Hzm9Er6(GamNW1lI zfpjmr7?)>nGW{GO`JC2YtgZ>a*<7h2AGUH9Z%O|%`{pkT;BSM`Uqj6Q7>wrp$CLk+ zeIp_vswgA!W#1@k{!4Yz*Dx?GCmX}pU^F8e0XsXZF1?tIp}8}`SMQOav$3h2%U@4^ zxh{qd5~h~s7JpxgnEu;qe|;31Ued+T#?n~O&fLb7;A^SuVrr{Kz{vLR%^F)vJ6Gqw zgIWLjR#PWa6M9=$8y8Cl8&7%%8&~Ildxx>5ld+BIUu$|(M^{TXLmN{&V^jLSAg*6) zLmPS{CqrXX8`CdR*WVsF{dG^Q-AWtlam$7DC3){i=8 zM)J!vu_KC4JY_R~*<0I{vunGZ+xY<28Ov(sPl=-2(;WGJ|JmQ#EnD4-G^_E)DmoO@n zmM-mFuXST`oGkfmoUfSNs_r+JSET z#XF3FZUuyNS7V&nc(DuVcl&p3I-3mgaC`ZcYdOjnSlC^U#DUeN?wqX%#%(vu=F^9M z5eOr@juN#}KrgA?Z4)?*+f`f|@VR(Se|&UxrwH8)2&f{U;sC>EI}o9Ul#x%z2H#h% z8uhQ<2(Phf$rJKM1rd#hSqCokUuuHT;k@LeakHwE2Lo<90RWsQ^+L@kg(@q>OM;Fq4U^<1~ z<+Ku16OAX4I7Rc9f(#P!>jBmtTZ^m=K#m8=!w~I33=38ABeo)hpluaJ9r*gE3ARd4 zPAaJgJF2C(LKPYA0CG>BKuL-f4?3iQ1r5fcD4-vYc!h@P%Go}W53?4pIBMe6XFiBA z>uHN!KRC#j3#{Ld;o7Zt?ImtF7)G}X<)ir8sa9gP+n9Vd7Z0Ksl(x&{66Ect^Rf#T z_11D3_>_B5xvw_KRQ_>-8p>W8DKsWw1axm`)Wxsxq*t{aEB3Q9(}RLhL`M?qQb*WZ z>N^S_W%-W}REe8C%cYmXGB=IzA%irYE){=&k34>hQir}sm{P(Dy=fK9Dy7feeGevh z^40pD9Y|0x;S=jDbclCCj^a>1PX;ult8JGmc+2qIlq2@IetkNT{`6A7nIi6H6m2W~@*eFOpT5#%8Vseofl7N#p_Jaly#Q{!hj?`#-}$f z^d#wJ>E-DE|4fg6{M6qLn*Rj_H={SFx1hJA|Ie!QzM$a$a`v$Q9p?Ryv*&N?|9R@> z@7bOIRigJ->c;$6_g?Qh^`jG70>`&UIw~YtAr*y6%yX~_SW$rtRKY@bvuRj~ntlb5 zaS93sjruUs3=5;>4H9hKi42i~@M_Lf-?7xIu0XOsq#awSTOXS{2xgnFDb8OskfS!_ z;YtkRcnNS@7roA3ORfotk$WL0%tjX~yQysbnaDd;di{_mTnT?tG%eH%JnyvC0>Ss9 z1&`T*w(v$JNRf{Y?BoQwiG_W-eETa$xMgc|_{?Lv9^Qaz5cLsM^O_>5CP%0R(8NA( zTJ&)Dch1nzIhVY;dwL$IZo(DLRQ2-p2zT^yc)7X3z|Pmv4$+J*koQl}kVhG!Hr_@B zV&Ujw1aqjf+`N2i4LZ*H5$%r@a#bVyebleC8V2pFdaO1sfu0`hW3x>8m)u^WrkIb` z7$+snQ0{;mexwh`n2Ir0PYRh~GiPXyaWFT3wdEl(XJbuNnxQlArLj&Tn~^c+Xim_W zo~OA^{+<*u<7AF>G{nL3HY08ba5OSw9!P^U<1ikBH2`M}Oec(@XHKd!`^xcP^9@IZ zCrXfZCrEb%6dle3oq#pCPgQ5uF!R%A5>_O+)}5`ARU@=?wR|1EL#UB&eD+Umzn1H3 z#Cta1n;)6)U#tCJfKGs3fvdiS!r5T%^OQPX_xC-8w8FOWxO^zg?}(!Al`X$_MK9ic*=r zx*p}DTWy1@lyeeyz;qH&@DpRWv`@n0n1y?-f*D!!iBek6y7n7d{J_u4kjt7(cojm8 z#j#{0XRQC=f6`j*i<<)9Q3il25TPXm0sE*anoW!5RlJlh^y0b&V5^;QkXG=**PWbD zX1IWz$UY|IYnc13QNXCu2M|DlszVkh($yc&^OCXBkuk7NQ~6Zn-U&$ra)iyyTb@C0 zGnhjzK|F_syxQ3*XZJXtnrXLn`loVYg24ptLrXbSc!YfOi23~WE<8UmHe{YtqZ8O= zGDtY4Gv=27mjmszq&cQ`T0H>FNLN(k_F2FL{j?H$HLGLN-XXm=8(XIB0q#9!mACc|EYgXfOWHE>9dSKg_I?6Fx=J4%_MpW zrYtb5gp8bx>XnH`r{dUYOc^@8#D5w#Crt`ar8GIXm>OxX)=OEtl>1&(DfR>cKYs&a zbv(c(bR&>Hggn5B%{HXTOZ%e-vo-+_24Z{b3nv{Zx_zAS&3&8WY2`!Oh@9Md%$!GU7x}Sm({N8no_tH)lf4Fl-MUR4$F?YD3Fh&5Yx72<2f8Q|A4<(NbhGxV zuIX>9Y|3G=m~6?)vC@);+0*+QrU9fOFZAq&$>>UHCLBdb5NVQ)SdXO$xVlZ3M}c0# z+_?>EcZ^8D6oe+koS;;nV$9Ys;Y_b(Ub#W~_%=BtC~xW6WG-NueMtN7|#t@whqkkh4x<1Pkq$rY|EC|xwq zW6_H!*N%fg!EN8N(X&MK&ggGDnAwl5AovkCwYP1!qCPi@!ai#fbh{4BeMqhC}kh zi%6tN|Ad)xIeNT`964z9=88@w_K= z!jTq|puiFwMzY_H{xt~hK5rP!c1%mYv5(w?nzHPj?b;Fl0@t-Tg5|DF*P`2{=L>H) z;AwjCt2h~qjsbpnWM=aiXSYM_1ZdY!8>2G>3m$2+AldVIc|2=i7aK>O+6^Kkag5_f zD^=K;{D5aZ3VHq0PPzTUi`G-UtbhkW7hw6-=5e*&W5mT#bL<5^734CEoqgj&YWoEL z^jnumv$B-Uf{6Y#xj}+NpWtdeA53nUqv1UkIgLpCo9AxWt@oErXA`n5VrSHiL~lEy zilukRXqPw0CL+eBL$P10VzFF z7;=H@Sgm3mL8a!Dt38bNI=IpBeLqkiYAdI1@Rs}J&x_qyo% zi7YzWHq3@QRcfCb9oSIv%U!rt4ixVRKY&h`(g=c~9U-!}6q z*Q;ZpWgVdcRkO}YA{{xqou3w~AgHZ{q4(`nCk)7vS$-3!R!qil!wJo^O`CWkrPsm~fz!<3>vGXTV~= zqu|1tI-GGq=?s@nDCOreq|yhTAEUC8h)pca?r{sU1Af}9FpBA5%_y_;1CE`6x%?k2+XT!xo5+i1FoFojMyeA z-L2i7KGkt>S-{7tvf#=fJZFTj$OI+D(jbn=-I*ZOZ?`Iq%M6`&{KK0v{IVbsb- z#=b^0kt@L81Cb_hUs^I&nJd8_d05~;gHztim{=F=g88tudTu4&of5Lp@UCVSe$NaQ z{HZY&%R=%M=5mK01FVeoxerKx!^hK-esb(g(;j(>mb{plDLX~+cDCmnnP%2efLegXm#)+cEC!V-6 zU!0LeYLfk`;?>FJ)!BjS)o-Ukg)Jg-m{H_%hUxd>`x*sx2Ozo(sV&jGh?)tW>6IZi z>20J<50W7pLr(r~qIWJ-$BPi>?CdA@#2qhBF%FAyy&YIxO{Ax>lZ+sdHYepUzrFbI z`%}Q79C^Y}bY`RxD)}9X)I2w2Dg*m;x-`;JQL^&GoZTKtN%CnNjO{Cje@AO7{zoDMi zgC!@QVfbB*OKNXS2kNu&l5DGOlJ!>n&YQk#QhM0l$EIwf8D3VBK_VoQ{AraRHhClg z)L~V`lZ6yUA zjXH!^B<+cF5~?c}9U;)c(PW$COJ=S*+=x6?78pfD;G4CysK%&gqPhv{JDt6#00K8@ zX~TU+Z0h{TPx;-Movnx-K^iPpH_|!+Im_o^aVNt^Y2xn^6?2*J){uqro##2z$P=lB z7K7v^DQS3SDBG0GsGbRtxe|TFUlFlhVP&H{%ic zuqi8}c&i$#u*$NEC44&R%@%TfyV0rw+R%>mT~_g(z630jLpGu&QM%pnEj}AtYIPfk zgQr`!bUp~GQiKRanq?s<6(8>7vGkrbs00h2FXTy0z+?Wmn=-}}k);daw_wn_nrJ5e2a?lY@1-3m?_0#^*8Zo7 z-{UJNfh&+l19f?tt2> z%k`{CD-vC7g6P#+h_a?xOHf^0jf#wvl*@rrlX~ow6W2AS1v>&pg6R~^Z(xyHKXjpUGrudYl*z7^~%KB1%0 z2TIm%lCDR;CT{9Fz3vAWN9e+THsikcpsZ|p)lkzj=&QWu^aRd5RoPf-T53vqzP2yi zOcktodSZ-hhf&6kLM~5rysx8qZ#)Z=%UxO*^}vBLnT)AvptbAnTs3p{A)xm?qA;Sd zFq&b*{LY#Dtk8Q-pV=&#Xs7O`T9rtwk02XD5|Rym1u|mElap47dumsY7Y*q7(_(a3 zGC%n`AhJ-{VFP108fF*5v5?!tI1aLeVv+ycXM)0TS)cZdlG;R0+y+ufML^750g4Nj zOv>e2QC}dlmD0C4dCpWVzB$CIKOo34bj_QAkt8jLH$V_yPz+7_)>nvKepOy-+qI~q z?{-Te`k+S zSC5PC-7FkVGWgd9W&IK0@Euew9K?5|*i8zn9B~Ch0uhYBv^}p`UgT%t?2@@*rVJCpG009i`rw2m z^G-&v*QEPS9C>^DZ6(*2tvA<~rOV{AFrpTMi2^MxanRs9P`R1n;R&Z$_L@v_P~Lkk zgz2X~u6QL07X$*@NN~4H^Ka{wH55ksIGeh5fdFmx@&OeCyOwFXINuRi6RV zb_rdeP+!&V-|xt!m+^v(bu(TKq_r*DXoUfmgVw&QP?jgmZ`CkAkf;klNl3sY$nc7@ ztRH~;e71Jvlj><-hnMGQtnC)V4g51`nz)Pwpg#NlFrxMT@R5FdXpEcg6|vLoDF=U+ zwVn)(EI@>eY#AEWxJEo_rZ0>p4lw>hub@i-de=S!mz%|z@#P2zk)?i5O+{uN&e5P{ ztmIr!Gv=7boNwi1VB(^b3_8ute!(smSBMEj*ci&Micau452h=SrtR-gQR}5>sWK2w zyC%hg*gzd#-}Nfp(*m*HQ2qI{+;ZlZ(hToWq(9Fq!@f3CmDoq#;hy|9%w@^~SOI~V zv(DD42Z@#cMSi_;G86>6`GmGMoiMrsLLVmqfh`PahryOXQ!1AnO1`9WNue-PRVA;c z0v(>sC=Zf6`+Y0EH$D=fv17r5bG#CDT|g*=IsGPAIX#coHw;c3G4vnoSk05Bb>177 zYatmC#q%bCRN|ZSE^6XnAM99o-y&>$WiM*Q-lA~5&u#jSs7V5{vk=S{ddhnEiDxVt$(yC`LQtn zzn}*Hy;$l0AOhxM;bdw`|F1!?|1%`C8ofHb=6{hE`wv+$dar*`joJQ#WBIrB|5!Et zTV0mYzk^3-YyMp|W^k@qDLAAexq;WHGY+>vUJfw&7Kl5Oth(g^?m)lh5NC+>AvYS{UsaoxSK?+ z0*R3&!fiF%0`8h!l`pbW+9xw`+1+DY7PNdc$-0>YaEP~L>h&05E+my2dx$D=e|8Np zx?y&|fDosS;o#_AdOjbzod$-Kx+(!T)kH+>cO%)4foL8LAbK$wXG3X#;9$w>~Be(a7{+TQ3OvmsV_JylIlc$eiXFMZGskW3Fdx#1N65NcGIsA*rVsyyBHc4j2%AA@$X=A2mTFju0DLx$RXq3X_HpyZ}-H=jee#i_+ zn~UN%?$clrPESoUjKX5h!s?4M(K7*OQiGjITR6a2U|4{VPIotvHh}<##WRR=zP-2w zm?=+6p*5gokB5)rs13K*lG$Olq8w3g0_rnz7l0 z@Cqa$<{d4{d*f?V3_Y#n^G_^WR`v!plR3I3%dD?9{E#o3H3=1hw3t^a2&;aAh)lAW z1vLvYDHP^#P_#1b`tY>~0&j(7#hxAv2_y$aH#-c}%Uy~F(9Gt&g{@E(S0vNEK+J;E zUbB}1zLnJNH)Bo_i*uops7bPSS7#Fbj@}(1!^)GPBa0k(&Pu54{7SGr%oPT5gZ>2n zweViwZj6{3A74JD5dV`TvolOKLYd68)C>$%2#7^h@+Jj|+ZQ)Q zm}^j2C`NBt1=Kc+adGHlPO-;&{p52jbo^zU`OqWgMYPya4tG#}8a8 zv%=;Gfc6O`#2z$DYUCzI9KF%Bo9ea(0u_E(??tE@j-wyCf|1pPjF?8&E;C|}K^pA%fQ{QfmjD1e2<9}WnALxT z5rF5^Ixez89_LSiGHRq1%ekfMo{!VoAvM1~K}I_3T&y8>D4a|HuavUK7M#hn%H{J7 z3plF^bY>L_cIvnEaCax#jzQbXkDolfYqUVP(#DLLb?*&KnwGF>8V$cHeGY=+c zhwW(NYdO=3^7eO$;IAGjYXwh(WDFZ%bvwShUu1^>C1XI&V|SjtfkQU6&M@AQ&n& zEeY~2k`@kX$3+)Ldu&5QWRextn1NKe;HNs$7-nNn%XP6T5iV*MsT;Z_VdW?rRwpyy{s>ZgN^J^Z6mgj)yw22A&9yJ=GCaqttU>AWf>%4 z3hrj(M9}y|${gT20P5*FsrP-i9VQXs3Jh{KkQwX-6WV|i%lqkk@1*ox_tQ+Yg;L#lHb1)%HmRavntxF5rR z*P_gsBQ+ z1)rOMu9}l3=-TJ$!N$qtooUsRdriSR4V=ux#c1d2QgKJG9(X++&JO*B#@R>m1-9*3 zA{;aaco9mRUFbaGm~kli1lLRdt~sy&F%)eftZ7a!7H7#3#ZeJF`73rPM({D z1@oXK8-tjb)`(BkxuvAr~i>sGCVH3Wd=+GZTdP==N@-^;Sq-j-HQd(4-Lv0u* z*(PC5Z#!_=?YqZ_O>Q&ztp9oV%h;rNg9t{YYvDz{z-IANfVwgnyj`(C6I~w} z|C$2@y;1|r&7?S@v{t*I^0yz9%dQ+s3U2Bm5MAEr<~lhf(da%e%$O48(2A#;XHTzh zd^t+ydQv3HMltlXMo6<%7X0v1QP2@rGH_by@jJKfdrnikxL`?2b|jqFFX~*Ll>VKc zJDrReN818~Y=ox#B952C@2;-Hw=pQ%@U7iDd)w&Jze{u^4?nwoKlpHv=Mr#fIbJuH z(4)910>5LvupEWpi0@c^cwAdj6oC@P-`Es+2Hj%y9a5BIDjP zWnSsMd+8cW#BXbLfFCMMHNecfoUT8!l?L(XS{gEj20A^rIoup8wtBp>ah$IJ!#k^% zgj4(fS!ku*+&r@=()7r-<9s1)jdc`5f2TwprgVf~q@^VkwqUZjk9B8mG}d4p+XfNSkBbx@ z6!jt9A1<^apcIpsk&uv_fTa1ID4h9&KOMwmQNxF@lT&sn&P--1;IZ%#(P8hy1O|yN z#uNc0c#*2gj^6<(4yl-krUOAq%K1S-jdW2R@5T>xUoGldA|CMG#KwmMPAR7IwGEt zI9{LNxSK_I4ZPiL{=6G$*Sh?3)_r$=75JsSsJrxdBJWYgHbsuqqey#tEJ6PDSq2PB}pW1Z}5yH%#?Jj)I=9$rKY$qRXS6IMfQX z=YA~>Fl);|p))8NRkNQR!bE#-$QuT{D@h!>j~vJ^z^0ZSIv*$Tm;PH43_sp`zW@3| zFWted0^vIoWCo%R3TEo!TtCgHIFR9>n0(GPwGb!A=_NVIwka~a2hLvfYj|mxEbzB? zHcP`V_I^6u6E0uTW4GV^)wc-O-YC<{3T2d;xdd|nkKG!MoZFu`!ruEnBb#Oj?)>=j zGiJFl1H*^#KWT_7N((q&Gv|9GYzKfjmepV6c2!ae$Tk-TnkTmD^t!1>bmro}CJS3Z zNxwR(Rv{4V?8yOeLS~>A)VVvbU$Do2>!=d!q8+S#xJLE5cZ@VcS{?s&L0VUys10Ap z2jz{bS6CK95n~MtiXn%41J0N!tRl<7s5z@9V7Bjk&i!PpUot_D2n}-=d3L(_+mTrA zw6{5z$M>abL6@jPnOB|JV=xHKmkp*yk`wL%Yl@$h@|%TR*Rko6eU$`QTL_xG?D^HD zG=qu1_`U~dO+2xG=gcFu$mOzDf64Be{(e48hsDuaaOA?79F#{cDSQu;4H5T=PcK4~ z`gXhIY*+ChX^)gBbD2ws7jA*+%Y!5qUV_}V;QOY0Vp2Rw{OO)g(!oamO|S0NdxnfE zbLZbRWIVRk~QM9RI=o@;!Zy-!Q@Fhv-r;k2tIjqU&q7{W% zYZMuKLqo(vkUFH7X~=?y`r+z(ctwn!`Vcd^RU%&jJi#=&aHQ_|4s-wHxQyZ}&=o9( zC;nDdn#b@-q>-^=AWPyp)K{CY|BSw5Mp9BzY|TPdpCO|XX7w2BLu%LxOvkrZk-Ab} zFu!{WjU!}3>y&ts(xhWVG6-$eto8|o>j5H_r+hm$hX@7LzA||~8H8M|ANH8rH6o1D zf0SZ=*iD|zD}W--xCig(+h=^Y6~f{5crUV~p(LYWqns75F_@0G5lq*d9K$(bMrJ-@ zN@`k+9wdZq!KBoP6*nmj3lr?i-jP3@pGkg0Sh?3{&vgKpeCv*YGiKhE-lPy3jiQ!*q+kfnH& z7dBTpOVt6a^($d6Z;UXuh(U8E@62l32Z20qL>s1E!+wK;g0>~`VMg`9-fi%W&}C8= z{kuPQ5`KCOZQ`{G&>wJ0OF?|C_m^tXdnElmMksf5jKiai`0aZ#uuHkqLiEQe!R4~0 zU*t|&&C6LjO50PPaj1{=u{~n)^93`bQh_cLLAHo;JBtOMAzqba&&~8Jg6CusGjcS4 zXh%&wFn)@|)51jF-E}9hHU6|44Mh*f1}TD5#hzDUxd$jtW!nS_qh`;{?I2{ni1`c` z&}zzOUlcyCBqjYZC^OqyKFd#sZkFR9==0DQajS-RY4a=>FBRbQ)Z8gn`*k{_tY=@) zE{5HpW0XeKE~QXBY{sjRem+c-^IRa_bbzH%8^$K4&taoNe*V-FJ- z&yO<>9CGX*XlSCU^@-w)3cFWWMp*s~Z9h*hv^c&Uac5A=}w)2{2~6wJ(;17RS9zp55SHqQl>gLG9B$Wu^RUbKU)^QL`-@J102JaVLD-6*=J{Y9h=znfr-2=*b$?wD^6ZV{_~MOOME+(UFi+1ECxeX?*^G zv7)ak)*%ceTJG)K02v>BeZz+IWap*-1-VR+J7Bm$KEoHZOupKCw)e6Hu^UTHzh@A* z|2i9pyhZFtoGUlXZ$!C11+xaDO;|5^Egc0DY+xrZd@Q*4Gox9Vdn;2S$s_{-i%8~e z>G>UndpEWA-t73GCpAXHP$64qGybg5AQtfzW>YzZebLI%+2VUv+y;3pISIJ!s z!q_~j6*LF?fgVVs<3g#wmR?%!9h#{aygDV+QnBNl-}H2lbOzY()?{*mn(9Ihc6ACm z0PGeRM;GW6U;7IT<{&rA%JTKQbwVA(-c}jEFJ$*N-pn}>lTn+^T#_uDz1|ICn9&&@ z#7aNX;~Y5EPa8XZfC{nqL)rxJ&q|+3adhxsv$}e(g8I&9&(o@xil-0WU`*Gl-JGX0 zr^OU|e99EbMm0TnM)nO~LAMF<7(9E#kcdEsRo;waJ5Il-iD&OZ@54Ke#^r)Pl*Avx z{e2Sm!x#s<7Cw>s@PqLyFP;a5BFtXCHeg#LOd|r1h4k@$F~EV>rA}_(Ww6H*@Sv@n)qgOo+GVYZgrB2 z^Q3#K+=S=-zP=Id7y7DV%ik0~1fC3tQ_g zo0(l(RQ$&t+=yg7*OYD24?Y7bNrG?zrD7Q{@j9*7^Xz zeS%4?!*pJP4RhO-{-C=YHDWk-Er}GFaXkQ5%z=PeMw~4?g_tx`j%jv; zW4k*unTUyoILR0}O$i5q#LcLFYkk~$S`v=;v^#)YI$PL1V7XpIP+Aw;vJEY=v|z`$ zyEaBJ0=br$50`LKS^BB6xV25EIDoPX zQ`t#95~cJpkJ?cxp-}3m?(!SyDZo>bGnY2Od zwtLLs&-fz zr6zi@*jkC10BpYPol}AIzJn{l^x2VkXqUImLN38`6y&`d+9<@#N(X%2{OmVJ?5T^W zV!RxLrj8;{A*m$+kp{sYR7U^@NPgpqM|@>(T~GzWvhvh`DTZMD-~=&-w5a3ij|YzH z+92e+y=;An>;~`(&*zuPwhD3BA#v<&oKV0h(=`#`7e|$g{o3-%yn=5j&(LuSxeE># zprrfd_vD5)`|yb9h5A$mFiLOYo#{h(a2)w+hfUxqsODhHYxDW$#aV~9d!)U$x3qM} zH4ap6lY>j~MvYfGAPAR;_=w{!sx`EW{>d?hU>+f{iIQ4N26e zQ%zbKQ6F^mj~Bxt3YBF7r?~yibB))u{I|qs@$>8oh??XUivn!W&%!iFDsbZ4M^!S1q=>ypuN3t7 zb)R+BA`)&V%|y;|aHvBwH`PE0yh(f>OjFjt&|`1})3i^p*&GC^|HSb_ccg|Nv&sJp=Ffj~>i=(vwSO!36aKPgOuvTr9lpx?T>jN^ z`HL;`WtRMNWBwg$tqslHccSl@gex5Rm*I72@PV|3^3=m_#_*2Hh zKNXNmcS{(&Fjz;No?>3i7)oZ)N?ZLsR+=wggyo`cP9F&^yA%p;^*gz{%4AAMYg^m+ z#!_F#tbl5vPa>6_eXSN6xsS+b7XU;!a1S~A;1UVxmKH#6bf6tz9LRdpC)lH=CQ=4? z8UnN4&nyTCV2wu=U8O1rWcA)tkxpr+bJpIjcbGGZ$dL3E^;FnQB5z98l6?=)kde(l zFXdNmUIeuwVhuMcg9@OMk~vV|!IgN@n5wlur18hPM?Wmx#}=<`#OC4sR%ZE0Y~cbzKu>5pslrGYp+viYvSV;oSHteG*M zS01YEY&ly80V(mf`8(5e6FNg*T?1Yku2Wy*tFmk9A2^-m-Ts$OpS@@GcML!ra;{mG zb7m<*U<_WfY~wa!G~uyWxUg>~#J=AxX@sni+~PPZAwFd18*8MU(J-?<9vS^YvhJ9f zmL}*4c@%z8lU_p5CeNP@A(D8j@8&0+Ha+EuYCH+%j(A*WpO4-7vX=b(^B94VE`)>X z_dRJm#2JYx^9lVv)pu3w-fpM|6ZHRM?VW=wUAMLGm>qX)+fD}^+qP}n>Daby+qUhb zW80m4>9zJ=XYKv%Q|~!%y?>-?-cM4qo|^NyGsd{Das5WmV)8Rz|EunoGFrdFpQ^y$ zrbZMR{^MW?o1~fH7JdW?O%}!Y~kg>GdqnK||d^qhaQvghWgM;Fpt+ z%W13|Y8v{wy==z`~t^*Ggi@`WMmlqdJfuN#hF}`E`oVay>0dbp*UX(zH7}2iUW0CR!VdUS zBwcI)494_xSN4eD3);C#NXJ>&!cs^FYYoR;uCC;6$dLxyW4$SwaIkA z(7TNF7g%#@J4YE|29poCPOAH{!*E-7RUEvYzwq#;8A^}begE*^5nCBrj7Fo$RSc8; z-lqp4^>xSW?Z*%EpsFSf3%dLCcct&TOh~g>OJ3tLYmUrUt3~~Z_pqvQyYb=~*gC5oN9m}t_94cMJp%H6 zmQ9Oo6T~+mUW0iBQ&R&|qoE-Zi~upbili#ZCo5+v4;B;Yf>22!@;+v)-pu9>0Xczj z5eMKufX5QHw?o7o1FfYva>>jpD5`3VD=tF(+yrH-f*N22OO8r?HuhWRZRa4{9lF+g zIMq**?tL6jd)5pfaWYrpu(aHK!wV)%Tzhc$q2ad04;KmjJJ0?DSQ)8>WfJu|V zDL`$-@+e#2VecAa#FK3y4ky%4thNl|C2f2!T6=h|+@TklH+;8>I8|+j4f3nB@!_1@3oExjbpR8K&*5`Q46(k5g2Ve;AK1P^bOX* zrF%_qjDkOU-gbuyx$-Mn5HdpnNkj$)d^p7O*eAo;C{_my_Vnp%U?~RlW0v}ENfX*$iZ@?D z`thqR(1(D~M^2AkZ6lfrEB~Jo#s=m-6by3AANNXFQC4tSU7gv_G2_+;?+YI19GnJV zUs;30gE!i_x12bhRm_Doo49}WN9s+^yF!QhxPsxBIZjSq0jNrtNNCw;sd@2vNohIJ z81TZzDS+Is3zw47-=2b&Z{*Q5qG&EB8If*k&chwk`!hATS`U$ zPnt3-{r}aRvj5hO|J%j?uXD;68UIF8{)e5CmzM9dhsEGCRWklJpW~mDV@FzN+E1tB zzjduJGyH1`^~d^u-?j3Oclj@`qmrx5*T z3hF~v3-hrxe=Km)%6LlV1#b!E`>HOlOV3L#utpbzK^;1!i}mNh&3Y~#k+E@)pZon0 z4cA3z*F~rUS-Pp@Yja`h7iDoTSz3x$XowX;RaJbLxC6;wgxm%oP#5T0l(^BJH_@Yz$P^zC{ z&O*VhC4Vkn3-Gb*S>!t--G_YgJ1m?GIe z4Bu3E_9*s^IE%`0`}AtWFnzzv#o(DRf|8|DLi}Co#ypFW!P%J9dvd+05hPG{)5gQy z$9HrZYB6Vn`F;f~K@}EnFrflWn9V2%f*wLY(5oBU68>(48ca@~-Q)*^%LaC&lJMC4 z!Vx`I1kG^)3#LNrpoNGmlmD=e{PRoYYEINy0FFJWLu#93hR>@8btelb(*;Ar9mYsj z|Hss_rJX3AAP`4GD|*q_TXof9#EsNkD`H~rPO|fEW zs!lvAJt5#29Sj8mw6cgo8HGZ$R?GE5q{Rg|j1&_xZ?h=f-jGQgQ+FC?S%e+_u(S@_ zbB2U%OW4_&i6g&sZq>1HFcDsK^zO*Ev8ly;WvD-mhMo$wrHG-tV6VdFU?)TO2y9S& zmNj0knYH!x(aN7aLU3x!a4wO{P8al@O7QV zw(AmsM3o>1EU1VRH2g6PT;2`tOFmKs1k$8o2aW2aOz{G$;^Py5H+8O@AK5%IhD0vA zmyK;;yP6sZz2&WVU9odIVzH_G5#bj{f8>rHU`_vo23RJb$vr=>M9T9C(j>?f&@9=H zQOhiqpzSsN@zq*p7Ahqo*H>4F^PL=Nf8C&@Od_?yXKZhJdhdr6!+SsCoqa!_I8Vz< z8MHYUksA8jowE(<$HtIxK_<+Wi-ve*Dv>gUIuam~}EU(gM)`PZ86 z=<*XearR&CZsAmSY>byKz2`P;e|l)&^*$38b%(j{>&ReAVsOc-&rcHpfHJ9`yp#qC z(BN-Zoq3f=owKyIE2RxdHDYrcTL$4koW2d#L7@g@XObpZEjJR!4J8HF)v^y{4TyPCVa6-y zYKC+$!dMXGd6sF(hJFH=Sl1oQD-QdSoVMwisU}?@M|3~_==DmWmu);_Zvx{MnJq*P zT~=*#^{b}x11kfcbTb787x-=bdh{G<;AMA7#K}oX5}ycml705qwvGbJ#OJBbll6tQ zj%qmzF12h>jw1eMKK(UhM9az-7?(QS_POi@6G@J^)ZrW=n3~cnZjqc$NiM01g3Qz9Yno?Mc z4PF4^0#WMQ(J?w5@a-TX(e!+p+$=QTjbwsdwjG;$>zUfEpQl^~J9d3TZ+-F%?!NwV z$Dv;HVBlixiXS61WNhi=CS5esKZY zhLdMwWL`%mnh;t=hN(T^tYe=GCw)^roNm@9bVAFu#b*8Dfvk+Ff{mU3WktmeJ$Wwz zS@6{rSzCHvDPc385fhP-TPdidbtWY07gLO=w;ll~M|Ulo`}@R6Hq7~+PE`>xVln`0 zz&N05gjx?MIn9a5$#IBdMAqaf&9Z%VPIYp$*77mRcjBub5gNLJx0O{K3qLALs%%R! zPS(tE7#179n`i&1=HQB(l+mN~O8&+d6nxwFZHA3}oEqA88 z%wY|h*3ZMOIxTlVFr(b6tW#>u-+&LuoD`YHJ!Z2w_pxHL{Gv3|Ot0qcVAvz6;%%VO z%3%``a&SRfvx>}16D2YtM6o*(mc>|y6>8zw1kfnw~xt3 zOIypSB@MTz_aRSo1x&7nJ;Ai_4v0#xAgj8M+6$8qx^PFl)^am`bDz2ny*i_36|QA9 zl}vWh5u_lb^^jJ#YpP5>aQP&iY0b*FZeUzl%C~~X&dC@R;kA`pa81jTWzp@xb+%3q(XGefoD(h0tioL6jBr|-+0e*e82)tP_aMQNAeVlMABMzx#aLZ1O@aIq%;=pDJC33$Fp$(6Pn2}X#HnXULe(cfx^ltlkSW<9M;<+?Z_QX|B&;fOFPpxJ{g6(1>XR$F0I;$!1rHqEiWL6g zmB;7u*+18Y$8NJ!2T&|Y^BsK37LIw7b~Blc53v`)f;y>f=T=T`NZNTGBNV=iqu&h( z?4mE)Xhthf94=s=p$h8di15Tv!LDziWb;`yIYTP$YH>8bJrMTa4A6orQDN3ssrc%C zz}=wcBK)U9@pobKyBuON&CbmBNp55M zO>SfTPvo}W2)4hG+dh~7MQ;1_f&4e*HrCH!*ME)Ku{X6ewfN+#>Dt*@JO6>+`Ipmk zdisBxZ}aDc|9$cI4_wY)#h<=`j;@}Lfx#ZkEtJE3$h6Y~Ok_O>B-vZE(Hnl>9e*PG zqjvNc@r9|Da&a#RNY6*qw~K*~4N)K8gqWF$Zxr-v>|NQlWQ<&S0=#{y@;%eDvl>10 ztPNz0?DWz-tTjZ0%&ava!y~c~lhTtC)Ft!sHshZQpkp#62r+6YY6@{lK=sq~EOi;R zShf7^w5(XQc;)nzw3IlNcol_sZP-R1-yC02z8G6peNSbEd2YXN|JqsGXl3`R zd-^b1qP(n1VR7BPJLbBH>lE+Ms4aLkd91w4+X?D>9MV2Ic$&0(`}PX$+WA2>E(}UT z{Y2At-nQ;Bs7D;tbnao{NRn_Ir_ZZ)}Iq0>Y zv4UF0;v{8~wY)qrGrPVyUqAbxl>N4aY{9(0VOVh6YCLwEK=WqW6@A{cE%0Ee5!Jlk ztTKLhYh#tx)7RGx03bk~r}&?q^M9UwFwy_zG5TZ`{tq8>abYDTmER^KNzuPQ=Dz`j z49uT^LONFF|Fio^#69)@#lsA{R96S#r1c=2+#&7>K7mY2oL}u zARx@&KaJlPaGx*%pRjSvFu@e1#y8>SBN3cT-A-CkLck%8l-;-h7tYN@Ypqa9`) zW|rVt1koMal#t_|;%IN~qN&_sJbL{IxcdlMj0^h#BoqbUlb`zYQT1nPK493<u+HxsSxHI<`nB2Qy86<8&&|3?~>?ZWou`u*5lkTP|;SH zijyxo=vNp9@d(iWh>{l_9P8^78srg(>&P#wsvHJkWs}jClhPYsgBz7m_y`aYn^aZO z-5HhL!AhLM=e!K!LDkeSyr6`SJw-K=Bcw{6FpFe{$kj82=Wq{w9nnxY`*05sQAu z6FXBI2Wz`OmQuQwhP3ihG73WSe<;R(-^rh`>d&1_&;I{-C$qBu`%Y&60%js1^+_*W#$P%xKKFht`H(quD6 zhHn7om|+i#m`OCw z*Do>`ttK&P9;&en%-m`*RFBH}L*#K^k9Wm$IoXIgv{Et|l{=~EWpNBTV@TlS3d!Xe z6X^Aewa7(F!yODu*LjGAQc@*k<0b9tpXphsX}Aexd1V3Tp(vu&L|x^3<|!xw)Fhwf zFv+~l*bON|v(dx^Hwuks+@Kfv$WsW>qbK7I#H!S569;HbDne^Lb!Brb00`d=vx8&< z)n!TOHG6qsN!^&INaK1noKdbrwSU7>$Y;!cOx=dr<40}GrY_E`&P+cB590?0xFD(X#gP*-+S(@7F*$|}DUBs;7!S?z1*0{b-u!ssL+0$~VPFYyJ){|%$T(YeFurYYa zTVZ=mtCO6t>?HyFMM)JQ@f|-MUZRU$;NcA=2>})7oHVl$xW1F2_|)_QF%`zR^xF=V zgK_;}GU!#I`3cS)cOdj2vx!$ivO;n7b=-UlX+J&d@hFyvxpUW7(1bzIf9yqfhV5001WrJTM+F zRFRkrF$d^Y6W(hx6_58L?64uLvk|tHxjCmRO+A;5;ryT@dOM0KW$oUCf0ODEB~N_LE!h zjo;e1>Ud2`7Lpd@&BByw0xc|g_NF* zHN2#p$Y)8oCFjghqs^rIBAX8P)YG!pm=4UhcO78&n0nP={=kd-?G7G8wv|*yarE@Y zY(T0e$YEcy*Lcgv)`MRM1bb@NnH# zP~4)wF&Ry8=#v{6m}l&=D?MI;R_>7!QdYp+8mAM0ajuN9*u2OT=ej~lRAt*pU*V}( zh-V~vL;@GJJLrXjOW*&|6}`_8@J@bedrJ3a6RAC#JyoW+vsJ~GdI1}bG>(10zp21Y z1$FAHWwNL>{r0MTqoG0*3wiq87})Z=yN1a@T*P6syO#3EI^IpBk(Pn5k-4zB{9_EZ zBeCII=WHRDX1CU5q$4UKT5WQ(FhU5l)MTgEt;g#zite|7j}gp@&f*{Zk}WcLPsakd zX(|M5!xMN^U#%7D9~+iFf^!tx&nr)6_80PNp;%8VLj{8mI+-0fWL|v;U`%_s_YU^h^wY{Qmbp{?DZIf0(@ri>nBz34g{sxxa@z#=nwR z#?Km!neIQ-Xw09A-QQ}o-^;&hw9mZvzpK$c3(0>=UYQvF7VIS_ zFZ}NV_dnj|ufSd53aRjQY1OiUS`(QVgE_%RwA8j&RraS(9bymL6cU1fflR6^PFqUq z#d~WGdRht?1_lNK*7tr$;{gGrAk3n&8G$@ok>D0~LDBi=8N43sD*(a+ZZ@gWevjK0SP2V|hMkf;0^XKUc ze_sfg@4CNco}9^QME2SZ>g07~9EPQEx9HkrrSi^6*g2${)VD8@Yv<+&yRBM;ldF=t zgwdV}>eMlhTIMLJ-266xQpT+!Y=nz9Fsfv#q9LlVdsC%+-+6a*weX$BfSp}_fXKw_ z_0)pS0A{8o(uPB>*YuJPo9~lumZAK3Vhehygj{QJvVE#_%o2JM9OY!8in!V8v^_yv zGS#mridy5)e+vkKjU$mpzrQw-1>TpI{aKPTk77oA54kTQnH?xwIZt7Rz#M}iRZ*Bu z4sHgr&nKCCR?;x9XGYWz`4XSXS5cHGgDam`0y8gXM!_7oDngydB0E;{W8T3Gt06^= zmtB^z__4Ti-r~e_G?hx9ze94Oz@o%U!TSW;41hTrL!d*vL$F2x*9@OGId_EQB7{%y zG($KB@s8elojQ8hJZw3o~sUDv;GEnn8+mpL02mfzW2 z&bABut6;rec)Q>dJ*MAx+;Po#V!ggT&L~dqY~{kZzIc6HBKl#d(4KMizjqdcIZ zceI~9EXu^#oJngWi|erlMLA63W(%mT2Z!X{N8o4O|HkPMHBm;vZX+wKbS*!E2MEMl z2s0nUg(c??m+wnJO;5doL%OoPSxnaeaF<$#K(3bKsmqg>u0sxt&Q@r~Gb|46v5|6BvDh5fUe-I(8<>UanEZ7QI6eFe{eT zdLh9Ku1|M(sUA|tv($%Qu0G&>Xe+WQYhtT5wy(z9cAun{HR8wdqxH=5Ef4v4@s4bS zD#&BZt3JK-HEs=pY0NczH%OA8k|KH-H7d$^hTj&pc@VhH!@kKpxajHh8ao(h@z?A~ z(f!`^B`|9sqmrMtOi=9WR$NKmeAu&Oo|>+{5^qGAhBGpIi+0zIix7sL_K}zUjF{?0!)2qQ)rIjZUnaMB)(;^3cgmBOLQq19I~&ixP^!gV8t7@F{OE{)}U zvwg0_*dUdJ5R0UapsR!+r+gETy4MIc&1$1dGiubcZ*jAv21MxHEO2-1=)BiS=?QYQmmkz%R%I(7=HvYHL~AgthyuEz^3JC5tf zOUArKAQU=DZc)oC2!bawO2z)A@GCW)Cd@~I!ZQ<3(dm*!OQuVlC4xbc*t1eA2COrD zm|9ijTyrmq$aE$0-U47H?`)+jlk2PS#}E?k*>=Lh?&Nbu-Ll?rOi{6dXvuov zvsWT>(OD0QbvNUc!dYNbUWyBYT9DCuI5(g5KA)5aP(G1q{)h`!qZS=jvgy+tOFia7 z4zZ=P_8SAPbXoifV*RLxPUv^*_y>SUR+VWsB%XCD7tLo+`q93*6`Ucv{4&2&XHVYX zS=4*C&`n`r;g8_g@-3{+4e?c}pR#_pnj;b$BAPobO3jAg?(bj~*Cz}u_&PkF^YLjszb64!R(7d%?fprt_pLCzF-`;5n zWqIZ=hpUiPN5}I86va}7TJ8G{9I={vA5N-YG=-TCvqNT-YS~SC`v@4*KjE%wZjrOss04(MF>*x`k#xpFOG0hWVHz~nI`p##OSP-d{!$W|QLKj%?fLr?KHFxUq zK?)|z6~do>nF`wvRZcw-4V7k|dN?DlS&`;C8OXI%K;b0y|e{*mSj2 zB|cv`wuIyVOQyt>G&~|7we%(+ar*R%C6rCcAH4w@0XX9nK99{IM6ix%xbkPu9BLn~ zPRZAwter0h*u>PwMZtq`J>(|O8<>j4!Gil-myZg5Sb&dq_JllF<6EfTjCtEme+;Zo z>`sbq#E^hUe{t%)4PHNUV}POXl;B|#SyV!qpzy6$e@BPgR?GS#y)AiLrKsSTe9CdZPVk%&LkVS z1#RUTIHr^OTQUT>7iQA*xH@(i58_bGr`w7@Xf0V`1+ecb_ZBZyVSeHvzTtiL&7dnv zrdNt+C&x`WyG3wo4r^2+8FtL37M&=29Ecf7IKvtT`Th2qe>O1C@Muxq!Gs0Kb_8G4bbpEy10g zx_K+SSFlR$wf@2id91Byl?@UBKDSCR9y5v%d+3H9a{nzpY#U9CjYMebDP`lJNWq`e zSH3JRRxY8|PW3>l_e+{4H0v`mh;o4VsiC`kBr&!)l~Tgc9!XkmcUX!Z+%=(J7d!r; zLQARyJKc3O7WKg8EPb@W@cid2^ycvKc8`uu(^ve25Eu22gR&$wg0eo!{BO>$2GnE_ zi?riGa}t_@bA$qh6A&}DYV7%lb5uU%a>uy6InxF21h_PT)Sa~r;b2?|cgqH>KUzcI zKS2Anx&%)9#zcK1Q>N+1x+B4lM22op9>IyP)Pvi8$#~vUts7`Q)y=4}2L-_?|#h#6&2p3@)T|k;m&JEbXWr$n!N< zOo&jBZvYQERhGof1{;PYY(}qVMM&ieqMk}7H|64+M|dcttB<+K`m2=6S^*bol}!=w z(j2q_H+R_18e;5%AnpLTqdBH3Vd#;1xYCWLg{4VB7Znu|UN%9$oVu#&*iMWKJ0v2i zyX3eXt>16m>lY6pGao%pivaIEVs_#1~NRKvX+&f6?O~N z#Lx68%YXgk4E|~REwt$4l=*`-OBl2m8};qcd{dz9QHv5xb3bEquT}7FZ$do7h%8Oo z<_ITZ2+FSouyjO@Gcb^N+jh8#S2g6Up6Pz5(Y z78qZ{Yur4MLKS;Xff{Sr~x1j8{^4{dQx2eMSou#^#h ztg#eOOw?_o5O(gtAk;D=S3m~p= zKf?N5K%2A1T|L7+qs>y*r4eg4MIb?Ak@`aHoLerQqZpyT1DdaaJ18Yn@4;t=9e_(` zYzlXn4ob%*R`MK(HW*xbXCsvvls7+(q*Pv!9Lcsdf~%Bdh8=s>vW%*g!f!xn!Kv01 zy{A{Yxf6Dj$@Q8&)I(avSFHpff)KU|J?KUr`Um=WqnkFXpE{&pra=b4GWoh-x~AoF zh{_urW(Ox%P4t%(bXW8iY?G#mDHmrUy}(>}3ut^UR>CA#OQ(!n9FZhP8r_fD4lF+< zvPCRc;JGsV$p8WgX6c7yfrhA=@>69|dEBsYs+7@_4Oo{;C+hVt<9C8M;)a9Cr6;qs zrAE#jLTZ|hY(-$n`b8auBF-^@MxAywS#j1+LRSV@S)iJ&ZIAgaK6CE#PfWo2X0+|p zT*%FlO5H}dxNI8z)NJFCDVLY;Dek{!Xr;V=3>w>USs`1UVeyG|-*_8GSb{^T<)op4 zpzvLaoTK=n3N!8N21JbnM1{CmD%Zojhf9+dCPAvLt?JA0Z#&3a5=8C;+OA3me5>Tu zQuC#ib8=iY7%V9IieN20HIM2b4aoRz<8{z2tv@4HpZ)6$)UsxAkq^9>g+G@r#%v?t zFq!!Wq`{Fm$ukw`*3hBlbkau@3wspFZ5Xmzhg!QpnE-1`_BTGV zJi6vdQy%_&1;>;syD_Wnxi9>}p$~}0o49KGvJH|=q5XwZa;zZkfv=WHmH@0*rC%(= zSz{5QWlQXX^KC=TSE8t_R+d}^(aDs~&66+Zj17TJ zZSSXkQADZ195XGxSR69CxpIsK8v7B8>o4c1B_YMPqBrd$B$$o^cbsbJUvz8RzwXe# z{{GfECj<7ZHJn#ACWKoh&HSB({$*T_DQK#m*S>9*QQv_aRL2~^Ginv23X+v@#=gEk zV6)4d45>j?hQQPa_X>4+l_+eMfatPpYyU9ch-|@3hD4MnY&G?axBfD*qk&1bisV&) zFB*+-pu&NP461gH(T<^IwXiQ?$oCof3IrFO3eF)8%+*EU+()sxnf|U7g<(OpJAPr0 zRi#(lj{s;t6INSVK=1BhYHH@&(Rm4N^{}IOdDJB(tAMg7CK*yr)KsV}Xx2n7VB9TI zh+cOiQB`raK&AA&_;qxc$?#!|n?H`21@u?J88Kp_5q8e*9Ds+zn z9Dt}k;7;*jMWlI)Jmi||88E|2xzIqW0scfHihYCmx`?ST>X}pgq3#^OsNHK9M?XbB z{LbZM`S_ud+X^=-oFdi_qb({wBYKMdV~gA3tut+=pE)0)dD?_y;*!o?Th@p@gnJ(< z;b3|0R1SL?mE2lR+rufR`6@xP6dq`o%f;E-u_ARX_4yC+#%aJtqR!X>{I1GvA&_+Q6I|M$L28n4EKhTMT&T=W+?F+aoFO{iwIaxYcvp z4b9i({k9iYMg<7X%!NoHBA3zz+6hxCX0$|o5yJOn;VB2)XShWX;sb@h3vdQK?sz(I zK3ltxe-%Y|Cc*dYO4rc1dTnV-0EKapqr`H`*36&SILug4fq4cti%4}a27Bc1AfnAW zW7n)uWI^Pz2J@I@usRQpq*FZU~bgwL{9Tz zy>#87#c#bwyH4UD1dJ2*4D!B|iKIm6?}*3=ukc(dM0Qqvin#ah9w=u91gS&+tAzNaRC8iV!*DqTG?rK?b3lTLCXFRA{w6fwT6hA zZPH#${u4NZW@sd)w3&ffJeAZF@y#R8&(BZH{~;L)x?$bh<`8seGJKK<1#aVESNkEa zF()T>Y5n-j8ZiZq@K!grccyDOFJURN7yDr3DK0LMV>0VVaa;a#!ho=0Va9dlZjBiz z8w0bFF4O!r`i}wFcIU2+UKvkgFo)WP%73>&<7_p z2UtK+Nwsc@gTI}CQzoy}X&8IAU-fR32~T-0;GNm?XW~$I;Q=X73%SqOJpff|Np*#? z@_7lzqgitFEC!^CxWPfX#BFM4)aGM)tE-a$c_k-rEgz2-9v(3S@LRbm$yucGWe)B{ zdQT`4m(1Z!uuMkB%E!kT54$*8H<#G!Jo4)Ic+y`+Ro2*uI&M8$Uq~M)Rt6@}(aw98 zXVuw}jQbO}(ofW>7j1-dfn@bL+Rr^UBr$w|HK9}WY1h1OE5QFKN1W>QoV}sxqwX82 zy`)K;@6$4gqRNPFf<5SFP=TF8QWn%1@#}|oF$@jZj7ank;PJN(o;jZ6Ef>v$-btj* z5b?-(vLH_nLQ<4KMK4ykflSY$Rg|s>o+y7Rx9K^u;L=ZLHITbuS0qm{2EiHk4zd;bD z0b!q^0E)>}V?QCxk<{mSnQ_v!e;vINv%rOXGZ)^A3*Kl9&W%4?JphKkOePDL7M>^u zVuYig490Ved%4X7%WG-CSbiSumm{mG|Ez_dn~`%cJzhW0r2dV*aXm$>42_Vq4I;FgqMI3tk!%*W2|XU^cO>%}3MLSk z$>He&|I86Nqx@k~cHJ4bNk@w#n{Lk@a&U2}U2bFBk0Iz0g^Yr!VYi4{P?*LmoO}bv zrGd9@sYq)7a64k4&=kOj<11&CBZW zY}6~nMsYvi_b9GBL4&y=88B$?q&zLm7#HLdo}E;zWC6!ou@ZU10+A^TfsU&npGP1Z zlyJ>!h&NxgghVhgp#t$qX3q9d0n+9^X-aP}gNZw6+RJq1$g)q9YbJ;_>vSUb(yN`P zn>1~m*I2x%rDw3Fac=Ox zwEwXGTldc&>;Jum_**ajdsknCDx?OIaueIlw_f2 z>JadW)d9@xx?A|s)z)G)7on7j{;L>Ei%M-|N^NH9uN%waTkfoo(RXEA?$U8tlj9lo zmt2P*Jcr(&-Q1^I@d*hFKFpJA8BLWbwY?)Nu7eJJ88a_2N-weI zvPh9IGgH{%d%!c{yz$+mX7{bwlzx7Mg4|l0yEAc0?aXe2Z_k&JS}5D(H!E$VHuZBj zHBH9dIP@)7xE<^!RZ&H3cB@B*@9%l6=$jDO9V3kM@?S4nrkGAcvwgPdYKlzi<)^u& zW$^@MX-*Rb!7esV>NzP)wi@p#{kWREs~HSF0u>3WBFgwXSSt`-ExdTfmsarCt;6&K zK5&v6VgcZm*yEhXGiq-)N~|wZS&iQ7Yc8NSU9Df9j(#wbP^GfVwz@3luUN~@ug#;G zeY*#2h)tE2{2bZ(tr+H0RRp|;WsY1GsVLmcE0q6PA~}y?2FC2WD$yZ5kxwEw84t`H zmMUPGgH`g$D~gA1NKECIEYv7*oYydeYDlolO_aZslP|HHcQXTJj=~VSFF=v&EAg5q z7>zuUzRyLGe~9TPx0R_jP6povB`pfCEklX+D zZJjmm())hwbgSqi2hbjT57vdg+6A6Rg#D-s{1Q!rOMs5Za+q=Lxsf#x7DtWaj+Vt# zrAs#`sEhv1Z-bx>^TG4X{tP!#NBAkC82$Qin4J()_??-;P~jZ&+h(xm&nL{O7UJ|+ z+&?V2@IG#G`r+NJbv; ztzpqZFes%U`{`Yv$UH3*AB&qbKx!Po`-RTs2Y3805N|X8a}x&QM3Z~)2BlJApkH=e z6D-rj3;k+j0=Lbq*o1xn9~5N!r$@-kq)y&;2C-coep2K~rm>?%IYezIT`-p`x`Yvf z+sY}Bc;G*{h6Qi+1$`&AZqPu<>g;lYOCqU|K!pVZ&)A!r?w=tIl%q$`ougJ8CRg#d zj-ukoOvCzm@zm;_0^zfB@Z!Yu z6Ay_w(EuA=gr;p}RPysN$=xChyA(LL)I%jxM3lZys@U|2^K|DK?RafP3G>5yUl}8B z0Y?CJqybk*2|+6ogT)bhswt`1!tbYt^<|wcUH) zg?LHRQ-471uRtmiL<7~W)DyrkU1!MUXuBj01QkLA`Qui>$wEOpY4%N~)U@mpOqJ)K z_4nrUk@@YeukVJRS<5)>xC*VH^L0HKmQ;(*HS|r?gXfDG;)k35*iqXn#J1xP(sTGG zvVL#EqKk+j;Vr+jce-;(mx3#tN6mZI5c=~lJENuU9UsMpEj6#95zQT(os{ka=B2&H~{je zx0(pcOX!t^{}nt+D@0O zH#!g4JX7ap4clh|>QFYO2{6y$^+?m6KD+o_1Mh*3buVBw)g;%^f#fzNvm{wb4qx9g zNEl7m7TvU?W;Y0H7UD~mQQ+Jdo}(J`8txrAZ|bzj*Uwn2uSemm9N%1SUna~e(lT0b zrU|5LcVURYFc{m~uG9b(-_WpVx!M3G#HW{)6_e@LGANjsQUhq$wi^g^r?}>qEJOnq zXSw7xt@(FA64UOQR+@q7(R;ef>D5aw;zP%ky;YK@!O2bQD;X<>+Z1GhA7Fl<2f27U zHB=k-rx`UWID?UYK^io_Zy9u1Zzh-)zk6JfD~1i05ET*I*(&2-CCO{T`88v^zgr19;31^o<^W6w zmXAgdB&c>5iSJbCU<9!NTn|vPJeD-6-QjNfd`4b|rA&R}<&oNlR33H4PGSxOruyp+ zxK+((u8bf-%`O#JX<@Mr7qRZg!gVW z>zZ!ec~pQC9?pdxux9vTKF*9kHB3Sxj_6ufy=mA_hn$KF=@)fgdoRjXi^nwyd}GMX zAU#(P#e5DNB*VjLRLwJSG|aQ6hO5Eus2!v7WF8Q{*D`tvJn%@g&MuUjX{np^goLW^ zX+UC33Grgb3^58eOjV!MGC3z2Zl5r7&oE>~S+Srn`GL^$|Hoe{XWFbTzL$kM-6;9 z3>fclp*(hz2P`J^wOf^C*U$xV@2>=DEU`i8>+XctIo$+<&Jp5OMB>hiQAU#PVK;kz zr(9+%2u!L`tag{LBgIP*anuPIIIosXc!Tan3f4u+g#A{l+}`gDLut~PoAaKom;HJ{ znZ3baNJfz}zwShQYDIH|fT_eTedOAPpmDKS5j59-QWmxHMuNVOd95vfc<~G zy=8D*Tbi{gW@ct)NHMd;%*@Qp%xp1}#TGL&vn)mnEVP(;bgS!D->R;juX|=wOkZ#3e|JJX0EmiYWs+YP-}BH@(ykt<8C2u0&SYgpGs{Waq=N2J?wr z1LF9hgJoRqVqgqE`%d#OD#?N?jednq1*B3l@SBvGXvz7ebM7;A2YOaPrD;JGQtg2HU?r8~~G;DLcep06FVe6<~04P3q{N6&T2xN+3jO0lB%IK8u6U^i{#Hq5eKjr(_1HPVo!0sDkc$O)|hPa=ZF+ zbw~o!Bkcm@;4DS@@LcUF^^1qL%#g%HKZtmMdmR;{T?X#=Ko7I&i8~7_oag$ttkh9f zZR@s`Y(8|>08KGUVLGxBTr6yLJpJzqBHSh=n4dW#WsKe9aynkWJv8-{lQL@lvCxwiS7yH8@TC zFphh`J3wUZc;qXeSOZ^Lnl-o0Z!Y>mWw6Pe*5KQ{faHj^edlB)5lKc*Z!1CKH?qpa z@qet~Bq9q|7B7}yb6bSSnN@HTRxXxwn%3PzK-mp_7`*A)^2EMV8DHnOmVISeG97$> z>;B6s9biA8K;3LLPxF5hjNy3Q=M_?3oO z52;RhxWmob7868hvmQqeGPmASzmfa0ixCN2nnfQh(R3n<{weq~dn;OiO1K$Haui&- zPp%kE-b2FqnE#D=R>OmFwzz!Tj_cuhura=A{?)x|h=e0dsjSJ&q!Fk3CaEPMFJVxa zfW9orC0x^~L~RK#`!LDP`cJowZIJcSsSF!9+ZSQRmTK5aC>R)6*w4>jSy@?Dw%1;H zi_{t?RpYJ4fn_h&WTShnj?9$hxY=cBID0?2*0qtlwonws5-O#5upFvoV;*8F=H{qO z;La(C>l@pf+VWhJLNF`ZgYC9T_!)a{=TXst|3(4 zzP|28aq>+RoXm+}N*iV~q6J(UbK3Xg+kkq3PsuK&qhsc;$o{B+xvas}z~0&GY%Anr ztKVT=iR;^W?>$J^ah;B>q1Q>j2R}^9c9a zQUN3}SjS`LF^e-*@Yp!sfmFsk-idKl4Kp7{=M&rBB2}7LY22^)=?GhN} zi0=ZKxGON*18PUPvYV$b*zf?9UGq?WtJwfwE*0TE;1Y?nyG1S61lCDIC7@YBvPR2h zjUhlZ0aEPYZaMo=@fc&=!IL&m@j88iiK11rKz>iB^!N==Nn9LrkniNdTgNmT#TO#9zy7xmgxgFsKi;k8K~n#|Ft&MeZ-wa1bX@95*s9~6^FiCMwG=V=%%h1Kp z1PfaP#>`K`+&}}9Hs>;c(a3hl|u_ z7MAau*-Ev=m8_gr@4u3~L3r8HRP=vd22?;k;kWf@mWA>~z6azff zZDgCGTHZ+&3>k|;e?799w%#`p~6 zub$-gxr(``Ic;SQI{68VAw$)|P*ko`V{7!% zO^=aC=y|KdHGe^&Bs%@oLsXg9BmRcOR|)#y#=j+SF0jG_Yp~DF%yp{_pJ%!( z=I)dY*lOCqINMEpq?qEHScxDQsxnHk)$<+5N%7{V)mhImAkVz(NYE{gg>R&6KG(l$ zu1C`CS|_0Tbba-PAcG}Cq9R%z!;f+^R@tk!+Xd0|3p`q1ctT>9ALm=pb^CSDwa$SU z=Zp(Rx7u??z7eNEVRX&bZ<-VY3>dQ$ed8;YXlqDi^AWHV7y30*s>JEAl8lB#SMstX z-E)`1GoAHg#&iG90oSCY7pHev|NDtG)T&G78;5h>4a^5`_njbF$`)Vb{?+$pfX`W2 zF)4*WRwzUfu{`02%gog^3w#R_N8JtHn#-EBdXM+>Rr_5fKKl%-OcWGTeI%lv$73+i z=YRe>>{1^mCDg{&TnS^q5QTvas(g#pAs%n;$PwKll$?iZBNFb$Aqh`_{w0 zajFbZ{1l3&kR^VakjB=_%t%RrrzxRP!Y7G}fVrgAjtnE=DMW@WIs?0*!iIHGt~2Q8 z6$W{}l36(2;95*X#Un@?V{mx7JulL>ZHZruB$ax?+3v4OfO87P`!qqb;+VwTq{`mJ z08`Ww=>xZKPd9@tJbFgGzCCb+0Prj9YykYr`OF-1Az2nNz|-sC&w59?_pGe6ctr?Tl<|culd2!!&riyltiJXcwpsVFcwYC_E$@d1 zSEi@ST!WJ~UF(&BHge@CL}}E~iee$;LxU8kB=1e!)LOs^7KEB8#nq$K)Z@)R^BtA$ z{Igv|O4)EbhLll~(z7XKgDgn-X#F|^z6(HGT;IY#UqdT-w%p^D!XK8#f2n{10J@gr zB?cTBZTRLMPY0g$uN)R&H3cL{k*FWGIMa0Zzo;=m%g(+zJxouvT#E9JAwOuETn=}- z0ZQitfO*1@tx8K3O;kFK z!?1AOPF?)od`oMwUGFhmtxttFpKjFYo|w`b8xmFz*Rx?ioXq0mE&#U_}@EDWiWXqa}5)+|dHPUbVn+d?pfB(Fx1sIu{v z9!`%a1jvC0(?i9F`53??`pU5soykQP ztQ`K?qM4|aDotfwO46{APL?>y>5+JgRys}=ERt{VVEB--z`m|jw~kIk$i&0a)6kTw zEo)$JV6<t2LA-(mZ(^!{9w1J`O)8C~(W*Dv=4dpd_f z$HLB}#6NU|OWhY|c(eeM0b#$JYt|F+BR4ztH5M!g9^~BFRj>MJeGkDp2CaCj#dSQc zP#8qWi{L+Oel^qEp}HU1EPdZYLFK4Up(QJr+p3M$bg~*UKa2z5TkT7ck2IsyT}!^j z{(uw~Bp^YQ+)>^nubZnSqePR-IHGWzZ1Y_vv^1LmYnhn%gyw&se@6>iG_E>rDTX^TYB`B_O4uy+4^m6G7eS zT4hhnfWWWYda2?J7e71Jx~ohGH&>f)8D{q3+2sD_jh>)8k+`7G%27lv6=l9nCV^af zUX5;Jh_Zz28xo5|#kV0<|D#!?bGD=INn!kKhpKJG28JKF=~RW^M8=iJgo2V#MPFFb ze>&MmZZlt*2|UStF}<`R1`EO@VB`qOwo$x0g1iex(aV50&yVvYA#-4Os=Xcf`eU31 zRU1b*1=^G6Y zXD=zn05feQ<-nBcCaSG^-e>4igxAGqHZaK58@^bRQ80d`8S(V9<#=-QSDq2^d5hJE z)wWgn+Rydf{ntjg>bk4comQ{Cm^5v{7V-pZLu|+qwiZm1~%H2}Q zEMK{HLC zb1yQ*`3Nro7as*NGq_Ru;O~eNuf{Bk5MDb$pFjfipHrTIxJhKIm!oGV-|wWs&v#4r zr=Q&zd4=zg$|&5J|4#k>vq6=E1;FtSa>4&N*;!RlSxHFlQ~g%f{3i-6+aGKpW+G;m zPn0VMC(D18zdtAcDu4fN_z(H}^P&HZ{LRey2a?Fb&`H_Ug^JPE($3ZS?~SK_XxpYv zrY4LIPL{T&|0K;a|7$Ape@y)E#aYgO5oiCCF$52X;B@=r55^Dx@-K{`wu8JDxQV2^ zXpKX^9_rgok;@L!4|io?2n=y?j*Bvn!`Gnk!pYkh6mWQRS#S|)X=m_}jfKL={Xt&v z?ZK}x3mbzdM3fT5oB~{|P2ZH{``SmD;@z$u{f3NL9^FmOKx#3-MbIHU61msH*3jgm)^^dRr zkAueg7oP^;&&mH2FIiMxLQ_Kevr@%0{>i7o@`q7_i~SQ21YiSvaglmgfJ_Zv8hi#^>mt%NOu>Q@}r#=ies&_vQO{ zhr&PllmAh^&R6d7E)Pp?_pY%_0H8>!_dgj~Z5jvCfpDkod8`^~pBco@1hkKQK_4A8 zK%lgwMOpGLUXjjzLZ*slUgD8KVGSig1;xc}LB@7gie^qmxk2_ulHyi&M$idKMM&9s z*%?|&<)uH18YAmBn^uY49LV><=bL}TrM)lJ{v z-H__0L$k4?r=g{R(JlTZXYk^Hd?u6Mwdd%a|7F2F?}B%Gs6^)Y{OtT!`r5{(9_op{ zGG*y=*79kK#KXnz`L>j_--sXPhb>Rjd(7L0UEKTFrt+^jx+emsz^9iv0SVEL9$IwY z_&56Z&1T2;<-2jaxaQR9gZr(xcZ8?S9rN$auk3mzOk%~_HQH5@O$w}cEy4k=q7KT+ z?&j{45;xzbp&Jl#(z$fc_uRKwxB1$8Fr6<`X3Rm?Sn_-^ml^E17*fZ52&Si!JUjx@ z(*l8k_8c4f{@s%JSQPhb|)|F_J6KNiYAd6!t({)*Z8WDb~p-v0D1{f9B>{{>>;FX=7+VK(}!vq+Nh zPgjvVqr%@EMe6@}?Y|)g4F3yN!1@#ZWBWJ!&mS=`&W!(T5&Hc8KhX#OymVRqe#-dI zgY%c)tN(dA4B+n>Gyhn+Rhp10D$7gV1EU+bv=-GtSDSs+gIh+#Mi=Y7x9p9EK#+q$Bx*K_#tUf)D}~I%gXv||sm^1>Js;S^*YBPCZx>Z}OLcUqho7M^ zEj@2%_JrUnjHpsXNVmG}ZpR0vaTknw9hS{I=Ctp8zygyYA6c`Im3};*-Oy{izwOf? z3kjzbAAtaKF(@!#6Kb~FcqllS=ZAZ^mTY!c9+lHYSa_7 z$)1R3#~B6(W@uULzApCn3RcR7p(Cqhb&_=U7j^N%dov(F!^B42!nA1N?jEBP$S97n zTVo7^dwHhSwW$T z-WAc6zpFs8CF2NoNn|K~CU09I{gUXCt~1#~gswo7ZGM+RB5Sq(ya=eCRrJVTuGJeV zd6RXP(T`Y)T(e-V`lio9a53po+WyeKh52l9_w?;zv^(uN_IKL)Mb`WMn?77ED=TvY z8;>agzr%emA%tfq&+F#RZ@BwigS@^b5eh_2{z21G(C96U2|6Wu@KkGhdH5Va<6T$x zg=-gDtG4>Rzok;yH^G^YYRuPH!OxpgP73ev` zdkZL|AQ`3!pdk+Lx4J1Pa($Ndzv(nl^(-xy56g_3(&y_64FYk4%*PpU10R zB$yeBbI5Bmb?)*{kQR`6wRZA>a~4r7P>WJ-8?+^6@)#X;2X}hep9SEQJ(XP85cWk~`sgZq2pN+!GX|C_w>Awz()Zj&ibtL3HI_3l*!P|>>!NMj9 zX691MCpsO^5wjZyYVw>x;e?C(Zp~%5qwHpmJ%pwav~-flqxxSrBmHuVHU0r`QiWn# z8SarX`6hvb53xRypxj)(CL}G+(}*p{1rcX4)ETEnmC%lRNM=fj8ElGN2D=z)p`JD? zOw4iCeVM6Mm_>GeIHu4qThAGl%Sda1eDljCy8b7(dhrNhl&}zmZ2SOEhd?t?!Ur!| zM(t(ir_#8$DW=bdLU3Gf`VrEADjMPaI)$h|-4i(#J@iGv_X@SOe}m8)7V%dt-)A4b zOS@!-ce;qtTvGEBZfZ?lyqFPP@55^Dtsu_6umJZ>!PEx2v_y|EK8~k2C6HfhLf*7? zU7M#A`EMgB@`T=<3o#VlnMTFro5l+4I}nIS(MN+8Nv{eSi1O4caE0N5(n6=kA%H@1 zP=*F2Z$R(rh~SA3Y+16nU+Xl|RP&3lUev3G2|tYD3W#=0KN|bU0poCyJMzmbGs|Hu zn7vs`Ko)xi*K5En6<%=HrQ)8Dt#f4wzFcqLrPVe!#}LLP5asFtQi}rOAt$CmjEn5t zl@b0mx5-LHxpIUZZm+kP0^yqb1wt$+R|*$~)*rq2mH-@&^RjA9Mm>=t=%*4dFHfy= zMdlA!+jZXz^76bUR*Jy^Y9mO_KnYn<>CY?nq7Vr48w3@O<;KS2xB+BNl)0YlZ918o zmx~@;Uu(rhzOrv&7Ao;3u^nvSwfml4HExor1t*Ld2h}{K=Q#+>#8M+@4`EvHZY6Z& zRj_UhZtD4GCN}%PYj=HUOo$m&>t~9Ui7@8!EiaevYXoR0LBNz5Y>`!lV@#b#+MlBn z3!o3xt8yv$ZeMW`#7%vdFl3!1v7#HB6B^M|F_*qc`f7TN%~BVCCu51n8LVtNyOTd~ z$qZnEq0b8ce!kQQB@O<@@l&a{z?N`52%WQE4Xekj zpytJD#uCB~CiMs|lXR9eL(ZY&X2d>pG>)*Zu-l6lC?o0|-wk z{!JK9fwg?-{y~~Xqf`h)K0ikuAAuiXJc>K)cG*Ujb`%`?2`Njm!$Xylq#|=PU>KJl zomjgU#2mAiV&(qK&iuB_5RrOtv_o;Fsjw6y-0<}1$pc)n>1x<0Mv8DwJ}THO0ymLD z0YJ)ZfoC53RZM(eJYrU-Oh-R1oF%r<0L^&K_hRZvYD;v-oP<0GrlA8&{3PM079|Qw zeGRcnFe47~T@ec@Ejc_%MsKF5tgNY}uXDh(X-agFE`ZXXqM!8ro7@|Em}qsaHlLQ` zu{fVpHD)hYvRlJ(HWGd3I7CJNsR81`{{F9nrm%~N@4yF=hl{x0d+rhzLqnm@<3&+) zmSz-WOpaobzlKab7fmH)8LrkFHnLkUoo4Fsdt7`#lVt^lOuTj#OYYHH(rmR4$<}0pIX-68_4; zZcg%{A|v8MNO$WDs1gw|*h+np+Z$dZI4`5)b6W<1ShVlhMw;sPlLg7Ox z%q%by4INp6$pMv)f)m`TjNP z0aDdmH?^@;Pd?;VjCuNxedaz6ISNNjF{j;!w=4u(3M%d(7o_Ffle-sZ2!f5v zu>3DMf8_iI+2!Q&qGEwDMf7Zse%GduSgEyyef) zM4ZH*It#<2lKK*|@6yKU9BZ!vWfK@P;Ao-noRM6)@-4E@g_=5+N&-wvOemH{z77}A z>k~}}6hGAO$q%uEmMotqEafG@msy4E;|&jQjaKLi!G~KjvNxA0nCKJr5+bQYv9JBT z_=;zH7{9yoqlmHfN1*nRY2cO~?ax!CT}E(YiHtiF)|2QEvZBz@zzefe($m-A0TNK3 z)1s!Slshd1?LF6T5&qd}LiH`bZSQl#P^d_P7HtAtRa3q4(n~Fj6(s9w?T~uKZXXMg z$gjTR}-SQ}XMX9Xb7n3j_*f$AvN&WWJAv#M4+D90@jMXsaSn-$W(lcByvBJ-1 zJ%R#*mIb+GW2%man4qUTS`Qm|*-F!Ch4;3xFmGenxsiiTqTfJVb^~jzt(R@?-R01N zjUzm1#R=7x3nLYPV{4_=5{thCI+S$8+=mV(W~cR(iG@;eet~$Z4DCG;iwEor=!=W6 zp{bc2QlE}#T?d|A8od@UZzowT4&yw(1|k(-%CB@)yk_ad>H*>bbkbu9eZ2Gj3$q-m z)OrvQ-jd2Ttx*1R^!-13k_tk!O)8<*#4~%;ZGHzT(L51*0U!H!n^?=--ERm~&S zf@0Q!yF1NMJQqj_HyY9Mc}}o7~`mvvk z20N_rjyWX9xLu|LS_Jym(Lsn7BDRP%g|Hk4Q7psgd_mN-VuaTwNfZ*@lsmK)MG$tV zo5IoN9oj__kZn!PLf=f_F!mG*czG%VCcm%4{^E0Vq;QNR#V9XL;)8h71Shtj@-s_p zP)^a3A{u2-z~qyV#h7tS$^>Yb8fe0-KCOaJ;?8-X({@y={?^a;Z-;z~^B4S3r7aZM zaeao=GE%oM`e~i>4QE<>WOW2JPBx>9$-q>>^b;IWP+qyJiBWu@WySMFevbSXy0&tQ)#|zI@dGA!?%XEl^J*Q6ZDuH>` zVTdPZD}eB6zaJeSCi@d(diDJI{aTv{Ju&+ea$|RCH z4YU0R1>aUK>5QP;xX7Ero(Pn9zMMn*B1%>V2>Ti7CTTZ#Cut|hC&=g9dqlK!RK>h1 zN7JMw%ZS``t~=zCnL05fi+CE=N$IXDEaz9%+$@7HJXw>Bz5O7j=VKP0#$qiCn&d%% z4^y=!7Q2VNkBWj&mU0P|ipJa}jKJ4F-LeKGH00wBcQCusitBbx+;MABFXF z@2ORwG(&Zy3d`>NP0|>$Z5o*Ba%e_rE-mG~Pb{xHiN(s>zO#z@Y57{|2*nYCv~2rg zSid_{C#LzLtOYOjxW+*aeq14w0mq^|l*^MtrVSN{FAV~#yujkbO9B0LZ}5>xcE8#s zjmA4Ila_AP`;}oVmb;~DCwtLEdkqz{}KIRtC_TK<}?NAD)r2Qj+sB+)uK%IzF6P0}$&nO3 z1kFUoN-wPa@mzM{MQ3mh|6OrMNGQc{%GDE`iwo}>>-9p;7arQa{N=jOuL_8u;CHz2 zU_p&WYtnk#q0d0w9wY-wF)v-!y=$uJlMoB43ckLwo__5E>0yy_UHa`M1}D;TejqIY zK9{0PZR~naO*#5Gv&CpDq(`*#rXZ zi80Y{PFatB zGZVK*`vBPGq!WJUp@7e8vnX^=)VF0)$H<}Y_!&9H9?k&51Cd3vgF_|=n!DlY zH&??}5EIRqLTl#6#%aZlwxs5zKfk1T83X`#<+8!+ISW5#n$7b67|~k%hXBx zsqoRVguRc8_6Q>Bh=0U_0L+u&5ma<>y5l<5S-utAF9g%d+k_c_XsXyCIHfnez}Y*{ z8$7)DK!N~G|80|E>%-+IC&i3VRr#wyY#kW@5hM#y?IaE-5n z?d;q7cm4A5?=C7nP|Pv0ry-U#JfJ~*PxPV;r7I<~6-Yg0vq(MdRJzKlIp=3+`*&tI z+lP6FJJWjp_06S2>Zl&`aCc$5+rN-o?M!$Yx;fnb%*DJY#7oZj> zE(3JbD!g&Gw^wiR)#xq`hLac0Xm}+0jC~lV*&nFcLhvGGQ&5CG(tV93P4OwVnoRTz z$Mhrc{<`sU`qfxoi(h#&TpBKJFik^1Lk;JR?g@^UY}W_|V zl_H~OC1dni}Gx}`s3 z1rFas^iV3C9DH8K5pRnZIF;tHZm*ZmbxgaZtX;K@uZfR@gL1*Vlh!mysOk6dvy_Ln zCbk-7dm*O-q$OQjc_yYYvtw?lgI#F7th~Y=nkr7op{lgHay)QOPa3xgutLu)golPj zt(}HWE1x9tX~mIvPFQ9Z5xMPTh1NR76wW>MieK!lJ|b)5Wey$4bM;PtE;?8xGZ<_a z!>L-wW{Fv%|C-B4zH~P2{N~^VY(MUnwX5?STlxeE4u63>SKaqf5YbL2?W#o?_rq(c z25cCo;iJ1S>|+_w^3ok52J$@SPLGL;Grwy!O8jG!1Qu2L2XxKR`(VO~nvpFu%owI& z3y9YCixy$EdkrGMcYCh<<-SX8t%XqRjd3U>&i3C3Cx6>e|3fWdw4Jh?$^l_ zy1nH@pTYor##c0V^5Mr+EwO?gSQG_4-Zi}N`CRf4GHOPendRdwxRXq+Bs%gBS50v_ zxl}s!N|v(9&(uAm&~mk6)$~FkQrbn;O4X7Q4%4>J%^j0s!{n5*Pg}NTvCh-vvgKVY zMT(HxcjXE=crc*|4s$b`jav*MUinTzG9>HBL#VL)!dft~$1$CHWg-+fn0FnDP1JL? ziJ%kFt|u`07sZVnAxzI)k#k7lTLyt4FfEZdBD`SBRxF&89tW6>TV(CDqABP&jOJk_ zGwPtt+R7TI(WSE^7a-ffR5NORX?&nl2YvO29liTj0X!WboFQPpBE3~Lt%pdJq6&*@ z5Ux>q9P^&DqaA|;0=9SyE%dy!(vNy*^8CAqcl;qz$7j+>w3Mv7yWbx%j_;w~fk4oR zicC@Ip?+rE(=H5Q3?crl`&pofK6_YmXASEQBCK8ht#gMwUM@!6yD}_tBjq0WYQ~T# z#f6w{7hcmd4SoU-=&vwB5+)-uRsQx=s4)58#ovHqzh0U`^ne`so*zu!tt<08zeTvn zK&MZn6z0kB-F1tux-^(D zzo$0<#<@U?_wLTae*lxP7o+gu-!7MI6)y6iYmd?&mJv78T3x;m+}j(VjKjaaFy%|S zp=1Po^LWmo*A|$jU11nv|K7BkEjQaaXpbtu=8dfQ1xIjyuK{@e1GAo_04YbDBORBO zd`v^3l~O)$fmNIOS9{NGKNUW}>*RI~GzyK3O3Yeu{LTBJCiOi+{bePuGZ9Lsw5E8< z5ISzNm9~_|z|~VCTm&_C;Mwl}b^-qg)QiPv@?D`}hwU?EqukyeJgZ>{8uIu67|SS6 zOY90yA7jzWRB?2s$R=!{?iFDiv@5LSp52-@nvk~~iCS_0tW3iiV?7_OgZtbqlo-x^ zT}Lj{I=|k4iKt85^rnWz13O;Pdh)#ZVPoY5eEu%F&M074jlSAUeaNJZtnOVe(!}x0 zHJs2ZD6Y%s`M>*x{4<@Ji~Vzp=TB+*e;UT5r70q#^hY|iippPk_J2sre?Tz+ET2#e z&j0EP`kef$E9h^-|8!dX_fU*~O=9~08H(}$h=BiJ2B1@=^-+Co_@D zj7g>+QX3M0qlq=jS)f-se(vsCS>vBvu3PDQ?{d3zxql^+)IZa{sA_?tV|bA9zPNa~ z--3kguO~D#G-S3Ixlg&zYL?YLt~H$yej~JTHKunVy!#QmM^=Ef+2@Yic1I}7%csNP zj3t8uB7iUDKu5P^vr_k!F#_i9<_djHPLFHI?Y=)0)+PH*B-(3gzt`%o^n& zVqkOD6M>&ze_2NJ1SqI2$FX_Hs@*lr4GjFlHNd9*DNL{c4nHn-|WX9mg zpj>~XhAbTkKRE@;^dQbItPuutq=xh)1wS!6>S+Z1pqCK?bA|))?+DL9G$Y!&z;t;T z@@C}wLGuvW9l`HJ7)U=N&j!Vf$eDAo#Nfy

Y~xccqPx=HfMkSCE3C5tzfUgf&nm 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ⅅ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�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 Qd&LfJlO|%bG{hjPEu%s`3G9N(kIw6!Uz*<5_ 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 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; +}