From 3964a6523a4d4b2e441bc86fd17bcf9c29bf2b45 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Thu, 9 Jun 2005 00:08:13 +0000 Subject: [PATCH] added libtomcrypt-1.03 --- Doxyfile | 2 +- TODO | 8 + build.sh | 20 + changes | 60 ++ crypt.tex | 521 +++++++++++++----- demos/encrypt.c | 4 + demos/hashsum.c | 4 + demos/multi.c | 4 + demos/small.c | 4 + demos/test.c | 27 +- demos/timing.c | 5 +- demos/tv_gen.c | 4 + doc/crypt.pdf | Bin 457121 -> 477606 bytes doc/footer.html | 6 + doc/header.html | 6 + genlist.sh | 4 + makefile | 92 +++- makefile.icc | 58 +- makefile.msvc | 51 +- makefile.shared | 88 ++- mess.sh | 4 + notes/etc/saferp_optimizer.c | 4 + notes/etc/whirlgen.c | 4 + notes/etc/whirltest.c | 4 + notes/tech0005.txt | 18 + parsenames.pl | 4 + run.sh | 35 ++ src/ciphers/aes/aes.c | 6 +- src/ciphers/aes/aes_tab.c | 4 + src/ciphers/anubis.c | 4 + src/ciphers/blowfish.c | 4 + src/ciphers/cast5.c | 4 + src/ciphers/des.c | 4 + src/ciphers/khazad.c | 4 + src/ciphers/noekeon.c | 4 + src/ciphers/rc2.c | 4 + src/ciphers/rc5.c | 4 + src/ciphers/rc6.c | 4 + src/ciphers/safer/safer.c | 4 + src/ciphers/safer/safer_tab.c | 4 + src/ciphers/safer/saferp.c | 4 + src/ciphers/skipjack.c | 4 + src/ciphers/twofish/twofish.c | 6 +- src/ciphers/twofish/twofish_tab.c | 4 + src/ciphers/xtea.c | 4 + src/encauth/ccm/ccm_memory.c | 5 +- src/encauth/ccm/ccm_test.c | 4 + src/encauth/eax/eax_addheader.c | 4 + src/encauth/eax/eax_decrypt.c | 4 + src/encauth/eax/eax_decrypt_verify_memory.c | 4 + src/encauth/eax/eax_done.c | 4 + src/encauth/eax/eax_encrypt.c | 4 + .../eax/eax_encrypt_authenticate_memory.c | 4 + src/encauth/eax/eax_init.c | 8 +- src/encauth/eax/eax_test.c | 4 + src/encauth/gcm/gcm_add_aad.c | 9 +- src/encauth/gcm/gcm_add_iv.c | 4 + src/encauth/gcm/gcm_done.c | 4 + src/encauth/gcm/gcm_gf_mult.c | 5 + src/encauth/gcm/gcm_init.c | 71 ++- src/encauth/gcm/gcm_memory.c | 4 + src/encauth/gcm/gcm_process.c | 4 + src/encauth/gcm/gcm_reset.c | 4 + src/encauth/gcm/gcm_test.c | 5 +- src/encauth/ocb/ocb_decrypt.c | 4 + src/encauth/ocb/ocb_decrypt_verify_memory.c | 4 + src/encauth/ocb/ocb_done_decrypt.c | 4 + src/encauth/ocb/ocb_done_encrypt.c | 4 + src/encauth/ocb/ocb_encrypt.c | 4 + .../ocb/ocb_encrypt_authenticate_memory.c | 4 + src/encauth/ocb/ocb_init.c | 4 + src/encauth/ocb/ocb_ntz.c | 4 + src/encauth/ocb/ocb_shift_xor.c | 4 + src/encauth/ocb/ocb_test.c | 4 + src/encauth/ocb/s_ocb_done.c | 4 + src/hashes/chc/chc.c | 4 + src/hashes/helper/hash_file.c | 4 + src/hashes/helper/hash_filehandle.c | 4 + src/hashes/helper/hash_memory.c | 4 + src/hashes/helper/hash_memory_multi.c | 4 + src/hashes/md2.c | 12 +- src/hashes/md4.c | 10 +- src/hashes/md5.c | 12 +- src/hashes/rmd128.c | 10 +- src/hashes/rmd160.c | 11 +- src/hashes/sha1.c | 11 +- src/hashes/sha2/sha224.c | 10 +- src/hashes/sha2/sha256.c | 12 +- src/hashes/sha2/sha384.c | 12 +- src/hashes/sha2/sha512.c | 12 +- src/hashes/tiger.c | 12 +- src/hashes/whirl/whirl.c | 10 +- src/hashes/whirl/whirltab.c | 4 + src/headers/ltc_tommath.h | 4 + src/headers/tomcrypt.h | 8 +- src/headers/tomcrypt_argchk.h | 4 + src/headers/tomcrypt_cfg.h | 4 + src/headers/tomcrypt_cipher.h | 17 +- src/headers/tomcrypt_custom.h | 54 +- src/headers/tomcrypt_hash.h | 43 +- src/headers/tomcrypt_mac.h | 4 + src/headers/tomcrypt_macros.h | 12 +- src/headers/tomcrypt_misc.h | 4 + src/headers/tomcrypt_pk.h | 133 ++++- src/headers/tomcrypt_pkcs.h | 32 +- src/headers/tomcrypt_prng.h | 4 + src/headers/tommath_class.h | 4 + src/headers/tommath_superclass.h | 10 +- src/mac/hmac/hmac_done.c | 4 + src/mac/hmac/hmac_file.c | 4 + src/mac/hmac/hmac_init.c | 4 + src/mac/hmac/hmac_memory.c | 4 + src/mac/hmac/hmac_memory_multi.c | 4 + src/mac/hmac/hmac_process.c | 4 + src/mac/hmac/hmac_test.c | 4 + src/mac/omac/omac_done.c | 4 + src/mac/omac/omac_file.c | 4 + src/mac/omac/omac_init.c | 6 +- src/mac/omac/omac_memory.c | 4 + src/mac/omac/omac_memory_multi.c | 4 + src/mac/omac/omac_process.c | 9 +- src/mac/omac/omac_test.c | 4 + src/mac/pelican/pelican.c | 16 + src/mac/pelican/pelican_memory.c | 4 + src/mac/pelican/pelican_test.c | 4 + src/mac/pmac/pmac_done.c | 4 + src/mac/pmac/pmac_file.c | 4 + src/mac/pmac/pmac_init.c | 4 + src/mac/pmac/pmac_memory.c | 4 + src/mac/pmac/pmac_memory_multi.c | 4 + src/mac/pmac/pmac_ntz.c | 4 + src/mac/pmac/pmac_process.c | 4 + src/mac/pmac/pmac_shift_xor.c | 4 + src/mac/pmac/pmac_test.c | 4 + src/misc/base64/base64_decode.c | 4 + src/misc/base64/base64_encode.c | 4 + src/misc/burn_stack.c | 4 + src/misc/crypt/crypt.c | 10 + src/misc/crypt/crypt_argchk.c | 4 + src/misc/crypt/crypt_cipher_descriptor.c | 4 + src/misc/crypt/crypt_cipher_is_valid.c | 4 + src/misc/crypt/crypt_find_cipher.c | 4 + src/misc/crypt/crypt_find_cipher_any.c | 4 + src/misc/crypt/crypt_find_cipher_id.c | 4 + src/misc/crypt/crypt_find_hash.c | 4 + src/misc/crypt/crypt_find_hash_any.c | 4 + src/misc/crypt/crypt_find_hash_id.c | 4 + src/misc/crypt/crypt_find_prng.c | 4 + src/misc/crypt/crypt_hash_descriptor.c | 4 + src/misc/crypt/crypt_hash_is_valid.c | 4 + src/misc/crypt/crypt_prng_descriptor.c | 4 + src/misc/crypt/crypt_prng_is_valid.c | 4 + src/misc/crypt/crypt_register_cipher.c | 4 + src/misc/crypt/crypt_register_hash.c | 4 + src/misc/crypt/crypt_register_prng.c | 4 + src/misc/crypt/crypt_unregister_cipher.c | 4 + src/misc/crypt/crypt_unregister_hash.c | 4 + src/misc/crypt/crypt_unregister_prng.c | 4 + src/misc/error_to_string.c | 4 + src/misc/mpi/is_prime.c | 4 + src/misc/mpi/mpi.c | 4 + src/misc/mpi/mpi_to_ltc_error.c | 4 + src/misc/mpi/rand_prime.c | 4 + src/misc/pkcs5/pkcs_5_1.c | 4 + src/misc/pkcs5/pkcs_5_2.c | 4 + src/misc/zeromem.c | 4 + src/modes/cbc/cbc_decrypt.c | 4 + src/modes/cbc/cbc_done.c | 4 + src/modes/cbc/cbc_encrypt.c | 4 + src/modes/cbc/cbc_getiv.c | 4 + src/modes/cbc/cbc_setiv.c | 4 + src/modes/cbc/cbc_start.c | 4 + src/modes/cfb/cfb_decrypt.c | 4 + src/modes/cfb/cfb_done.c | 4 + src/modes/cfb/cfb_encrypt.c | 4 + src/modes/cfb/cfb_getiv.c | 4 + src/modes/cfb/cfb_setiv.c | 4 + src/modes/cfb/cfb_start.c | 4 + src/modes/ctr/ctr_decrypt.c | 4 + src/modes/ctr/ctr_done.c | 4 + src/modes/ctr/ctr_encrypt.c | 6 +- src/modes/ctr/ctr_getiv.c | 4 + src/modes/ctr/ctr_setiv.c | 4 + src/modes/ctr/ctr_start.c | 20 +- src/modes/ecb/ecb_decrypt.c | 4 + src/modes/ecb/ecb_done.c | 6 +- src/modes/ecb/ecb_encrypt.c | 4 + src/modes/ecb/ecb_start.c | 4 + src/modes/ofb/ofb_decrypt.c | 4 + src/modes/ofb/ofb_done.c | 4 + src/modes/ofb/ofb_encrypt.c | 4 + src/modes/ofb/ofb_getiv.c | 4 + src/modes/ofb/ofb_setiv.c | 4 + src/modes/ofb/ofb_start.c | 4 + src/pk/asn1/der/bit/der_decode_bit_string.c | 101 ++++ src/pk/asn1/der/bit/der_encode_bit_string.c | 87 +++ src/pk/asn1/der/bit/der_length_bit_string.c | 54 ++ src/pk/asn1/der/der_get_multi_integer.c | 67 --- src/pk/asn1/der/der_put_multi_integer.c | 67 --- src/pk/asn1/der/ia5/der_decode_ia5_string.c | 95 ++++ src/pk/asn1/der/ia5/der_encode_ia5_string.c | 84 +++ src/pk/asn1/der/ia5/der_length_ia5_string.c | 194 +++++++ .../der/{ => integer}/der_decode_integer.c | 68 ++- .../der/{ => integer}/der_encode_integer.c | 87 +-- .../der/{ => integer}/der_length_integer.c | 36 +- .../der_decode_object_identifier.c | 99 ++++ .../der_encode_object_identifier.c | 103 ++++ .../der_length_object_identifier.c | 84 +++ .../asn1/der/octet/der_decode_octet_string.c | 90 +++ .../asn1/der/octet/der_encode_octet_string.c | 85 +++ .../asn1/der/octet/der_length_octet_string.c | 53 ++ .../der_decode_printable_string.c | 95 ++++ .../der_encode_printable_string.c | 84 +++ .../der_length_printable_string.c | 166 ++++++ .../asn1/der/sequence/der_decode_sequence.c | 215 ++++++++ .../der/sequence/der_decode_sequence_multi.c | 120 ++++ .../asn1/der/sequence/der_encode_sequence.c | 265 +++++++++ .../der/sequence/der_encode_sequence_multi.c | 121 ++++ .../asn1/der/sequence/der_length_sequence.c | 144 +++++ .../short_integer/der_decode_short_integer.c | 68 +++ .../short_integer/der_encode_short_integer.c | 97 ++++ .../short_integer/der_length_short_integer.c | 69 +++ src/pk/dh/dh.c | 4 + src/pk/dh/dh_sys.c | 4 + src/pk/dsa/dsa_export.c | 47 +- src/pk/dsa/dsa_free.c | 4 + src/pk/dsa/dsa_import.c | 68 ++- src/pk/dsa/dsa_make_key.c | 4 + src/pk/dsa/dsa_sign_hash.c | 97 ++-- src/pk/dsa/dsa_verify_hash.c | 128 +++-- src/pk/dsa/dsa_verify_key.c | 4 + src/pk/ecc/ecc.c | 385 ++++++------- src/pk/ecc/ecc_sys.c | 436 ++++++--------- src/pk/packet_store_header.c | 4 + src/pk/packet_valid_header.c | 4 + src/pk/pkcs1/pkcs_1_i2osp.c | 4 + src/pk/pkcs1/pkcs_1_mgf1.c | 4 + src/pk/pkcs1/pkcs_1_oaep_decode.c | 24 +- src/pk/pkcs1/pkcs_1_oaep_encode.c | 34 +- src/pk/pkcs1/pkcs_1_os2ip.c | 4 + src/pk/pkcs1/pkcs_1_pss_decode.c | 15 +- src/pk/pkcs1/pkcs_1_pss_encode.c | 30 +- src/pk/pkcs1/pkcs_1_v15_es_decode.c | 74 --- src/pk/pkcs1/pkcs_1_v15_es_encode.c | 69 --- src/pk/pkcs1/pkcs_1_v15_sa_decode.c | 91 --- src/pk/pkcs1/pkcs_1_v15_sa_encode.c | 84 --- src/pk/rsa/rsa_decrypt_key.c | 4 + src/pk/rsa/rsa_encrypt_key.c | 4 + src/pk/rsa/rsa_export.c | 64 +-- src/pk/rsa/rsa_exptmod.c | 4 + src/pk/rsa/rsa_free.c | 4 + src/pk/rsa/rsa_import.c | 76 +-- src/pk/rsa/rsa_make_key.c | 4 + src/pk/rsa/rsa_sign_hash.c | 4 + src/pk/rsa/rsa_v15_decrypt_key.c | 73 --- src/pk/rsa/rsa_v15_encrypt_key.c | 68 --- src/pk/rsa/rsa_v15_sign_hash.c | 66 --- src/pk/rsa/rsa_v15_verify_hash.c | 81 --- src/pk/rsa/rsa_verify_hash.c | 4 + src/prngs/fortuna.c | 4 + src/prngs/rc4.c | 4 + src/prngs/rng_get_bytes.c | 4 + src/prngs/rng_make_prng.c | 4 + src/prngs/sober128.c | 4 + src/prngs/sober128tab.c | 4 + src/prngs/sprng.c | 4 + src/prngs/yarrow.c | 5 + testbuild.sh | 11 + testme.sh | 52 ++ testprof/base64_test.c | 6 +- testprof/cipher_hash_test.c | 4 + testprof/der_tests.c | 236 ++++++-- testprof/dh_tests.c | 20 +- testprof/dsa_test.c | 15 +- testprof/ecc_test.c | 195 ++++--- testprof/mac_test.c | 4 + testprof/makefile.icc | 2 +- testprof/modes_test.c | 24 +- testprof/pkcs_1_test.c | 46 +- testprof/rsa_test.c | 210 ++++--- testprof/store_test.c | 40 +- testprof/test.c | 4 + testprof/test.key | 15 + testprof/tomcrypt_test.h | 4 + testprof/x86_prof.c | 110 ++-- 285 files changed, 5920 insertions(+), 2287 deletions(-) create mode 100644 build.sh create mode 100644 mess.sh create mode 100644 notes/tech0005.txt create mode 100644 run.sh create mode 100644 src/pk/asn1/der/bit/der_decode_bit_string.c create mode 100644 src/pk/asn1/der/bit/der_encode_bit_string.c create mode 100644 src/pk/asn1/der/bit/der_length_bit_string.c delete mode 100644 src/pk/asn1/der/der_get_multi_integer.c delete mode 100644 src/pk/asn1/der/der_put_multi_integer.c create mode 100644 src/pk/asn1/der/ia5/der_decode_ia5_string.c create mode 100644 src/pk/asn1/der/ia5/der_encode_ia5_string.c create mode 100644 src/pk/asn1/der/ia5/der_length_ia5_string.c rename src/pk/asn1/der/{ => integer}/der_decode_integer.c (54%) rename src/pk/asn1/der/{ => integer}/der_encode_integer.c (55%) rename src/pk/asn1/der/{ => integer}/der_length_integer.c (60%) create mode 100644 src/pk/asn1/der/object_identifier/der_decode_object_identifier.c create mode 100644 src/pk/asn1/der/object_identifier/der_encode_object_identifier.c create mode 100644 src/pk/asn1/der/object_identifier/der_length_object_identifier.c create mode 100644 src/pk/asn1/der/octet/der_decode_octet_string.c create mode 100644 src/pk/asn1/der/octet/der_encode_octet_string.c create mode 100644 src/pk/asn1/der/octet/der_length_octet_string.c create mode 100644 src/pk/asn1/der/printable_string/der_decode_printable_string.c create mode 100644 src/pk/asn1/der/printable_string/der_encode_printable_string.c create mode 100644 src/pk/asn1/der/printable_string/der_length_printable_string.c create mode 100644 src/pk/asn1/der/sequence/der_decode_sequence.c create mode 100644 src/pk/asn1/der/sequence/der_decode_sequence_multi.c create mode 100644 src/pk/asn1/der/sequence/der_encode_sequence.c create mode 100644 src/pk/asn1/der/sequence/der_encode_sequence_multi.c create mode 100644 src/pk/asn1/der/sequence/der_length_sequence.c create mode 100644 src/pk/asn1/der/short_integer/der_decode_short_integer.c create mode 100644 src/pk/asn1/der/short_integer/der_encode_short_integer.c create mode 100644 src/pk/asn1/der/short_integer/der_length_short_integer.c delete mode 100644 src/pk/pkcs1/pkcs_1_v15_es_decode.c delete mode 100644 src/pk/pkcs1/pkcs_1_v15_es_encode.c delete mode 100644 src/pk/pkcs1/pkcs_1_v15_sa_decode.c delete mode 100644 src/pk/pkcs1/pkcs_1_v15_sa_encode.c delete mode 100644 src/pk/rsa/rsa_v15_decrypt_key.c delete mode 100644 src/pk/rsa/rsa_v15_encrypt_key.c delete mode 100644 src/pk/rsa/rsa_v15_sign_hash.c delete mode 100644 src/pk/rsa/rsa_v15_verify_hash.c create mode 100644 testbuild.sh create mode 100644 testme.sh create mode 100644 testprof/test.key diff --git a/Doxyfile b/Doxyfile index d42b778d..9e2eccc8 100644 --- a/Doxyfile +++ b/Doxyfile @@ -23,7 +23,7 @@ PROJECT_NAME = LibTomCrypt # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 1.02 +PROJECT_NUMBER = 1.03 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. diff --git a/TODO b/TODO index 8b137891..c93ef6f4 100644 --- a/TODO +++ b/TODO @@ -1 +1,9 @@ +Things ideal for 1.04 + +- ASN.1 SET and UTCtime +- Start working towards making the bignum code plugable +- Add OID for ciphers and PRNGs to their descriptors +- Document the ASN.1 a bit more verbosely ;-) +- Some ASN.1 demo programs [for now read the source code!] +- Look into other ECC point muls and consider a "precomp" interface diff --git a/build.sh b/build.sh new file mode 100644 index 00000000..6867c2a9 --- /dev/null +++ b/build.sh @@ -0,0 +1,20 @@ +#!/bin/bash +echo "$1 ($2, $3)..." +make clean 1>/dev/null 2>/dev/null +echo -n "building..." +CFLAGS="$2 $CFLAGS" make -f $3 test tv_gen 1>gcc_1.txt 2>gcc_2.txt || (echo "build $1 failed see gcc_2.txt for more information" && cat gcc_2.txt && exit 1) +echo -n "testing..." +if [ -a test ] && [ -f test ] && [ -x test ]; then + ((./test >test_std.txt 2>test_err.txt && ./tv_gen > tv.txt) && echo "$1 test passed." && echo "y" > testok.txt) || (echo "$1 test failed" && cat test_err.txt && exit 1) + if find *_tv.txt -type f 1>/dev/null 2>/dev/null ; then + for f in *_tv.txt; do if (diff $f notes/$f) then true; else (echo "tv_gen $f failed" && rm -f testok.txt && exit 1); fi; done + fi +fi +if [ -a testok.txt ] && [ -f testok.txt ]; then + exit 0 +fi +exit 1 + +# $Source: /cvs/libtom/libtomcrypt/build.sh,v $ +# $Revision: 1.4 $ +# $Date: 2005/05/05 14:49:27 $ diff --git a/changes b/changes index 54480cf3..5e56f67d 100644 --- a/changes +++ b/changes @@ -1,3 +1,58 @@ +June 9th, 2005 +v1.03 + -- Users may want to note that on a P4/GCC3.4 platform "-fno-regmove" greatly accelerates the ciphers/hashes. + -------------------------------------------------------------------------------------------------------------- + -- Made it install the testing library in the icc/static makefiles + -- Found bug in ccm_memory.c which would fail to compile when LTC_CLEAN_STACK was enabled + -- Simon Johnson proposed I do a fully automated test suite. Hence "testme.sh" was born + -- Added LTC_NO_TEST which forces test vectors off (regardless of what tomcrypt_custom.h has) + -- Added LTC_NO_TABLES which disables large tables (where possible, regardless of what tomcrypt_custom.h has) + -- New test script found a bug in twofish.c when TABLES was disabled. Yeah testing! + -- Added a LTC_FAST specific test to the testing software. + -- Updated test driver to actually halt on errors and just print them out (useful for say... automated testing...) + -- Added bounds checking to Pelican MAC + -- Added BIT and OCTET STRING to the ASN.1 side of things. + -- Pekka Riikonen pointed out that my ctr_start() function should accept the counter mode. + -- Cleaned up warnings in testprof + -- Removed redundant mu and point mapping in ecc_verify_hash() so it should be a bit faster now + -- Pekka pointed out that the AES key structure was using 32 bytes more than it ought to. + -- Added quick defines to remove entire classes of algorithms. This makes it easier if you want to build with just + one algorithm (say AES or SHA-256). Defines are LTC_NO_CIPHERS, LTC_NO_MODES, LTC_NO_HASHES, LTC_NO_MACS, + LTC_NO_PRNGS, LTC_NO_PK, LTC_NO_PKCS + -- As part of the move for ECC to X9.62 I've changed the signature algorithm to EC DSA. No API changes. + -- Pekka helped me clean up the PKCS #1 v2.1 [OAEP/PSS] code + -- Wrote new DER SEQUENCE coder/decoder + -- RSA, DSA and ECDSA now use the DER SEQUENCE code (saves a lot of code!) + -- DSA output is now a DER SEQUENCE (so not compatible with previous releases). + -- Added Technote #5 which shows how to build LTC on an AMD64 to have a variety of algorithms in only ~80KB of code. + -- Changed temp variable in LOAD/STORE macros to "ulong32" for 32-bit ops. Makes it safer on Big endian platforms + -- Added INSTALL_GROUP and INSTALL_USER which you can specify on the build to override the default USER/GROUP the library + is to be installed as + -- Removed "testprof" from the default build. + -- Added IA5, NULL and Object Identifier to the list of ASN.1 DER supported types + -- The "no_oops" target (part of zipup) now scans for non-cvs files. This helps prevent temp/scratch files from appearing in releases ;-) + -- Added DERs for missing hashes, but just the OID not the PKCS #1 v1.5 additions. + -- Removed PKCS #1 v1.5 from the tree since it's taking up space and you ought to use v2.1 anyways + -- Kevin Kenny pointed out a few stray // comments + -- INTEGER code properly supports negatives and zero padding [Pekka!] + -- Sorted asn1/der/ directory ... less of a mess now ;-) + -- Added PRINTABLE STRING type + -- Removed ECC-160 as it wasn't a standard curve + -- Made ecc_shared_secret() ANSI X9.63 compliant + -- Changed "printf" to "fprintf(stderr, " in the testbench... ;-) + -- Optimized the GCM table creation. On 1KB packets [with key switching] the new GCM is 12.7x faster than before. + -- Changed OID representation for hashes to be just a list of unsigned longs (so you can compare against them nicely after decoding a sequence) + -- ECC code now uses Montgomery reduction ... it's even faster [ECC-256 make key down from 37.4M to 4.6M cycles on an Athlon64] + -- Added SHORT_INTEGER so users can easily store DER encoded INTEGER types without using the bignum math library + -- Fixed OMAC code so that with LTC_FAST it doesn't require that LTC_FAST_TYPE divides 16 [it has to divide the block size instead] + -- ECC key export is now a simple [and documented] SEQUENCE, the "encrypt_key" also uses a new SEQUENCE format. + -- Thanks goes to the following testers + Michael Brown - Solaris 10/uSPARCII + Richard Outerbridge - MacOS + Martin Carpenter - Solaris 8/uSPARCII [Thanks for cleaning up the scripts] + Greg Rose - ... SunOS 5.8/SPARC [... what's with the SPARCS?] + Matt Johnston - MacOS X [Thanks for pointing out GCC 4 problems with -Os] + April 19th, 2005 v1.02 -- Added LTC_TEST support to gcm_test() @@ -1243,3 +1298,8 @@ v0.02 -- Changed RC5 to only allow 12 to 24 rounds -- Added more to the manual. v0.01 -- We will call this the first version. + +/* $Source: /cvs/libtom/libtomcrypt/changes,v $ */ +/* $Revision: 1.92 $ */ +/* $Date: 2005/06/09 01:06:59 $ */ + diff --git a/crypt.tex b/crypt.tex index c785e83a..9e17fe29 100644 --- a/crypt.tex +++ b/crypt.tex @@ -47,7 +47,7 @@ \def\gap{\vspace{0.5ex}} \makeindex \begin{document} -\title{LibTomCrypt \\ Version 1.02} +\title{LibTomCrypt \\ Version 1.03} \author{Tom St Denis \\ \\ tomstdenis@gmail.com \\ @@ -57,7 +57,7 @@ http://libtomcrypt.org This text and source code library are both hereby placed in the public domain. This book has been formatted for A4 paper using the \LaTeX{} {\em book} macro package. -\vspace{10cm} +\vspace{15cm} \begin{flushright}Open Source. Open Academia. Open Minds. @@ -771,13 +771,19 @@ other modes. \index{OFB Mode} \index{CFB Mode} The library provides simple support routines for handling CBC, CTR, CFB, OFB and ECB encoded messages. Assuming the mode you want is XXX there is a structure called ``symmetric\_XXX'' that will contain the information required to -use that mode. They have identical setup routines (except ECB mode for obvious reasons): +use that mode. They have identical setup routines (except CTR and ECB mode): \index{ecb\_start()} \index{cfb\_start()} \index{cbc\_start()} \index{ofb\_start()} \index{ctr\_start()} \begin{verbatim} int XXX_start(int cipher, const unsigned char *IV, const unsigned char *key, int keylen, int num_rounds, symmetric_XXX *XXX); +int ctr_start( int cipher, + const unsigned char *IV, + const unsigned char *key, int keylen, + int num_rounds, int ctr_mode, + symmetric_CTR *ctr); + int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, symmetric_ECB *ecb); \end{verbatim} @@ -789,7 +795,12 @@ of the cipher you choose. It is important that the IV be random for each uniqu parameters ``key'', ``keylen'' and ``num\_rounds'' are the same as in the XXX\_setup() function call. The final parameter is a pointer to the structure you want to hold the information for the mode of operation. -Both routines return {\bf CRYPT\_OK} if the cipher initialized correctly, otherwise they return an error code. + +In the case of CTR mode there is an additional parameter ``ctr\_mode'' which specifies the mode that the counter is to be used in. +If \textbf{CTR\_COUNTER\_LITTLE\_ENDIAN} was specified then the counter will be treated as a little endian value. Otherwise, if +\textbf{CTR\_COUNTER\_BIG\_ENDIAN} was specified the counter will be treated as a big endian value. + +The routines return {\bf CRYPT\_OK} if the cipher initialized correctly, otherwise they return an error code. \subsection{Encryption and Decryption} To actually encrypt or decrypt the following routines are provided: @@ -867,6 +878,7 @@ int main(void) key, /* the secret key */ 16, /* length of secret key (16 bytes, 128 bits) */ 0, /* 0 == default # of rounds */ + CTR_COUNTER_LITTLE_ENDIAN, /* Little endian counter */ &ctr) /* where to store initialized CTR state */ ) != CRYPT_OK) { printf("ctr_start error: %s\n", error_to_string(err)); @@ -1349,7 +1361,7 @@ int send_packet(const unsigned char *pt, unsigned long ptlen, } /* process the plaintext */ - if ((err = gcm_add_process(gcm, pt, ptlen, pt, GCM_ENCRYPT)) != CRYPT_OK) { + if ((err = gcm_process(gcm, pt, ptlen, pt, GCM_ENCRYPT)) != CRYPT_OK) { return err; } @@ -1359,6 +1371,8 @@ int send_packet(const unsigned char *pt, unsigned long ptlen, return err; } + /* ... send a header describing the lengths ... */ + /* depending on the protocol and how IV is generated you may have to send it too... */ send(socket, iv, ivlen, 0); @@ -2452,8 +2466,8 @@ int main(void) \section{Introduction} RSA wrote the PKCS \#1 specifications which detail RSA Public Key Cryptography. In the specifications are -padding algorithms for encryption and signatures. The standard includes ``v1.5'' and ``v2.0'' algorithms. -To simplify matters a little the v2.0 encryption and signature padding algorithms are called OAEP and PSS +padding algorithms for encryption and signatures. The standard includes the ``v2.1'' algorithms. +To simplify matters a little the v2.1 encryption and signature padding algorithms are called OAEP and PSS respectively. \section{PKCS \#1 Encryption} @@ -2509,33 +2523,6 @@ If the function succeeds it decodes the OAEP encoded message into ``out'' of len $1$ in ``res''. If the packet is invalid it stores $0$ in ``res'' and if the function fails for another reason it returns an error code. -\subsection{PKCS \#1 v1.5 Encoding} - -\index{pkcs\_1\_v15\_es\_encode()} -\begin{verbatim} -int pkcs_1_v15_es_encode(const unsigned char *msg, unsigned long msglen, - unsigned long modulus_bitlen, - prng_state *prng, int prng_idx, - unsigned char *out, unsigned long *outlen); -\end{verbatim} - -This will PKCS v1.5 encode the data in ``msg'' of length ``msglen''. Pass the length (in bits) of your -RSA modulus in ``modulus\_bitlen''. The encoded data will be stored in ``out'' of length ``outlen''. - -\subsection{PKCS \#1 v1.5 Decoding} -\index{pkcs\_1\_v15\_es\_decode()} -\begin{verbatim} -int pkcs_1_v15_es_decode(const unsigned char *msg, unsigned long msglen, - unsigned long modulus_bitlen, - unsigned char *out, unsigned long outlen, - int *res); -\end{verbatim} - -This will PKCS v1.5 decode the message in ``msg'' of length ``msglen''. It will store the output in ``out''. Note -that the length of the output ``outlen'' is a constant. This decoder cannot determine the original message -length. If the data in ``msg'' is a valid packet then a $1$ is stored in ``res'', otherwise a $0$ is -stored. - \section{PKCS \#1 Digital Signatures} \subsection{PSS Encoding} @@ -2577,34 +2564,6 @@ 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. -\subsection{PKCS \#1 v1.5 Encoding} - -\index{pkcs\_1\_v15\_sa\_encode()} -\begin{verbatim} -int pkcs_1_v15_sa_encode(const unsigned char *msghash, unsigned long msghashlen, - int hash_idx, unsigned long modulus_bitlen, - unsigned char *out, unsigned long *outlen); -\end{verbatim} - -This will PKCS \#1 v1.5 signature encode the message hash ``msghash'' of length ``msghashlen''. You have -to tell this routine which hash produced the message hash in ``hash\_idx''. The encoded hash is stored -in ``out'' of length ``outlen''. - -\subsection{PKCS \#1 v1.5 Decoding} - -\index{pkcs\_1\_v15\_sa\_decode()} -\begin{verbatim} -int pkcs_1_v15_sa_decode(const unsigned char *msghash, unsigned long msghashlen, - const unsigned char *sig, unsigned long siglen, - int hash_idx, unsigned long modulus_bitlen, - int *res); -\end{verbatim} - -This will PKCS \#1 v1.5 signature decode the data in ``sig'' of length ``siglen'' and compare the extracted -hash against ``msghash'' of length ``msghashlen''. You have to tell this routine which hash produced the -message digest in ``hash\_idx''. If the packet is valid and the hashes match ``res'' is set to $1$. Otherwise, -it is set to $0$. - \section{RSA Operations} \subsection{Background} @@ -2698,15 +2657,14 @@ to pkcs\_1\_oaep\_encode(). int rsa_decrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const unsigned char *lparam, unsigned long lparamlen, - prng_state *prng, int prng_idx, - int hash_idx, int *res, + int hash_idx, int *stat, rsa_key *key); \end{verbatim} This function will RSA decrypt ``in'' of length ``inlen'' then OAEP depad the resulting data and store it in ``out'' of length ``outlen''. The ``lparam'' and ``lparamlen'' are the same parameters you would pass to pkcs\_1\_oaep\_decode(). -If the RSA decrypted data isn't a valid OAEP packet then ``res'' is set to $0$. Otherwise, it is set to $1$. +If the RSA decrypted data isn't a valid OAEP packet then ``stat'' is set to $0$. Otherwise, it is set to $1$. \subsection{RSA Hash Signatures} Similar to RSA key encryption RSA is also used to ``digitally sign'' message digests (hashes). To facilitate this @@ -2729,7 +2687,6 @@ the output is stored in ``out'' of length ``outlen''. \begin{verbatim} int rsa_verify_hash(const unsigned char *sig, unsigned long siglen, const unsigned char *msghash, unsigned long msghashlen, - prng_state *prng, int prng_idx, int hash_idx, unsigned long saltlen, int *stat, rsa_key *key); \end{verbatim} @@ -2799,8 +2756,6 @@ int main(void) &l2, /* plaintext length */ "TestApp", /* lparam for this program */ 7, /* lparam is 7 bytes long */ - NULL, /* PRNG state */ - prng_idx, /* prng idx */ hash_idx, /* hash idx */ &res, /* validity of data */ &key) /* our RSA key */ @@ -3060,6 +3015,34 @@ provided are very close to $p$ that is $\vert \vert \phi(\beta) \vert \vert \app range in order from $\approx 2^{192}$ points to $\approx 2^{521}$. According to the source document any key size greater than or equal to 256-bits is sufficient for long term security. +\section{Key Format} +LibTomCrypt uses it's own format for ECC public and private keys. While ANSI X9.62 partially specifies key formats (it covers public keys) it does it in a less +than ideally simple manner. In the case of LibTomCrypt it is meant \textbf{solely} for NIST $GF(p)$ curves. The format of the keys is as follows: + +\begin{small} +\begin{verbatim} +ECCPublicKey ::= SEQUENCE { + flags BIT STRING(2), -- public/private flag (always zero), + -- compressed point + keySize INTEGER, -- Curve size (in bits) divided by eight + -- and rounded down, e.g. 521 => 65 + pubkey.x INTEGER, -- The X co-ordinate of the public key point +} + +ECCPrivateKey ::= SEQUENCE { + flags BIT STRING(2), -- public/private flag (always one), + -- compressed point + keySize INTEGER, -- Curve size (in bits) divided by eight + -- and rounded down, e.g. 521 => 65 + pubkey.x INTEGER, -- The X co-ordinate of the public key point + secret.k INTEGER, -- The secret key scalar +} +\end{verbatim} +\end{small} + +The first flags bit denotes whether the key is public (zero) or private (one). The compressed point bit is equal to zero if $(x^3 - 3x + b)^{(p+1)/4} \mbox{ mod }p$ is +congruent to the keys $y$ co-ordinate. The bit is one if the $y$ co-ordinate is the negative of the computed square root. + \section{Core Functions} Like the DH routines there is a key structure ``ecc\_key'' used by the functions. There is a function to make a key: @@ -3129,11 +3112,23 @@ int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, ecc_key *key); \end{verbatim} -Where ``in'' is an input symmetric key of no more than 32 bytes. Essentially these routines created a random public key +Where ``in'' is an input symmetric key of no more than 64 bytes. Essentially these routines created a random public key and find the hash of the shared secret. The message digest is than XOR'ed against the symmetric key. All of the required data is placed in ``out'' by ``ecc\_encrypt\_key()''. The hash chosen must produce a message digest at least as large as the symmetric key you are trying to share. +\subsection{Encrypt Packet Format} + +The packet format for the encrypted keys is the following ASN.1 SEQUENCE: + +\begin{verbatim} +ECCEncrypt ::= SEQUENCE { + hashID OBJECT IDENTIFIER, -- OID of hash used + pubkey OCTET STRING , -- Encapsulated ECCPublicKey (see above) + skey OCTET STRING -- xor of plaintext and "hash of shared secret" +} +\end{verbatim} + There are also functions to sign and verify the hash of a message. \index{ecc\_sign\_hash()} \index{ecc\_verify\_hash()} \begin{verbatim} @@ -3150,6 +3145,8 @@ The ``ecc\_sign\_hash'' function signs the message hash in ``in'' of length ``in The ``ecc\_verify\_hash'' function verifies the ECC signature in ``sig'' against the hash in ``hash''. It sets ``stat'' to non-zero if the signature passes or zero if it fails. +\subsection{Signature Format} +The signature code is an implementation of X9.62 EC-DSA and the output is comformant for GF(p) curves. \section{ECC Keysizes} With ECC if you try and sign a hash that is bigger than your ECC key you can run into problems. The math will still work @@ -3170,6 +3167,38 @@ would require at least 256 bytes where as the DSA signature would require only a The API for the DSA is essentially the same as the other PK algorithms. Except in the case of DSA no encryption or decryption routines are provided. +\section{Key Format} +Since no useful public standard for DSA key storage was presented to me during the course of this development I made my own ASN.1 SEQUENCE which I document +now so that others can interoperate with this library. + +\begin{verbatim} +DSAPublicKey ::= SEQUENCE { + publicFlags BIT STRING(1), -- must be 0 + g INTEGER , -- base generator, check that g^q mod p == 1 + -- and that 1 < g < p - 1 + p INTEGER , -- prime modulus + q INTEGER , -- order of sub-group (must be prime) + y INTEGER , -- public key, specifically, g^x mod p, + -- check that y^q mod p == 1 + -- and that 1 < y < p - 1 +} + +DSAPrivateKey ::= SEQUENCE { + publicFlags BIT STRING(1), -- must be 1 + g INTEGER , -- base generator, check that g^q mod p == 1 + -- and that 1 < g < p - 1 + p INTEGER , -- prime modulus + q INTEGER , -- order of sub-group (must be prime) + y INTEGER , -- public key, specifically, g^x mod p, + -- check that y^q mod p == 1 + -- and that 1 < y < p - 1 + x INTEGER -- private key +} +\end{verbatim} + +The leading BIT STRING has a single bit in it which is zero for public keys and one for private keys. This makes the structure uniquely decodable and easy +to work with. + \section{Key Generation} To make a DSA key you must call the following function \begin{verbatim} @@ -3291,79 +3320,289 @@ This will import the DSA key from the buffer ``in'' of length ``inlen'' to the ` will automatically free all of the heap allocated in the process (you don't have to call dsa\_free()). \chapter{Standards Support} -\section{DER Support} -DER or ``Distinguished Encoding Rules'' is a subset of the ASN.1 encoding rules that is fully deterministic and -ideal for cryptography. In particular ASN.1 specifies an INTEGER type for storing arbitrary sized integers. DER -further limits the ASN.1 specifications to a deterministic encoding. +\section{ASN.1 Formats} +LibTomCrypt supports a variety of ASN.1 data types encoded with the Distinguished Encoding Rules (DER) suitable for various cryptographic protocols. The data types +are all provided with three basic functions with \textit{similar} prototypes. One function has been dedicated to calculate the length in octets of a given +format and two functions have been dedicated to encoding and decoding the format. -\subsection{Storing INTEGER types} -\index{der\_encode\_integer()} -\begin{alltt} -int der_encode_integer(mp_int *num, unsigned char *out, unsigned long *outlen); -\end{alltt} +On top of the basic data types are the SEQUENCE and\footnote{Planned for LTC 1.04} SET data types which are collections of other ASN.1 types. They are provided +in the same manner as the other data types except they use list of objects known as the \textbf{ltc\_asn1\_list} structure. It is defined as -This will store the integer in ``num'' to the output buffer ``out'' of length ``outlen''. It only stores -non--negative numbers. It stores the number of octets used back in ``outlen''. +\index{ltc\_asn1\_list structure} +\begin{verbatim} +typedef struct { + int type; + void *data; + unsigned long size; +} ltc_asn1_list; +\end{verbatim} -\subsection{Reading INTEGER types} -\index{der\_decode\_integer()} -\begin{alltt} -int der_decode_integer(const unsigned char *in, unsigned long *inlen, mp_int *num); -\end{alltt} -This will decode the DER encoded INTEGER in ``in'' of length ``inlen'' and store the resulting integer -in ``num''. It will store the bytes read in ``inlen'' which is handy if you have to parse multiple -data items out of a binary packet. +The ``type'' field is one of the following ASN.1 field definitions. The ``data'' pointer is a void pointer to the data to be encoded (or the destination) and the +``size'' field is specific to what you are encoding (e.g. number of bits in the BIT STRING data type). To help build the lists in an orderly fashion the macro +``LTC\_SET\_ASN1(list, index, Type, Data, Size)'' has been provided. -\subsection{INTEGER length} -\index{der\_length\_integer()} -\begin{alltt} -int der_length_integer(mp_int *num, unsigned long *len); -\end{alltt} -This will determine the length of the DER encoding of the integer ``num'' and store it in ``len''. +It will assign to the ``index''th position in the ``list'' the tripplet (Type, Data, Size). An example usage would be: -\subsection{Multiple INTEGER types} -To simplify the DER encoding/decoding there are two functions two handle multple types at once. +\begin{small} +\begin{verbatim} +... +ltc_asn1_list sequence[3]; +unsigned long three=3; -\index{der\_put\_multi\_integer()} -\index{der\_get\_multi\_integer()} -\begin{alltt} -int der_put_multi_integer(unsigned char *dst, unsigned long *outlen, mp_int *num, ...); -int der_get_multi_integer(const unsigned char *src, unsigned long *inlen, mp_int *num, ...); -\end{alltt} +LTC_SET_ASN1(sequence, 0, LTC_ASN1_IA5_STRING, "hello", 5); +LTC_SET_ASN1(sequence, 1, LTC_ASN1_SHORT_INTEGER, &three, 1); +LTC_SET_ASN1(sequence, 2, LTC_ASN1_NULL, NULL, 0); +\end{verbatim} +\end{small} -These will handle multiple encodings/decodings at once. They work like their single operand counterparts -except they handle a \textbf{NULL} terminated list of operands. +The macro is relatively safe with respect to modifying variables, for instance the following code is equivalent. + +\begin{small} +\begin{verbatim} +... +ltc_asn1_list sequence[3]; +unsigned long three=3; +int x=0; +LTC_SET_ASN1(sequence, x++, LTC_ASN1_IA5_STRING, "hello", 5); +LTC_SET_ASN1(sequence, x++, LTC_ASN1_SHORT_INTEGER, &three, 1); +LTC_SET_ASN1(sequence, x++, LTC_ASN1_NULL, NULL, 0); +\end{verbatim} +\end{small} + +\begin{figure}[here] +\begin{center} +\begin{small} +\begin{tabular}{|l|l|} +\hline \textbf{Definition} & \textbf{ASN.1 Type} \\ +\hline LTC\_ASN1\_EOL & End of a ASN.1 list structure. \\ +\hline LTC\_ASN1\_INTEGER & INTEGER (uses mp\_int) \\ +\hline LTC\_ASN1\_SHORT\_INTEGER & INTEGER (32--bit using unsigned long) \\ +\hline LTC\_ASN1\_BIT\_STRING & BIT STRING (one bit per char) \\ +\hline LTC\_ASN1\_OCTET\_STRING & OCTET STRING (one octet per char) \\ +\hline LTC\_ASN1\_NULL & NULL \\ +\hline LTC\_ASN1\_OBJECT\_IDENTIFIER & OBJECT IDENTIFIER (words are in unsigned long) \\ +\hline LTC\_ASN1\_IA5\_STRING & IA5 STRING (one octet per char) \\ +\hline LTC\_ASN1\_PRINTABLE\_STRING & PRINTABLE STIRNG (one octet per char) \\ +\hline LTC\_ASN1\_SEQUENCE & SEQUENCE OF \\ +\hline +\end{tabular} +\caption{List of ASN.1 Supported Types} +\end{small} +\end{center} +\end{figure} + +\subsection{SEQUENCE Type} +The SEQUENCE data type is a collection of other ASN.1 data types encapsulated with a small header which is a useful way of sending multiple data types in one packet. + +\subsubsection{SEUQNECE Encoding} +To encode a sequence a \textbf{ltc\_asn1\_list} array must be initialized with the members of the sequence and their respective pointers. The encoding is performed +with the following function. + +\index{der\_encode\_sequence()} +\begin{verbatim} +int der_encode_sequence(ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +\end{verbatim} +This encodes a sequence of items pointed to by ``list'' where the list has ``inlen'' items in it. The SEQUENCE will be encoded to ``out'' and of length ``outlen''. The +function will terminate when it reads all the items out of the list (upto ``inlen'') or it encounters an item in the list with a type of \textbf{LTC\_ASN1\_EOL}. + +The ``data'' pointer in the list would be the same pointer you would pass to the respective ASN.1 encoder (e.g. der\_encode\_bit\_string()) and it is simply passed on +verbatim to the dependent encoder. The list can contain other SEQUENCE or SET types which enables you to have nested SEQUENCE and SET definitions. In these cases +the ``data'' pointer is simply a pointer to another \textbf{ltc\_asn1\_list}. + +\subsubsection{SEQUENCE Decoding} + +\index{der\_decode\_sequence()} + +Decoding a SEQUENCE is similar to encoding. You set up an array of \textbf{ltc\_asn1\_list} where in this case the ``size'' member is the maximum size +(in certain cases). For types such as IA5 STRING, BIT STRING, OCTET STRING (etc) the ``size'' field is updated after successful decoding to reflect how many +units of the respective type has been loaded. \begin{verbatim} -#include -int main(void) -{ - mp_int a, b, c, d; - unsigned char buffer[1000]; - unsigned long len; - int err; - - /* init a,b,c,d with some values ... */ - - /* ok we want to store them now... */ - len = sizeof(buffer); - if ((err = der_put_multi_integer(buffer, &len, - &a, &b, &c, &d, NULL)) != CRYPT_OK) { - // error - } - printf("I stored %lu bytes in buf\n", len); - - /* ok say we want to get them back for fun */ - /* len set previously...otherwise set it to the size of the packet */ - if ((err = der_get_multi_integer(buffer, &len, - &a, &b, &c, &d, NULL)) != CRYPT_OK) { - // error - } - printf("I read %lu bytes from buf\n", len); -} +int der_decode_sequence(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *list, unsigned long outlen); \end{verbatim} + +This will decode upto ``outlen'' items from the input buffer ``in'' of length ``inlen'' octets. The function will stop (gracefully) when it runs out of items to decode. +It will fail (for among other reasons) when it runs out of input bytes to read, a data type is invalid or a heap failure occured. + +For the following types the ``size'' field will be updated to reflect the number of units read of the given type. +\begin{enumerate} + \item BIT STRING + \item OCTET STRING + \item OBJECT IDENTIFIER + \item IA5 STRING + \item PRINTABLE STRING +\end{enumerate} + +\subsubsection{SEQUENCE Length} + +The length of a SEQUENCE can be determined with the following function. + +\index{der\_length\_sequence()} +\begin{verbatim} +int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, + unsigned long *outlen); +\end{verbatim} + +This will get the encoding size for the given ``list'' of length ``inlen'' and store it in ``outlen''. + +\subsubsection{SEQUENCE Multiple Argument Lists} + +For small or simple sequences an encoding or decoding can be performed with one of the following two functions. + +\index{der\_encode\_sequence\_multi()} +\index{der\_decode\_sequence\_multi()} + +\begin{verbatim} +int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...); +int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...); +\end{verbatim} + +These either encode or decode (respectively) a SEQUENCE data type where the items in the sequence are specified after the length parameter. + +The list of items are specified as a triple of the form ``(type, size, data)'' where ``type'' is an \textbf{int}, ``size'' is a \textbf{unsigned long} +and ``data'' is \textbf{void} pointer. The list of items must be terminated with an item with the type \textbf{LTC\_ASN1\_EOL}. + +It's ideal that you cast the ``size'' values to unsigned long to ensure that the proper data type is passed to the function. Constants such as ``1'' without +a cast or prototype are of type \textbf{int} by default. Appending \textit{UL} or prepending \textit{(unsigned long)} is enough to cast it to the correct type. + +\subsubsection{ASN.1 INTEGER} + +To encode or decode INTEGER data types use the following functions. + +\index{der\_encode\_integer()} +\index{der\_decode\_integer()} +\index{der\_length\_integer()} +\begin{verbatim} +int der_encode_integer(mp_int *num, unsigned char *out, unsigned long *outlen); +int der_decode_integer(const unsigned char *in, unsigned long inlen, mp_int *num); +int der_length_integer(mp_int *num, unsigned long *len); +\end{verbatim} + +These will encode or decode a signed INTEGER data type using the ``mp\_int'' data type to store the large INTEGER. To encode smaller values without allocating +an mp\_int to store the value the ``short'' INTEGER functions were made available. + +\index{der\_encode\_short\_integer()} +\index{der\_decode\_short\_integer()} +\index{der\_length\_short\_integer()} +\begin{verbatim} +int der_encode_short_integer(unsigned long num, + unsigned char *out, unsigned long *outlen); + +int der_decode_short_integer(const unsigned char *in, unsigned long inlen, + unsigned long *num); + +int der_length_short_integer(unsigned long num, unsigned long *outlen); +\end{verbatim} + +These will encode or decode an unsigned \textbf{unsigned long} type (only reads upto 32--bits). For values in the range $0 \dots 2^{32} - 1$ the integer +and short integer functions can encode and decode each others outputs. + +\subsubsection{ASN.1 BIT STRING} + +\index{der\_encode\_bit\_string()} +\index{der\_decode\_bit\_string()} +\index{der\_length\_bit\_string()} +\begin{verbatim} +int der_encode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_decode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_length_bit_string(unsigned long nbits, unsigned long *outlen); +\end{verbatim} + +These will encode or decode a BIT STRING data type. The bits are passed in (or read out) using one \textbf{char} per bit. A non--zero value will be interpretted +as a one bit and a zero value a zero bit. + +\subsubsection{ASN.1 OCTET STRING} + +\index{der\_encode\_octet\_string()} +\index{der\_decode\_octet\_string()} +\index{der\_length\_octet\_string()} +\begin{verbatim} +int der_encode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_decode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_length_octet_string(unsigned long noctets, unsigned long *outlen); +\end{verbatim} + +These will encode or decode an OCTET STRING data type. The octets are stored using one \textbf{char} each. + +\subsubsection{ASN.1 OBJECT IDENTIFIER} + +\index{der\_encode\_object\_identifier()} +\index{der\_decode\_object\_identifier()} +\index{der\_length\_object\_identifier()} +\begin{verbatim} +int der_encode_object_identifier(unsigned long *words, unsigned long nwords, + unsigned char *out, unsigned long *outlen); + +int der_decode_object_identifier(const unsigned char *in, unsigned long inlen, + unsigned long *words, unsigned long *outlen); + +int der_length_object_identifier(unsigned long *words, unsigned long nwords, + unsigned long *outlen); +\end{verbatim} + +These will encode or decode an OBJECT IDENTIFIER object. The words of the OID are stored in individual \textbf{unsigned long} elements and must be in the range +$0 \ldots 2^{32} - 1$. + +\subsubsection{ASN.1 IA5 STRING} + +\index{der\_encode\_ia5\_string()} +\index{der\_decode\_ia5\_string()} +\index{der\_length\_ia5\_string()} +\begin{verbatim} +int der_encode_ia5_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_decode_ia5_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, + unsigned long *outlen); +\end{verbatim} + +These will encode or decode an IA5 STRING. The characters are read or stored in individual \textbf{char} elements. This functions performs internal character +to numerical conversions based on the conventions of the compiler being used. For instance, on an x86\_32 machine 'A' == 65 but the same may not be true on +say a SPARC machine. Internally these functions have a table of literal characters and their numerical ASCII values. This provides a stable conversion provided +that the build platform honours the runtime platforms character conventions. + +If you're worried try building the test suite and running it. It has hard coded test vectors to ensure it is operating properly. + +\subsubsection{ASN.1 PRINTABLE STRING} + +\index{der\_encode\_printable\_string()} +\index{der\_decode\_printable\_string()} +\index{der\_length\_printable\_string()} +\begin{verbatim} +int der_encode_printable_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_decode_printable_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_length_printable_string(const unsigned char *octets, unsigned long noctets, + unsigned long *outlen); +\end{verbatim} + +These will encode or decode an PRINTABLE STRING. The characters are read or stored in individual \textbf{char} elements. This functions performs internal character +to numerical conversions based on the conventions of the compiler being used. For instance, on an x86\_32 machine 'A' == 65 but the same may not be true on +say a SPARC machine. Internally these functions have a table of literal characters and their numerical ASCII values. This provides a stable conversion provided +that the build platform honours the runtime platforms character conventions. + +If you're worried try building the test suite and running it. It has hard coded test vectors to ensure it is operating properly. + + \section{Password Based Cryptography} \subsection{PKCS \#5} +\index{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. @@ -3436,7 +3675,6 @@ int main(void) \} \end{alltt} - \chapter{Miscellaneous} \section{Base64 Encoding and Decoding} The library provides functions to encode and decode a RFC1521 base64 coding scheme. This means that it can decode what it @@ -4030,8 +4268,8 @@ To initialize a cipher (for ECB mode) the function setup() was provided. It acc can specify the number of rounds they want through ``num\_rounds'' where $num\_rounds = 0$ means use the default. The destination of a scheduled key is stored in ``skey''. -This is where things get tricky. Currently there is no provision to allocate memory during initialization since there is no ``cipher done'' function. So you have -to either use an existing member of the symmetric\_key union or alias your own structure over top of it provided symmetric\_key is not smaller. +Inside the ``symmetric\_key'' union there is a ``void *data'' which you can use to allocate data if you need a data structure that doesn't fit with the existing +ones provided. Just make sure in your ``done()'' function that you free the allocated memory. \subsection{Single block ECB} To process a single block in ECB mode the ecb\_encrypt() and ecb\_decrypt() functions were provided. The plaintext and ciphertext buffers are allowed to overlap so you @@ -4062,7 +4300,8 @@ updated by the function before returning. \subsubsection{Accelerated CTR} This function is meant for accelerated CTR encryption. It is accessible through the accel\_ctr\_encrypt pointer. The ``blocks'' value is the number of complete blocks to process. The ``IV'' is the CTR counter vector. It is an input upon calling this function and must be -updated by the function before returning. The ``mode'' value indicates whether the counter is big ($mode = 1$) or little ($mode = 0$) endian. +updated by the function before returning. The ``mode'' value indicates whether the counter is big (mode = CTR\_COUNTER\_BIG\_ENDIAN) or +little (mode = CTR\_COUNTER\_LITTLE\_ENDIAN) endian. This function (and the way it's called) differs from the other two since ctr\_encrypt() allows any size input plaintext. The accelerator will only be called if the following conditions are met. @@ -4101,10 +4340,10 @@ struct ltc_hash_descriptor { unsigned long hashsize; /** Input block size in octets */ unsigned long blocksize; - /** ASN.1 DER identifier */ - unsigned char DER[64]; + /** ASN.1 OID */ + unsigned long OID[16]; /** Length of DER encoding */ - unsigned long DERlen; + unsigned long OIDlen; /** Init a hash state @param hash The hash to initialize @return CRYPT_OK if successful @@ -4144,8 +4383,8 @@ The ``hashsize'' variable indicates the length of the output in octets. The `blocksize'' variable indicates the length of input (in octets) that the hash processes in a given invokation. -\subsection{DER Identifier} -This is the DER identifier (including the SEQUENCE header). This is used solely for PKCS \#1 style signatures. +\subsection{OID Identifier} +This is the universal ASN.1 Object Identifier for the hash. \subsection{Initialization} The init function initializes the hash and prepares it to process message bytes. @@ -4251,3 +4490,7 @@ but should at least maintain the same level of state entropy. \input{crypt.ind} \end{document} + +% $Source: /cvs/libtom/libtomcrypt/crypt.tex,v $ +% $Revision: 1.32 $ +% $Date: 2005/06/09 00:36:17 $ diff --git a/demos/encrypt.c b/demos/encrypt.c index 67627f7b..1f4d7468 100644 --- a/demos/encrypt.c +++ b/demos/encrypt.c @@ -235,3 +235,7 @@ int main(int argc, char *argv[]) } return 0; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/demos/hashsum.c b/demos/hashsum.c index 23946ccc..4e9b0fb5 100644 --- a/demos/hashsum.c +++ b/demos/hashsum.c @@ -113,3 +113,7 @@ void register_algs(void) #endif } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/demos/multi.c b/demos/multi.c index fdc8dc6b..33d17a28 100644 --- a/demos/multi.c +++ b/demos/multi.c @@ -104,3 +104,7 @@ int main(void) return EXIT_SUCCESS; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/demos/small.c b/demos/small.c index bc9793bc..f3204240 100644 --- a/demos/small.c +++ b/demos/small.c @@ -8,3 +8,7 @@ int main(void) register_hash(&sha256_desc); return 0; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/demos/test.c b/demos/test.c index 290861d9..b1e3966c 100644 --- a/demos/test.c +++ b/demos/test.c @@ -2,18 +2,23 @@ int main(void) { + int x; reg_algs(); printf("build == \n%s\n", crypt_build_settings); - printf("\ncipher_test..."); fflush(stdout); printf(cipher_hash_test() ? "failed" : "passed"); - printf("\nmodes_test..."); fflush(stdout); printf(modes_test() ? "failed" : "passed"); - printf("\nmac_test..."); fflush(stdout); printf(mac_test() ? "failed" : "passed"); - printf("\npkcs_1_test..."); fflush(stdout); printf(pkcs_1_test() ? "failed" : "passed"); - printf("\nstore_test..."); fflush(stdout); printf(store_test() ? "failed" : "passed"); - printf("\nrsa_test..."); fflush(stdout); printf(rsa_test() ? "failed" : "passed"); - printf("\necc_test..."); fflush(stdout); printf(ecc_tests() ? "failed" : "passed"); - printf("\ndsa_test..."); fflush(stdout); printf(dsa_test() ? "failed" : "passed"); - printf("\ndh_test..."); fflush(stdout); printf(dh_tests() ? "failed" : "passed"); - printf("\nder_test..."); fflush(stdout); printf(der_tests() ? "failed" : "passed"); - + printf("\nstore_test...."); fflush(stdout); x = store_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + printf("\ncipher_test..."); fflush(stdout); x = cipher_hash_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + printf("\nmodes_test...."); fflush(stdout); x = modes_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + printf("\nmac_test......"); fflush(stdout); x = mac_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + printf("\nder_test......"); fflush(stdout); x = der_tests(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + printf("\npkcs_1_test..."); fflush(stdout); x = pkcs_1_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + printf("\nrsa_test......"); fflush(stdout); x = rsa_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + printf("\necc_test......"); fflush(stdout); x = ecc_tests(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + printf("\ndsa_test......"); fflush(stdout); x = dsa_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + printf("\ndh_test......."); fflush(stdout); x = dh_tests(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + printf("\n"); return EXIT_SUCCESS; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/demos/timing.c b/demos/timing.c index 54c0462d..444d08dd 100644 --- a/demos/timing.c +++ b/demos/timing.c @@ -17,7 +17,10 @@ time_sqr(); time_rsa(); time_ecc(); time_dh(); - return EXIT_SUCCESS; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/demos/tv_gen.c b/demos/tv_gen.c index c37d1af6..e8ef4e58 100644 --- a/demos/tv_gen.c +++ b/demos/tv_gen.c @@ -664,3 +664,7 @@ int main(void) + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/doc/crypt.pdf b/doc/crypt.pdf index 9eb60c6cbab9ccb3269caec6440559309afe833b..a50ea929e45e2daca85c5d84b4a1eb7ceb06f354 100644 GIT binary patch delta 252222 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

-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�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 @ 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

96>{250bCIz{?T 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

B%#l!)wpLRRix1nm_3MLEjFR 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

lW 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­t%cM6X(#=~ ze-vmw6XQGs%0&W00y4&F(KrufAr*C2D!hf^RT%UK6GB^!cM+VJU)H_>qC$w0FrjE(oG$MGLL zav)q;}cb(X!Qf}4azA5{{cf5YA#?%INLb!Ul1{xW+8kKnpeP&7zv?R9Phx7 z;Xg1I*q>JuxK#q&$~%TLMDG$nKtcx|r$zhGxb@Lv%z?xCrxgC{tq?!PTkzv11Y)!u z1F}HV2NjSBI0qSn${&3_g405*z~kTFg<%kV2NRK@f%w{YfMrK(h!s$-E1LfY6CR#-PJM*iQV! z{*zHh_8;)a|LNy4*=Vo;0SOTfr$y^McuhrkT?7KcOjJN72ZAB*AWlp$D}K3#njaXV zzJR|rMZpHVpM(so5L;O=t5!W3UWiyhni4fiMI_gW^9x0fdKK jFb3ZBmv&<)*L@J1hCh}L8pPB^@CGnVNLAI)+DPbs_m%UZ delta 232377 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%0AM4jAUe$BQ@{W*`ABGy);<~Il^{d z?xCh6W}i5IPzH0JF6OYE4Y_rsY&IAxj_`DvnL}sGKvR%xADtWx1_HrLy`en+H%);3 zzcc|(URKbEH9(@ZJqDl+kMd@}xIXl61mW?~+0P!o3>4$~g|TyUbArlU0TQ6lbU+}4 z>tQQ+2EZPXg1YQWMek(c?%`%>>iB;q)_((lI5^nYK`p@mNzi-|;1hx&taYIn(1HPZ zaJs?*QjG=>fXaUXkU+lC00Gd|F90M^6j9Q@px@FazH8NZ9JK~g?TP9STqtewuP;JE zBPu-Skc{&d<0$1QmHspywvLMMKW+Enu>PRrXe6#JpSYLsOEDEfbyi%vZ-lBG8f+JL zEiX$S&$G$qO+k0yn%)l1*^%V!*$${ZNM_}t167Pu(9>lN@`2k%bDsDUxtNzQDmT#V zMs!5~c{dD@Lks{8f|Cv89rM+j^;Uo!0)i8f9N_cl^OlPd1R_oU>I)w$$CsGot1qbo z0DthCR^&lI2NWc#5}pcZY7C$YfT{+x(v1V?pdmjK3C2M#MF2u_b{^LMX%*LhKZ2kj zi-M(-wTBHUCl@;UA|W2X?d^m7W|M4Xv5z>C7t&B^Bc60BGyg_y!&y z&Z9l|wpgnL!to!@Ed-3}YmD91F+;6fGUx>vcGS)T@sG{|*Jv^Pw1DqOknYEQmMX_c zf}p0WAkU9*I;o!u>n|umDdRP_;9+v%z3)} zybDsg``=}`|3?+d&cpXVb-6kIzYhLib<=hhs6ny^fBqz_mPsRUG zYW`nsDK`%r$a4lD4FcQ&et~DSw%-B35h0_Kv)e%hYhQ>62m4nNR`=T1JRt*z3;@== z+%9hK29k|GLOI5pAqKf~iTHnx52k9h(W zdEU-I&V;h_=H9aQ5fI!KVGfsN5`lM~Pu+m$s+Jnx$s$+I$SD8a=lLUm@L_W`sV8r~ ziDbL|v+M01>&^Xn{<$ZwtNV^&@t#{KaE?ITMP*_`*u}iAP5IKe)BlJ{8n|P`4Oe71 z{Uex3DkI=?2$HJAR2j%7=4;-}$l`T?Y>8irX!kZW;aw*Jb*^-dpDstxH~0+2CEKCx zeW5tRhBcs^iO=;&LBSq zVa*4}l!*9Xw(XdR<1Ym4VxC~4E!P*4RV3BH;8W1%25opw{PHJoxYK zX9CYfSl&+wXb=+G4JEAMi(rE(Y#mE;{CHZAL;^k763Qzuei{%U2`!=2aZK&p^ zEhx(K&H+9~?fp_+D}4;(qzkbgCYDX3O}FYEzT&*3T3#qkrBd3% z)Q{53P57YjmJ^B)1B7|cNrU*6d2LjauJUK%^K#1&g(rSq8vf$JRS1I*IK7*WfA^0z9~b9bf?T1J6Lw{Lqw?)x{c0a&q7wyQ zWxPoOf9vd8aY(MGP`}?nUKzNslE9^QgAqXXb@U)@lDq~TdjYR~Tkr3;lfu0K0NC*6nNL zw4+g|iYOVKjd)OM; zdgBg549}r*S>^2)UU9tWkTUgvm~T0Dp7E(r=^EqIQTdtOqnJmv#>_v^bh04ln7wn# zUB^}VS|yef`x3zrGPI8ACXm+pA@4;~bggcY_$m2MHi7&_nN~23P>%J8j^O(o!Dyv+ zu+(tmI%LqnQ+FPVf5aKXb|A;+qr7N%?HF{S3gPwUC1d4^FqJtVU9u@$^;uoLEbKoH z=fHHz&0T3D|KjSyYIQ)as}=qowxOD%y(_S|%nF|5?qFN1lQ@HmE;MdZ03QN&ec5YI zP=M_mHUPmyn>A04*uICwxT?n;fPFvpw3fH2<2-;{e={(QIK$wzT=OGAgZkdT z(gj*d!oGe!8t- zO(b&XME?CNScxWRFq0<)J2#)8sf7>!$p> zyuEmtR{dFW+HEqUXOVUd9zeVrKV=~>r?{jNO6`xsX@Y>{5V`ICuY5=^8BRzgE+gwW z>biO-a-Wf{3?AFu#SgN!7bt4Ld2pd}jri+0G$P~r zO7(*$qKK&7U`3cAj0c(t%6due(*zj|6xMW#7 zcJ9OYRa3w#1RxekRU^yuJw<*!G9XSK21PSbVWbSiqYAY)E`fi=}HV9l#=X@H2s4@Z9M4)p zv+lw6On2G6O|3m~1d%A6QaLo~A?|ayIdHlCZ<*r}WODND zUj1~Gsy+-sJCXjhY`BiIqTu80G|)5!CPNLUI!`gwU(ohvI$$EiUCw(HSX2m`Z=U6H z5_?Z|L)ST{@IgHWHJwWf51yGn32Uem$M;v5*>eu&tw16+3sHtj9Hmd}%ZcW&oC<$} z&CXC{o7#Lzvw_U48(XKkoY&mpoRe!3n`ot*k;5!#gmIn%vD1TCGo(glSEPfL^=r$Fqz-Wd?TB}-5@l1 zsVSL944Ix4s$yReL?I3KT?44Ge->^PiUZg|{*kdzR=ZgD+TaX&7tv!hZtH|2v-+oP zxcMV14%x&oir6tp2!FTpVqW~^iJUU`@ssM0;Lbc4o>GALjdTR>?dgDW-Ps31XK=9R z;@ff?{FdqvIM~L@fFC~-#3JP@T9%2KrB2%%iWWM$0O}<1k!-GDq!jRX08EV?4!Vg; zF1eH*q!PwbUv_Fy~6*ctp;nF4lWNVY+>)Z$14Z7`mG|GGCml zR@@Sn(jEr91JAjdr!1}2L|8N6^-V#4|(?i`!_fw>gje z2_v}OkozPFj<3jMSG*soz^>$rO<%_P?nxtt5*SGzs0}_7((T}16voltqMhsgqrbIe zdc^WEUDb?QxVIzit#rc%X)`W7cW{RK?z@lq?YFpkp?TiF zXgVakLMv&>RLRraXV$H+E9DS=U?JC>$W9L(qY1nt)xeduEd>yM>0qYw2oH#ZXsA_I z$eJ4&#WroWP*FDg_Akvmwfls8Ytpji}65-N2 zaZ<2FKj?{u?O|~6<wW%r;%*LlK1Vu)S&E^#v&~8IT4bV)+#l z(HZ6nUi4tmR5m->S6l0NoC{{hH)!PXT6q!#k2(Sm4Qv-zSAa3A#Np}zgbMm68!y>Q zrp%c+rD#S=NQGyTe7$xHd*mHs8n{xh8k{jj@|olAW?eQ(Qtzm;9#T4qC+==2qUn=- zXW8rbw)%8q+{A2YX8meEfmq|lStKarYp4WaWo48L=Eh6?cx#XHcI}iUs zF3F8d{lN&AN>+?ALCowZVV|3wMu0xqwbGw_Jj)A1OPS=p!Bi|R>GWJyDoH$ctez5n zVnAr8E>VE*t1?kw^7Y>y$}l`pJa__c&_@CcnOAv6vhbAf_bK%Co)<@qhOqcOt`@%p z8=;h4>f3AV7FeSdoA_^56=8fXr^&KIzEJkqv>y;UO~K>KiGohC;MKbBC{8|=SEx8U zLXet*5W9M`FxvMoc5ZHxX-TS?x|VM2O!oI5Y#%e!3)1IYp4lK@uitXkzvG&8L>Xp) z(l}>9&;(FX5a?e#SJpvzd3r>xv}%VrF`mIA3xyn-gX2js%g8;}8Vp%rS|S~n*NlV` zv|ZFrAm^ACqSQfm@Ni7p+1WW8u`{&s(mM(Zm9~VGJ7g)V{33O|!EG>;Okh8@g3@6V znM@F*)B&4%tkEBL%`oeK9RfZ4xzD^nFHPO#LOaH;w>vUuMS4_hW3rpSjOsP5>}Lg2 zYvieFCfef42rZSh2BxV6vCaT+r*oZb< z7s>tkXUHZi6MN{L(K6`XkiEAkp#!gI52BSwc|9JDY+@ zu_}L|0kT34eZmRlhYKdi*a@D;1DG8olBsFUe}(*LyFKQfMd_nY=O; zUArqpWw1^n{fJdXj28LbXeo<`RED^Y;{b zj9uX*^L>Ch(oeB)7ncYx{Rv<{=(fTi+a`%dqa0_Zf(a$E?KOm<=bBrP=gJS1?Fo8Q zxH6myU>qcRJrUM%Z+UcHf>{-q4Ju}*j$})GjYd6?UdfdS3cg zi;%Ez_=3-T_%Q!RE;h>4lh?LhLd{^VRawu@N}}qZ*f%m&{~Rxm0gH@S&1AkI z?neeF@Wl&JlA&jd(DoK%Ol28;DE(=@h{#iEa(;pS5oJ6ETo4v@(}gY_nz(?bIYUIp zy2GHe9Fl2@(C~C`U13xYlsprx)*zddAV-fk-8@J+k5FeTjbTeZa9~S9?0vqifBHd= zMO8U!Mo(d$^coGp2b=^FHAl<#yGLY_VIHCgd`g*JAwDYp(ERPN7!vn47cJyCQ7U;& z<{`6@xOnCWsC9mM%`XVE1zau4D0`3=04@)~; zW$t7wEcp#i9+sN=L<)U4nWser`~1^>kH%42oj-kGZni5;Gcz?S@$0+m3$OHH9W};@ zm!X{`!%ms|+s=0~`Sxz)dY((@f;YKdp@=Z`r$CGeA*ry_N3%_SXw)UlxvwoG-K^38 zqVL4M_@GsuK5hS(-g~&pYgzajrkXe7sWvqmDCer!+VG+W2qDMETnH*!|3Z{FdARsM zJ?mc_n--mQCxUP2QyeKtxcgMx^$uT#W+aySabNbAUFbM{5Po>76t3v064Qtjw6C}N zn}&uQh;)vGqSz)7L){Ap3l;Nkdg<{vmQMrI2UZWB4=p>h-$lOX{2eg!@~Y9;&En}V zH@jw)C-B)7a<8mcYnsD~oBBtjJz4)4XKdBa2HcH^(2RRs?Wke_&C+IiQWM~a80UWO zQLjwb{>~w0$u${vH8^tA;Q*O^1FN1=W1}WDcmW1ou&mpYwffkDbcHt1Phh z7Fcrg+_~-@nBnXys9)f`z2~KS8n7?Xaap{V%U9Hx*28`FfIPKYa8z_LYtcErtiA3Z zug_nQ)&p_YKD=-; zpwDtk%!NG2`#BhoT`SHuvJlRK?zmP+TqP-{(>ckp!&8p$E|LUo!zoGo!hf=rHQ4@V z5`;@6L|fN;yb--=#jY^)`cUx`PV;YtcOmUbtbQG0e%y!kD>#L#T{kZ;Urof#ZeV`i zyTR4!s`73Rim`D2$U)iPj@2Pc!6QyX!Uy+K1XFn}H@pi|ajE_%|MA?rHLLAuXKax{ zR-wJrHE(wajz=!5iuC>feLAg0wm(3DEqoR*`X;qQgh*_(V=S_Iy+@{p%v~>!%U8#Q zlw-960DTDu%!h*h;kw;$1Tv+rDDb4Wr?m^7;RrHYaTSgbYJ`f!`h6Snj{(D|L?Q)SFjWWdNEYu0>nV}RBAY$nfFSn~*$+b`%% zHYO6CodS_g9i4(!CFuaZM4wE=34D3L9{Mo@D6&6X-Cc=$glgpxzz<27*9Ty?i>ij6 zI;?=C%QHEco3*hIvPUP9uLr&P@UM>fKxvrQ(e+hq`SJ@$%s*4+cmsJ?BK{w?&M7#v zsNL4FZQHhOcbqTj*tR+x`QSW@mct-x| zO&O)+_vWwAGj+;7WfwY^UhUZ1erM@|l@!i1TCK9JKkMJ$g(|ni#Ipx~OArQB#~EgO z`yJ{EQc^`x6UER0eHV9y z`$XmrMNQ}>@29CQs@EE!Cy1|&JYM{+*xjyU`3x_Lqva4UL)x*j$B*<2&Iala+8DdZ zhT+_5+qwJELWsVKJ1$^gGWReN4yxD(>P5a|jIT!5)e7QW`7s30%iH-XHjf4!>9X?D zB<6nFlkX8D0&I=;VN7uwQF~OS&v!e!3#4x>$NUZmz%+3>9N$gJOP39es6K#~CO z0Z!86`8V9o$IsfTo)Keb zY<-74L~v;;z9j0%SK2f*^~i(Q@+@qFqv0Vy3M51Kkqx$f`)>1Z|HX&ZAtTpuYUcfk z_bK1IOvw2>o}sw0e{~>ZZRKG*d?2WPkoRg|UkI^=&EdViXt9g11bQnT?@&9bEbIgk z^;V}rKC z^_Lt91X`e6>;RsLky!sbxARFtIxSVkt9c{7BgL-DT3U*oEx6p8(FB}^;YkF6=Ytdu z))C{0W017b1-s?E zuR%RAD?K@7{C>73R*Y~=v}s3xvJk10$AhVd$AP?-2(DD7oLYD^-_mo zakM+0`)C#P-TuO!<5W@BwA_1ed~jACp0w`!??os&A;c>jh9RIf;3}VKI48RZ;ZFDq z`mE;-E~OXZ+xyGI&YH3f@ooJD{B+ph!ti^po83SwGWSGvpn+ph{O(9!F|E*V@nRv! zh-h9`wzh0G+K2B8kEXO${@!@b|}u7>*Y+3=*)O;;qDzi>LkN z^dD767bi9?D5>ZMw5-AOM!6PeK zbPsAO!Du`LdG(jJ+q*3fhera4g7tZI_|ZcYKSnw4zv|q`LkBY=6eOI`$DmtTth7po z;j&}x@a7+UEKh4Uli9!+3Q)8{!(fv5Hci$!G-~)1q2zn5B}N61p-cJh;Vs7BFD{rU zpe!ekPIg&XXmE7Tt%@@K4aGXlVC!X4L#U-wiyyAtG@Yb!D---FS|c7AjUsY(OVI+HIUdJYqZmra9k53pc|xLTbb z+cYIB%rzw1sVaa}g+xj}S2rRSQUwptUyfsfOfMBAL%jD&EJ4lHhVy>Ay-IV(s~F5$ zthZ9+q{=QI;H~blLGvHvwi5%uN4$fY?jFJ--%a6F1_ywP&o8b%Xckr~qzU3Eq4Ayc z=S?z1swc%3ngV&pdVGY|I|gnxiqo^&MPeaf6V+< zNP?^1w`WBxe9rzNvymJs4fH4+{IgmTUsZFVP{h7^%E9`$WSEYz4eiujxbtaFKMOBs zHrq<#uzUv6rMF2Bk{%gbbTswkRU!zEy=Lp$4qL%kYkv$@bX zc)S!uUQ>;m&kuHBtYeP7H4qi*0Sr>Gy70^u(3o+dCn9SYzM7C{v%5hor#TyvatJ?i z-aNvE;2hpT&Ov0JF{eo5pKPpxED3oFz0aQe9@v5V+i*u2Z)eJ}{L1#quD04fh%^q= zCo(%GEOPSo&<;W}CdhrkAs!{JM+K4R38W?Vw z-{|p2A01oWvgY&g=|(Q%=7PrJ^le_-SQt`&@#PXtZmt)j6&emKoEO~WW$h~F%kg!7 zjY^XpB0icI-9(KuxzeMx)T&TSOLGn$8+yIw8?Ee&_0>(%n!!@H&Ed9* zNu974nWA%6ltp&-bVsXTdlTr|;Gntrv*V&fR4@cde^0-FwWhM)q`=v4)B2-hVIa|# zuIJ^C9vslyuJdMN_u9*! z8E)qeDHc%4EhUE54F8VR&Ko1BZ4?PNeeU+5n?5T6Rv5dNBIUf9OwwE)_+#vPy z85=L`wYwWHCRDL9F3moDv#eSPGq1TP+0WwjkYTqTGOA^aH?*b(C)O2>ztSF`Y0oEU zUfc}*zCi3e=F9%K+kof4g@&x`?3`&!=n&#*cuWx4pc1XEOc2lz>{I_gr~a#8Y%E;tX|n_n5uI|I(Hlx9({Gve;wLD{0N(=2+O!4qg`Y+ehQgv3@$1aN(SJS2}{AL&DLkFTgaZf9!G1l z5~lQ@TUWKYE_&hnS-=g0+F<%%Y%HlQ``X;zj@Q%96^HFmV*Rc?dw~?wYGt|Nfb21z z(Z84{AuBq;qAO^}K{M60At71^vp2MuQuIH0Cd@MTkKBbB{4wY8(}-#Z$@Osdn&skz zf~9W|rx=Ca3aq!Ek>#tp+&h$Y@0U2A>o<)aF2y+&KnK%@bAaxT*S8h)#rsr(TRX@z z0Hf&VQ|&x`?hs8R?A}^rWQ~mw;$nv4#g{>&pUYGA%t+`91WOLS>kJ2Q+?@^!%Z85& z5l&rfAxnH8>d1NbA&cYte>^;{3vrEz*PU3ois;(X=3}N_-rOI5z!2h^9P41(QREFdJH-=mD7>YV|k&`7X7NoShBzYW_PL^4RN56YdTa<_7A0oSr>SvCKHbCRzL|QxA;&D6Y2BNUDGK`AJ{Wir9jU~;&(h{0BR~}awO7xbJIV8mO{)3H?Ef!KA zZMEdysG{m8Fh+f&N$cZTJz5*jeh4!~d8~vWEyr=cykS0*i;$UMX{=>3%2+=4rBWGl z@bmrAJYXj|&R?e&v`JEiw@23LaT11`xlb8y({RdOf=;3SAT$i>n+6=U0c@zvP}UGb zL-^c&L$$565j$Z9C7nLvb?v}hf2Y`dYQ!J0n(KEBQ)o2aQh?6T5i6`dSRwaH$Y+Z( zY$;%Xugf*!T-bl@keL@r}l?k=e262t4H!0Wc=$L-DH zW@k)0i2u~h2Pv5zs74S=f&EzzQ)`734NI4FXWIQ7s|z&t>%h0M`#N`rIvg5E7kc{g zwlrZ>O&4q!Z2C@+nGJSym8I?_P-HnlItn4!CCqi+vpsU?5wZYv&1yx`SZj$4drVZkk)I;%?!0~r&r!?CQ!LM+Tf_Gab{2Vv-#mRWc8Rnd~o z--=R*0<5BfB~YGaN?SoKZXT~tM2DP9W+#?9dVmTqFfhYlTl)bL*+=qU!0rIUl`>7j zh9=o=qs<~vBhI*pSYD;?j%B}~ghAR1uWy7)!w0y}>4$irSE)ACdI;=3RhnTM5R$`# zp0OLw^>0)^lUfL&5PRrmmlqoh2q1+8!{3?%eUZ!`0pa)YzgPicxH00kqEj(Td3~(y zxF?ME+6K0=J65ls+G+TnE?@~@I;{y(r^Y( zHt|{8KPVkN_Hq!eh<|jw$XG{Pfc{JSa;hqLgQBfUA#%Kls>n;nZ85gIZ9DP()8fT2 z@iBvB{Wvnz5$Ux%)L=}31%g5b#ycJ!TVd+*INZThaS7le70|s-ZXjACDuq@zQ z$7ScriOZs>0x#)cEx_`u=fC_JHuvw9Wpr|otq$jII(Zt}yn<8^rV0g=Ksb)JGO_ow zRkC+;6UkL+XSfSV{&{D?8mwKWm7bCqPIW)Vz4469%@Y5BY)Dqg&UNY^*3y4mi)pj- z&$^ksi@R?K$e5`6?01Byoc9nR-;Y-Vf1$dCP*6qwqaAS^rJ*Cy+p4Zof77E9HL2ne zZjD^Vu5tEA%fPV&Er=kq2R)bezj*tbY+;rsf*%ZcAc1Zi3f;7=Op#Z@Io2VaT!AR!Is&>vmXy#Ou(_#kf0!`5W zt=iVen*lo7FAl5=wAqZSw+`&JjO-axkdze)aOh@y3{efLaRQ?#fvtP|lJU5m6MYuA zpgRrylVA?G(hs#$)8p3NObP7PvO)wEDqioarKa~N0?v~KPYtEoGZCTiorGD z@73=nlem!kqY<#8+0*qH{_xg4JH+wU^e$)C3AkEY(g1`+#2vvpOsFUjZp~!AycoD? zR~qnqvtJ}w2C5lyKom*kfvB4ai^6^Oqxv-yJ=S8i4#GaWrCijG^}(xu3V+x81JnxO zX}bu07)25Kq*x3pAZaL^UfV)Sq$(3AK$9?XU@edyQ$;VJ_NosGr(sWK<0q=gq5U;5 zK+Y@A(Z)S(sKxkP*`>2XxOmj-tKnPV&t7!n&^0d_Nvc&8fjUYY5Rg2Wa3AWV*u{|6QaxiP8BDv_UIouS0$P#dSPf(`nk|U>YS7nGp@EKXROd+3 zsr4NX_YZ}*+R7f_E-Fk5+Wl}!3ugH1v{#NF>IzL3%2F7?j}d z9A6DLRFU>}hB&7abbEiDXFp;_vq(%Qv3XXI3ls|<7Y@Z#(h3Xt_Dv(i6OOh=Ro{$U zrv)OAjjb{GT$=!3PQz0`C}z~`POHs9OP(*G7wvWprKtiV-SWxA9-&Cmy%1CXxrchN z&FWfD^M44O_WWQ}rx{n;ZQWk(&6DRJwZM{iqPg_bt(%z5=_}$ROpFj|lqk9#`V-V% z0vwA^nmp~#-tRh^esU2Po#TCE1qUo|7^nrfx36&75OR-7oG|8n00F}!8bT~v~#$S_B&phwg3^0gPT(}|EW(vXkKFy)Uf6b*LaT-#g>)hlSe(N*}tTCe|5 z|57cgNm{G9xmiOZpR7w*2gbn{!eXdKi8^ne-%L>{7D711gt?kpiGTTwo0KUw>8;fz zdNu>7!G5dEr2V36m>sjJ)UvVh0Om3J)LF}=v96``CXVqM@QX7+? zuErq5s2k}-ONa60_u^9&NEUr|=Y!Mi_%a=n!9@DY5kvOi5)=4n_tZ<}fqm7GX2bJ| z+bQy4M66sjRL!E$e43pL?$;8v0)(*KF2c&WvXZ~JhWR5`{XI@sVWKI9c{(7Du$w8K zo64(CArfkCy9vH)Hx5dY98**3bdIuYggP%Pc4CWp69kXhA4Lu-e8>x}H_{QnXofg; z!3#~FG78qs>GK$etkM(`fDk%qioapQe~?7;T))cyOguS=*8A0$>+inEJp%7tpwO0` zR-^=)(%V+Rir${hDEAWOL+(59O#|p~#0dSt?gPsj#_Z>X{xJE`-}g!yt;EYk9GlS$ zmm}A7-`dC7q9G4$?!uZC${fBnJ43Q)Q-6waRc%_TY1G%?^CoWR3ryR1E4$`lZ9ZMFaCCv6tTcChu=pBMwFc+!@< z2;6T~CQR2ro)1^h4T!aHSgpq^y(xX@yJmf|uo^dyQ$(F@RApsiLX}Vb`W}}Dd@-WU z98`2ARnnnI;yyQ5JGr;SN>0mV=Qw|?{;ea-ALA6zvZo&lojhG6*6ZMX@f3NBdW&ex z{LCkQ)-wp-MUIIdESctG8iU@5`XnNb~J7LYWLR_7a*1X5unN@T-#hkj*q|I)0R9WAN#eyJ53Ri5Ap1# z=H{`3AcUtQzPAGeRi}5*Nh76!zz1jlj+O}1d{3C&I*JbXW2jTw@6_SC`;Y@pKp=s0 zJt6p({rlg{3lBhmpIwSFgLLN`Zc5l{T`)$hqi9F*K;d3vHkWJ4$6duW89{Dh^zf&|+st^Snl6l`U{W2w_al+s+fu%X+1vE0y8e2S3yhZKRjO z6}US2JaK7`{aGwg!qINB+yw6gzVj;3R%?;v{!5#cRM+E|ns%)lQO6F~P0uQ~FYS93?NgVZJ(j#(mpN+kcnByZg-T|OM#)>`2^_9BMjQu*PZ~Ox!V~Vf z(CDs8ChgyTtx!Qdr?~yvp+rG#NJRqH5dWw&_Cfj4uNql~duQAlC0h{hnG^44*%B6q ze97B3Zl!eK=G-RTMeppHZiV@I_i29TK@t&-!lsduyFmJDxr|MYhD_~?=3 z>r!5)|K&39{b2m}{4~h_ujBLl5LxTGZsV69I+=Ei>7G$ey@G$Sm!HQt%?!{Kq!ycd zd_oSe!Cr}e&@w-e{73uymR=y|zPdi~izo|aSsg(Im|)=q(Hp07Q+>|su9D|?VKPCS zvXm?0lC=vVYDoM3 zxHL+d#xtLPGa3cWhf84afCW;7Xh39lQ!L7e>GNWPGG3_z$TkNvm4}ZSItzr!noP*Z zVa(91okZw)O?vc%YtMXb{P%eZHza0mXE~1CPAy#(2o^UwC^SnaIwDezKBA!Q*fgQH&$u2DJf4d* zeq|8iqe1di;I|VG?ZUy}wOy^KSE7`Rl0+qH5MZ`8@k3)3M8$~yI>+?$Hc&~u+pF*4{^l94@){R`U` zrUSZsSnZu!z!#p48~Mw)++g2j_B`MTBE7B)jVO>&)>9b>W7Be}w0LNWg3EImuC zf_qxA(D_2X9rn{r-2U!N%zi+WMQH}>l>|c2+uQpiZuu1Ks1ZmNOm3h947{{UyM*@> zU$mHE;GXz!ZjoafW;5%cjywVZ=fydD_1jQye=~7~S$PKx^3cAC{VDjT!j+Y3P1dHP zs@SwCK=fo~p_A0aE07rLw3ct@w`JqyEA+D_H7m|8l?CI^Z-1b3EWD(;yFFFzA2LUN zNP5zA^@kU}s{kOW_ixm&Eg==A+rI!9sTMa?IbU<>sL4jP2(K9OQ)jMi#K13?CP^2n z*h>0hL}mz&CP@dYC=+)v@IQ`fqFRT0rQ5`ri2wL%b3inwt>&z$8JT94xP^tPa;jzL zh~p3;JJ6m0U?qYX&bGIwEp5dt{Pg|=7$}n9up|~ruq41mst%a^wuD*KTi0-LP>QI5 zsEhyvjggAE^$WhLEBA>`4G3}?wjTitbKLQALjFu4vaul0x}7rn`LRo){4~%X^!hEa zkQE_rbfZhD-%NB`(Log0F&*a|riN z0}7_CD*s=^z98?Mp_=-?ydzx{g4q0-_M4Jp>CyStB)kOkXjePRL&#$O6#uu`<%zz9 zBfa1Nf*bpd$M3!n$RoSBU)<_5#?c=4E*TznmgT@Z_JRyEXtooy;}ALH&9%?qktY0P zM09Cr;^YCEbK{@^gW-<8eYNT+AK3eH`<~=06~i}tcGJR(aIEo0}sFh5jExx6Ufn#Fv#Ax_BatveGwx1S*UPa3M|lddZI zQ1-wws!^_|>$r;iOYv~qEd%F*eC;QyxbA;gHVCA^q+wIqLCuK|zmyWL#6j%aCk-et zHaauS}ip zh0FSsD~wTO#);0wPy8p+2*hiSZ_iKrWdAIGA{#K{zJgS34upAKMH#BCEGrt5b zG0@TP;zcqKgnwOBVFasIb^!uKb~Bl`+|VvrRZ@_jZM4$`7`3WwqZqVovz9FOf$mD@ zf3{@x4`mSMJs&{b5=aT-^|wa=p!E|4fWMm789-O7yAZ!cZF-<4=~9PsM&~Fp z-{FjtjGGW!4*P_rNb~Xd;FGk13p!*)Yiti~gZQ~(ud#5dvwff82(CiEZ4aoul*N#` zj0915c$gEXC@3Gyph2=@jJ-4`g#vGzWh_cmB}}La4O@=2UZZESQHc3?mv4DVIXF}z zvgq*!V{2RNE3HO7225ve^K zc31N!eOK=?El$PI|0cip?i{$c5c+ynKk5X{wcv`@yFA6^8gpdcC~2y1B$MY0aFUG&aSgog|3@J-hcya^Tk%S_n_-`x)bn8 zlEYW1q`8Ar-*^10W6_=u29GzP<171*_9YX$E0XY9LWBsP)t5V1PByI(cWtCggYa^5 z@9e%UV%9zmE?65uaF%cSw;eETo{PFrojSzk?;i35XnGCpmFs*cHu|CTwBolCWLCXcA4>H?kuJ7;vLSdTKZDO#xe9R*#?18=ag)MbIXtxetg zaR^jQH$+n>jZTU_e(lT(=gnj);9p3bdND7FAa=!YB9_H~yaio<1FhD2=cSK|~6pnpo;q%wu`_-Er^^EMYd{cpFG>TPV4UMzoqg=eb5ha zk2aq-e5I6u>NAkX<|Tf+79QpA`TtCn9J6$sQkJ{kb zI##ZKu$+i_bSh7>Nl9${GzC9C^U24yhq`;FDff#KE5kRKQ96RA|9EIr?N99t2q%$k zNM=s)xPKA)TjH+eib*wn}8B;NPQ$h$|)?hGg+NOC|k(o`96W7gKa zPKr4a!Zz)ZiMd1(&-;dfF^=5a3m-%zC;w-5LPz+Y05UrVZ`umux9ws`Tiam~fR%eP z{|}~@Got*bhruHA6dIz+LVzq8>7o_sfwL+RL1(=lNeAbb@3dYOox4l{Y77}FkC4#0 z2NtoAIZgt?M&3r#lK3^MF19Q zt&P$WB%!fPU+hJAD&jy)M?EHsIQ^WQe~-h784?&Kc%wfUWXX(Z_5vQ36JexORnTOZ zb9K9T+Up;Nc;`CJm6;L>sBTah1klww6@F)phl!=?|@E-X>);ZX*qY3*FFa2w9=Atr1e=Mu^Sw%F^WxVj4S~6x;4&5$| z6chRxhR>@B3D}Rq6N@bYM@pEG?a4k%6Fmf6=T*{L(nxd!vi)VO5YGEaGa7pQvQS2n zg=>oZ5Vtx~Dc8Oz7>io2#Sa-qc#d`??1qI(L|zD@&OAU_ke?nY(vUBsl(A9>b|P>G z8xJC^`TnNiPNs^SVhQulOQW&C*3@EBH@=9~hizV1J5XuZsxIy2X<{kV6xKK2y`3;H z`F`D$2}M0lZlqhB+u$WT)p7;djDczF5hzT$jLm(4-PrNqqaRCb5-MV3;Y#^%PSCJ` zlF0H4A{0>FlpIu|4wzmVHw-1l(FK%xF?;{t7 zi(?r?neTIv;z^=Qxanp2(Ap%M_Tn67m_eUYUr<$s;qZT9`863Qdj3{E?&5WHe- zvCjha5wdC#Mk!F-Hq>ornnv^SA`{;W@Mo_KU?FWh&)VV>Jh(uvpB{1Ty+!^U8Pxj2 zw1n8f!wl|vAY+Y;6d2eHnDleJ+ToHw+mSRsorBm9EX>z~PZLfbgs7E8>oJF)C#{lq z0gm)`(>x~}Fh4K0Ban&M8mvQq+uZT>5ibJ&m^;1s*qU?5h$xGm#oj0`XmQ8XMfvhB zl;#ROyUU3rsjR;bN4M|HN1e@p2ent*kNc4g8cna)CVFld)A+t`oFL|+tzukmyT+Hf zoqNCclyNl+uKKO))SVnPX*-0r_0wUFU7xqSpo~gTI1A%u9bPNhKK)yAJ!B3Oy_5oq z2d=lioh$rv56jcdCS`Mfc^!L&uuL;!S6|Us3o#&0iDI5r2w+;W60)HuvjfY#%*PP9?0W4Y;$UFVh`ZLig~y=Y|VZ{;q(PIrfk_~mz+ zc{}&RgP_yP)t0e`uftiWM?PS&-gmU=k!T}KOIq0BB#8<+@X>8W2Yw`0srV6?JI%fZ zyzhri#|I!7(QidvKFd8~87_O`KQeJk@+ytGu3u|M?%umiZVul4 zj14-V_Wy}i{A#4}VaVH@byy~M2ZTN&Hc2b3A|%t`{3U<@1G{r}ipIHgOBDW+Z44(j zh0IX)UTL|;btKw&bjvfnqe~wj2;&?{srt6pd{9_jcOo8L)NSnisW%9G@yvE&KD$`5 zp_T_r#_goHfkyD z09sd>S+hQgG!Tz|bx=pS;H*5ckOX&Lvc$Gs4_p;1iGXUc;L0HMX}|m-+%hHGSj_Oc zhDeK@1C+4X{h&%OO_Bw^Wv0ekR7zFzucVy*oJlT4j>+2tgN-SgoKeiTk}4W?94a1{ zi0oA9znY#0QvA_}V;MS){o>s=;$@qZsQWtAreI40;dHRpw0ik()>Se9bQ(J zv^}YjvHlmhvdiA8;fc{IwSIZ*H$npeUaNCC&SiEI7GGnC-=H~yON z^%=cvLSteO1Q>@%V`oRlckTSbM|?g8_2|FXohhT+dQX{pLU`dU@jLf!p3Y&qxe6?a zdQ;z4NBHmmqa39y#SyLQ*jxPz9Qm#FhXbGwxM~@YNIQptRnr<(H{I*&(%jR=h0d#( z@n-f9G50- z!mUJH&4yH;Dq*RcV$Y+#9A>v|6%GpN$7+k^df}#U*YCdF|xP3sVq z&HZras8`z*lzU!U=W=MO7}ocfd3B+i4QBrE2ZZe7PpzQ4ontU58yF$ZE&vi7r~!h8 z5k|b;^vj!$9&H|O=pP5YZDvaA`}jz*HLA7IfjhdyJxWeq*N;HCC)<6`aTX6Vm}(BC z91>QyueZNkVaE9~6MM%DLz&-m)eqKgiLzkS4`G=)3ii_yYoTskrG*I<1qYQk39&sG zyz^VG;zaOx+`MA6BqKTp18sOVpoYw2aWZe`E_39Cz#aE0j9X8!@&ZD+8LUts>HQ@@ zD>sYcpnsgo0S_Bd1XjgKVBp6rOz-5}?(B))?bt#RSwMqxYqHo~I6(%!+FxpHFbP!H zV>);iyI9$ST051Ldzg_`)A*mk@Jr;`GdHm|j>& zf$JltwT(DXIqq077JN}xdq>@YA1Ruw58L$Y8qcRl`lzGCg`WPkQ#~7E{5N6Csv3gq(Me&Mg)ROX`-?ycP=~?TR{Hh;A3!V^ z+CO4vTtI~whD{@_ zyV2g>TF=Ycz8jX1Q9pZkHHiGO1`Q`($dI0veV|#TLh71f z&(>Na9=J0Gvj(`jBxigImlFW_*9+ieq}n}I)b|unIW28xf=TNNl&Z=$B?LMKlV>Bb zWL`Q0#l(tw8^O*b#%V^WDSQ{eCH`cOSxwhwJM>k-*?j(Km3<2iMFJV{YI##Jz?`|S z{yQ>aar{PU0oAdaJT#7g0#kZp#jGrjH-b0L^&Rt5hRP6qgy!FKPMpqtd^*-kDBB&E%9zo8+4_Jn!r^!-WD z?F9ySM5CpO3ok3gQY`~rAuDAn=d%XzAoIHMd?A0ove<;7$AV zB{Kjl?rIVbC?wnd)B6X%Q-d;y;4pQ<(!yvDDAwA^qr+*0gHI-Fod2qN7w|n1)Td3f0U@ITcB;WCLmjdgC^!_o*%jl7Z zahVVJH1|G0yV?c_p=Rj}iH%8ISP=FM1x}JBV3HTVc4%RzMGnq$ z){m!3nPPLv3N*kokkvK8-yJ3yN7F)3p=awLICM;~&4V&}gMZb1nr^FOoMt(8z8c1U z0FAn0%u64{NxzIehGky)NjGt~jxFj8!t~=zw)D-zW|cv$ZeP!*lbElFfnY5DC$74F zZoaRIyW$vWy+Vyb>8)~5;rK80?K5Ym?sf7v`!nu}FNRmY`^2d~kjBkyN7+9|ujAtE zx{wTs3>J=K)4xstOEu_$@v4R7OB{B`K%&GEsehuZx&RR?L}Z=hf*`e^NwO8k>;i% zw>95Hq{r5_9mKx=II5JMDq~H0uK}o23!6e3D?h|{X*Dlvnlk^lNjTpU0ufj$r4Uu@ zIjFzfB#PbS#x^3!${}8`>Ri;HN+^4^j`)7fk0Go5`w(EYjsayHT!@6+d!JL~AV_R9 zvqJnXsP|;=-Acr?yt(3fnxo(~=!D`4N2}zyt9UGU5B8KS#&!c?Hk!6=y2d|%0QvXy zu#PApoQBMB#dMj!qfNl~eINL5=eBV!>Yn?pVPD3%;^JU#gPXd{q?<_QPutAJ+r+}$ z>5F!QQoOQbi*{ai9P{IuW3-tfqeA>l+g6CL5%=qOQhk(Kg$H7JU3`83Hwl<#RJT*& zc{hM80^DPANkw>KkfYbj%dJT%DUNuzSAcF2IsV5tiQ(;SZ)w5cAqg0;EXsC$1sO`ckcjwytSxBrLz;nA5r%uCIdpM-{^n>5dhQ^E$ORd=pg{hWgSi*=N!rb3^Ms z)}y9q$R{r~^rzze_eQeMQA($R z=**)9jYQ1Ye2REc-XH4}+W%N1%oUGHxsBF?^NFcPrj|ZbvFL$8ycf_Xb#uq7Ix>lw zAuYA#Ruf=r$C1gf5^a2cBM)e@eVs&YCT8kEz*Lsk_8*_+^B!fb+Aw0R;nK^h%*JqN z0oY}4?gE#k&5vHSD8F>&(x7qWu1%Z^4z#4s&@Q?kRvjAoELxo+tIQRS5n!+GnT#x( z#|R6nF&>CCznXwlgVh{somn(7nG<%rg5`w9C21lF4<1S4)w=ch2QD{pM+He;O>-0%BgkteJqadZK_a{1mNsk-P({+#ED% zNDc9U11jg3$^O%xNl|5z!~RLuh*goeKWcJc7nfH=c z4(pWO#Gz@GY=`A9y2lBceAMN-=uVrH6))~y3J_)VC#EEBUb0t_)n14*djxe>wfsZvr(lYiy0(AXn5gH99Gc)8 zvMhrt&4#no`@02d>lAl)JFVkBV@6juqEV$DyH3jvYqTzVol@Of@^eHsdt?vHc*PO> zbL8>nU5Q{>YHPg-6pr{Pt$EKQgA3wCWbWn03Ot2oHw+q>HfJm}O73#+HRajnZ3+Qg znFpS?X%pk96x~OepV_7y)mkJmLURN=mhA*Baao;#M#_fbW9%EI{2ZM?H-q;sJ z@EazBgkGNId(4vy0Nt(2PByta2Lt*_1Uo}xs$s)ow*Jt4dViBz5Jx^}F8kTAaLx22CWo|yzVSQD$;EVD2NJDj3}!Jp#)75!n}8J)GsJM~5oX}X^?%>)u0&#gb9xYE za+~S<1 zySY^o|H5$Af=UQa50g{G_ZC9ObimHu;*Oge3ID1b-B1`B(0p*mwFz}=`L6Bfz&j%j&3KJG`TWQU5hEuBs$ zU?8{gop&D(NCaaxyn<09#UzZ~beLAX& z{EsyKKcPx4ZuYcV*>8=qae#0HmcROaVH2SkJNH=*FpP-5``q7^88~cTI9$KSB%&9H zh7gM+`X#84(XQ6NyiI*xwRQ^IZ@SANXfgcz-Ru2vR@19A#t71&`unqk5L(Lr?lRWO zm24d=__;HLN=NLwnmdg%hno%28TCZCv zmi4aH`%sl_R9FpLrJd4QlL}+*1`sdU{ohfIzIP$b}qu=B>>=GzVcu<^H*Z=@0+14#Z%8z5>x7T8kcv@?{XDa1M5 zA-2OIUJMm+V+WO^>CssBSPc~b^s&PO<_Un1&YU+(`ET?;2IMr8WghWx+MvxJ5K3qXJCli1~M!Mw=#M;`uNqaO+K-x0`)Z-}8SC=)cjxLtij{l0_9^P@BfM ziDr~Aje^#FXttsQwOBLewn~LUNUBlQstX=&X(_8q7@)lD&w_<;AwQLy?6f~{2~y}v z%)(`nY;jfY;H0j21`?bCI6;h~u{#BrozZGdWNV>}oyhYBNovv%jICot$qVvWN6$2% z8gK*ZnbwPaD4zf?Y~JfGlLaVqOZ&<_JP>A_hDJyQvUMH6Ceok@DtXLfW-e_waJNN1 zw^}o$%_vxNE=mgs$dkMl>S=lqF%2U~XW^k0FwN?9G35ctaI|L0U2-ulFgaam~8^O&K2)mka(0srnDzhrwj!aQk&nD zY}jMGlEi6#)su&YVPViP8txoDB3ij`|5n`BcJLQ)0zE!ZTu?Ph+(uGTj6+ljRZ9K7 zA^WM#=HLR9mbU8PLfDLkMl5#3S-|v&6_ca6sA}j!^1x=F2!_p#{hFnPJ+))TLZ@4# zKZ!oDBrWjKMGsS}_05kwvfxns!2bK?ndGn|(3I1qY-*{3{U5U4GAxd!*&hzDNN{%v z?(Xgu+}$O(JAn-z+*u&FySuxG;O-jS9m2c0@8>z!|D5;3veiA+)%B~YWoCMMs{B&| zEe4*oOBRR3PAh&L84fW4+d&1k>v9oy=N2D>PTFu{DD5^neafma36EIQ-#j3q5@^2S zNeIGYH@jm)X(zO zGXlF}+tkDaf>W7iiH*~{UA=Y_g2Lnp7lRqIK4_T?MIY<2Om{LIn4yr1O$9k_-GFu+ zYnMpo@UxyN(q8*`pm(?ep%NBxV*kZ8@pvRi99^&_?@bs-k?+=FSZGSi0B2y4>;Y@v^ViF6S_oylIYFSsjAW_UH~22gMioU((5=6wpU# z8cH@x#WUbZYR#l}fOdyJ3I~3f!8`a^}tDKc+uCt_=Rk6K@1^AGHehp5;G4i5y>x*8`t!7(6|gQI8g8>2*@0q zG<%&yCN#C}TMUZ;ev4(PRq$yr)CvFM4dQ(O9=SKB`DOWKiF+}3S8&~o51y`92Dge> zRs=ll>@xiMa4^Xl=~`(8$7*C}>FChp2`-%)`91|??wKTV)wR0q7I{ASdi87h2g7J-^?Bm%CTZfJ}3Br_zzr2~U{ot=vNi68#Bu`KN+cuK_{rtkwANUgVE+S*8 zTy`4()cDhhkPk=I@&pY>#qu@bak`ipRegajbpPXwK-8*8&B~u_IKw~BdXIc8{VK)P z?`M9vdTf|{C}>jih&|S68<1#HlEz}r?A@s8M?A;#`x>~(6#%B#OIL{~dEGOc0TcbH zD1!K5EVig}OpLuev`V)s;NDNOzH-bk9O;WTs<3H zfC;j5)iJyrx{BLLxD9M^tDd8zyWfZRWO9grg1id4d;w-;%gWNjYa}V{;?#Q;6V{(j zSOznk+Qc0ij|$O|!Xgf4piAKZMJbW90xTf(bq*B`M!1X?W{rj&OZ745<4n>*uWdc@NrdAY1j%Yx|8 z1KRQ(NQ7^74abbVnY>lTG1Q?&Zs1G>$p)WSMm)@RDDV=#*M&HdiQmkHT#g2hSrdkk zho|;IJ5rghKs%OdOyAb$<^32@_Gx~6bCZR1%1|l!dgWER*`?43Fn#7+twsY*oEi$gmsXFcml@?0+vYDX4Aub-V3r(l((pM6&La`#91 zY-PJ&vJ)savTY{61Hyc^dAn6U3ls&g&sZb~OT|Z-L7c(cFJQ^&Dd ze?GcwLFj)9X43B*ZZP4I<61xt1tNNCp@6>AmALQJyk624(U_!qxO;zKnt;@wg*+jx z*LUQHiCZDOdT31$bM8?VW_&<_KtKA%>YY(Oe3tcU>aH#9u)FbtEs1l268LSTWM*pJEI z&87ZRy8ApY4=<8Nmoiv^QZh7a@^$KPG{Q=gxr@!srIKXnDgDgN!Uf#9T#y5twd(z| zT!k1?htAM+{BmR72kG#KoZ`O9WGv`hd@`4A7Ny3S%eQ!RIyD& zgW5zMoihx9g}o^b-ZU-{x4@e@##qt)qFBE;^3l{8`xuF#Ir|vWeX9M4+VVVx6h>Qg zG|r+00bAKPf6aypS^1I~79Xd|qZ?7`GZbSoxn??ajO7M8#l`eL`a31VZt3APYo#Od z66fk))vRZjn)R$!X<_^R_y;Jm$u6t0S}o%k*AV=JYb`GsI7`mD+l%gHrjfFV*a#wo(5cn9GUmpY)KCg65k^+$|eSfs{b0%H1&XS)p zeqN*+-N-ZefmrKlV%*qCV4S!_@L7v=bVK=Y`gmN82AWo=ail$ec)_FpfSSkRw;Z>*tx^nQu#pDY% z$q;r)HqnOGpLZ7xp%-xpyIGWvVkcgsEAfBV?&|S)eBC^)F~+yO0KE|$I=w)6TMtSd zWI}qU3<2Z!^PO9VwuQ2hzEBxhH%3kL4R-dN?p7VE+u-LgT__-1?;}Q;n8?wqnVMX6 z@G(}Su&j_p>5{1FR-&_$!2s>~g2c(y}w zr!tJ9ugDFwqqac!{lS&rGMFeo7rl5|IsGvCfC-4$z~zbLHc`|+P`C6+{OF=-%9smW z;J45dTB0SICWOwX=UA&pcK=Wowqm@!JLS*(^f>c@>d(*wru=KZ zmbgQh1hM+H@`j7q_shC38=Pp!24tPSyd#m-jS_yiUH;*?Y$$}+mg)*$go z97}-Ah^Y)wR}RJ=-*F2?Y7ugzd4g*k(8F@P>%?!3up$gA0gTB+7+HO()-t&LFoFy2 z4qotr(WWy324vKI^&C}%Sx8m;H`}=@3zWVd&;34)0=FJl6``_Ix z&LR3aj^(fe*{=($?zUe{(rW28J23gq(uRPjJ=S%|KNI0PrXXc|!~cZy%xCBr8tqGG zQk+E`ei1(2b34%$YdrSd2q>F#!e`9saPvOr_*F9oS?`8NC>;y}Rfz-MyqD^Y4x**KU+S^c@oOg^va1R^ynN` z`Mg7inQQhH7F;rt4(6Ezw5Nx>zmPDfC0qUfQ&@1a{dd0_8z%?Xe@k$1g5v!lFhKD} z0BT^T{;~@JH+JS14WYnT#bju+)+OTIrEra1d-czj#MfeK_TlWb(3Ezf>)nr@?ylEQdpChkzh<)Mf9^aDj@G+cVy9>iVlglY zWd)PeKqn?ybxnz(+hF5xQ!C--3md)S06zey-U5stbFd%tBgYe|zc?CoyefHBY@S>D zoG017&IzwoXr51la3X=Ed}zj*kgNzrB4`fS={B-a&Va1!OaXr1`lUvr^u#akhBb*_ zs@LALy5F(hGdi_jclY+w9KWE;6^6TYq7Dg;-u=uB8o->^T$MR)T7SFStIp1DbL0W~ zlcVZ9N(H@~s;dOv-tHu^hItTjTNHXURgNS1k`f9u|JZ*Q;1&l=aTxzZ{VZ20u0>Rc zB_a2F=axprBhV#F*`FTj6P$LO^@m`R4?n*rN$q^NtX<$XMLr>j*S4<)*}L*u*;9U; z_%^0X#&GMzS>8nZj2()bn{b`qh2&xa#H2db%b)RbN7$W0z)G#C<`Peh!bJ9VmxrMS z9p|)7)6?Zu<;|_-ggz*c^bDF(*=zOSfm_} z5Nc~&MX(sDHF>s`6pU(YBQADWSa@!_a=vnRP*ZPnhR5Yuv`qbG;!ALAgOVQk_R(Ib40nqg21r0j5;@xI|{$T4O$c zvHnvH3F5lw-T1iZ3;wQwl)Ew<5XOELslu$!TTQkj@A#$2Bp`~M;V=(Q*HkTZQ zc`-VXz${Bhi26;9h?O-B*NNhHZV7_X=b!*A(n6uptUR|5=YKT8SsrvlfNaIBt@d)A zTX|6|ZNg+c)~!2sW8dL~P*8fwV%rzO6k#Oz-_b9t)6bf$kTM1L=r~o?;K{#b@yKLE zv^mo!m_1s2*R!ub(7F8^t85kxps(W#<)f~rT3Io2utJ67KX#Qazhf4>QI2ddQ8*cKw zXvPC}hp)-sF));rh+1GvdolCzcQz{Bed2<<|MQ%i7I%^yJvqjY1Hs)Q`4mfb)s84|;+2qdh zHJ8(&y#=hfUx}%bsHyS;$q%fWgjIikC>cnhio-~m6hnTI-9xTuDhSWlH$)WT!oS?? z@IOQ%bGmiA#_8@reFbWiIg6eo8PumvIZp&q{93@Z*>SfL!w6OLs{R-euzpOgK!Y1X z_A3iqUFQSsavwob|MeKNlbMd9dsY+kf|k{GM~kVt4Sk411s`URgI+T!^j3Q9UcV*@ zOnq5R>UebJj{*9~ZNwUqM7em&dH;6$ovU&eUh8dAcrv~t@M22SL(r170XM1QX#<&{ z3sehBh=uFcPAZD_Y5=FRPCP;be zl`)#R&mrf1>kpSO^;s7J9eD%VcUG~xO+IDk+0yYW3N&ka-$@fXX3+*>p|Nny>Yg{> z?$?A7C@!))W!<4P`%8IR5a}i4b6Z^uM_uiuL-xbcJ6eI!%VkMPM0RXNW!f`pOg`k7 z&Py9x_57BpWu1D*41sUP9)eV9QPM^%<2hwXk>sf~{3sae%BE~BdFVPax6GfG21w(p z+J$6!t!=D{p=0;L@WBA< zw7%!b+$0ZJ$HVT<{(A&~u;vAC)okZGezmr@|G4!rO>Y{yGft{4C?IR(@;E$h?jm?m zsE2y3l^Fc+vRQap$58A8)&VSK4}aL8)ReO3q*#AupxFac)@NO8C5?1qo`*XMe5ncX z{_kINTzIU4na#B%NpE(V+~u0sWMU$rJ~Js zxT44hX|LydnC-x$xsf`zvY8p$e23O}SM=8_0~ugr!;`+_%}4gv-2Py(bSIbaMS~uk z2(-%N6Y5Gtk|q3z{cO@4zQm*6HSKlEw~6R|$~W;BhIqo1r-=07#C&(qEj#aL>N71j zY6IX}jT<$K{c^R}`!7-(-040%Vl@zc%N_L5v+UePcJ>>d9GMM!v(cI~ZWF^7**qNP z{;4)7wNY2Pcyrs-Mhq_-P86j|wqL?o-9j&%Uf^wIYUi$701igN^FC|e2#X4ZFHoAR zqJ}HX&N3Ry#Vz)h2QRW6OIvpFbQvXONTa|^i$(*P=J5juxa20G_^OyOCox_(6%#>1 zs#?l2Oao9Rhr-q=wsnPufN3BLtFnM9c3mC6VqM(V28J^6h&r0Mp^-eUGK$DRc-w2* zy10ATF-SVtItqlGd+Sfmtz@9< zw*q(vsq#F&f|3YG>tH&YpwDGAIaJRPBxUfLyk?)vjBOg|z%!N6#C5UpmcU;U;LnR% zE3ibK1=_$2PttUUs1soBSzs z{^+ZsDinp9VVKFfpBRM=YU@}g)-)~}SnRF`W#V>fA>=33(2a%jqYa2ufgBzI!9xe) zL)Z@lFH;LRP`{vTzC@)$1US7#EfKHWQCSwDoNmzg^faiLLsBy9z#p(}o1tr8FKeLiA zzCC#PB|V8XT4kUmayx95$cI+XX0gxntj#lH+3c+8=k>MqT3b`9aVg^$zvkvJfi6Ef{G4+15g@x8vD)4a#9EBu^;gRr` z_e+f9neek*tXQ0nclkJ~$qg<1ewRCUJ{OuhKaldjTt9L12tQcDbtL9L(JM!O*A-Qq zNLp`iJ2iZQn;^C|)`+qEfgPb;QpRp&awrsm2%uBE2lJbp7Gx<~D&!>gDoH zxgGcp8>I9Z)XN6I04ZAmJ_6WT!NnF0to|-oYsoocu%aGx>_|T@eIB@4+Ffkq$U}=2 zYeOgWp&f1d7$?n58wdQg)NaV7p@v={K|h#qmiBb;BaHe%-pQEk>m6T)<-@XIPzxw! zJ1KKt$Mf5Wz=IUN`IEio#}7AI{N|e0OoZdb%d+qN-WTK6f1)XR8Yz?9*6`(2pJ@1j z5Z|0i6FvB6X6C&(;9ye_=o`x&jgS$$;8)>!a4Qqgb&j0$=}xp^zwtk0#F!LHxSnM$ zs|O|!AS5J>oZ-`Xm$pvt%~8RPR^Hkp?q5@7+`8O{%V=QzAli$8puuv87Y#gzy!i4~ zu?qa9xi22?F3djChO>Qmx@)WZe0VAeTsV;yRD%7Ic#KK-p}#P|IE)^npB=nj?Nhq~ zgV?!y0N2y7r`X0-a{+;F5s$9AFoAt?l6W#3;WC&kX+VM-mBf#JugXoj8sHT1q5`)l z^rSK2LH0V;gT4(6IFoF7HtL%u4s&Wi+U~|FKN48rO>VF{{yO&vlSS^`dGx~>NEjXG zi(Nw|bOm>=GTv9#t>|dFRU(8HF$WiE&y&o}+KC*U*j5a)KJ@hKR_vXpvjp$kgG2Uh z!ZFV)Y)7)u_~^PF{VLq{O0Np74=C6^AAgf!7^yXYz{;?)O-Hx4GqDAw^}{eJ&ZpL^ zoA3f!>gJQmbqq2nSm}t7-Y2dZAQ7A=M_EqpC`{jXOvS2*ZE>ABSHx)6t`yv_UTPZ9 zozS}Co#hJisQ|4$Zs+zfW>`T==DcrI1m9(IvLt2>$iqF8gFjyM z1^K4yC>0NuWgzCG{>(*BoLV*QtkA9{oG$+QL95obwP{S!||NZBg<%zWnmRFt2I*VB|@u{Lt7R$0y22xex$0q>y)+!f?rG+!MPE~}9ZA95) zPd>ZXR2V8!v+-z5%o2@cSmIy{%?}F6UNlui3r;_Nxzr3BX>-q5D*+z6>3L!u`FF-F zT0TsqwaYgM0;8_zf3iPHQyEi_R;=wVm9x$0ED6cC0V)v zoe&`5M(`lWo`1z-f|7awnGif6wq5`gXuAPm2-=ziiyH3*U_x=Quz+@Y0gitsM+8~) z0mA;FQu_ZxH2>%ako}_?B4~Qxznyl20A(GC(S&;9tDg2mk|u6BJMcaDn9D z1UYvAFt9lODZr`T=4$yWoz~G;0{_@2a05C8)I61+!KL0l#s5cj21I59` z3W68~U|?|mtx)>EIJiKf3ji0;@E8CGg1vcj3;+-DuTJ;lVC4T`44(i~f1x##|NI{u zI+Opw0lNK5ff=!z!+!xjL4a~*!FFky0+0DiHOo%_^}s*F@n!*!5Y6t3fDlLsUeL=j zz!0C4fd2FS_mu=ycn&T$kn0K{8qwerv$&(XgWD%oR@P>QRRBI5==1`B4HEth zwzS9=c!P!SF4#?WR{#VM>Ky+AfRFtjkwpgp6_DQ{;M2b|&>aGp|IPppaySH_ zfb6fpRP`F*<3D}P#fJbqxa28l4A8~}SXA`p{{;sR>bU@mGPnfr{SRPx5X&Wi0g|2V zFILk3F%S=E>Jp5a_6n@D@D>>1);U<3(G@`HFJO}9zAFGT_tx@7zcK&W#89`3lz2_ynxuKN22q!NvwlKuCG`uTa&$_WuXPKOEVAoB#C*Hc0sb zKnKao12VY+yYFu|3_CA3JUcIF`WYPe=Nn+@{Fi@0-2?FcE0_+ne*a&Y|5%Im0c@?x zJFtYQO#nNn>u)n=6Fl^k$i9zYDBu{u{(Arc^ko--0m;Dz znmz%e2IHayNj?3mEBRlmLvpZ#wk`n5pz~*d8fg9rAOY%H2M>#T0V4pv!wR-96D$V@ z4?Oq-x_SXfIjz>)&uA2JycCA7P;IziRwPWlT`dJ6Hi?2x$1^S7^*+d}w4)%n?|_|4}{J3i|(s zI%ppSng&Kr_p^kW90&syIvvu}5mbu`?FeN5=O2QQ(0|Hydu22x`zot15)EHim|S2* zU7T5&ojdSz2;myiVoIvHv82kV11hjlz3sj0QLxQ}TDIU%JG%`wsx8*{TVZM=$mpa< zDZZOl+^JN0kX6n%G_Hgf*}I(IPp#CO@~0^lvA^Zl1J^TO_zz!&4qsmMf$7(`IacZZ zlzb+$p)FS3BR^|{d{hb@@w2pz!NR{RMqrP2NBwB|bEc3;tq`*k z+DR3S`T!k5@`|a&P^1F62Jq>aEK{|7sbWmo27x9*_pz!=1glij2El##N_b2O0S?|j zDDSltU_*~3{-nBELPHl5QQV~VqePi5YDG*^)wT3#4$_9S@w=NO>zv{-TBexME!+cc z;^SxeEdMOsUvh?|hSCM?g`mRNG&{?rJD}o=a0d5btMq`@V(-zlGjJx`F!_5>iD3~4 zA9T?l=>({Om~rbmFVPqHiKv}^;bfp_jh_u?9S7^IY;3|gafdCFqLgi%FisjV`#o(U zw5!SsPV$Zvei8|0yC0pfXh^a&C zk+mrJRW>0oEX+s8O~6|x#iBSR2*wgpoQO3n5>Y=5JtkdNMxBhPPEM5zFSr)+*_AQETli%B;)A{ALK-hhntf&6RJA!6{P1(Jg ztL{$O`?mo@hlWT}F8r#TE_!rU^!<^kyl=$?YJA3c5FK0bBzb6Wzd!2sY@270$pzj% zxCgD6%<^OesHLD}_7e#c39x;}7Ro&vJyr_zgnL5tFXvNfq%V~C$j~aJchaU>JpN0z zpQyG*d?(Mq7HIC#tFOZd7Yem@UK2d72kQ?f=LA3=@aIALk|WZAUMc=3cDnq#b?C~Q z6w4XTo>YZ4b_A_)cUZrFz)Boe$mS!)b-HfAK62~ehp!kljK;O&U%u}UDPr1S1f4pR zEzqME3^|Tj;@Vq0t16WafAf1jCDo0<4i>mtPmfEiN&s$}*8J)gRXPNccSW0aB34ZC zdUaIY|K3J3b~J$RQ)P%o*8Y*^d>Qohsf(!umf$GEVY!lPMMZ^wn)M{WA@`WuB`5gN!zd@rPjH2z@ zUIFp6AqWI-dFx%aV!wC0h%e&#!^WTgy_HIoUZwSPbn3!?dFoRtJ`W9F4y~JdL$e2G z2auwfoS*EApJs@@NCRg5W@<@&!A~LF5b^U234G%v1$Oq_St|@J9cx^XeJFG{9mMxV zq;pQEqT@HLqT{vv(SwI?g9*3xtAX7#=jBPjx@ur~o7$%3Z@NHvu0|(cW0{TlFrP_t z=z28m{7SU8SAHU9IAN^6bc`hh`*iHtK#>M&$zC!sVomtX+4E z^zwCzC&RzG%8XKMwA!-8s&@> z_amaVJoL`05yP4F{TfeKFYFDfS(e@C_ug}kTQL+w(dHiph(^Mna0(|TKA-|?{Wx3< zlUoGzZ7pV-3olHfK?WLlwbvAs?p@@_o!4uy6f}&YBAY zOvsrsV1;0uuWYq?-#i+0x3KJj*6pz?txv%HEPw;;r(og`*{X>a8GZVWbibV1VB4OB zQ4m^+>q}S>(!l6DyZjzI_lNooO*T%u+eEx<_xz|9O}fI(KEclbLg`F?^JiDVY%4~M zxfFI};QQnA!8$MAlgqdwUapbZ8DR$p(D3lX{bjb?6<3Bx8{LGQL*_^_h<_wwbs1Ef zo@eqourJKK)7Ng$H$tv)C1z$aMp2KM+iXYmhwUhW0tYHawOF$S3+*fA-E8*S_oH=) z@R~vyytJ+=z7HG0+O9Id0qf0niy$X#2cA%3k}gAE6o*B8&{-fcBWQL|B`dTVko})Kpa17-K_kgmS?vq{(63R_ z(OyZ3ZS{(KiUvJqdjnCG0XZ%FLW3mDT#-WEbg?}}mNm@Qpwvq$QIVeQItW0YWCDw} zy1qnBo?d8t)gY0wNBenGKcrf_?hEmA>uzY;Oj_ne^+W81FYw~!>o0LNWU>fgk##Z3 zgI|m11<8gw0OpBd&c%e2u>$R5HOuJ0c`LeH_ra^1ti;L3dppuyZDR6ncfU!ATjXbt_LyD20`S{whxy0_o7fNsg+o512 zNS&5Wp^eTaw^%GQH6x{LW&{W|uR^DQE~z5-*5q)re13A&=soUpfrNQScZc4X;8Luq z!mKu4ij_paFU6}$*cj~6q$DC+ivG;_tdzGX2}<>okA*smWAH!?i?Bz(Lf~_}54}OK zeCKB}9yBh$j0wjUJ9ulIZCts=aDr@*ELMtF`&GPl!y zoPlc`)z9Tl(j2SWW@BBUXdclOudRiP&?*)Glop$EPauVe{X6Jor3`%`ozxE{g6?Jl zT(7%~2mFZ4)J1XURcz1qRZ8j*NW5#v-X@gis9S3q+N;oq>M2-EWD_9y5bkJO77;bb zM`ZPDL=|3){Z#}hHx&5o;I*EQ27(LrT5)uQ)0%2;A#0YPjQ(jOmmdqe1*wuGo3SF6 zUagl@CO9Y@E&aEWS|90$jd~lY_C}yxsAkiHwq(q?8QfL+wHURVco?33z)q!7xSWJ` z7G0nb1t!l;5S|0-8XnrSEPkx*h`~9FL}Q`Rqz&_F*y`z8 zrMgGaIWi4*vz-%GV*a4$pNzUTyzCHPrXu z;D3gZsaVX+xP$d)?WY%%JhAoYadY|L`Le(HNs&Rn+OD|KTKi);awa><&%V$6GYkvB zUvR6JeA2h(X~#hg%Hq;&z|y%T=)k$c zgt(a4;5)Q|JJ0=6ZeOQ-cRyn&3EVrYIGuJp+ms;*g^{*E3)&0fFyIitZ1FV=FA_Uy z;6I2W${DU;co?IN2>eR7ene*6WbO0r7>0;&p^EiScH*r0LR~|FAQLGDF%Ybi3T@R! zO|D}e%nyIjY$Q z#!9aQoz->!iR%SUwmVhwb*66ud+PVpFoXom}d^~YeQ5974#Ey z4%8i8?~N7+7=q}Ns`6}J5`FF!c$|%E*DJj?@Dr8SS%r`vv$fDhoA!iV-5?mIiM^0k zv~u#*Zg=*Ng*Xj$Z8-XLn)q%@1$(E`AAPNt%V4CuR z1DsD4QnF%bvI)PL()GK@ouJ1IqhEPe%8N zjK&^IQs-*z(PHu4Gx6KA(c=0S;JAR2m*qjq1^=Pn=1rFCaLmzKcx`?CNte}qhkN9g z=!|;1`A6p&*tbD{kDc+%0WI^af!F#X%F(Vr`>f#I4;G!ZHPkV{v%!(m(*x#Z9%>pM zI=Av_Bd>Q8*U$$NVf&S&KlPBE;>|v7ju+h%f@{C{rvx*)KK}0J8*wf7^qNZrABKFc zPMCx{=^o>s;CBma)>>6K1VF=-_jQWDFe6-FBd<@g93#nnk+gr%@3!-Bi(3qBJ_PtW z>I-oXd>QOe-b@DG^uKB{!fm$s!&%aQlzkeiS#LLjJ*O{fHpwv$DAAZf^`pkap&KYPe*(7;PfO4wV)? z;bO_e9*x(JXv)P(pXxnvGNEnBQlF6atD`r{%+NxU6(JRPHGyi$Ss$0ygJ`k95}6u4 z!7`MlGa+vp%5IxRIbm)IsE^SZ>llhMUtk|kU7o!A*skT&?XWdd?v#J|$G+d*pdB+;HszXbRh3*eQ>%gh z5&qQO0)kw-!f%i6mo{QM6t!Q4g55`)rCPcd(4E~bsb|XhUXo}9Ef0AIgWWe(e$V$h zvxh21+{1=3S{c`d$L}*=-tId(_V=l)gS!%F;l#cH>tfk7y&Jj>-V^=|!!i(Vafxs$ z3pxGnNfE_>c|uv?_FCI2(c1Lqw3R6)l?&A;Jm$YWt?}+33w>jIo%;?>wGFJ*JLt%h zjuc#)nk9qhYNz(R@(7Xd2x$FUqW@+?c%*Ou$*pjn_p3rJqJ3#y`La>@OXAD%Pynn~ zuiGU%&=q3;lrwQfYgu>l`FP&(qY1>0qIYZxh0i<^mvj6evaaRmKmeoM)7)1-OT>Y1 zii!Br0(#vZQMwm+Cw5zqOKiLTYEVmC!CebI%S%YPSjm=VG1CPC!G33Gd(@*=`3nUQ zm1;`LeelC|TcOlk(hK(zAI{(Qk!2PO4u;%>KN?=BqY=JQuE z_2ttogft$si|b^Z7=p-e8!`>oTc)abNBDN3c~)>C5b5j|E~p66Xzt7CO1# zf#p#Q@UhB+ux(r~#O*Z~6KO61RW=3Qgi8`HmdW$m&mo1N=@%CxNg|IvX#rXbgZY{` zhnfwqHFfA@4zl*b?+ohwqLfS)?;iV^kvJ}yS|2ISjR;#~&U$S6`;Z;B+hEx!Oi4Dxi$4Z? zF`0jna4#(MT7+f4?~?S1r9?cEG<pH=fwfHrE03K*mz zX$C4;EG`MpkoTkz;5+$Qs>1;l_l0r8v0(LP_9u)Z+&2p;lJp?-dyb@nB*3<+sVjw= ztc||J)&c331ca#_*SsisMkoxCpnW}S8@z{D6E7n>4s2d5x#Fi$s!AOMK57|d$#z+q z3T~sq9GmkG8Wc$TF}FlqRm046c0fJr7pW}u$bD{$5^KCkY8`jCM#3~=WhO`JZ!t(P zpk8}g-p`JPu+n#Ts-I!{x9JL(jLlVU9u$wRj%0bak`N9m8uU3D+&np&4C6gnq&KYo ze7K)kG|Gu*;*au^%U;dF9AAb}JLk+@lPVe)|A0uVLQ!(pK^`)LcZikr1q7^USv4~UZ9{2?Bw4=;j>Od{<}KqEO_yKL z$d9-D@d_`%C?$WkvmN;6vO+D9QmilKa9QBl4sT3ZW!!B`T<>(=W*x-;0f4m=smYJp zJ~99r(0V%6XA#8*Wh1IUwgTz25=ZZ`uA@jkik=6Ci9k9^t6QS3P=!cQ1kMz znJ4y%bRfhth_SFYObn%`eM&^!tL#-|KDWP6!Rf<&Io&$lx-q3>3^S0Yys1RL*>3ZL zK0nsHrbhj5bIEK=SfAMMkd62zgh&ee6}J>trem@U5JwDeo%^IME4-b0P3;)LX&Jgvl6_)<+@ z!`viu|kmhuZliu;0>4%&KwPR5tO zWamO-077$-tB-vBO)=&s^Xr-3o(k&@|BQFr3${kE>eX+cDy&zPxlI#|-donk2Z!B{ zYLx1|SNExna<4y5T~&}72AAz0mD(i2Ls&cJ5eqkYh4YpUhmebaM$gWGx~1JuW1n3T z6iQ`%6zU9*xV;1@`d}{Cur_eL08FA#Ul{h;ogQ(p+5>zO#Gk!o_3pm%;(A2B=WJs| zvt5adkAJlUGOf!}X%z&(<+>vkRz}QlVVrrc50ttY?e149R#HeJ!N_<-D2Azux)pac zDsNC>SnOHVMUk1)F}Bq)9r~8i=@n_pq^({{EbK(1c)5|2TL)q%LYs4>NeF!Bk0IT4 z5@H&P=Rq@ocKPvjFqVSZF9bR@OkAktjuJUtu5MHjcs-U>I}x%Wr~&x5G7MK^;ooQU`NdS~V!MFO<(E;6UnSZX&i4`0;Iw);8^5Jn0?1`Z zW?rUIfqO!0&D}#~9A+PsU~0BVunOQKV{cGAAiyaXJgw1<9xoS$vpJP?>1mH2J$#M( zWsS^r&K&f8E(;M4BZIt?R%LMZ_Kb*lU3&E4XhXyTx#)<+S}*gym!*rzdFLywuXtBi z5`99w|M`tzZ>7HRoRgSKLmY!Jlxpmb=#-(f1UMDFAj91!nCvAQK}YOM)(_V)vFpa` zA%1YM>lo%IX{eG=+)a!2YcGG}m6b8scMGHBy;1R~CUv;(9(OZ&R|2UN#`r&~h? z$xh*sp??ZSpo?xiuNWz>L@IIqan?S?sHm*pugIYChwiBmNGz`+EimRZzsx*_I!3r9 zF+k1plK70_hb3%6Gr33IyIV(RW^WS0Mh~p6X#3d0Y+~hA(<{uSo|b`1y!UafhQZ%) zO32`&6AH6Y*8=V=u5OXt(t2E%T7m})!Q6^ECxz4W(?>~O$~23?kBx?CdK|>(fxemT zI?!vWPdA$@rgv3KxlysvD=_{UdC-v8o%U$s`ETnzi9c@E@lOK`-aTG@{MN4S=KFvv z$H|vmjS&uUrngF~CPBI~L3O4GVer=o!sdUj62tB}h*{`=jb0dkNj(+t?02%@ZysHt z2GQ3PYgFVS0_Cj(VTs2F`s9h*vpS-gA!GLbgr8OMB*+g8Ha$n3;^#W4_b!F?yeS7N z4!eHR$~2cL;;VG_Kyib@fm!kM6jyHOfF=`XJ?9LWt60%9BS zjdXZI3Qk@|$Lq?lKY09@D~r|!Yp@Tibh}(0n0t%#(@tS;REKy}#S{(%wDLp1C}eq$ z#9g=&Z378Fge<%ORI+3Fqi#4uG1XUXO!)M8mJ}DU?;s=&L?87CI1SbngGK^x?L37mnh)pX`B#P(~|%=IS0M zY)JOeHJwx4s3Hn-2F=aGjHno!q%lu+OMOkgJ(_-405tASz}?Wd3Rzg zZd0()p1Cm*>rXzW#|dH2wO!H)*bqY4_Gh&>Jo5@yP}it^Q42dLz9}*A|9&&j>^)-? zIQX)RPnWXrWweSji!E6#UvD$(RC49E^Yh??^$u|tR|5x)2o@o_9a61^R?>pU?cm&X zbh*d3vAD>`-oZu=Ah_Zz>~uUe^GXVqPiA1fB1x9d17DX3rJ4adARmUKmFWBMPy1~d zR$O#dK(|H!C-Do_l+#F&JR!^7-sws2nEu&SFiJk}V1HSX0qwj{At~>ir;981L|UDn z)bn&>-lYtC~gJ}`H^9M#iyTFX?M;L}!bI0=rL%xjboI)#)hwc&V5Ql9WhI)}Hc4bNT} zT!?iFWXTR)K7**J3L5Fj#z(%JQD2-3gouR{)=b;Jv1UgUgw?K2fr_G{4*j;sIRxbi z1^PjqXb{$DtoMbwA6+9v|tC# zO1l!}-5uK$NH0ZJf6aU4WJSU&FLpWORJ6=`*-_MFkF z0$|ab(o$q`HIkJfl8R#d^oop+dgE0_DW*-%kTN;ZKGgpQkU($0D)2rjwY`+`ecPzh zVv|OXF+3SK;*C)*q-zDP62#vBh9%uuG5|SZhc6?0?;*;I1+xXRp^3w*Y#khwdQ4x# zCjD0MgH0yif9E|Wjf>q^YL)dYb{2QggkWbJen*CQ`7re{wJZ8(UmqM+g=~lsZa5Y6rOKLD!qv$&gf9O-=$B}HuVOXopGe|vs)n2gB zTWmM1*M~tMY;VtYBNXX#;?p&`ftit$Nvh*0w4~-qLzidAx1&P~YmL6r@y8%fm*O@~W_6r9Qre`QC_+3LE{qyE_G=36)|Ly%xr+A=^& z#U@#co%lIl&{$RTfw5z{5<)}UFS5S z`4onmz^xrm?@MD~Z;WmI*)cORU6&8VU`kIf;M(1CN6$*D!eDUL4s ze~8YX64)13!PfTiXGSt> zO2hMd*wZ%WWSwD0THt|SrNX{_C_sfGf#0=f&(ZQqTf@G>!&0z9^nq=`T5F1zwqB~w ziia4w>i=NFM_`z{MCW;qXH+8V)c2j_{5y%R%q5 zYSYRU`W-;Os5IG(l~f#>_2m+lROXa?CgZpc#S$54JGCB+6yliFRz zcT85=eeX5wYTrSWDZECC_$+B2`n%D3Tg|KgUrpEluXA|GM@M_deK{-F_4!Qxf0O@j zCf{DO)fRDZ+fefQB`mqsS8)_)irsnq@OK*gu!1!jvkIyXbBfsT!sZPh_j@*f8vY%T zPj_>Picy+L5sw}$MX52jXzx3xv&!KhG=!9US9+LNfd}~Lmv4975#YVeS(;Rqhc(8P z($cV#Mzgc*e6J4L{2V6xc>tx&f6g=ebM{I@$v}O8f$9+~X{XI!43=%QU}<#8lr|$; zJsim-G2W1-&!8H%>nv2Z(Plv#hTTja(ivx<6!Ltn^Bjq?brzW{stsmCCYb-l(VswC zYMu|ew6-{!lgx?vKpB~tmXFiKbVq!>HKYAQr}j@fsHe7K7b{-0T#){ke|!UT84E5W zLz}dd!nkM{1gPDRb7Hh};9*R|QXg z!gw+RoycUegp42)$tJP_1@acUoVb`-cu`rIf!*q%h|5WV7$J#XR1c}T*F49Bjix=< zV$ui4;{sfbgYZ?Him%`df6|F)#-@y4cZcdzhC`$Yu)MRVSm*nQ6kP`>rdlC@+t$ z*cRuPvU&355wwtUKYW7QsZ7WPhqY*e0f5d71Q|2sPrc6knfzoj) z>Du(%Tc2WA0oV5VZ%%73t;F2)^Qa~}Xp&(TG4o9$ejfFxiM;ZUShg*};=r<7_nRsl z;2wHCSbVRqq7@zSCST5C2KH(=Uf!(PY87HV!8M>f)>^bHd++%zN2Zb&Nk77q5T)X0 zVnJ^1LzI2}e^+{*V!}5>w!mlorU(IFAfNC{A@IDWFzPUTMhSks_VK-4 zw5Qz!8=`#!mv5#ny@NtiOYvY69Yn;@&YJ{h=9mA zfz**YHZBq(B4|BSB7G;1gGh@7N(z4S(9@P|LH2Hgf7Ri}C0zPI>J^URE!u@1%8d6= zlCnQD7ov;xkJ-B9$8?ts_Ya!@M1e=U#hx!VJo7%V>Jvn6j;$`P%c^ZNe;H$q$$8+E1LkyNF}IhDV|05Qxf(E!J?qD2xp&`hzH;^Ax;d-7HZAuPtg-w@jYm(wCGNq5GvkK7K5I;r z$+g)<$W3Srt%&9ncUNwoyn5J61AbWeBies`>!$|wLGNZEvNR@VNfS5Jov)5Q9C#$4 zI`VKJyv@y;xo+CzIq%&%TYK^LVJR2Of1Fp~^0Tyy*eSyrT+W{*J6B3b!Yt{rs8%Lw zF^jjhYE|tNZ+P%UnK)RY_~HlXbx%@o8D8Q2SrR{J^U7#v)9zs5Kvqq$Ev!%#6PV<+ z@RY}GTGM;b9>QLb)+hikYy%;ZS#uZCmiclR})Eu+Hu79Rtfe<9#P zR3jXNqi_limo`=%+ml~U``@~)#jbh&X-i={{&c&)X)~|6md!>WI1Y=hae4>njr%x47`>v}*zrC+#3k zo0zB*$Y1|4J2jrxYkk`a3es|N%pE}%g{L@+o@4C3nFQ;FJ8yxW^S9vd3Q4#fx z`aC>GP%E-9ER!u2HzW{9Mct_!KUjG2P)>y>TBO{F&}7*tjp6YU|I# zApN4(CxwLwZg22bf0x3*{mV*%8rC)XELpWIB?!2w;g3$;+}&{MM8~GkN#Y14$Y@#1 z9Q=%bPKDNQeg(DoHCf9)=S}Nhf5o;G;%oThkKa?r{UdI&)ZiSe^u$1tOtWmD0}}@<5}SD z?|*&T8yntSvrI|WkZo$|rx#&PA}jBJOdsJDm^J_og8xLkY>8l_N?#Cbb&#TUUNWuU4#CJvxnX!DvHfv;!&0?)N z<^r*T?dYZae+J<8omP!c(60>Hq72-$RTpYVHiYR@AlZ;&fJ9Ews#a%0v2Z~CdEx46wLKIf;bPqkTL57!WE*&gN}w`JVJMQDdT?%)66^QG4Zl?v^%_h-6sR)$}Y z6kZaI=wi|v9sF@6;Ap_vdvG@P#NPQGd(@gWiQ^X#f5i%6J?WG{WVCafo=du)Cidq^ z&pV5AfXhfTXG)X(Yg2DaMgTA0|G?@14@#ddu6RWIMS=-v;sG5VU8%3EvXnMJGk4bW z8W~QQWeXN>EsHCYW-ABXAx^NJJX_dI{fiwe@LCZQ6&0miG)Fa-7CKkj6=?GEA$zBw z_ahv?*}6T8^|E_67X#;zI7JX}{}_cdt09D7cF zKM^>MR;!_MTN0)GcGwv*5r{XC89rn#=|vpkf7_9&Nz-QJ-1`6(=Y-?fDGz1vg*5J1 z&^|1%VY>8~9epl6{8A>aksgV#Hfk$5`Q0Oj5B}kk_6EP*t59r z>j?9oc^~xoH;?A2uYSs-J^SeM=J$_QM}iQei;zaM8e?cxk}e*SAb}$+`|G%)%~U_A zf9r5?9lrXwTKwC8Y^=R>8@0)>N$aHef-&f+weI)tef7jup0QCvc)h!218}2B7izNq z!vOgHTYI>u!yP{Ua__nF`qZE*!AqYM1`(jji`kj_n@P`at!tZm{jO!$f9hUu{nowC z180>_;EsK(b3K3?PULI*|Iat`=w|a@MT&RpVk(71eMk~)gV>B{YqCz7va31VMdW|( zh-u}YVI@_?xII@+Jn~pu*UK*mT{};)bn9Zx?$+(HrCWD~`G2+Mq|ui_76uayGd3VF zAa7!73OG15IG0}m1u+IsT25I+M3R4-vKVwYYE1|65q5CsmGhXMsg0y8(4&jJM-e-UF6y=gVRdokUygGLdJ zV_Z>zc0j-gVic9R7!(R9ikXrbs%lqBK`{z7ffNNQ$e^M^oPtwqV`7v%pZbjHq@yt= zo#f?Qa(JD0%Au#1{`1!BA608rt+V&pdw<{l_C7S_>O#>pJ$`*y&=x$|Z%;s8&r=ebUbQaFHzhSkkr!dKaxB`QeqNi%A7eKE0dBuf}IxW9>KD7nIcmb z`{+{Nl;qS5rA*-wm=Y^f$SH~vR_4fKQesnOev0_?e*|S>$i}3okowT9YAt))UKf9eft0ToF3P(hS0HJy5i8c$87CQvU^ z&r>f@FH#dJ50W{>P(bsvl^%16cKJ_9yyTqgT-SOxmGrmL1JduAH4J7G*tTb0f98+R zZXY*mf80mzQ{7wK&$y3`Up)Tkb8gRN{YEDwRn%*$ zRG{#)3S2ryj~Ccp&gDxn}&5TQ96Z{{Hg-Iq2VZ+G8q}9r?I!8 z05qVUlDrudyqsy#-ylcY;VQH^P5dDTRQ)VAe~UH_vG`LroG&FYxSox~krva4Sm>a2 z*CnDSy35%wAJdtE*vK_1*a=GFHAGK>IH;*n5--J?@`|EYv0*ZnpuJ^{BnsV>wl1*n z4kk?#1}PvT2Ek5)VKA0ABq7f+m&p;+K~qtZo17{O2R13&1OjwbcC}_Vq1AH3KmkdTDYx4|J!v(O`#P|PKXxB*pg@Flb>_sM&=RVBhqkS#9BVzu8%@w7rW zIrD+BG)%y)On4#qlf2vXr%2WgIQ6(x>k42%Ktaq8SI%6x(6~8>#|8i7{~Yt;p6A;T{;ITYBSr6cbLWQuTOXS`(_rBqGum`jb7yO4jj(KL3opVFm*tC77jrVobMcHKYXOAe+zoy zP>wyeb2|h;93((s+P0Lf+p}fBKCWSrMf9?u#6IUmri&7Ea&$TOv{-3OrX#W|2w2Si z))P;{6YqN>myshw=0;%^gQnNIIhfTY)q{fgUyT3QHI9I;R%N6oM9a4Tn}(@cwCQSn zpKZTj>Fnzqf(y_UUYl2+OJL7=e{wnAY6$R2F*RdUOzV%yW(-H z-*_uY-eArWlr8xdX#XpWsb=K+sM;kLB;rJr&)M`~{xf%XojJi4K z`!~dwzK|Sp7TCgE-CYzXjI}dy>LOo0OOC#iqBqf0G!q4)Q2a9T!b=7G(tp3gMQEz` z3*sSWzrOki|AX{4{640Cf9-%D%zzjO(asKDxg%B8e1F{e=!`*Pn(Cu){}>lp%}p z(bRQ6p(c*9qR`WyT9MvLAGm^iuk;R*(xA26v7|nz1NQUFAADjjf9ct|Pw4GC1_r2f zel$fDmJiNoMx)+Qlpm7gRUf)}Kc6}$mxorz9fFLM^9CJ}^u^Ft;T-99L$UZFM=EJuw zCg^Xr3uZ@0trghMe_)0(2cmORg=~3pQ6{i)h2Cs+A2!a26ndh~NdSItS%^SY91*bQtQ z7)*aFgw7`ZCtA1wV*FJ}tQP%A`nYu-K|N;ue-uMPJ|b9C9cZzIzHJ?tZOh-W;Z@qi#Y7}%??X{t2p9Yhw1c};vHp2ymxPm4b4*7vC5 zD@OgfU*t%;evrsP2Mj^`UpVq)P+3r}dGD=re?&e%LeZB-Y!dM$WZ?)$`XYK0_Jub_ z0J|h0)L(8^wX`-jxAw^>6ZapE6#Oucuf3poZn_x8R ze;=A)F+{D;i&cFRY76+6EeHRH&iT6`JaQ44$QXR{A3(ToV=9g9LzUGnaffApKNBSz zw<)3$1$`(-7@@CgYVAJa7zDQChXTBDO;J>OypWX?le7gwA)zbRzROCqxY>E@s3DTz zHqIh?IKOGIA^H+(yo6|i-pAs0&ZgBVfB8h|){(%P6kvZncQzS;&wnxd`*TMRcDD*O zn})K;P`%sm5K*WMuS65^Y`hx3hQ0ANya7$a%h2Y17xd;E!T}?4>w-P3u?+I~GHE_( ziTo1p$k+0GiF~fX9GZt#qYyM5%|MIL6tuzvYv+~CS(8+LutV@a%0V`0RZ4k8e|TCn zuq!wG0nvya{=>C{$1=8b3XPedg>3dQ3p4GA`3wbHkZ`@uLZ7gsyqgji22GXL0Bp0p_CR}flOiXrICkL&&Q-zf z;e9j_jeGOqE5Q+plr-USr{Pd5TJeDX%pyVWRB#tEdt>F<8EL8JjE+5Z)rKm5_ii2N zfYpPld|lf5i0wj!T1x_E%MIm*nvrXW;h(14bL&fsIHQ$@Td3leM07z%e>hzDO4$1J zO}o1ke3i6X(_IAzSzEq2EiErMEpRC6E_wltCq+(1Htc$NK6aVug(u_5UwVIYt>@Ic z79LMp$OS;^yT#_b9`c45fHQEst>0v~J5IrS;Mh{Dw1mMz$Y&SHX3c*p*AHlTAVC3x zoLy;E$g`A+ZL+6sQ+xk-oVW#+kMD!UA=L`*? z2R++RR8_J|UA(KD$DjY%r+gP7lx9kyv81kHcWqte)9P48r#{-|jAVD-h(6}vcKOZt zk?7mLwlLTLe)71*DFH=+fGL<+?bGeoyZlP}3AhVGCmh4w*Y#h+e=v(9@ilHI_?xm3 zU3d;g$cAtWt~H%)zWi?IVX|NkE6ocUf?*k~hBdIfFen?l1Y{?`6E+et>T?{i&}h;X z3F;r^xE9c5@#(2s;(i0<$<;VZBcc}QaBtLvX` zTSQfVx`)UD3HQ*Bf7=o<04?J(r0U#~jYWB-#letFIw??UZ#n;dTPt}-c$_%_4~ay~ z{e(Og*wwEs*n9+bTif>RYtJ^P6ceVadGiOSj$Q)x&Iv!Sg<&g$*OB>zGu_ffnt3kM zI=bA7+xDQ8S}BgIV;s+38pl8Dy2#@GjHSli{Zff;)J3`al!!yL_iP} znFkq^QLwvrcQa2i4=RGt3W!+ZL>x1C)fl5Mxk-$gm_)C}8?%cX^72lBX1F)+f8YJT z{*({;(C5@%Yp=c5LBaIw!6+08%YXGQ%hs=0H(}mVr*)GZ<(~|fhAO0CJ)~EZtB7e> zPeVttMbj|#=T`XBK#b{+QwA_fg<^rr#(BXZF=5;M{3Gnf&9k?gJY&XmySahBVcWKN z1=%h2itzUh^opS0?66xEyk(njM9iypb9d~pbCrK1+|JcE+&3)B*Qa~id4IuyA(0Wj zVRlP{eSE`$7$$L+%iNftElZtZgMHR7n-}7{eE!xI&S8EF!u?$rMr>QPD01~XQ2}dq z?(kZ>Bs$RBZQAR7r@!G4H^XuAl-I^hwYThHW&)2Y`Y?G#<(!A zGwYb8j1x1RnaHeXmND~~H<-bUH516#Ft&^(6U+=@1~OKRiW$W8Vg#l)-F!AJFvBrR zn0AGe!ra5EN1f7MnV`JWb3@Nt7J(K|*f{nZ&W&s2ZTKYqi(YejTYvYC>NC7gPTx6w zzw77NFV*sOOLKo!f8YKG2J{(FGjQC%O9MNtbXHGP>4PQ=dQVs+JQ%#kdXROM%|M%6 zn|hme+r_qKTO6`|Xz!uhhrT;(#IT=#RV1ugVfky1rrL54rTd}+861I^L}iCH9uVBw zlm)S53RwvJDCs^96@S^yTB3jruo=dHuZed@rt>~w+@4K;LMLXwnzG&p`kCRnKz$g5frl~5z`JwCR!GqAP15T%gd=*Q!b*#CBD-BTS+A!@^e}qU zMelRCymNTO#>kBU3+IFFZqON0OgZV5h0wqs4zJo492D)dPV~NX`@)s;2h?=`_T0*M+K8w~^tUp?n)N;Xvh^>W5ut-LQ3<YCYLZP{1fl|DzG{Wj z#eemh(j&*p+i1a$#Z~y1Z-dpak)H~LA*vU&Of?6JlG2PT+pXjsGHBB<$XKglrN^SM zbPqIYq#rrr{5!?mI8|HYdbiB&L&=yCuaV)z=9`H)?()g1>RQbP4wqzFkR|wBASNz8 z#(OpGVqyu{@A^qNx4%(Sb4<*wh4au9P=67`zm$V69zDTf%8p3sS0Se`8!Al2#u7s@ z@Z}=AMZZZG3_i5dTdA0Em2d#|C+YTrE-jTTCkJiFW;|u_rO0|~$AbrKfyv-c*FEOY z*r~7}J1LBu+4PuJpas5%qcUw2xRbN|+2(fw?>(!;a~;!!#C*LWiXJ%T|A)I}oPU(o z`FU=FL0<&62Oy_XBi-Vl!eBUPsxlejAn?^9>#KF8kKzSx;7t!%&6Pm0zC>4}HRvId z@3fZ{a+bj}QIvj`mC8ZVwkbQZIwlLHkQ0-v)9p!7zq4ZLsYN9VX@?n!1Fm0Cqt}Wvxf{J{ePB?ftfJ9%I&iI`Gi~W0Nynr^WKLaeE3z~8A=lP zZgvGxnW7E4O5pb!jQcg+tRQPe9B!5r?OU3tU@?>uETzUEYt=0b!M_VoYA_TQHZ`Bg ztN{M%yUU0b8Sd=1c(*&8^Ux#~fB{PRYqVRaTrJ~T{EsI!1CQf>cz_zTb$|SpjGD7{ zM@)o9^}bMo1l&PJQw<3tF+@Ygk*#D4+L4jC6Jt@0 zqtQ#<*^^urR)Et%?@zX0Nx1=c;eFGW$N$!R`D*n=cpt6>H@$OoN%|~U2+n(_crEa7 za*kXB@_wODncwE=Fv%LnDsgOwO6Z=J^Eh0O<0+uqF@%gqfo#xpI)AydsO`KjP}v*9 zeF&dNw>dYg%U%et0#PKa4e;2w@U^&Q@<%H+dxuaNd?sRu+3MC0qmj9f{jF7xu$L$- zaAz9~t;Q2@lpao&(W&?hIgz7^*Y7EdJwC~)&d2~=mU>rWN;E|Co(<9a57m`7AMI>@7LEh;YwhQRYQpEX>uow0i_a%8# z(>d*>8=%efn090fJnrsEhVD<{Z4<~4Y{Q`}j)&Rv=EE#9L1yGXO^$S<1`%`5cAJlB z)O`4LnU6@K4xU1mQg|m~Lp%F@uIF5hi1qI5++@%3>eZNw6MtEp2K$|gNIza=cVMc; zFADh-pVL!xSW$DJxKortKfM4)u5Opf{v0i>>0muKm{w*UcfA@dpQ!cvm^cXHz3XKSUF*MD9h2`>K9^Qv)asee-eul(5t?BC)a?)jyV5r_ z1@Nj4CSL0l0p=MOJyOp$&H z$Ds{S0mo&ihhpU^?)#kIa7v*#t;Y(qlX0q?wU6|oI8j(G6lJ8ErJ;3JaLnrlCeZ(6 zSo}~Fwtr?V&I6IZ@(@aI9SvHYp*HL?q?H3-1sRo^PdQmE_v#?pM;%(=pScD2Ktemj zdP`YIS*)hX|7hy%-Ms3)IrUcjiXn3*LFDkzn=J|Iw8Avl4SYDHMreqFi-zQqEFup<3ifGm)2AZmuboPV zFz;35uv*RQUhQbOnLlw4T4IKI^`YTNn@?yb|88lx^Vb(0{XC zZvQ?yTGgT>=`9q63i^n9=(D9z(TnJqF8nf$jUuVk;OC%4 z?q@g(_}iU#h=V(O&P4V8B7c3+FX!ZQI!Jdu;cz76zLiVZZntgi zX^l2T5Bjtu4b6Tg8gcjkWyGD=**8C|01Cji7;;Uy<$U)h-NwR=7Jv8IsBU8WqLWZl znVnfySnpNub=WH>p=c*)`Q#XgSG#kEj9(ctzzp^JdL1vua-N_~k1rxK(a#14KP}A5 z$+`-*A{U|!qa!E;78@fBT|VEW%}yaJiM@@q>5l=V^Av3oYGRHUM57swz{#%8Ss?q7 zh?Z-#MV@psPSTu}1AoO&!hhz$`*GCdDK-!VnWsbRch%C=zog|vj@VM(DsT(Beo6gJ ze|5KYe}O{tVFzsbr}`vYmJd~x@er?BW}tkj_vCZ* zCRG`!pfjb~#-!{7f8ga7e*mq}1lPK5zJj>5v~3cK{@8=G(Jv|SAE>7u4F?w#W@ddZ zHYH?4_T+ckgru8++s|nnX5K@1hHU0NU)^>7pAPol-8u znv9K&_5(T_sE0M4p5C=`}0K^aIYj0^(KRdx# z(l^{Cm=E=z`w~r5qqz-jcPiN<3%2Oyf(vwlcymEhYp4`E8ZKjg3|Nk6!V5PcGGrX(U6f z`WfENd8>JWIQx_E>-0G^-~Szlpxv08q+jGJnC+$ck-R6kK}cgtQCuC|gc2SHo)g=@ zgE?czz}zvv-{?LQKSot4&Dc~bmVco2NO>Oqd}Q#y=qL@?i@2&x@Yj&P{kzIa6F4$I zm5yFL=xoVYR@M2K`{Hj$zo{uti?3A2riR4A7T%{O)O@6-y7|oJ_el>jfQ<4Xz0_lA z4kyp3Ow;m|OPM$@zf6IGd>h*;Jrr{Dzz7XI@nj=_jLq1c9+j@o(dF{)tbaerq9!Hx zlY)YDV_xQGP)tiOlZ}atj*5w#Kzhz2LxGIro!^DbA~EAb^$8A6noeekIakXsHZ*s0 zMf!~5aCgluEWWkouAIv@O5s9WPH-{Q^Vc6_HGOf)d*O!AZJUGC$HRo{=GxZ-3qFI(G=^hs-*9?x~;M!yd>?7dISKli3S}h8QuVeaG>z zBT=xCpY9OnYVUgb&YiO@4P~;)PFS-7ogOIwFDUT_H6V}3h4FGFFh{DoNFoWczUj5{Id{ z$B3~{)Fh3Ff*-7^h=0GCdU)}_OE(v9h2by*R)OOlx81M0 z><$DO9Xh;H#p9F;RGO%APV@M?qzHdv>Ps#@|}f5UPZgo)iqT|^UT2CJ+W}k0^fzs^EG4> z@rqBNCTFK@j5N0!r#f^%i^h-em7_9L4wM@j+U~E=uMXBKs@6Z^kHWR`o9E#!e|z>7 zx=){(OWyLV4SzY>T3vVK!kWCj26e;1d7B znHZA`CFXv?Jqvmi?;2z-m(|b*Xl1UN7h2lj99wt4+H$EiX*NaMl&(1aFWoXmEpy`4R6{6%^W`)f-korP8IiE@^ z(NTCLj+bVz2Xq<1QF{HZ1U31g^BoI!Y^FZ7r)(;|?)vlBS1yliKYvo<*Ju(byxXyd`{(Z<=Xf<5_>?4VVjAd*<1}bR2GtX1Ad`WtUq>cW#Zm6s zMHMQIPt4V37au!PT%txtoK%S}@SOi`?8|C6sH9sB{r;eczx(HZ<9jz(>dIgWGkVmRD(a9Z+wLPuT&{kZ1}z z6w6yC=5;vbk<1+QC}+v0EKcl=Y#(*+p3}?v_G-%N+ZWk`eft^uS~AT40E)3_=$Anj z1``)EI3O?}Z(?c+HZnIk3T19&Z(?c+GccF2b_OQ~SxHGnPg%DtdIeMg0y8<6f_nu) ze?i6o3Zv0P5fhVWVl~zV)qd z$r!6{j7%nTSUrFK+{LR$&GvL%HGYEh##!ty69;q?2g+BHoB>u*9Vym_2K3SN!q4Bp z%{_2JPev}2xq0}^4&M?V859s0?KFJ$e+Z}X)22;vnic9F8MILy=H#i44)hOIN7H{o zoR)=e4DyeTAL}$LB*bZ{^ouB`rT$U=ks5!$u5D+Bhi-|9_K$S(4EOVo3}cw2aUQec z!!~-lZVmTaG<%Ex;yIhV=0*m%MFlQ(j}BTkFJ}3CO>l^MVO*%MxBZymBOJOle=?!X zGCPJD!wh29FpHTv%vk1a#)t7@<}%}$!ORlIjd5XyFz(EFW+=0ana2!cmNWC2iOg_j z1+##e#Ef88GXKGhWV{&<#*=YnMl-9KMa*nwDig{$FgA=WUEYPpjIp90Ka$Oo?dxXW ztwPSp*UCSz8fn#TJ=fZ-a8?)p{d8h9*I4k^~`-^*c{3>6fe{}*gx|qcU z@|D}bx;eJpi0Y`*%-ZA0$Nx~&&%qMLPAznx-Lr~He@Gx6YH(p&59_k zJA^|RctHf6be5NEeg!s2^C-jh(i!&QY5sfP4@tM#o`ExilsfFDAk$N=RqW@v;3tp^ zZYs9Qa1r*=(RF<{3}TVF+IF_7B5H<`)V@A}br7@C8^ykjm+5{5AQ!YA`(oeR)7lK3 zPN&rgSy>6&A(B%c*q0!G1s6*9BbTdm_| z1vG#2qUd68Hm&5qK7z=&o2N27`d`!h*OgPQ6!O>)~yQT_mziH4%}S@+26^g zB++}OImYHgxl*)Kl;9d`wIbCyW*O-PoQr=%&k0Ek#qBMV1-C-9my5L+&SU>^Kaufd z%A~hRAJX^U7#xpNZvBM4l*B-m@T3o*&Gn=3QCXu|{kaon=Fkx~yINMU)-v-NCD*@ikdN{T^4ClV*}_D_@1vHfV7>7d}vqMLuw z+RS>U!9hV3St9Ga%c~cyN(i8{djj_UlI~vFEbKpZ+E@iGa5&zyK|&(D@+CXckIK>9 zF_}*;(CK68&m#T=F-)wO+WBokqF%Qf9IL@tC5YEpsMPEC=9C)B^`*d7nHAC6=`=yZ z;a!NP30lS0Qdp|9>N52@h~YXXOZtB^I*Ca%qjxzjs6byy37kcJtGpw*V-jBl*)htQ zvzHy4S3Qf;HH6)-$&jQIQpjk+dyj_&FtK#mnZV}Y zc0eWkSaj*=sk2ue>^cTl0K2Q}$s9vUJ`~aef}vWVSdf)w9Ac6(RMG(>MH)-rC!=^b zT&}2zIUM;Za5(VEH#iiPWABjuUaMk*Hwq_MGV3>8=*)XH?cKx{zUf$7@j>9eIPFFH zks-5JEmWy0kA?`8S+YfK>5Z2gf(1e#lu&17Xwe_6Xe?`ZztRj(AfMRlS4*&a+}oMh z+|jeqmwkc-CLtWZ06g~lf9!K9<2!n(&$4f{e0BK3#hTM_4L()Xt#4YF#DWDof2hg3 z&bMq05FUulcJIKof$QdN9xp8`^KPRx4xgGa$|Sq|=nisn3>Am)s4x?|hl)pE7MltT zI;~N;Jvn77Xt<3H@p~&9iw?I0w9auMa(}`phs;u4CQmImU7;w|(OXngT2GQV$fTX8 zs~0t6o8{bil*S3`@Dm>2Q{Z2|mwtl<5&=k;k%I*{0a};Ig9R-Cc9-{q1v-D=gnL&S zFyVj=C5EgF>JJh)&7Qcud-s%8 zRL3`{Rlb^djncQ;FMk!irgHgvb3=Cdwgw4XYp$zi$MFqP#v@`OP;QR+4!1-IZz-`?+aGNBY zB0l`33klwVflFwn^$R%FeD(|!Nr`r9v=sk3`gFyAB8|Uo$8^5)PFE-?kf?wrXoEZO zA-z6v#JYC&hrA80U0}GTZWyIpPO0#=0w+R^>mJgbfP-0kUFNZGE;%t}hj$O{?i`xB!lEU)+HTlpE(p8kG8kJW19nAiGLVv4&oJWW6@t_ld*L9V^{Ze>$Pf2QaLYyuwK__Ia4$*|e zLP$H8dM~{#?J{9Z)IXK;#0DGbDmW#3n%8pOB=Q$Z0(tbT^R&YFn8jXQ^aZSi4X19X8(^nY1YfPeD3tJ@fU-{cX&*}^}7r5^X^EoTuf1051}v}BBfYXLbYyhGN)rZ zZOKJzyzvJ!Vl(^jHu{qWLsm`(WI86Tff#=p%Lc=@w6(8??<}#{!mfbKoymKCkFX5y zBG7Ih9Se5n=Y1m`Xc;|F5M_u8!leV1Rb-@T>7x}UjTnyIty?7yxl;~>!V1fbuUT{< zOKF=mEOAF#+Ej2R@f(D7^m5ps|S5t5u3>!#OHy^|XJe zOLOK*X;yE+_Iabfq3ciHag&zAdwwT~)zG!>!P}JEZn_sOgi+w_sqx|dVCOHpcH&G^ zWz6*dwKo306WHH3g6AJ$fz*2Vy+Xa8TiKGblCt9R<15>f4oTMQ@eLe;1IOGY1HIP9 z1^Ws+efal}ohWUk-+BV+J%2qcjoN=Cg!rsY4hDDFbZkc@1;$Ee>ylE@VP}>--7o&i z=aw3bH>BKNO+i^oL2-pBOUB)X9XilvrU>NS&ZWd%46**+tO(YQ1%C*Ek(Nm}*cQT& zft?I-qo2Q%6n6w=Q80|QFzp75DbG0L*6g%OaIA#vTw^i1it2tiyHjo4W_f>G20L?d z%Q%Zk!KWuKp?!tq>(P&<-UD$tpGgKkU@4-uyABmJLTtSs+!x^ ze=?LP$mk%_T{-lnvHzF+#HToytug8X1#;!}ui{wNLA1j;_h{a>$?*%E!`~xq?aORQDi1keh%0|3R%oTdIUqf&Kg7vYWUUJe^?JzR3KJnCMGKk;B^gXu zcj5tL9uSZ7#2p6_Zf}eMb^*7u5DJBVSsz{R$?+N*ct8&~bSHz5i>TB>GH@A*keCVD zvUmZlh?SYl0qI%2hD;__#5yrir-Mu`u@H9V8=zvZ5(gvu6?y>9<6eKT9iM%8344@2 z533Z}j$wZ=vVZYN2w9<2A6^3S)VN!dku=Q0zX`M7p9=pon-u;5d*{l5t0fKE_*!LX z%61J+eNA3mSrSKqNG$AdEhM@5xS?D@*5$HhTa?);ZLOx1+uIz-x3@=Gm3?=;y#vGi z6LMH99SUV`WOHG%%O&8U+=9x=#qSAInssen5ozK15Vd-~uurDkD%UvbL-R#O^C;)3kIC zS=#J*lQdh?y=l5Pr5i0>fYKt1Y+4WnWf5cs2X*GoJfqG@J-yd^(!!{t_Zgj;Cr|%q z`+Xjd1i2bJu}C6e$9)=rf)n$ zdE?wOXXH#l$0nnwN6_L&IXo`+wT*8CB#W|B6XN32X3Y(lH*4{V70YL>PKrrQh>8%- z+7yu%ACnZ3Mt(`0wJkX+Ato(*;jGn(iL1akh1Gl#Q<^BQLnXDw$N=XK6@&N|NXoE@C? zoTZ$doDj}N&MwX-&Kk~q&Sp*kXDVkJS;UX?IOh@049;YK&J>P6XFP}IOyDdaW#ag9 zYPdVbj2|Q5t>N7pyK?MT&9|OfMfH#0JO1i~{D~ zqx?rrlV?qN#DA>6<*|UrF3~OY{i&%_?NdLP_R6%Q(-9OHr?iGVM@@qXY8f{)X&Zqu7eR$X0SW`F zGQ=6d4R&*(y{zhR&Ee|96w2~(;1|bb?w5tjWsoH+1XEjw3EG(!Xw^0YWhsR6A_a&; zw6rFVp9 zOHNMn{~8U|(lL0&>ag8Fy&-8g8w>`kfpwb;>!6gX6g#qI(W-4Boe6J!`RQN(yN3Cb zhcQ@;W-##`ijvGErBI<`*5D)K{J#(?qk@8GgywZ0JbUn7%^+*5G#5h!)wj?0S%)NiRNtqDnnmVTvJeMt7e^l1D$9roThGVckNm6Mo^ZNQ65WZ42L+# zOcN(%MM;A}M~!aS;4(Aimn)9BfvN?eT&&H~h}l(mK&R5HLCcrh4mb8goEd0{kK{TP+UH_#rO&Gk#+DydpuRSWAHD{XPdl?ID6%wjDaPZ9rMQs8vGd z7O>e3V9hUKNwfPuxkEUcATJI49{B|$;9Gh^i6b|_`h$3AE_@XQg2tHo4cu&|d=^EkB1=f34PDbK$2BpySy$o+PvXcUj6xrLW` z9t(2Qp9f!B`mmdG&Tsk{J&I_5vh*_ywqPe69qYc*SBrQ}C)l>LM;i|Tb*w%tI6Qrh zAcz%i-xazCsPC~o{><%ijtv%P(tV1p`sd2)fc zKnPi&)oXMr>LJ;U0CC988%p!sq)RWHG&L9~Q=y^ErZMLw?$d&R6+nV15h%43vgCHX zo$c4zG9d%+he6~{vw3Z zp2F!!F#MVMfI(LbdhMcjN_Ug(L}CF>$1?oF-{v3&g&;24ceEfE)G8$?wCpat5>MWL@B&cFpFfFapQ}NO zZ=f;k;2-|b`yo(Yw?4NtMJ)g=>m?C~$xxQhjP@GubfftrIP$E1mv;|8M(VE6M(e3O zLh(wo+FD2Sp`M(sdE|6N9}06pvI{H)7He&ODcg#kw&v7C_5+{nXCj)5=KU?`SkRvE zxC9|9I~`h>`ZG9xOa)?PGJ7VCwl$x-{uWR@1zQCXB0N#Jft96(2kruDOYR+;$%{gE zl+{Eo^b$e-C8TcWAq5iCjqtANXvOs=xCmCNH}=qm+4#w)ap2;k%Rc{UN?R{~?@)U| zkF}1qxacnQ!e31VKy_4!5}v>-V4s%*{?}cZUOV(c4Hxczd1CJHh8jGj~tl$BGuJkGXz*Jsx z+1BP5XeH=>uhbQZlhl&^kV&PN=a$ygI9s|Rt0L#6;;9KrCIgQdx6X^(Ofs4!>^Yw` z!{cR}awAn4d_{sZBo1;R%Oo#pG#6KclX7Jjh*MKD<3qbL+P>^Wv8`4wENUA?@=A2+ zdI=G`t7JnC)JZ6y2hpE^8S23)iI-~ypr)kutlDyack!YA^^Se7#qCZPGxCAxihcj0 zYBgFLY(}qYk)jlS_?gS&=hC^Rz-`gsH2<&Arvr4xa@lTGMsfl_YHt)A04XGb$llK2{E4KrGhwhr=Xd@b5d4#Pw(cMF+@@@Nag_m}V z?h<-DbptIN>~nEHI*F#7;(4Zed})D3A%a{=Zpo=Gt1ay6jXbmtkB@vVsGrE`i-_BNZ<>D^Dcdk@ZL}G!Rq*A?Fre$)r zB?*XVBx&oKYE9LqTGmu$?uJS@8Gm?xSGjkRH!dF_t>L>-fRkJQHV+k%3BKb~<{)I5 z2V(XmpEfi%znEarJc7m4+ze8@X#D)RWj;9%UBC^W0NkP1Xv84l?>-pS|Ci$rN-YC@ zwt~riBWl%FphQqpYK2m3Jv&Muqln<&oYHgh$XgM&rulo&ZS*Aly%q^Y&yf~?DI|uv z+MtQbfPkAELMZDz{WTVYnuv++ICzx z&`(_36vRW1qbUu_&XguL)h#p4ug@|k+SSH{lAI>!q;7rq`#Yc2uU(ygqE~9t8NFoO z_tkRD^athUULi?^=PB^app6y-i5}GVqeqWA8+3V6epa$DDGaE8H-8K?H#Sx?7jX=Yzk=~8If42A}8vlEqC)YEHZjrf#X{l*xQmfLUWU5n40y5OedvQMY-68Kg zc)ICs-4(`MYAN}dn@n7PmKg+lsYMrrXVA;N=znS-B#yzGMWY;*eBsQUe~Y6Ut@U;z za~y@WsV`)}7CtCJqm>Z#RuZNSIFj1d?K)WDU|j9RXGs&jD~NPg)>=|}k*>;FWvw@u zS#u>Apa=#7>o(e}iYqJY-2G<`_4X0YvC0kl2&Fn66eDWpsxNPUugz`_-5DMcmB4IW zCl<%&cx_sd=s`t4I9qh`&RG;dYWgU8nN}w2GeAPg6JOXF2p<%ksQtiwi?LRie{KzT z6L}%b_INaIzUgO{)v=9cUpK2gP31;U+riTb3 z-vny6xbv{xQ0?e{W)Gv6Ev|wNqJ3Uy3Y8)PO}}qB-x?RmT|+c6_HX~f#!Mb2PFtM` z2lzW%V~@5w>uQRavX*o=5BX4UIOU z1yvP;r{1yfZH58^F%(vfS(%Zlg)}A}Voc%oghl)gXcFoC9Jh{tEX_zmBeq zhF-om^g5JAWlW?NqS+{jG)0fT_|Mg<(*%dujvuR)#nxmlXIs!5#FBuBn=A)FM;J~J zqn8q8$d+4wb=FoAXWN)YXwo(SWw+&*5YfqF;|wyZ%%A_%B2>a<&TKOyZ)O5X8ukcof zSQV>((PXtU$KQU-PC(G^lb(znP|Xz$RZeMfT8JuG zu%>I>C+IPvi8Ijr>tWZHz8RS#jAbA0*fZPp`Hc<|fG#2v*{|I~2g}YiT<=9$h+pi2 z{bj6OX3r!x{LOegGc!76Z$$Vup!TCr=&E~v)$jD4aUU8udKO%8P*V^`y`hd&N^IG+ z&E@s&eX$KeD;95kDu7*vC#B=(A&?jwyuho?$REu{&-RJF#^W}Jg%f0qT8WXM^!|v) zdh$lYNL0H2c0ZAq24c0)-tT!QFF&zulUN?FgJyq}Z^)Y7_p`epoKo%Z4g@Wh`(j-%%(PD8Cr{wjI z3=Z+hBuiwlHpIujt$tw{O0Cg!waiq8J52H&qAdIXo3l!~S?So*P<& z$0FaiyE~4!89aSG{VKd)+}?<0)c3K4uCBrNfI43KMtDFtNx{E<;6&kTas)1a52c=` zUE<1Q!M>z@Ddjn}&F+JZ%)=*8^4C+yL&=Cc&Hv6%KIwnyCi;l35<8O<5(SBArJ423 z?k4xc!@7p1lh$8A7tirL{T?OVp+-|N9q`g#>=VT7Ss0E3ULSy5 zza1@sn-uOJR?>oS=SR1$qN6Q;SJ<|zCtS^BP+F5VtPaGj;q%$_y}NgXJe*c=dy?IV z>*RVuhvO+RC@gZ8S~pYfl8rP?d6UfN>&K@CC4l+M;JU|Sf~&va#sRhF^UQY zUTrsF_R;$jF{|*ALXJUdNH?hrPz)BM-H`u~DK1-GsL+Lf4!O8D8_^^e zdh$IUn*Raa_sRR6?sBy7?x*Jf(G>Dsd157=y8?%<&$NX1TtAE^wU_6$NL6aJN(VZF zj~<#U6XP*KGGh>*bL@<0M_FT)lZjU*G= z>dRY+m_U7IO-^mLJH3N{P?B#iTH|;yNMa2uiHv^zbpowun>att7Hv-iIppbddTKNv zV^iff+nikJw4y1#O43AWgs*ve4x(0?3=OI+3iImJfJUI+cdKFVIQxKP@3% zL8I|D&zj4gSYcZRfq-WQ5Bp*z4wp#udeBnJe67WSd~c%JcNsJWt#hO8@HfhjOvWoN zT<1XhjXpTS;p?6-IFXq!cDZxXc$aQdqZBjRmm*e>5>5Fd$MsK67+(Wnpa!c$}SCcU%%u`CDz(mM#!+wR$=_qtRmYY>6Ok|?pIn5c>6-b9UlMz2XUdaqt{ zhP>qFdj~YhO}=t}_czNQ?7X~l-gBPwoaY&2j9EWMCX)?Yw{7+Ie+|yl>>QUl&z=)I z*IoM3N*p5-U+X81m2V-LubG8(Co0-r6MTl_&%-cw2);g)k;`QE4lZ^9fl!Iq8z?jFJZ3=_Y^VQG~A9>-<-1KhW*vkUZid--0c6~UhN zAzm9+hI(&Y6}D-0xKD(y>z1{Ver{V|pFhxc!HnpIGsoM^o-@~a@w_R6`?WBBt+D|O zGlLn&Y-iqPmNPS%@r(=O#H?W6U}iBBnDvZ3W5Y~jRx-1he@VbY>f~j0nDq+5XOud z#tdghFt0HE8B2y|%xM5iX{PCoWz2iBrLu$l2KF<^Ir$FxF|(;=C5kzU4&@|eHY;PD zSra#e+sB>jf1la^8*`oc^8tASXAg`RczTf6pc{j22FDIQHND zr54YzgMXH<*I0rHZA{{tN}0H;dm*1(uE`34V9=x{M-g4m52KT#K@*T3oSp_@z(uK* zb@~sW0qWr@RBJdB8wMT_P>_)adVOXWjvS2!<;TQEF+;6v)<1$)XokN-EnPUBC3nSW z9y!vke;@~xH1PFZ4B256KQYMwWpXh|9KvT8XXai2x~sP)4cs6QG_Zlj%j%9pY( zE74podSQRQFdh=3wc5B;AvrQ|)hytM72x!v=XE#=N9CN?q-wQVjaHSO9vcI}oa>?e zf3=3zqT{y+o4uLXuOJ*@$!p)u!pS(h3Ar3$@Xuz`td_jM!Ey1K^q58*!INb1okT+- zgo6d~rggulgfOi(C@o48p^XAARIRMmf6*K6m%ZVJvQo}NGW;{OI;i5r(>fMwdw$4@ z&rT=iX`e$&6e_qd^p8m0w_~^Nbc(dV<2#MhwMVIQVfuid@ zBUVfB9D@IaugQ;eFXLYz(3!=BH}5_CZoy?TC{KkG>JQ$6tLj8KaQBs@sfSIBr{_$zh{%IVK^&kg!|e)JWs+6cMlu{Y8ws9s z;u%`ESB<@OE5w0vu^t0>95d@NnN4ixjVB|?s0TA}Hrn2OjKc+@C+m4K60rZRj*aXt@c_LQ7y-K&2;a1s84sf6&7567EurbZ6XrvUl@r3O#%xrR4?AcCld$^vYz|A>pJIHPr7<2;D}G@)2mul zO=r$$S3^5=Mj3Z=FZ*0V2Y!zu;JMYiHRhX0knoZzGTgeVWf2D4#g*vE> zPmUW+Hj!51jvp#+o0LA9iL}$bVG;z=H4jGvNw9}tJGX;SqMoYXB zQ1vSsQ;y5g)IFb1DA4L6XqZ9&0T7L>nAG!4L7Yxo1Qs=rU9A#tvQVYd)n%6JD|O|- zRhyKdnnm;!0q|DuIjY%ue+q+|^oBH@7Q(om`BGfd!DwEVqKipLfOxGckxVE2*4eNI z=9X{#*sIm&G@tdE~*&De|W{NWQ_ zrAL7Kl!)ZsKmzBgoO0+gTHboV*W_7p=T`^IMW6r1=%=GQLBZiiW z=69-0@B`$Lfx2xH%p4wM#kF=1ZRt(y8nlvkSK~K4dJzF9kzf)+#*)dzlX#*fvBE%l zS)vts3Z#cz03 zFVo#iTCuA)Zahx&gbjF($3H3Y&2R2JMP~XPvQX7Cz3(K-2K^7T!&+#f8zh=#@m28= zkF#Lm%GF>?W~qn@yCllG>l;ru?l58L2}up$LW=Ayf4zbroJ`rfh%A#zj2-8d5A)p? zt2(gJRk5mDDo`2A%Kd@4FE9lm;3kL#U%*tm^rF6Js z7;ntMx!7Mg5TCpsqBu9>{@Pk&S^LSY2VLIsws$>1$ERFL7W{sE{yrTN(UP6bIOoCj zW{f=~e}h{X@;v*N97p0B{zT9jD4`7@oc_yaC;eOE@>LC`HJN4l^i--xV!80*$hx}X z3PVj)v#Z)IJStppt8veBrpFXE{b_}7zFUX4YJX&u7kGlYdaofmB*iflHgHa#tU?ET zl?H2WvI7&eb0u0ce?UgH>ZO#DM%o|M)THgp{UkViuly~Go%@f} z)X(yj!r?e$xCsv%vBfl8YM@rM8Z{zDtdpo_OpEafyw5!ucbhm0J&IpC=vi+E{iCmg z@Gv{#C=O7zL33PHP@^}MwyWsncGCNl*DY-oaDOknUtE@y5gVyZj@7DCxA}$#f52Ku zzL@kNr7QUwVT@F-Rq~`iw$NSBHe;dFCha`(CIx{!bm?U}VO&h&@V@afN0Q|UxS#(* zQmmHX1M6TltfK=8ttPTmnFZ_#j)?V5aD@$EUF>+({b!?a4Qs;1m9m?(PJ=q+=qWMV1QVHn8(o!JYZq(l zbZ*~G(!^Tb3cYfz^UO7&%XKTe+RxwjZMaxXrKW5_yhM-U$-m(Q$_H``>6Y{D`toB3@$OsSo=)U0%LWP>@$t zTYGNjtypOS+kE=``L~Yue~GMC^-|5?Q4^N;+AO>w)ik7g6#v|$^rtoTq?cu%wIb!@ z29`fJvA_FXf+71mBFCe6gB<DR|f)l_iyX-YG?8y=+jKr@rl zQ!^P{=`|TVC6Jr-JR)XlwnhI0I_UKTTBPlya3lwqY7lvojGDi}d`?Mb?#Gh(^VDd5 zYyRr1Qj@iyO-+!@e_uY~@sMQxLNzPs5`S3VYyLiFae2@1yhwd&HCU8Fu0F4l>w7@o z9Cta{3)DMk{O?pyVN}5KaB5TMbg{Wr#$X61E z>*4YXzIv4{Ei5UjD#t;@W^_&x4Oz=2M8E+-&DQ8Yr3+6&e=&4OJ~7YFes^gAdWPjhWhPgF zMFC}#+{))ze?Iy-Da{L$ezmBAjO?6p?q!#YkNPs_*S&`SV=_MPO~&WHaC5(Lcj%x( zw|bl>NliJrNpnDrr}ziUJ|b2diFvB6Yjae6V}qf!BDs8jfndz5q0^ST)b6oRwTC5h z$lTpTZi8IJ<-fe!(OIe53+lfKCzXa=sG>IZfXYD!f2B~(5!o4jhHaG3b~od(zarE0 zeU{K?auN;Q187dYx*0yZC^P>WaAhW?uf`6Ns4rOFSLP}@f)B>09vDqrd%TFRn4tJZ z@;B3{zwrTU2&QZ9v)J&{fV_x2ZK;H(e8@9MMGO4M^4E7QqPO@4kBPXes30%*o&=}2 zDR6gDeK!hbn>x?x%>^q#Y}LqJ`)?D@)eG zG}!7G?!x_>FI!|cPkns2Ds0jJC=dSM1?+FV_vL3;Ah|F1-(mZ29c)=eSw(5($t|bj zf7>MW`TRCc#IZB(ld(=aB7NLcSuXrLCr*`j(0fCHj99%3HiYa|`MT^#@PU=E_r!rJ zS{O5}xlJD&e{2$e=5xyR*|((@-$skFffi*Mg!Gcm*Kj}!nzTd}d8=mwStT7&l$|<;0TO@D6ifL-N%d53*T7l0*xpoe z>L_isEGUfAY9KX1*crV&ej^RtrC>){vOZm(4qO~0>{pRaI!5Cw^Yyy?T%oYIf2H#d za1UU{TXry>4B6{YeAZjlRn%715>&s}Z(r1od0*P%0G#>g9uCF93+|G!dt8!y)T)=E zAu+y><_9GU$)hKZkmEA^Cr=IGM+e`p>Nt7i6UrAY={3O~Y0&`?$a&U>HrE-;IzQO+ z;W#pkELud0R{<%(1RVYS7t~%_e@?wd21Kld`FjMEkq`K_5d3~x?g1m*fIJR|be%f? z7~Y(04R4O`dmo5Dp1O(y4U+FecS?Lu#7%q}nec?Aa5v9yD`wml}&V1p7;tXOjf11;((8HU{ zMWgtT&&vlrP{HY`Oa?L~D^4GrsVUIpbFRvL1nA(VS^uo8ATRqX%8VSYRuZaBW21eY zoCudV8@6++PC{;NaZyf=P*h48z7udpF`9jR{TDEZ_h_S9j(xe8D}P z)k$Q;V)^2!o9o}c<}MJ$f3`?_*vb+1$wn%Htnc2SR3m%+xbs1Qta{2v6a-Y$C~y3r zufB6)*J`&Y^@e={>Hj+46!jN%W0Wz{6hfugn{Ni&S#Rw6^6JrJC+da4;s9L!fEKz- zj-TLi{sHNl^&$^gAid8!Cl}9Q0dMR%x9??s+G^1Jv=RR);bR1Pf8i@~aTLD8uK?me zY8B0_Tm*BvT_ewr* z7Km~SZw)uUe+YL`cA@j*(Y-)vo(KUpF_S?~z`$ z+edk1ivf?EM%&Zae_knr?k>6bB`SE#QWnu#9}I#R6^T{8i?#}MRF>4i!TLamrERbL z0!y+=XqELAMG3`G5os~8X~KMBR1oL?{Z^JTHV^^>>ZtX^SmkzNt00cbm>>uUtcM~M zzNMs{kQzfpg2o~?|3Gf@`Bo0ps8^xR86Q`0x0Lk`U?Kc{Y9F?H?qEvA_2rWV7o4qt@(2nz{GHqQe@aJ-tO@&}qx4dz7;jTa4C7sP zffZrGS7#h@QJL~enxK(u_iu1>_4jw3^<*;+!G&M`^~t-z-;r7M!q@d5egt1~*X=$g zDq^5XkiqU##osW?`haA-%4(9wPgvVpq?_I`e8JLxP6@($8?XyUXH+B8i{IwV6H zw?7*ye}z7`M=}jRZlYLxAQ#O^5)YZ6k1QucNbdbpv#zAVL z2Eu~`GJ&uwi31Qyrw*6NN*qVHx-dP}LR?lM6iR$OVu{ogR}EN){f|f}F+b7qg)~vC zv5JSU&tABG)KGM^9xiY=k}L;LGIFisD!0bSe}?Azs>5Z;M%P@S{qR{m_1oWO?Af*{ zE;eevYW7T+2p*gdt4}C^T*>xj8B{09V!q9%dCwjnpFMk;ecIZZo7;q!ut8<-f3NVE zq%~LIZ2pmHs<>2HtIZ6K(m+g{KpyqHtx)4(O3^Y&Zat=A>kvHd{h!5DmdL~ao_tP# zfBlz?;j#yEyoq`q(7_&8l5xldRcRmrxYRg^O9M?slnTv=nTZ}u`fS@y<`Xlbh>O!| zX$j&AAuCT0hB^T!AbSZN09SD@brJsb?o}L8{$j>RW2SrZzd2^!bcprcEVy>AhbW3- z1(`}`j_UuIIqv__Ec&T`BL9TFcm2?fL9%8|RK4Jr7!yuKVt8(3MLb6-I3Nn2J>R1`NP z#!+ac#FfaXC@$S#i!9C3Ajl?*AT);-*;k=y5D;2$p&L;Hs2Mj>?lOru#&RsJ3W_Ob z;(64y;yg@9P0iH(>)kr{ob&zeJ>R1#u@yzrwEcEJuhpI#XDc>%`nfJRw9svM(}ABt z^HZ((X`-zpZ>l(YD1Y7h+*IbsI1IJNHDht{XOxJhz1I6HA|m6p!9n|DM$pNN)kR!6I~vFg3QRaQi3 zA`irZcE+gyDnI`h@xgtUw>0xlrQB?ZJ|7=KT#8@ zNz`QO&y+nijv7x*pjc|0po$VxSrktP(p^?Ftu$5xq9bBPoFFFFvDVKdGbP8ROQc!+ zXuFT1IjK~N1-I4US_1}HXg~)(*DM-J8(PE~;phQwrNZ~(nmP}dOb!zl;z;(90Gvf; zp$@%JigsvIm4BI=l$HjmIkI#zhp^jRVJ$2??t5$hnb0eM9K5M`c;RYq-`nDg&<8k1 zb&{;orx!sfFhtL^zFJJQ<;6sz6OTO zU*br{5&66MI2&i5|D~!T2{IFNvJYj-qSkuH`U??`IXLC2tVyhI&pm5st8QtnwZMBQ zBDT5P8GpNvbZ>GbSa=%~efMAQkP+ctJiwX?a3PN3l2bDhAf5>@CDhlOs@l7@HTr)Q z?4?TPa!@28OaD+u?tN0%CunPeCs3zjEQ_Q9woiF+OV=lAyO9?0jd+dyDc};Z`eMf_ z&2XMKlK-akxBsPN@xov!QvE%>rw!37IMVR{0e@0KgE^JTY~!UCTv01T)!pZXEXSZUB}WHG(zsoT zJ5qgNGx(S6tjf@5>$8DLfwTk}>5v|T)PI^{eQt3fS6bfI@eG((F!w73OebUatuOyJ zSk_Z^uC^_zVV@=>e&?dcZa5lUUcbQ4&~E8-GA+>maHvu?(i#%eWwdE*6VR|2gyTi% ziNCUN6Q+Oq4k>a4^Fh-88qVp>j^syeO*-uRr@ljX}v`5GV%+4K=O2EH6^1TI2( z8xe2f2iT%w(1VE~L6Qt0vyP?cwRyS{T`{AQgb=VcO9b8bs!EFTp9})mQx9385}evE(*j8A&AE ztYu^xkqxXwTk|&+_ggq3*~&V>lQ#qK9O+);=F~h{u|~fELYURzPHrQmP5j_*){`u_ zok0EpI{=tTQb`(+4CmQEQhzWNQ*$wCkP|k$*ieWri!*5J6Dt8z;2!iAc9#!6D5!-N zxS3S$R^$g?!bTveNy!>bTwG*YH2h9kFo~m<4&hp7qO}MIhoo$i4njGPbwmUQfH|nF zmb5}o{<$*dLoJahrDpxV;exP!0kbgvWSaE%G-!jpIJs;12Qe9ahJR7%F_cwFvSTxR zlF|-mEQch)4ChJCw7mR#MG1i}CCS*_X6Q7B8N%|obDceT z24P-0Rw|ZnRRkzyL_^}z(m@CDlN0!*(vcfFiyV$?{Shaa+vsMr!VTyk!gBnPMKMhG z-wh6giuFEv%3o$Fs()yPlT3SfQ-CTwTs80Q795N2k6*sMr2UD^YvBIbaN{OCX8IJj zh>VEceZJg&Ht|GLYjvkF?bOZ!&fI6c}L|fcQ<3N!uuj8t?D3E?~iWf-G=h(Cdphu|tw$GgW zocENMr;eXCfubf+&r&m~$<%YyEXs>|o|;X0Q)8(q)C<%&YAQ9Jnnq2aUZEyZuTs;g zm#7)kQ`9I*PAMo4DxP|p8bbA@hEcikEmS`$Mbb}lr_V0weCg+X zQ)MG$+hiB%W%RXv$xI*S)BeJMg#$+qtRLhtsDALU!8bhi4Ou(n?$AX;KOXx1Fxjxu zVF!j=hCdv!VZUfPwtD5Sx z8MgAdvp|tT^ZBMcKA#b5Xb*=5>}b7RTv{gq$0Dg%=2*&dwWfmYkOfAgc02BN{+B!@ zEIM%sxL4H+Z<{-z4leL5rovW#xn_AmS236?npJiC8{esFVGz(e@dSYrG{7mg_(77= z4W`3#5%$3WIBe?Tg%V4pP|R$neSt64?`E){Sje8jS7kWGji@(%N2OGZ5}#txT(qIO zuJg#>K|#Vah4EWJ5dj+^!eUI611Fe@`7WI$3AB)F&};JXvv{ujCA30+R}N+{E1{pc9S8X8PO0x)c*@oS&I zt_~tqbHRr8+a=PEIRP{ZRYO$8d-FeBOuHLy0qS58H*z)?GsJF;JjE^!HV-ZJxQ%8~0b? z@%T3TTlF7CO)?aJKtHH{Il^m!7w)V2UE#z_9c#re*u&i?3-`OIkL4pw2@nU%&4~g* z&{36@o~_B#X;e50+wfE9fW88(AShanLbK9pkLG+J5)`ozAVitT{a2yPxFZI=gujtz zd+}MBUVJW>l5R*b#KIO=M0-eS?^$b=G`~L4i&>Zxm$j@S*a!7FFyy^GPRQy$%w;HwJA&uYBHjo0 zP5HGReJ?z)as@I>78*;J5_;>l*T~@Z zqAMbs^U&zA1*PMIUFK#r5BY4n=6*V&IjHB!h7?~w6^ZS}kL_iYYqLj}5iB~y5)hsF1q9NgZBZF>is9=1EUgT2WGkbn|d3an}p zu7l8){PKf2gv;syph!(OGlt#8T|g_8mkHKgLc5X5ze?}buK%Wnc47ZCywF9mpDp-I zpVFKyL;_L^Tpt-DO&3osSnjo#PMiR_RSpCoh8o2%CT3f+(=!Bc+S_egx=j z!@ckh-V=IUx&GR+p(plACUY4{HnB@So4-S*ExIoCWIp!6ln>UrHB|TW^;h1ZIIb%9 zf&d_vCv4~OTaIfa4;tEJRFQoUmJxs(^`qpo!KYL@kTI)lRtAVgh(hKi+Nl9B(vAd! zNz&Ief|N`r76DqOg|o>QN}PKh(dQ;7H9xFhbe;B)rJ+bV;+Lm&(5oVpmcr`m*pF{3 zTg{j{WT|(?H#9d*BJ>6&i@Ig6cRMiinXWLE|NDuZLl9YhV{ug ziQ3kU33Zh^S=%_-afZZxJI#Q6VOlbch5vx9_-Qm^5lv52QV`v{IyslG|==960Ayg``c4Ky~HLnK99U>&LD4;lQd`ffwYXN#OhOna`4}2ooWC-yn9VR`C2|V-`%MgIW5xiqaL5CEyV0iS; zHuHUNL|;NR+S4zj0LbO@Zfvlk%||;D#7!h+VzEkF%K4Z!xxVushg0#%1TBe=*-n~_ zGN-lrabU}qA?g%b@#ai+ec|@Ce;SM97O?$;Rlf^ zc$4FV{JCWlpDLkA@OAO3m-Pd7!t5sqCmcMDXV0Y*T^$1CO4v>xvHMwEvhF#B_mWs- zK+nf6E(risp0zWuV6-3K8U^FGHuKcCVLef~IP%j(bOy>S^mQG&z1on;B;TSNq+NX| zT|gt%*T@fe5_ZiafLLGC558Tp=to}?!rzi-eB)n@YPCq{L#3pn&xIWZZl<;XM9h7Z z2TTNi?oj~lhhLasg7Sn|umaZIl`Tr=xJEj`Pbo`?f}hFNPHqpJ?)$YZeNavflls|Z zGE-A09yTdZH})l-5krTWGzxj<+#s^u&zAYn1D+a2YMr(}VG7DfF&ZcI_W>->tsoVB zItu%iLaSlE)|qe;!?gP_XrcuksU5rMSfB&)z~}&Jm~KPnDl*E|(edD~5*y6*cCGFS z$$!Y?^G83eRJNkE#9-&baB!+>vVYm?u^0*CYFLI=(q05;DLjMFIL6%4QG%bN<0wdQ zRoy=~)IB@C6~XaKr133>FRVR`zWgf#K9Uf|s|mrWp+2WE11=1VP$b&bGImzuD;Dgz z0>J^L+{A~q;pyI(8ey8-K4`8~+sVk&-ExMJ{;fd@sm`v#nCe~K0@^*GEQj&nK6r3W za-`CW;leC|PrEd{@TdwX_t_8lj!r3>+Je5C($&RdL|R9ySq757kfd50Jrf>L>O#Q# zmhd+l%XuV|qo22*Qg2)V%NT2)_{?y{nOs?}x(&S!%jU*oG43sQZN`RF!u7oV@L#K;PTD!tU5=4N#53o@Y8 z4OJ6jfWSGCwzKZwTA#kf8Hd}^KkWi!q+&X&FAy)yX8gSEaDyiEi6ZOA++?9pjyJX!h7`-Ut<9q-OG9h4JpfE@nw13tg%W_3l7y~6DmdJ&6QBk zYOh1$K8BDG?}`HsD}E9YamS#T$v&gqe|Y`wyE@;z>2y;*EPLpF#ka<`Q## z+Ju~-KT}U{;-yAspf?Wjs)TlnP<9ySd><@+{GsvQt0 z{6(0uB;T=GEhzs!p2@!Ra}KhMZZ1KX0U?gbV!Cd2aI3%r z{4%&R*})Jfmc{RRDba}ZGaL#l!{Of24FzlGDXzLR=W%S;*R|U5FB)()LP;q|<)Tpb zBa|APS|<|do6<+G^muI1LR-$nN=8U0r(12iZDO}0Taff#1vg-IuINUdu@x@Yxl?#r zWJs=5N0DAr5!}(?yjC;t_YsUmGvs)F`C2-iiYHubP|@r!80RfSgrlrO&Q2e8wA5ud z{p4)};H5NUX3DRr2@6oBmT&I~nL{)9a2ho=no1TgHDGt))b}5ms9tzURY6|cKn2N2 z@1~3C_W?hpbM7#ZZPKJ?cpc|qP~qfhx3p5dqR!}!lmPMAcOl5#UKoqXTBRiq@{YkL z^&Ke7*~YYR*$?EABugF2bciWb!H_P67GhLq z->L$F#*3G|r>T~k^Uk0fQrR;V26+W7Ym;a z%+X?n;|BYCv~+-gEMc^Tn)sJJrPZB8ak<>kS_~4Ow;>W9Pc*z9mV!Zrm5q%yH#0Gp zt{j|@=!xeC{L3rw zvEkUuQfaGM`ASuy*zOx1zr?9^cDd-mL2o@sDSCO^n<^VSE(9RXiNaDo>N4PC1M&Nb z!%tE~E0y?*f;R=aY>~2)C$bp`PqJPJOI_HC&g@XyCwTRQpO2;0QW;`uL$vY{dUH(sXA)p-_h442p@JC&YYX)cHVbOf?y!Ud9K-pW%&PJBn11v zmr(x`Sh29Nv!=oi{cgUeo{*={od1t2#& z!CZuO6T1-CIun0d=p~dGRQl>yzp%yT95E$L#w_tTB|AYiZ@`@H_0|H(=A_6EP9Dk+8ROUBqrAPDqA1$@|i2G;n{Sykc zu$3Y^*y^Eg*1xZH`_s2Aw^2Cg2W@oBk5_wD3Yb^tSZ0UOZDPi)w5Q!_XVd6d9{Zwa zFZ-n=Hdd3vXrLe+xj52HHscFTv|BbhU#A?tEP2V>5{oruL(nEqO%b{b;8y0aBxcF_ zgvXkVC2v!(qQG1Rxnz3oV@bvu?^uFUrny9734J6nU9wZqqGVOhxnw*MtR+5OT%xc^ zL2k+UM8}%EAy-|hrtnbqS4H2FkTvUEoVMVy>|2H2lF>vSHVg& z$snS{Rmo04n1XOvu?0mK(5}eCnshE(uYzxheTRs7DWhAzVeHb3zFVnQCuYCn+4Q7$ z!ObRZt#!(N%JWX1UwBJkH2likv19jQd(PZ8JL|*z@vYwb`R((LkHz37u;YggA`N~Q zm=yT!bsN*qDhw*T5X#e-ZRcflx|eSv{9~9H`h@N3{)#1G_+<2r zk;(LY-1c^`@R$tpn4GsP-K>^-p%5YGr*WR_w_c`cNDo6miM0K_dmPyoMgeBcv{oV0_CK*6r{_*Cx>!;P8p>V zNYDN=EF-JZPC>#&1?DLl61wHyHmBG~)09d$7}jgD%~> z=4$=#!?p)0{O>jj?YoW@7#GS4;hYyCbqgJYk|EMj{J4%(mhlOb!EsI7+x8h3i3l+( zzJHYZyNX1mfB8z;`ArlUd)Fffk0sjm%a=O~=-nRxK<$oqj$)}3a?arqEYdn|tt5f2 z`bub2BhjWZFG4?@oJI`UdP#L|jev<4iZs?T9JkVZ2|m=wtEvH#UHiptk>xMJac)6% z?_M?A{%tQmQx!ppEE#U4FsxSPgH2h9tY6HT&6>NNrh*hgVIH#lw2gH&UKI-3O?Plc)4^lkaQ5;rtEk|Rh$1ARt1DqD%T7UV z-a~91Q>ypbq`XdY(Pdz|=}(cQNq&??D5BP339h4XsG$pY*zS`#+h3&LVJ79X!;^nE z4C(mdg|z*b%@YSFdD-oa--KxP904gkC&MeT9DR zJtDNt0*ImcT^1TQr|s6iY`f8Hl}xx?1<0qZdFoYS)l;CTP7F9CIKE;Zq@-_mok2(t z{A(~+tm=_WL9bl4(P1h@!cE9B{>~~&yC+r(#>xM)F+{C-&aJ~f46u%p}NP;H|uVzwYwcY(+=+}rNxu(2PiXI z&ccz_O~PY5oI`B&r?bpe>=M6?_|pa~!x@FRd)s%M4#wiXmm8LJ$<3CP509iPyzuH0 znc)`qxx{fm6YjRY{wOivB6(oi_5rOH@VTcp8p~e0+qKfMo_+yDdr!i>BjBCK*w_hO zo2)P$+YhL8wyzJFL_E`f>_laZA=-m}DwhJT*Bmbb>gjv{XT7TbXW~Q;$!9_E&;*-QG&@CB%<{k-Q!l~ zU~anx((+TeJd!@C-RW-feoj&a#8jfa@$gOmgIp1R#z|xa3as*d2U;)iX9oB>g=(w# z(c66}cXtgv*y&wWeaQF6vI*KQp|T`p-LqA+kvK`XC)kitghUOjd5H9IjL_HC<^CC2B6{fi<*aG2a`wAv!n3_dCk#K zyU=Y&&eY>&8JG;D1Wo4y5SjbE{VKUsYLIp2iCZQ^ioH!rS+cI%h45IgzA>W3oaQb$ z&6!$G>gyg*DpS8HMA&Rd;F#N9#0-V~gJW;7TJ=O*uB-5;GiK1P#)Fr6HD1$^mn)c^=tX$j0OEc=|;}{ zyhwRC31##DMJ{pgq4@kLo9`{$zpz$TPMp_t{b9VJ-C@n# zHL7g2-R|~;$}g}0+}qPSuEG%}!mnn}UHwWxAINE~7(;Vz)I@n-HKLb=Hsw%aLZEpG zO5O-m)a++F@J8M3-8me^@2j2RFRvk@|JF6O4)a++|Mh>rm^&9Aw2>!3)SC4LyooR6 zDuQ&m;bC$-p0*sHkR9v($`SGfc}zDkxpxmJ5imU7pY zAsreU01@{C$cIz#`=(=8`GcCyOg@=YV7)hdWu}xdZ$3LYw0lvR{nr>F7r-Gg!N9=O zLy|9&9|AKrK`~BcprG%a{Hw`bySx7^A!F57PJwsxI}>1I81*^34i~F>$N*?IJn~L8 z7E_gtg?}>SC&*L9aHZ*ZcXf4f{s_*1y`so5{S?^)9FQrX+q2ppkeL_m_o4Hn;*2OZ z#@-j12^#3`0xoH`{GjK+bJ4TtdNj&?p>P$@bx+fJqj9XD4Q3@Q+%IFqT^p2wnUK;z zwXnbvR7^ZgE!Ejxn7ym6&*vzB8Gy6`&NWyfd}-~)2>FxVu=Zfs2JZw)mu7+Y7N@M8 z@;e&=9|#SWU2Fo}ThCxzk@p%7YQ`lL+!R)_h~7g>Y^>k6s*(ogWTjCvVYZhOuw40s zS3$*+iAPzTBe*0(P&eTxUcC=Y@8wCYJ}ViICR;0rdV0Q#Znkt?^!rMai%`P;jC20E zG*Li`!oKMZ#bH)YeDt-%oJOXL>ZO3usu6xb=OmO^yMam49Pk&Ca{{Zh?k@@jpFT(V zrN8v}BP^ZCbn#4g0pDID4A;TS#hUL1lOabkWb=M@2g|Lq%_euEJ~y_W`&Cpd1TCIs zm&!Bb!_hUtB%f%#>-6L{yeGby(=M+r0Kx*ME+)Wn2_z0tb*m1xGK>RyZ23eUnjrxQ zkwX#A3y@Fn68$qc{-91MuQoiq8p*mKG}0!^A{`ln&8TCwm zTdnJ63ufAnB$6L~dPNWD-1SzCqD0L_%tqGVJdz&5&c=+-*u$QDW4WZ=7S39?!@ zz3teo=RNWZa~2<=cj`f6A4q~njub{@D_RP@BWVMo_=AJ zE-Kr)@3w#JX^3;0dw-%J&Swo+AagP|V$3W*N^Ja@4bA&EtBwrMBYgFaSVb8VT_5(z z)`t7i+V^bXM1n26*)um;eK9~C7&tf>7)U*MaZW{j(RNM43tCgyaFMeLo7f5{__EfW zP>*NGbXf2H`?t<&<-2<;=gUGI^$04tV5=9pd2I$_b0RCD#QWMlkL?)CpVsNaVU+cz z@NT$k^k3YT=uy;FB-oKx1W)F_q_6dr#a4yfg;o&9wyE0z6qnZKE14z9XgHaDo{UzM zc0?=a6uPXBZ^_WwfmfPg`TYcd^JK(8gx`GV>$-p6T!UQmtuw6aAm7;4jr@;(Sd_r8 zfI%qx`-*bAdVA9=LKE`6Fe63>WbG8yX zG-A``Zh)0K=DpfWQ<7)}uQAZCF)D&G@*@=*9Y6 zZ+F%_FCKxP`d&2<{E`}w2L%Psz}rz(yHXLj#1JY8EC3QeSF&!1zDVOKz>*VLx{;Sk z*2$5vYIl{?p+zuGwA{v**V`q%@W5RX6Eh#^Gqw1~d6|`LKE)u+Vn_#e`E^$oqh7P)!DSkbi4^!=19@yUY@s z&CaEg+yH78)KPO)V@qOOMrxM8!Mo_aPRyR=#?yJ7VfdQ?PP<6x-%k$-{6!b24-@Ur z5JqH~83V=KB1-kD=E==xRhYMEc_24}AKsCncM1|tqE8l7N`5n}qeW7fr#q*asiyoR z4U>?w$~xDl-;WE>+@D$-Gyq^QJxn&U#wL@dCr2gBxLWjgHzq_BOy)yq5j4_NF6a>E z4U0|ryt^G^I2|wmv#spE=Yy$)JTdr&Jh$g->~8yKK|m8fc4w?j_$@{V_bs_BPk13U zGAFvD5Og&kS@GDuxNG2*g_qM+PueLu#+9m6FiRy3$H4=p%uayS?psQ4E1Y@kKavnD zYq`ER7IHS-BcuuTpL7Wc?S^_NZp_&wfJep;_Qb1qTk`HSLwMqf7@Hmi@U4J{LNn;x zqS-y9L8d6Sf26j4s1F5Kji?;**7FZYxZ;ohqKI!n5dW{4Td%a_x zM~fZEWaf~~@-8|d)w_GBX~hr~hWZ`m^?<*JYlsv|vW3!W)pd7vqJ6xXAg6TIm0w+} z@9iAR;*}`k^FYE6I9Weu+!X9=cUS)Rt<6#g0^bCHyuNOTH{-RsY^Gu0vlaG%#TRb2 zE5@Ilz$PMu!T>a~I&{u)7g&XlmJo~jvB$1J*l2UdWN|5}B3+IBEmv5mZn^%lnfu`+ zQ7r=(nT2@_+eDul#)F}I`HfAJLV}sef-Di3o)de{uE}ZVHtWakSO*wFV}c+Gw3k@3 zY%Tyf#G}Tt#6R=-eVf%c5I^$^3`7XH3;E69yA+`B2EYRYwt=)w5_L`7-)t5>4Ut4? zeGEq%a)%XT@v7m1Vrh7g;X!BIcQY#F1I}Y=DkS>$^RX?~ob)X1m2meSq&}U>*;mT4 z95%V|mJ|xV+6e&%%}~gL#x1%%ieesh6=*>Fp$DrmyW3g67;T2|=|;V3D9R8Pe?E9O z?*+*9INm>)ji7{SSW+Fy57Nm`4;{iNUlHLN(56 z*Y{}341T7!*E(jf1QooHZ!S-iecsS;HJV)#MSPhCOBkJ1*r^eI=)oNZOB!9UF&6%H z$jO}sk2s3_=gA_32rs(d=*<1rf-LZt3YlK)LaKyxFNK<$Q@^Pz2a~L@Hy|=9EKF!X zVpev4eA2gSKz=Bo?$^_;pqd3pQ%lS;itKGSk9eDK?EQ2)Gptwh2d9#SzoMpFT<-d3@`G7m{+ z!A?7RvUzXfNfSMaY@Vh^Zj9R;q~O<5|K-C}2OGX3Fg-BAndvC#sp~1^Om;w=q|X$r zO7SDBz<`l;yq-_jsGJ$(8>G0k`YZb*Vj4o3@Zwk@(adJ1%B?6%_$m) zg&Y|iNrwa|HS#hez>tp-OXgzD3iM89%44$jZrf;F`&Z;|_&SzdKQyvA8lq~Ss5ihV z3Dn03QI#4E1x5fIcIzy&VZZ^n_o#UvSJu)7)xD(@1bvl+O=k+f9NJwwcyxO>*_MbA zOqv_&saL++`s~z_L*C>(Xy)QEc8)V7l4)xY>QI2se??%F`$i6cPKVm=&Nb^}`7;Wh z{*h(x17a?4_#hSq21U~OjFGAL0+<>Y*t)kX)|Wd5Bqe|^^9;ibf=h`jx63);k&=_y z@szW3=RG%cG__ja41xLU$+i}}q1{BvkEeu34HYv72Rl`0?S1w95Ccpg!AHfSse`Gt ziDNXNY(#YV$6+2ed&PPSOcq0y(`D5`La^gD&Rp) zxFR)SL|tw_3f9DVKX!YrSv|Vi>}I3UUTOF@l@3UmbZcLyUUwh=J{YBbMn_c*YU`91 z3PW!>y=i=TX}+?5+G=y27tfS$#p`gMWofv6jlU1s-@g}tcaya5a!}WD9=WX-l8#!? z9!3JkotdKMf8;2{Ov7=JV}*=UtgKVrsxsG$2i_!1OD6=i3ww&Wi`lM007*njM?%x6 zrU2|&p^j1U8bJr5Ll7ct&4A&e>dWxK!jvOmU5H9y#)_LH2&|6faSD}5^6ziiHnd@xW{h?(;yS8&k4g1% z5^5i?;HeYScez8R=10tndAB%zptXi~I9P$X8_<> z9ZeF9Hp2?uioQqAK=KLTlS51HEv^&VFm8co6B~$R8{druVFOq5$E`0phdl-&q??iK;d{r<2ASUP*YR&~xxJgO4q0Cl1i#3(20`p|gC9;jmr2W5 zR4Y0PmJBuN)IIN24nz&`e0!``s8*xlW=6X8mhxa{t8=WtPQ84fKHAkILjn3K<{DvI zTXC7yK`?aC#*_(>UHl`N5HOu4$k6$#yR3cOflc^k{)Ub)cHK0U0p$5du{fO6wPZ<+m$kpWDS`6Rn&=`0wg)rM%Lcj&sDdOhy-|bO* z|Mt#LWtyQcwJVJ)bz)U)YwZN3xSVlTwjHLWCiWTkPOy>pprD8Ed;n2qH9;`cE&A+y2NlYH)=W_&I*qi^nw_XmTj<2@f zj$YW13ztnRA38cplK^VFnF`M$nR^IQW+n~<uHV+=HNYcCE3UY*O|3w zn7$`6GY>}rXABamL!wNt-EtwKM30rQ->PekW`{!m-60_g z6|D^%UOMAV52_Wr!*L9V&`%x2FB%~yDiNkgPJ~yLi+6^Ljgg;#lc1a{67FQlAC&3j zx5U=aua0t2wdvd0^!j%Aeo>wS{tNJt$NAq5erk2}uj-GTiH$kc?%+4l6ciN^meXu4 zIRK;iRsFI4UqPm9f|ZQ63C8H`zq;ot;<2fiz_AVAxvE3~5#-i0G*T1g5liPhxGZB- zI0f~M1?XZYU2R)hAJ6$DQ>ZHvHC3= zd!0rx{qxV`a5I`_Hh+XjNFrfW-uL~DGf}r@S@W@?#kEj{jGv&I$NM#}sUmQ>G9wwQ zT*$)Oj5|rJM?w0cX_{)qygW{=e0f1xGg#0wg0=3Qu7#9cv*v0p9S~KeS25R8=NYZH zo`71R8R&n-Lb*Im<bia7ong6v+mZzbSl!7KN;=4*A96;F0pU zMbzykK>)$)5b_#jPDF>ST$BmAAnX~g+vPwM>z@9bzDZ(@{W;XqQ{M5Zi0M#$#UH0Z z&krdj;VD+&y=P<&0ThWDF_^PR4o=B1aT3!V>a3;iX(eV+$rYqtE1Uako9+=tk(1Zx zv}b${^B>-Q5DJKU_P6{rFWw6>)}RV;dasu^Yq@kJ%5~JvUfF{ZT&8Tf@}38LvDl&v zgyv~kc5mM~-KY!bLkW>=!NbKKjwxKQ^Fr4^xc}pd)Hz=5R=a!86ry$>JzzlFHn5YouNVUVz=!dMf5_e9;8w=w z`qMNB^o+B41HzsmWW&b|Bg7s3Hjit+ae-0(R{l_e8>ylItA*7|4$7GZ;~6<@&T))m z&z(Idzd4BD3%FnH4%K7a&*l%AA3rm9wmcW-=jFMCJc-JF>W=p#=izR4YKKrVXA15) zdTCE6Xme~D$g>JK#TYu+Hb~yHGFL+g1icwGL_P4}A#ZXGT;~B-gv=OBbeF5sbgJBR z3D~-se?x)9DOmV3=VAKba(qFH`J=lmj$gHUqLwD70MHq4R0YRBk;?Ax7r;+yd!>DR zoY436F+qW_tt|58IopKG&|7&`DL{6-71W>e3t z*3UBP|4=F;>er1u34?P0F#iS2!4o?dksG_g3iaw{y}^y*fbhz-X#ls}{<@24|7kcB z?LzzJ0f_Sz4wZ6e(c+9p;?4e`Po=T*=*Af<0atoVBJ(!`giPK-RtcDBgjmJ_k1Jqu5&E{61wj@-kqCLs&oe}$2Y00jisMQIy?{G_ z?INDu*}?cyM?oVjMp9WcQ3&+*%tcZ=03Cn8$zW}x9uuIs&#n*Fwq!|7wiC-(GY2n6 zqZlGx=gQo%(Z_#&f>gyUTyMc%`YK)aS0f`NhF@w>ao zi~qmW@Bf@A|5Ku1WMF6i|EOO!mj8$P)ex5yQWb8sJOe`qO0|mt15XV<2g?Dlu>D`B zP_~DM4vJZeYqP9dav26|ab7)^+ZJO2fg}zps5%k~I!dZ3a-0vM$aD6!aO2GfSwoW` z7*?uCxD^s|p+kFO+580)+5Bl#45z4`>3#RIc>;ZUyPNNe`mMNn_ZQs>&#Y69GOdve zI3rWKbvd#^J#=G6 zi-CK^c827_qt-6HcT8-hAC&QT7MZ9q-6K|WVvW%$O)`r6V1R?kDSdnjYb3nhw1ig=Og05!O2Qm*XQpRDgPBub8ehVGl@4zrZTtZai@QYV z7S}onU|To5Zyyl9t9DGhXR#Ut{=hYxRdoXF?#NEz09@b&xWdIq^EnN zs*1N|~A*AIUjMa0ack~DnjJXYh`pU$RjgPChRx=qr@PJ@q zJeqLB2Y^LB5=>S?&0US`5|~b`daIKA5A7U`dY<4Q=9=yv2q7t_Xx`${^S-%Lm9no? z6>8)1gzGjj2gI+j*SrA4to|?tV-i3t-ho1*C&}JZl1ixkxNioInI}V65;6GpdA~LA zAYk^iY8*fw6ac=m@YS#`PDn^it(#d)6ex-3fvSy44m$xc%>?0ZVDHbsb;=Vt^QFv$ zbP&jlL|f1T#=$A{E1p;Cq3di$fpdHh>&WX1qxhla#XGU}b#5+IW4KVB8v~@Do1iO( zY!>le4mN(i8iJHKk0E1L7P+>hu9TtLZ}Cl(V_O}S4tO3#2@UgbgnBe zNLR~7!!(La3mZhIsA)xgB+S<)%AAC{pNNQ@Lp>ArDa)NHbGYOi{~_T%v9hlK>OS&8 zs;=2C&Z8yB(WLPj^Ab?H%4}YupF_asX-n{JjZ!2ag(5y!!lf$?d7F=iO#%)(`ZKb6 z82WzshEC#OG=DwP9lA^3CJ};KZtwWelWCviW#EW-n4o;1A$UN0#XlZHzxz(zw1r zJN?JU2Y$l8vzEl>%UTMF*DOQS8F2|}AHf9GR?VG4nf%g`l-R#91>?~ZNjRTX%`Qld z5-vG%8e`y~tvz;}$Iyy7Jc`T+Z)(KD-0Orf1|=+}>fg9|Uq5^7KqxD2#rw?QGB^h; zZoVpEb59-ORyzPppnh0-Nn&*|-QmmO;P5R8_f-UH5}L}|$Zgr$&Y_?!o5O{#o+J^k zHyn*TcI6bloUP$Bsg|K`#=>5LG=e7nY4?P8$3^3JXOL;3h1ICV)Yx1Xc>z#P7}J!LDF9+$*`MHgOd7Hb zNZY2pk-l#HhfQFXTDR8!w01v2iqcbV43{qCiXfjQ2U(o&Y%mWaTe;A9kdR0ySt&)> z2+`|+R|N=qTdv7{$A#g5r09c3RgcNx0$fSnF}8toOcf^6EEl5)Qf?ERVyUvA8wUcF zo{}QQ7g6P!V(pSMdywmtT5l{P`@(VH{2Z`zpayfkjB%j1p8iL_44FdnCfe~14XBlo zGeigMY1kbR?(uP72u+Qn{ApFSborVWKow27+y?AC!a3XY^TYa4ANlJz4>I%+;%8_r z*8FzH?@wK6wS}3DzK&6t5;XXlN76YSZXYTlI3!}1O-YL?2h?i997~By%pJBURU^Y| zs6P~R#brM}p1@xbBgW<~WtBG6`NyPr)?TDS8SAJW0=jB}dXMH~AvltQ5+Rs!WQco) z&;hjLpfJU$q;dlK{*Q^!pHdpz$4(nxQX_7U3iu~m=kEn43r8i5_8>Fm+AX*m%I7eP zeN-0xWTo~$F6Y4n)vY#X(rN!F?pPb-wE!iG~)U1X-1st`{Y28n_sJyy8+tStHTcP#?Nu=kMhvY^%HS;vhbIL4A z8k-Ur#tU={>(p?DwGO-gGqJ6G3lj@a+TYyW@r{_O+8mNw=C|4-nLyi)ofE9Z2jq(; z@S=@I#JXoeyH2Y4(WX}tQC%jJ9LgCWWw&kmC6AJT_`9O4V@Kf;Mab;d$E`_Ij$AiR zgbwFKs%)>F=j&u$GAi5mOEszOThG;25%8>5!;Bb<{_LKe!;_VLpg3EuzrD_(A3d!r zQ{wEjMXsXndE?Lwkr!Y2W6UV`0!qsz^_N||5BOf(KC^lDErye+#{+iNw{}B?k@y;# zarFWA)wsydlY3-hJhQ!&qw{SE{AjLFR1}0kiGUtwo;Koojb)|vH0|Qai99qi|46Fc zZZ|s*SzRNU&d?2JDl(~C>qk1r!cml!uW`n@wZ={TW;3@a{MUevzv8;q0Fe$SlBy#e zKJA#wyJ~HG-OkPu(k>NyI~}lxa@h?y%=Pntp+E(Y;B{0|6CAkl6PvyLcw+mzncu&R z4%94bmC`V7z>(5`7=JHolEraPDO}DE3KdB~b_VHiZ}2zl5P&bb*J4+w=VwQN!h%Q< z@=qT6b^o9L5tC}mHNZmyS~uZI2Kih*Wd7m?50H?~gpz$YGDVREiv4KN3!`o|sDkSo zT%tQVq_u_B`UkW*!xjxerfW)CU}_R3bKjR!{E5dD5R)HLcWpK)%V2&yYoAMBz=Xrw z%B>=tuyHvmL?G-|%k2KsMllwlf|#-mYk>;JRaS-iyn^%m0a4Kp*e8jh5REkY`+jPf zeB%4_`7~T9wL|T1v}N{^2Y2)q^N)*=J6|E8nQP2Kq1#zsDg3PvD6_-EA`UbZKdD!> zp81Cyo<8f*% zuNR&H0=}*g?f}6AK;A^Y659N(%-)rymoxe$|GK@j0`k(j@NuMC&I#GsYyqjII#SYC zhM)mvfv$vK^irZr8kM8frIiCS0>=ftalF=EwYU-2N(pfoFHN@qbzqAi4wsa=N=lv^ z<@H)il4u19bW2y|=VswQ0I95To+Q*YP>2ki$ZJ5Wk<6_RxZ}gQV^pJ-X4su2IPx{=Efn4U^i!%?P5OW<7pz=G;zZb zuJ*)%DmmM=Gyv_*SiQW2uYx9@6m*NjWr=&pm=B=XyuYL(s13_GPhWq-aIIsA+n3{-7bhJ<8&@fKk089 zrIL7|@wL_Wecb~p{Ol$a6MDzR`8oP=>1TA{dxXS?zWX&?(_SCh(%otAV7e#?gx@f9 zrVa>}H7(VJ_^!XB+G2oMx1)3zuU(lIDTqnG0g_tmBsX>!;PPj;LHuEq#gt7b*QXWI z{AZH|vlac_XxRr9@Vt|bfxOQ9It^1tX|blFquw%8F6 z*`gLBEcZDptXC-l_A`Kp%#!t=D}s)*Cr|)a(OJ=zgshQR_ShmFxhl&6G?gPXfAYJi ze)Mtcm!Xr7SO!`X=D1R?hK&0b{ZnK-mN*v)#tO#Au)LOh z4THkyb}Y8PC-xIh%%`@6gXFwu9YfvU4D$_%Q2)w#hKAy3&GPiKbgbxzDiUSXf(*b{ zp`Ij$ZAc{jqa}^Drk0|be)M2ivxgwnc0-DEOo+SSG}}2}DM+j^r?a%IDvgM+lB>6z zshm>#q0Z7UT{yTR%f4imdk~rM<-t#OzV0hM>=i_cOh!jY8d9hXj+Yn$`X}_#v{Cq* z6B9&h!2_+OfjATho;$&%^YmYDK~;cUKPKg6e+KBgsJsNjaWw7we@NzQ%!#VVl9+$* z^7flZ4Cq+SZ6C8TPtzK$J;s)hU>&-O3 z>6~|BfMCg0Xcs!Hmz3@<0v15ImoH?Nev-BaN+($mv&_LyC8NI>1fsHZ8KAEu*2Q^u z`a}{S_6_x$zgQoq>SVYkwp-m~+juCNA(iP-u_;!&=IIr&=If}BS zrlzFgE-!TNmBhSB5Jp7mZICT?wPP$d`J9OD$@xgowC%NLc@RQ$)j5TbJy@=3|Rj6n2Tm8K(> z75-tN$~;r!keUBN!WFFB;njZFb)aX8_m?(f1A^RXRBN;40yYh zdngdNw4%vu^l_l?gqq!SHxo-iMy5F?n`))SQ8#8`$UdLhDmNv{C}4dw#0$3dY4`AS0QndZOR2qp zPpKw!-l_TgU19+LihC>gy(6?`8&GNP+8b$1-}-xRK|zz6>pnz?M6pqf#`ulAO^I4B zqTFC`O-lyy|KaK#+rw(RaO=jlZ99!^+qTizSV3c>v5m&I8{4*x#(4YO?>_d2{Ug>o z<~7fGjuA$)c$fDN;};lhW^8+LM6TKH_LRt=Zrx6=kLef@-zh2XZ3UrN!LVeGg#}xD zNWk9`=<}^%+bKZW>^XMvu=GQ{%RKupf$=17kozAypzdW2Gi)bI^63VHP1i9j`pH=l zK}mLLbCw)wh(}L^03mNu(~3-z_ZGEAyLEomO;@Hu11?=p#@gBcW&20|&@r!K`wyhe z)64Y(pT^?$f?B2CBesMY6yW@AiqmeViz2m=TQZy0K_ z<7ai`Ph|_^PQq$Yl&}FG#VkK~2gQb<7Ak~J+M!$py}o=m6(DL$%{({!{8^6m1xB{b zTxUaj4rI1U#K>6${HGId2HE5J6FWX%+vS8BP(a@BKFVx-R)cW$MK$z{##1l05O_-9Qs9n#F(pn#E2Q?-ERh%cEJMk!cC z)wjH&i24hUb^yOx3H7WG%>+ze4?2|`-5n`x&OOFmwTxYWKUlUF!ZjyiCegBAD$Qb_p)Vx;J2PnPq*{)NS#HW z9Da~2(Tv~I*zI?{F+t)k7eg@=*`k(s%Y!`}`rW@DmhRorKP<^Iau)UlDO_Vj1bx*R zWBZ=GB#A2{-0~cZ|J{ft8frpa>PcFO3aw1>uM;S?^B0RA`vy~BeH)jeM=9x%2mYWf z4h(TMz70e&twR)S^y>D-5E1qhBxgHlWhPhBBF=FSC`_@ej6Is08o}S1abI=YUBGmD zKze(hfg$1e1cA7vusWTPujLF@>)<^69UH1q?laA)k0v!Y#2ze{3c3SpRL^UuH(|Q4 zMGOJ2P#UYLC9MfE5wlcI(IZ6525?g2X*#7JVD}!ci4JMdL`c}onCxd*gxk_rXu}&= z8R11lGV|p^uBmC_Sog|uXSK-Dhc%avG?EWtTk7-!e|+7cq=$HT?r(A6So)wibUl0S zZ0dAA>^0*v-6Mg_OQT9dCUTfk#*4}I7uiMo(9dKJzkCa)j;e-ph^zva1AfXncHjKF ztRIK?JA;@z_-h@rtxva6o?P1LR#J{|vA9htiSU6qRItK9` zY5v&?wP|)uPTm`{2$&73r6RH^j)~EsXE~4|xEksUBOgg4JpYt&21U@C9@v~et|6$V z>kYsm2lmj7R z3|OQ{70O?rIbJM}O%nID6zWLT6beYy^bxYO^zkXZK@}}yv;33@mn4t72)}=p48_?) zHBaK;&%=YMx#eJ!YIZCHYz!zI$Dwbk>ir?v%apqroMKx{0T$% zpYOm958uYz?dfS4Hg!AWw!cc0E4pc zcGFPpSJ}Fhy{c%TLU;ZF!AscCkoaA8m5jY=w#Yx0@(J#*D%k8+>ja>@+E(RkEpj_P;TSG|03O9Pa*+dINBl?%APpym{ zcQdLeDT_vc{^|HTm{_}=%G{nOI3 zd}03yk~pB?v2{y?CmIoFzj=}8?=KOzd{GECd&`YTMcHq^`n&qZXIE($b595m9|njs z__+<5>J+pbnxHy@jTMQ{k`N{pr}V&+A@{A5G8=82^DRencGQCwBD)<=lvG5Jq&c-vdn3!6lH8eAj$;?mh!a9Vv!ao+JM19NIsuIm z*i5tI(Q|nqN!8iLKLLjR$Nsoh8%^lW9c{4B=NUDmJ4rq;KYf8PVaeb?=77M{097H; zj^p^2nN64?3ebdg|FIcKN7)c^W)Rpk_8A7LkY!$88kxd^vX8g(^T;fXP?O&1tnO;1 zo!?lX^#aq(gCroqawa5mU;*zeQewXeGaNm2y5a*p$uscA&43j1pKX2*0BAbJu*uPIeoJb74&`Yb?v~ zX}`NdNAh8N@7ueZhM$@@nMK|Hx1C7hb_Q!Db~bDy6URD#XurWoU5HcKVcz-kcmro5 zHt&4K<+U_CPk=6M+La%Cy-r|J;F;p)MId?|F|K971P&!AH8Mtsy-`J|Q7#l{H@5M< z&>1VJDF?^Gf{g-b1*?8~2Ei`u-1os{kCJIc&~~ErrNe^kXrI7`>BTfFl^;msHRiW? zJyM?EdlYb6#H3Zj)GrfHsWMcXNcWtLi)#(y9lE=o`hY`ech~4zeAa8Hc*ctS69#6X z21z{p3j(P=WSR6=Ue`%8`$dFvFa;h#L9Eo%R+;ilGpmNW0=Zr0aJhqtLpWK|v$0!aYF%_ng9nP?@W|-&(wXLUnTK*gED0U^D&CfW7VQ5KN+fx#h z7BVY1vyV~Z5#l9mjtaK5k_y|H1KGEZV2(&9k9KH3Y3)O0 zp^D}~xr#6EZSY-LGwunz=q$W0Z}UEbO%^;38BL?#k1#dTopGye z{1mzvT3XW8PBu!RQU$@* zrOnt~tXU-2yPcoHY+(0BHi%R&UYE5;t(m-sy3LLSPpcVz;1jH**$3tS7UJzwWicUP z{`WI))r4~frX5O5Mz>KQb^T-gCtG$hl5lF*tq`R@b;IF8u}B)uqE~i z4*G3E^w_^$84-9PswjK+-YhkABxnJ3>xd}?c)zVzu+SiJdxwX1a#;XV9yB#{L6nHA zx>|fv8B0|iM@~s%#qf&O{QTNhA5qmuRoN&DcPT%=&rw|V_Z}b1?(OLhgOoa;#Z)VW z024J2MyJCwGWDxqhPxSWKbcc&Xi>o{369i4^X=#}j)1;87D~eSOzHtA_Bz&xE9I|t z$*s)dVKLRoP1# zigL|01+y~EKNf=}mcxJe&d+`U8NbKJqUAN;O8*R&lrqELzuqOEETnzY|Lx(eC*f-$ zvUEmn&pP1A92m{n5TrdJXBvb}^e0Aph~79Ty?DarPn`C^gxPz#xZF3gIVMw2?>DYW zi=eAoJ!(4(*9S>e8fYvVox+wT| zrw@mH5*9V}i-v^vNO~~gs)t=XjYV&MrvSG+2otDV3*q1iAtGZo86rixi|{HCy3g@` z15wG1fY>Z&7#}hGGj+jW_+?K_yM*XCbu;6-;Lz(2a1*n+{mNa3G`e2U%UZY}XAqT4 zHeQWA+p|8udEUSxF1}vCfM$t-Zc7;j+E^-WAuPSL|FFYVIszUsuHrQvhv4Z1)<;!sI#az{&b_ z22Vuz;9;Ly*6T}p`>TZ)L)<4X{%>C+7W~v-J-35SJ9sQ~0`wWLq7vVD^e)_d zGnCTl?7}x%vJcH50XvW4ja`n-x~sF3#tvUTCd$Pi^`~vVnPFJ!@#btLXWt(nX9D9( zl=WFS`=w6;AX{bB75CkY0^nULR;_|`gv)n+U4r#&e<MAzyN??)#!O`Nga_hI-9%r?ER^-+9tu~jrfCXjh-AYJw!i=cM<{v+ON$S~4 z>)P5L2Up|C=rAQiAkC#E%+wD)G@%@!vi^F>n1WNs-;wnZ<*} z#ZT{RVD~j^$uWkbkXdt%5T2=J_7a74ovD@L2N0N*-9`hFNK!$WPw652ctkBDxs%%6 ziraOi*Sh*TYbh|PqV$2A1|CF+GmFOP;o5)b^JJuL22OvU%#>hN2Lk~uw}C9DH>!1+ zzR#a(jMS9&VXuir(7YU5?+Dhiv6JjH#^)pmTuiNI8Fq3j%KVO`c|-n5&Pp({a?3?o z*(CN^a$|$?8@-c{m~Nrw&OfrzEq7LKm>fZd^}xxO5M4brRYbjNq4ru$1q-9^ka_Bx z@420f%N8N`p4Q%@*DvE-`fZ48k!ug7s7G@;*W$$T+DKFyd^Y=Md0>{y7a0xP(>ws|3vm2$9(r4>m$j+IYr-2|u996_A7R!~y7Do}Wa-pa|H3;h zU-snpzck2*v+>}v{v^p+o_8fa$nudCkgnWJG&v($FP{4gdN`m`)^)I6~lx?M)+?C z_}`<7m6?St)fn^Nqe@OzTv|@MB@Gi22PE}B((@=5WCy^;{r`*$RbDV!s>@4{Ff`nf z#X60p5W0$vIT%e-F6Dc_hqTef%#`~1#^aeo$mw8=;lG3QqnkN?OUJi8*RpSFMy#r8 z)~Q<3UE8`6<$T(5AQD>l`D)(&^80e|RmwTex^P?a-uCFSB|!O`h(UoGVYdYQHfVO9 ze2h@A)jxvm;k|JPf99-uHs0&f`l>9an{EG`Ot=hw5pJgTN6vVMrNE3xsad;1$3`cp zpC0C%FwUCy46}AQo^sbZyT+)Wo+s-yu98fvN$ruuei1*aWtnlw)zo@G4=ZL(4~}w_ zEDMg(EYphE`X(yb%TAl%u*dRz0)|Y_Qob>r-+DP~lts0KM_Kb7Ri#_`M=Gji3CVO#fjSbCg(WJ5Wgg|gVKNzehI4*a zx%C3J4OvqVuB?55hRXMUKphJkjK7%dIcp+SB^D}ZWmOBfHh4`b-kBNl@&(PR=l{St zh<|a}10stsm1JK1gR@!tvLYIpHll7s`KU2MwTodYAA_-c5sVpwQADyhc{0009x;q6xJhIu*A(E*MlLg&=N zEd^!fB>bA?bc1!U_Mo|}(xBh#H}h>W+vyq9fHDMub8fnsq9FBmUbfLluN;dG#8xUT z8Z_#;3Uj~vFz${5*rKBaifVpJl!d8G`q=yt>99i5%EPXAh0M-JsB<5o=8mB%p|DcV zYkb;_JD#j6#j2HI~Ut8Sov(rISL|(Cd|48JO5^4Bw$+ z>B06JJyJs_=qe&BeJ(dcMhYaJhdh&lud=xbR8uOVETW77`Xbz)DUx#&p&(~gH5URS z8fJJG5^#}}0^u$w6y;ll>ejG-mUzs&N9H9z7nR*GfJ{{qgCibPxTddF$d#GW7Qpt4 z6qp8WWOOPT{P6#hA>lmod1?iIkI{MX$^~wY?}Oq@ zs=^Rf)uzk>nhl8_Qcf^kvLJM$NiC<5O_wu>Z5gT}^%}H!>X90=z}LgU5R$XU?_%*G5KoVkx80Ry8%WIV(?%wk8A zipNNI;**W=ujHK0gL8^92rWbzQjw$aI47h7n8jaUBgqQixpUr~@u`ugNcpw%4m9oA zns2-SWu)qGj-U$WLK>dd0Xnz~x!4UeajS?1Hjr9Mje?5i=38ekB9eHfy7d^mR7==J z!5$_85Q7%>p2MWm)|4Z7NrKTvj*NtuTFOGgrbMOI=p^FZeFI%Ig%!`gr zrFaIQ6#CpKMz(SsKtjg=ciLfh(TIC~MK=w+kaCyyh>*&M;W;LVp-3>P9J9&1sI)7m zx+Kvx>_8+!ONAa-;V=1(#uA@2l$Js_F=i^0!CcF_UPe4yEt@%USZF#;=7D74r z1r14@HYCO|^&=deN93CFBGwFOYA4GqpR%rTJ!Blb6~Zku>D2kwqpLoHtPgmq#clz` zC@!Aw?c(QHafy$hP!-RC7AS%lM57jm@twsiFEEY)1BO!Qp0RGf$h#WKP_)5<4H9== ze^4d_gw%3S!bNgDNU4PD{RX3e(ZcURSWlFDM3bUz?-5oWQe=iRvTLO}Dx49(>=L-6 z;)6!Q*$*%rY8H$U4W5Z7@)ru`!jAx2>el-P@ZGsurODK4P^L2Cma@2Vw!c~KmKlzA zvm#w`+sYUW7(d$s& z5f^omOVcZsOO(Ae(Tn8FOG&o-1p@zg7^4ICl!e+6jy-vrKgc~IOA9L|{2W2BbqA_p z|GH0nlly)VxM-rT5R7hL3=jdZ!cVAC*fi}HwbBw8y9EJPw9>q3Nlm@3obMFfF4q3W zPfY2~s5mQFLKbz&4uy32T}eM%wFxSnLI{wz-^8+aaLF$X>z+#B$_&2^IjxWriGPLqnp@ z1rixQsf;s=3j@+aG;>6tlo@o~&aN7AQ+KovRrEVG(&6Mlu;u2q*7g}N*+wVgDp1W@ z9&)e`cUJ9cJg183g3ccSDQ4bp+Wf*bg?;;9p>Gabgx$lk-U)y9!BM(Xa_V*0F5klD z+QVzi&bI_r=fEebT;>62fPCuvQJa_gLYU0HEVOte#AFxqE&8n9wsT_{)Nw_ni9dRz zg)D;6tJA&*_yI?fi zK&rki))#-)^+MvP%^5^v7oR?xMMB9%H$s$1?dqN^HzMx6 zZjKqXF`4>Mt-;}S=rDUhm3tU2hecD|8sNLJ*7; zkA^@JT1pHfV3=H8JzKD2Bw?38B$0D;YHX`7Yu$@q?gQlEj(=c}8+!*{aC}~Pp_jV0 zt)V%BkFjG(qbEG9SK#N<=rmoIgj;Z`G&-%hRpLBj5td_lL(GER} zTY4qvNJoA07dThl5H`Lq5vY{~h!=NR`;iK}fatchB@lUTIfP|5hrU+aIw$5lxEt&L8p;!jH2*w zwJO913h(xs-cnX?-RM%z3$rb+qaXwEV1EI(d#eSOYv&)PA05mvqs)a?26xn-O+WX1?uWxAm{YL$4)^rAgO9jFiUW`#2lyQb@?j^); z13vxx=!OpD6gCZcOF5{QWvKUx?U=Qj*I&6fl+dk0X8<^%2)}Ru(Pf&AT{7ukuvhEY z?cZBtlPb^hJ0&EdhKG={GiJ;V^u74y_yCAkb7};e;IIlxme4KL;0cXjjik#joA_ZD z8#fb^NEHoQ*=@;qWdw;J!^W8a~)%*jr2r5)q^{qzUDnp$Tj-r^4VK9)@GJ z)eKi|W~X>`hM}4{DB{_)>P1W}C+k!0Hb~L=9F1S;QfGNb=bAdCbOYl>Z-}pE^uQz> zM`t#iW%^ouNm%$;8d|}Aqq7u=PBs+I(A@T_X};oDgs1@sudg{C4uUu7sroS?v>Vp@ zSHp;gpd?k!`n6A&BmP45eA?$h%6 zl7wMyUUV%!=749xySRACQ19nRu4&+90y5{}a z_E5WeBET4$2Nr8R3Rj;Q8ZU4EhQ`ub8!H7na4>Vns}q;~y9E;O+(L%SP$g{#z!0iX z3o(K=Vw-nnt>p8>zOQ>MfMcLJ6KT#r7f%l;=$H4n#_-~`rW?@S-)e&xVkMx+u+cM? zNjk3el0jVJ&;NZz2S~g?jwp@IeH58v$DjKk}So8OZEhlnorbb-9 z4M`sl23fqa1Y|1N9+ie3OlCx|=*y~0OZCVxuBN|wA7ck7~^Q6zo27wlk1vhsS0iKVKL*v`dzP`DN6vP8D zqzmLqVF9~DjpV3dNhDNAlMLk&XnEKbB)a;^74pPW0cQ3@gRwi0W8?_lW)PDHqMz2p z+^e#20q;D;cF$orG7}^K^d}l_u2~a)WRn&ixqStT zq;EI>I@J-*~kD~wy@MCqrN0i4CQ?HYB!+PzLb0xUZL)7%25Zl?0j zwpXVvZMA#o$sVU{u9%3C!9?S>smrn_;pO+s-U)-FIvoohC1q_rmD!6QGg5SPYYi2F z+)hijp{{~BM=8{r&)hGe4iJhKSMzyv9!S~cWBc%givp9qX-r4k3Efz&5gNVjL_}6h zz)nhY16s;+$F*w>@8|An-0XpCwPsbny#9bRjMgXIlIxk30bVDzpND9XdssjeqP#VB zpDAjeDd^S;fqj_Aoj0lXXJjcgw;xEtj7f^`*$%X2}IGZwbKmXF)Kq>-Cslud?;?`&u!nu zeNsQ#vfqgGUNi6CK5|Zu*v+~nAv3;+Hw$UoZ##!RJa?>Xf$s0M1W#biPFtsV=(LM9 zrV$c0F0f}hys(HU<^rfXyUKOCErFhG*)+OA`~x44Bh3MLp1;C4{-jGq03ir{vWWZs zCx^o|_b4zrYY514SHC~GzO?0Edj@t|_nodE&@_VKS@s2`~>nB!9 z2j*w<^>b|*C69MWz3-r&k#X=#knPgJe0&9u{g7I-*xsUWr)Tg+fJ}u89{sMkFiN1a z;_!3{DU0{Z@bxU+$zl3*?TDLXbeuyjZozpGLUQXBLPVOk_`e_@?PZlG?WYu_0 za!zvWBF|?Ews+^|KC1xIH$HLUMirO{XT)`$qx{i!y>mUUt-$a>YzUSiFHh9w4@v=D z`FabYs_=*?4%&uafC`&0J7G7iFb&mxsh^<teSBZ3)Cxf#`vx#oMLZKdmCF8p4RB zQ%zSfQA8FZvf*)FHWCUJEY1f#CQJ~VUe6K`5D*wpi^oSL=7)|v*&3A)5>PY|bRWxY z?Fnt_#h?_0a*9(UpJ%FO1NqrC9}Yjx?Z0bnzn`aBps+!Je4p0IEKvBwKH~$ixdh5vtXNM6#3$=+^6dGllP7HDhcOl`f>`1WC-LOd;3ad^;R$=9 zC$&Z2A_vHbNn;1XZjE_j-#I(6VT;1wDM_{pll8Km*6DC;;p+YL$m{}V{O4@0Z^u`$ z5njM-VlueEA(6y15_1Wca~XJ(QEiSMOG-wBrk+!Y0P0FM49)D#1y+E*dG(^#_#9Y= z{!q4*$jwi8)%AWSq+$H1Jol_TF6X?(xJg0qgR0om8AKw^KD3_6fkVn#R7U+q11<*HIpSU|GUS8IK;i>OI+1&aO^n`V9 ztAfMP>oF2iIi{ty@!D#Ou@!5hvzWr{&i^ z(>E)%h)1jgfI%Sjpzjw%K@Oum63q^JI*2%M2M-zdk@A-bvGS+H(cN&EV5gVyeZBd) zhgYam6i2OmUkHpQ-?j;)DId#Iv&J z%=eY&Syi<^$LHLw!92j(zdbP3!BbV*c5q5vAgY`1TCRG*FRuQ~nY`omlMtQ>g5x)a^8@J;FtzH*f)y zA5%P>&IkPnQBSE7>YAByi+}T9-dZC|?kNa*HyE_q<^_k?2W4qp?$x1yGEpfy`5-a* zL`ZZwUrKc6E?dms-#^Yo=A4zI3HQY?;c5M3AT5-?x~w3Gsf1K*XCT?|5#(j(Vd7Hq z1d@E&vHZj25@y=vDY)Ti)SIoQwQ zkx+aIVtvF2xLt={%G}-_kWS=;;05ADoW_t9eR+`feD!#-1jH5OYX2(}I$qD1n`Tp% zgvzRgP$FMZoRE!=$iYPv4H#t*VjHYAwW4cc76jnKY?&4@d^o`Gy!Nnl43^|_Z~i%w z2%H>8|7&O*>bL*j4JO=wA>jYwLQdw?6n029NHrC02{oOT8Folmkkm;~2$a-w4oE!U z926rmyg2|-N*y!;o0yzZCOYLy}7F|js!{&C4pN_KVp7aI|>*ko(7Gr9DK#aW|bkzWans!?RgD(O5i z1=OjB{+}R33qL@at(v%=4FL82AJY7_J=vf4;Bs z`PbCO@*%cE3Z_}nUtZCom>2HXc?klR!zIJMor&irzacpM=Q_cOMVh7R2UuJ8<2JQX!Z-G{@|#v3^nNGU#2OhyAfy8tg;-h zS`MfBCKiZA%DD0&8+`*mf!F^&p4iOKe!=NhHz_S4)=$V1x|e2gBGj`{uSe90)8lO} z6r?iF_?1;Y_t8=(Z98_VAw>Q<$k{h-`I4THke~BoUkp9PDJKL7W%2cnp3d&oOt%fd ziwMLHV1tAJV=)Hf_{O1cPB7^&0h%u{>FCbH_w)XSZsYxNB4HM9k>eyF3MWi+(T))@ z=od1gK}TWoc#umX)l5+K_qBBbtFG%C790=L32&uZ<6RdLn0U1nXsrAi9DXJgO3_#< zJSGg+R0JOXCMZZCUpMaJRz$I^Inv-7cL*>(tImd$+a06woeJe-}toz zgAn6@ja~X$@@edDI=vE#TDALe{*w;61MS%Mz^|YFQ5XF_srqbWw%s($g?@eYb?S3J z6@>r%#dXNi5TXhJE5Wy5WSWUKXaPsB%!srJPAgnoLrxIjwJ&D)+S8jj-beHNiNlS@ zoqE&17o?VR*tIV9SbvS157T6GmZToJndp^<6;itE759fwKdN1tGILco1`Ny*4}sx~ zta{LVw4~S5wz{sad}=9Cxs=va(RDKzRwx@RBj98qgy>96Tbx!Daw5u?fDtRt@}pn?HWhoix*Fnntb3{>c1KoHMz?!V2>6*YBOMfy!rspEchhQ}Y55}(W(EsoMx7tqK34>_4B&FGukmAZg+^n5Eh?-(x$kD2 z1bleV>?4KW7VHJ3Z!5Gc~9>NtAjIv+DA;DbV5ZwqC-Q0A|tVVb^hJ(23!{iA3an%O`E__jMfQGVjW@UlbY8yc@=xIVeo2w-pO$v!@hyoTNFeuZXg)Qb7K09dC zpR6SxO%jT18(uf46hxjC;WWq`B*{GJ7)1JrLeCO(BCCbWHXG+Sh|-Vdj=U@{BIke6 z0Mt)=#ljtzoYJdypSI}XT_HHLXb+zc@b-2H#T1#8r}`~F@^4OeZWn%Lz6#>h`t=S6 z76isYP7*v=-F)_8h0)_Cav!Yc%ZBFQaQx7kuQd$wLF{2QnGZj2MDnvQ8Xie4M2vm4 zYVQ5LbisL#b3}MlI`M^l$-`s*5X^#T3j8#+jBO(LClq?;nrbE3A4?mO!y7mC(2lNi zY;NW2{_c)1wM@RVpjmzV)_<}oKpt}`AXGvCxz37) z<_OF%msV+z!vl^VK`{fw%+!5}MTDFw0kr zcD7gF1%e^z9o+g1F1S$BF-YHEi^@g#HEUqVUyO>Q{chB}L=`lt^e?^#3L; zyutBnY$lQT8{tnpK*P46%Ho|7V-5`e%2FUUsIlskx20DA!qN* z=K#^4xn`H#2a&h>#iff)0Pz!*QW)RMksuGVs^{;8-3O7Qm{TBpQJqZrKgn;Ax8^Vg zNQF-M?`}aHu0nR**|ZlcV5X-l+$$3ZmIV}|Yz-1g>SNCLJ7e?&@lg*m| zf0CgZGKLG*#GQ|3DN}7QB_UqKmkkudF$7ZRJ>QTL8+sKGK2IIV!0Q{fDuaNyxQ4WX z9o<56brn&kg36hTE-ch9)JOerBuBH|KQqPS6s2lt)sb$d%DeartZM}DH0zGsBlXeQ z{HuTUm_XlHvgbG(cuTnpx%bK+SfpSkVW>f!32CV7Y^k3ZK^`1>%+pbOwNSmRj*1xQ zi^qjL7GX(vX9*S~aT+2JEK;_#=jBDYsDqsv+*h`T2t!&5;lPZ_G7%ZvwX(M)`YEY< zz+{!QHwy^kLn4R*5NxhLgFO|KbwBuC@JbpC^9I-s23R_&*frj=`I;H7`ZU7Uipt=Y zOzkd1fH{a4V!Q(t22kWbdB;U9bw`AULZiKL zuY=vuXdU=e&BR$wlB;~Cm6jswgT?P z;>#|q=^Fhux3`MP&bH>1l;8dlwl*u0Es=Urz@%F{i@^F@O<-pE$?TTK#>T{J;E3r2nCU;x1(|i2-?&CiOUKJa+v}gMsqY>5*kD}xH;lS00qWR5CJ0Bfl~gAk1;xIu{q9V_cydJrR!J9kG5N0813Q*I^ln6u!0j9{7*j|u z0wlA+_0K-+=nl4))3SklA!uqkutvJ}5E6+AN$jfp+ms}Tx5(_sY?2r@3y3RPrNH|d zG5_Sn5jxKaoUFO{e!ttQA5J)b)OL=vsqOA0H<#?aU#x+NSX`Kq#c z0FfYq%Zh$2oTFdB3ZE@_rgCLV&C!K%?%tj~t)9xZN{ON0qs4lg0;yY@9ezQ>hEe7vd41^;OHOvmabfQ_>= z#32ckLcLS0ZOWL&o|i`CG3oR8y(|?Yz#Z9dSy>-GZgNW?;lJYIhgbQ4yVSak=kZt3 zgN2bay-DTgOC(yXe~!HFltRVQ+sJT_oEM zSl>C>npjkGn7L~=!hnnnEBQ4=1CB#nN@Wh@oT*y;A~EM7-pPmB>~k`Shu-s6InwkS zdpDE9kyV@c9vj|F?bR2>#)qjBY!@$2P1KZcN-NM9xMaR~gB`4=gxiG-J!Yafm<6^S zq~M6LF=;z3sGIo&%?JLMd{#1ybVij8!z;7$HI}Gwe0{=BVt=sE0MSj)P7b z(Z23+$y!Lhm_km3m-S9%d3>kOot7|2)J9hH*^G>6Kld*AhtT!P{o-Ad?hgSUFG;^I z;dL3^BQ)ba5H3Y3V|4TV3WPV@M7+NMzwlNEeT}Kg3vB|dQn5M&f@TWn?U*@Kx0%QE zPQ)|+=rf|597_@1Z+1I=@!Yf-83eQiN{@~_@aqOp$~i8;_=~s3u&drX=Cwh}>PF4J zg}Hac!6GyfO~~eF$@OT9B5msoTtu=>;Z{O`)xpOI za;;HZ%sOzZIjFZ z2I51f%y95ONi8ktD6vLm(48YFu}7-?htq0sj^_zj7pc93@&PN`u@YwBs_i2=r#qM(%+862?!6k`qnN|ghQh5gGz zmkS^9t?*t_u4{=nU=_@(aX+v*HnzFB!EzmuiwmD?XJjk^;{!A!fT9{WN0dvq@M^3o z-aT1u%#k@M`AFNi4kGJ7G$qpRr^StZ_f?Y+;Y@o-FM}s>L!J++$k#ow^$c=BKy+bK z(Y8q|JhED{`g2~U8IPV6-`|>g1(LvJxDaWrR+Q4^c>ScybqrcW0wRpf}tbU zEe4km0SLxAafxxW>|0(yqRTDlhF`mhQ@>^UwHSl%e~LTd&z37c~X^+MP|2vBqv zcQ+MK3h9@3uennrOECxdn%NaBsN%yb!I5% z@>Q$dzWr{tvsv9KwG4Npmzy1+3*B4#(E!6~TFLkoUX~jHwQALG@C!KY;fDtuC!AL1 zvI?;xqOr%>kmc#(ohS~B#($;Oqhbe+_kc-g4BCWjenV!k|Han&;$k)^C$?G#Fg;=} zsXr)9FloT)7@tBd`OP;Xzxm&hJt-f?EMHhoOsvk&JVXbyPASPtSC(CD`TWi zu0q^otpObsy-M)$dlR?>FRj*Gq-zA_fq?=+U|_kRrl!2ShC#Myq<^7UKrZS)gN%aT zVF369_>j~=#Zb_0!^Ybjjr}KyA&K@+U>sWQQiHMGCaYE~bg1>niD8fKuS>WenUiu$ zlnSnel{x}%YS)47Yg}Bji}=jmn&hLhQdyBq>D7aIMC(9bmYrXh$(-<2$DYNYr|$mv zqCwK?cZ792>747C6@Qv;Ssb0VFW0jf9H&m7Jb4rH3TFqWF=_tAvZB9WUoX2c2HkLc zt+52GFyIQC+NgozrrRTx*>iD`FTx9eu{B#`f1ERqjf#V#VcdHSAyDl z2A2IjBT*VT>qgMSrq=YjHf*C3x17|2|HwFf-;09{Uc)(fBY)m!!+k&-?p`}ac26aN z2)GA%26+eItct>FMl2U8WO9%tJK~ca11Mpz$am#0pcPI&4Ex<=HI}?jAka$=oH;|a z9}YZ+oePJ4hCfGrMm`Pg7CIWyht+=&X^(85@o8DYs4}$~)p(*?h?TJ6xy@)Cq4T{8 ze!z#+@b$L=wSPvJ8vP9Os>n%5JqfD0RYvps85Ls^3*~2dSmvpKc`2v_dCgR>ZsDm- zUSg?#3}(`>KQ!ew89``{VU0!-%|sKq@MpbOHW_w5)h%=~vSE&qWV%m2yoZx=D%Urp zr}u>e49olJnN}04lO19lbVuwgV;jv3#i|y)ASYSx+JCvz`rHQwzNqE>!>BhT8v10iaX1{lPl!~l$=ZrEVjuI7Tcyq zAH|3-1Am!^4N@1b)?uTkaYTzqV^j;#NTcUxMgbYwlaO=OuXNZIVyCTy&GaMNN62FD z6tFs=ETW>QKI0TqlUjniX6o??pRFufE=6X}U>ddRmd(4o2jEBtQ{mkKF!A@eLnICb znc?i3TQtt1P}eZe$bDEGQFbnkt*3uI1c%7AY=0zCY3j9}6mv8?aGVZlrv`v1c7h%x z<=_yz4z)z@63$6-F_)3jvV_LOs#%&*W{1jqO40mO?Iip zF>3!$y9BV0A@u}N+@O&Ec&FXNmFzvkH=U5wemI)_@N2pZK+}0~PGGkSBTWlG;ednW z6CV(iTpI==0Oh0KzYH|7sDsyg=lH^KA%6+2c;6pA(W=akvSCmpPZH2W%y<4zLyT`e zdOGG6pS$_!24t9?DV5AWcF<_J>E}A+PZ&$#XaX?Ca%y^9VH~@b%D>r~(xjrg2Ae)twx4Uyw!+%mk zTYz~shG0%bYUWueNIRP5as~;~;&TM$Sce`4sbz{1N@x2CH7vtFOhD(qI^ilD8%86h zqq9P@v0zxbWj<~```udl;LJ~LaP>6+MaT+`LxYhST94MjfoL=w|Kj_Lb#?yuh$$dC ziVYEXM!EuO!i@id7VwK-e*UGcF@MOTfVD%n>AkL(?tgc@0|&%z^|JjAEpRT}5p|RxZ!X zkt-B==5jeufHbNqOc@j&7~{U|i4{(cp})L!fB(j;JP#Cs41cOrTofirN=Zr5qGgHt;}|Usax_~%_N5E;ce7C}+D!UL z;=S2FH}QP3B!?KdnKZnc{&9@H?7-UVa3P-kz4j&$gYykt2+f~AeS!C{1Vy66gp^ny zp#;T(+G=HK-3i}Ild%#Wg9GY>Vj*YsZ_wnIr*I(T&U=AOcQ}T7x_>ZvXc`T&lT$$n z_02bDAAWmo^V+3bwym8Ygd^nI<9@4x%kRS#*pqhmIq*DG(U2i?4}+G&9w3HA3}ne% zaM;5gc*HP>MJz8C|LWcX@~|{VEEx;jTkzmKo#m>J0_{I1W^$nU$60hzuB0RcP!Zu` zL3~=gJcWhd{<%IUG=EQ049rVP3(K>Tvt+5dOA%HD`@!KRDmaw`8x(YsFv8t2Qj!vp z2!xclFru{K!+B_W(WA}TE!f}3qnh86nJJembb9IiQ6h4%-9kSajKR zne~P1m%r(J_J89A+pU|dw=dIf237a5x94y)i*eKpA-h5LhDbZ;I~B~p4*Kc4pE!`O zxkEPv7bY@k1P-1hlTs^ZLotR90Lc#;eT)!j77x#DTq6HG4=%a`CMq) zem?)$X(kTNrDX~71ceABnA>l2T)BLg`tJ9)zP@|o(2kwOj3QBZgBxb?;M7MYA>}`Vx+(f6^^HL!0;0KgDtSKZX%o4cGNrui^aNeDsa! z=Uie)O3l8H1L&+GAP1RLd3a$&h$K8Ni9wJ4w112j0U7qZpj2E^kzJCTuAQeL-$Q#m zQLRm^r8LNp9@~>D1F;sg+`%lNW)9gusOfB2v$KhP_r!2OKWs73CAjhJ2e z+J8IWt&`y>WQw>`&}g(7ZGDeMK~u>66^@3R8RUb~=&x+>5hlUOH-EZ&_vUmggC^Uc zzF%oQy5u?>eI2G;hhwhe;@Q#pJO1Wq)_ojAr)4WLdVCZV9~PU;pz1%@N)uBOfy6wt zI8s%asl+~lPu|n_JUbnCdD&W8Hrt*(*MHP`k6Eyhjt?(Ce!R3iE2~tne}A|jo<$Ct zF8aRbB|Or`YIU<69(m=CcBCYtqOBc|%q|HzuunTu$35`4_G1E9YPC3Yr9mk;y}j;2 z12_drDY$@#3&CMHNmQM=L-xuAO-Mb1IF8QV&KuO$42jS&#)(RHZOq zER6-RA_hG`ZZYw(2_VcIgcV4#lHhaXYnGXkg}Ym-L|Is_jLweBWM_BI?3{I}M?I73 z_qe)@!{*%Rxz&h_mqaHre(PNMu74?FnNSM+sj%Fbiq<14WjWLR*_5J&^1 z{6tpj8xyJ=;>J2J`*vrIE)8TbLs zqzjHmE|qXcW;27DcFDNBQyl{UA}ygYeQV2vZ}aF6`z@u&J-U%UUe2w-*)X? zxX!`W)kk;O^D1cf-sES@18+46beGrB{hp!#VWQ&T=@do|a^-TFLVpGl@fSaSv(>@4 zq_{*7K}8gciz@!O2}dxW!SsF_RDk2qTtVej%j+BXatVfDDmVrzb@;B5p0KXlSGGx^ z6%QB)el@Zz3}Pwne)&2Ohl4#A{I~l8ryjru19vn^O2z0Ko|4KNimEg0#X4{rC(K_l zZ4WExysX?z+!rgOvVY^#(R1i)mXI1Rm*K6##DcJVNlpU$+V-vO8#{CY*_kD$#3$li zg3F={)6*4-492*|*S>}c*q}UkhW>DToul%>`!_bMIW{b)0$+S6xS3G#RT-0m*8Tk!O$X}_Y7K?CqOFs27y?=njcaKr6_6Hn zn1S+1wnmC;qaopKKXe%$*1-4Vq4;bsCV&hEiL&TW3V+S-CTZvk-*C|zp59kmFY3kJ z@3?}18&PjJz1?&7tIi-m1ttmOML7xCi7Yf*a1=3MB3Ko=S-8)2)gBjTzxc$YI4r&; z8KKqX-(P%ofjR%Q_&K;k4T{axz+ALFi$viWJaxaW{!Bm9h`<4T)dL1}4H!re{|$qr z1RDxvZkI$B1`wA&83hRhH!(3Wml0bAG6qOkNk>dimq}X&!?i&QBT zQIJK(ZCqg#be20h&X;<6ulGyqcE_1{X70UDp8S#XOOO^CMR$ zu35Ey<3n-r@oN@68om+}x|<(=x@S`8UO_Hr{I+vcIl29wyN=(6PR~Rox1#4~@FMv9 zmFssWrDeqx6iSM-GqXf7v2pWa7Crs+Q!&ryr59(XCg;b*CyTPu^O8mQ$Nrct1*zHT zBFV!s&+p$KvpIZ6NzCT-lJw%T^t6cw#}(uimWtAgW8w?a(u?ymlk@U_k_)r47p0_& zl6gG&yyqqPsfqE+r3Gml;tJD?G7?r4XO?7%vP*OKC$AIdrR;e2ndcTSnf~CkNj-eF zm(TEcvw6FC8+kAAp5{Hwo5S19OW>{GJ;J-6w~4osx0$z!w}|%uZwqfVZ!2#NZyRqd zZ#!>2FP^uYw}7{kw}BUb$NM#JI`3BA4BovwiqG(Y&+_KuhVgFZHS+gPik_qqSZ~Uo zeEZ}#BOZ*naI>12LY$oP$dofvb8jJTxiPJD`W@39k!vH5-@0MOq!}O0Tsia0+rGWM z`;H#ruV&pmYvZiKS?#m9JJ;R$T2y-UUZsF?xeE*j4;kSg*#u|lCcJBxuzgX44CHn`i4){Y0{rvY{ca8``($Gwy$pZ$k5_MJfN=1dHQc3Ey zs{J~Nx=3B9DcsAgj?z^otylv@qWp00OWxPIu2QuJO-}F;gSovs7i4gAl?n$K9IT<% zOt#$UZ|?%a=7rp1MUh%erQRpm3@;Looy|Ml*X3<(C98LT$abY}FUn5O-vd>!*C_3) z1vhwH4!Z;Qg9sLy6r!ApT{{nFy!O>spP|XEWaM{~5})mrk5`R87^!((aP_p1uGEM? zOGrG*8dsgoXC+yK>xiYv+HPyNwp;ubzd2y?+S*uCO>pS5FMt@dXXM21;_j$OqLd;= z26E!X?yMt!H+sW2onC-uiI+OOh|?63itMTc&=C{6XZ;q^d&zgS2MC|DI;V`5SMQ*3*Lz=CCikPRtNngH zTtWHQ1)-SG3}FS{dsS6MrCthZqNGk<-`3LDf9%D7-WRyLxoB<zc1*Y+1H66xv*2s5B?w|5#LNcKV>-7|qehl15pN_M{iTA{Y4*5&>);zhN0 z_8n|!{0~kQWs#>=Ec9DTRK|X8V@v%7~QNLFg#drROjV?(6FD(fOKOfF1{Md)n?ktPR^om#Wj- z8K|DvCgJ4_!q*UM?=~0@K{OIZTy03$_xKYFxJZiI!d(?s;RDsM3YKQU2F7qv7f?qO z+7$6+{qsq&kIm<%hLL}9+N1LGHa~LtZRhzY`a|I>r`no&g228u)YJ3Db^lR+FcFx0 zdNr+AYRSCaWfdh*0aGI-wad zlb(tbSM1!&Flp(lR%dO-R0?y^W-vG{WT3mfr2`*M$N*nSG=)^y9S3ucfj!ZOz^T zc-=`vWy1KnC}V&RmjogA=u%-A)0GR9dMT;GjDuIExV{}zCDP1c`NCBddZuT`A ztR^qD&Lh-HKwl}{w>71r0EnGcul619K(_{7qJpOfd;5WS!}GL8qt`H6e0YL6;=&2` zjMAas2p#=(!S{`X*~Qj>hpWxWq9KRMhAd;wkMd!oh8brWlme}fF5kk5W57-dJ-35|NIl4clxxtv_FMCsY{8%}^L zDd9@FBCe8q8Y>+iE&TND{+EWR>mPVO10&&3fF7%@N>3{DMK7$}v~tUO=?)+k-FE^# zI^2Ms{1ci&ow;=5_%$H@e0m8-q|#UtDFxOuHyG;7*sAy_hR1CWq6OpV32nbD7~~>_ zs%*V_9}qH3a24KvYD-&~;GNJF9s|ZTLjhGg!D@F6pr@=&lsmsQ>t!Gifo7ry(1SNN zpIf?fcV=1+rFbQ&A!FQqloCmH^+uq7={{bMDqTd&byDhexzO6u(pp#39c;6Df#`3{ zN=V4zZkD7|*(-MEWB{?I`a_EW3`W;DUmJMXsS5q*Sq%Gs%gEa)KpRnounn#ljyGIv zH=hO%aX9_pN>0E%G@px`dwTI7{((b1r~IhH#RhB6P!_+i4=wnrrWuGME&17VxL-j^ z_*pM!C;il=FcA_%aY7SqQOi?P^QC0zD`~a4KyXvJTe(?*J9Na$?|M81K)h zHCwp?T1QnDY+1J@Oi=y}M*<#_>aT_hgJ|xxI$Yf6=*`asAwlSV;U^J3$M^Q}>j>v5 zM(;djYVcgLxa{@bng%doNvfCZ(YLkt{0Cmz6G+KkFNw_~HD$D-gu9Jc z`GdjKQ|BUM(nohdv<`|vT=$aE-UBs6K;jY?<(H=KJzR3|)&A25>d20>0W_Vp z5|N{`u<{>hMrScKd06>Rq6P7uv7C$)7r7$2H zz|Y`+FZlHh*pq+eI~IePwNU7;(4cU_6NoP(J{&4snO6QpS|+t~??x2{H+NqI=HRD` zI9`s5PqXPS#RyAbse0V~Z9yJ9^9zQU1LL_O^mV2YRgp&jn-6KeyxX zF@HA?+Au&)#wN)d(3xv)JdB>d{&z=FgQ*MMW2&=t)?Ku;nB1*L8vQnFTk|1* zjE@=_3wheo5-1`noMKGQKu>pWd*a%Cy9&glYB00o#ead_KhBoFMTHowu8%+Qhi3cv zr!EUZxuNMo79SU$=e;tAR8gqT)RB_jtmahQ?+EN5G2H#JXA&--K61qApjf8tFDgatsyKZLswDkTSxr--wvaB!-CM=p{c?G zro0qN37j|l{zh-#VA8>*TvW!~ea~H~Y}1e@6er}cl_(ND#Z9YP0z)G5fVQcB9a@P% zg{!P6uWaw;;nYvilYMCVV2`*-<{}GQ^UeG0nYL6b3=(aPXRbCKSEtp4W5cr8-XGl- z1;fb!^?z@;qU9=m5jI>o1CpN`E;o1VE!{XQqeVWgy|&inF_ZOgPvnZ|iC|%{*g9E@ z(H=b6)#9%W)?+>#a%N|4OXv81B^xM}NQ)iu@5PJC?YS>({dv5oJv4}Jfm6gAsRPT_ z@7}*BBWxhq_Y~ryqk|~U$3J*hfKssX-1tFxB-G;(J!rPs2bS>zrVE%XC7H%OK6zmn z%wm}heALy5IIdSG#T(mpApMm;4~L6TflkTLaxIxOXM0ID5M>H?=fq%tfFGHtyfD$H zS=ab4j~p5ipx)8RLSI#_sIai8Q0$R52HFGd8Y&z_G^?&rBe7PtQtFXA*+2b_@OtqBBiyg@UZ>(>7(iyDl=m<0( z9eU}|F|Ys&2F9hwlB+Q=z!>zqX=NJ7#svvmR$sfQb8o>O)w6MAc6wTBdSzJk<|p9; z85Iuj4H%KmUv5f&OyCi)<|wOFg*SEE7){IdYN&|bd^qb!XOpkTOV%B5o%)*zRh)oT zDGxe4jjY*RA3paPPP6>Skzh(FQaCaE694<**Ke>n4^z$ogTsEn`?{&VX4u*a2An*? z>?x@%Ev2y`x&E!ucvJijDccf?6*5L$*t*y{kJExg?&5}`-bYu$DfKOgZoZh=^+5_y#wxX``z!j71_ZiBZbs6R({52aM29`r#GY z|6{;aQYmbIwY{=CJas>-#UkszhLXdUh^M9Vp9|2Z=vASmIq>;KFhe6WR2OK=i=kv3 zVg8P~{u2qF>`htQMKZGZ+%^Z^+nmjuuy{PX84Y#=)%DG}CM+WL-O5e-rK>Zz7^)&Z zD|sJiKm=v(CbPc*+d)gItun8;D0k2C^26tPE?SI#q${H*Z3Kv~hLNx-3%Ixn~30j&u zY^3KT)_;4S(LIEwA^wC(Y)5}o{CG>Q5X14sbF<0i2zao_d~l5x{r1&zfG zx#nVjSOmM)Nk!V>LsIB?g9$CIbXz_!=?mYI!V0h&3X~|pnec;Gh zy(cpbi0qt}EA>!cdp1m@-lCz>hSB>lk+yz+BKUS*=yhS!;l`e`W;^Q$zw0sStg4a% z8j8tm$QVzWm;rJ-W1$+EZWZK#T&q%5ae=YisEm-B@#&l2Vxzs-CmnKDmzqpNDkXvh zqiEtK5!NTqVXH=Lpe#!`%UFDR$OJA3yv;^CoEXzG(1&kHp|T*;i2YGJ!M57ttg^s= zKn;!|R>G=05RIv2vDcs@A!}6cn88qH(7GVn4Hk#l9@a_W$P8{<16uYC{|mnW?PG=K ziu=-X%8LsMeMOxvx5@4xjRuxwfnZst>iMjVIXM(2njRk*&cJ5p`|qGBWTS3KT?4wz`UUFmcitzHXWSukZ}Mp{Ft%g2Wh5{y0-(h6M`s~Mc*x6*o0SCeBe za~|AVEy$ulX45*gA$%dqtu|ntBb;`-)2TMgEYz4Ev6FwfA`%OoW}6u|*QGLl%gtji zBTrPd74HxTxl$=tnl&CZ74mcJ82(nNwHi>4S7ZI52ilA1ev$feqVAX_1H>mE;Cnf3-&AQ;0Rlgaef1r z-+(rpLccr3hvty0Re+XoON6>=MvvKDTCZ`K{l)-3N1M5`1MnHo4b+Q&h6MpaXjCalW-YY18CC71)CikkAX1hEsBCA+}wv2o?HHZ*JASHV?tH< z{U}Sw7}jX;eui~9i0*jz%WFVfXxX-#o6HHhNbccqZBI1txa|$-2|xPI@9`rumN4e5 zpp|=0$msMMTwR#-W&>+9l4f%&y5kUfvS!nXgzLDxD0CP8%)XR+IIEGmFwl1i&Jb_x zIr}&_3qRmq?#>(%#byeB9cHVs3u^G$xiu11DX4HxVnAvkP^3>-;K&6f5GC6nx9Bi5 zdfLFW$z85nU=s26pwEC0Pm-LpmI%# zjN`4{MMakSN0<7!7N^r4!6iFy4oX$(l1``c6 zG9WM@Z(?c+H8eLempyX^G6q&vLPbwimvwUn=$0}C5tnXs1_=iZ3w3h!57oDRbOr?i z1Sd)49G5{B1{0P!1qqj#oE+kjMU>xQcp0=l&^gAOHCItZmI~UVU{XCo8v7P{(er6wnV%S%odt z^=yIkds*9>nz9PgU+}XE*nBom#ICvX*X=FMT%mx?%gSx3VSn>D7>2R7NjX22wbXFg zt-J&LdSPReq?=YhHb(g zz#gHS!TZnjH?!YO<;(rzvszujkscRXlKV7nY|3#`I zk^FEnks=d}$yu!0j0wfSU9iC&^4j5mt zqt1vk;^^~ETHOPaiHX@0mjPd}lt}U_C}vwFsef!Ss6mDo&omtW%M2pA{BkgMm~~16 zA$YN(sv2;SArS6!_=AT@-_YbIa2mh0rKfmPVM%o}p}m+Nse%d+G|2_R+KvLy<97kD z#a%?#8@)%z0gt(aT#33?%O$m3Rh3?d(+nx!prjeHkU&GDj8y7lCMvkfQrDX_TL72I zL4VZlgCLpu`ZDwr#6rtIy7Y^)YrP~|75Vr#a1;N{mS0kj5R2F{i5!F-J_uQQ!4xFJ zCaVclU;@3N9gkC5)>&k94_Rzekcl=d`)l9N*e`5+hI*8w>ZqHnCbOl}0uFl@c@f1k zP~EaWjppuLzwU?BDw4)`?FCGA1s%J>Kz~2^fE9}cdw=_@aL?s41BtU|4jl&{?vsN- zZ8T~0L{piloev6Vw=@sbj|g1?z+c?;T(jC^bos0{ubu2Vc-qXILPpuEcqcpuH*V5SnNmxY*{-g=r^Pi0Xg z^~AS+{SsoJC(%=A4SI^8#wiP{v~>8r$=?4RpC_l^T!PjXR)3qHrl`ZvsSt0{n0SQ7++hY0-Vp%b9B4IKlg^|j z3Mh#vSs&XAnbg;)N2s;bQ{O(Hee>kp(D($|o425f!6-x{!J){we;(}kUG5pUT0*f` zl3xjUt2PqvwRYP4f9q&p2{(pAwR;9tD zH5=12eD#kQRXmE;-`x}5b>?MiHGP0dLlauw0iw@Uh#Y}Kh9uyfUR!UV0~A6o_#Cbn zO%31cfs@`TpLnR|4B%)rdW^oFMk`)8mYrK%*}^4d^M(Fqr~!U!8&_Q4mIu0f$-mHh z>@)H!O>(o2yewxeTshW7Pk(fLg!4+3@SDv$N#344drJV{A-&?UTU{1=x^QA?zAAxg z6X;objyKTAG!qGsgq48ztS5WljRodl5IGroRH23=Ie_0g!ui?J-Uw+n(yC~XbrhM+xn?}A&pL<3lN__d z2#xEMVd#sv+Q91QA!W$M(#yakZ>uTW$F2GDQEpM`O**q7UE{;em@15pei)z!nek^P zQlR}Ti?i?dRtGI;$A5ZZeo?8;_RfBZQZ-UvTXT=Fc7-}aZo=yH&N!p#t@v)?7;PfX4{jt< ztOVoaHD+ocmBF%ifrH+Qh}6?2kVqs3LKd$d+)ab`5cPHHQGe>mr`~?;#*vx6p@U@G ztDdp89A%}J%dRi4tpFaBf!rpwM}4k-2;lt^zqo}XVCUU5pGMDKxHcakIA|Zs&<-Y< zxUO<3%Si;A$}Ed`WKe4!CDugw({&cYpqKfh6wZpqT z=b*I*!f?VEsi$#cbbjyRT{U6-k#YXg&^t_Y<#q*(&y^!jF6tVH|~vf_K*I-?z4GpKJehP)rX4KmwmyN zV>f3;#{lo{)Nlp5c3y58rv8?f?&{{B-({v=L_cEb#cH<6ENQCVl?!+_?e%XYE+u|V zxbs2fCp1H+Dzx>M5OnP6fxm$y1gXQiB^b$RxsNn9{12|U`jrV}n86zz=dk=Ww zcht&2rEMTMmh9;|K6h;PH0@}9qgz#>Ro6rNo#l)VMy8VdvEqW=Rr^Ya%Ib!uDp{Hv z^?%t8RpR!FIfmsj6CM1rUbLV0;=QMr2N%^wm01a@%$)hAx&A@-;TRDf3%v0UPciAF z20~sc$)TNttBv;4qGa=?XK#3$t4d70g>usJ0=Llr&;n!qgr%x)*i`~XXa-SW(r+83 zLt#YLC1~OBYfDcHjvkpDn2Hkp#iyin!hb`{&!UGCpTVLqkfQ9o-GzWxi{gi3{eMUx zCKAUWNJFyp`*maD z@a;!O8UG(ny~zs3!tws-QG2G>;qcj;Uj0mlG*q7EwT4S?(0KqwEG?PSE9)Ikd< zl~RM2I=EQ9rYL32NGw=<{s2TQW`BR1gik90AvU*yn2uffb~@te+v(ux2miD~tFn<6 zowdc@L?sqW))c4YU^jWdk~#1uxYH-tjUG8?hXFW51610Z0avLEGCJON&w`F;BQGp| zVijAoLCEX@SEtj9&ZoR!{nFX#@}>8p@aI{8mNV#^iNy1)(KY4>w}HoP zJ}@YZC!_H}VzoGQduxb_dOW^mRE1~x@O{_sC+=JNd}!s0Vf)IJ81{F*7CI=GK^6uR z4K*|%Fd%PYY6>$kFf*5Zga$GOMo~^iR7aP!ga-VVEno!^mu_?h2?uiv^m7Yw*SFGz z2Acr{5s9 zH46G}1Y>TaF;R)L(KrxMoE1kD5E%qyp65wuX1e<{O*79lQ`3MA;(#cQIBQJwMH8oJ z)MsK$)R?HLON#vbx{X8rd&&Fnuk}}fu3l8#TeZ(V`|MLKqWYOoB9Um&f|bkc*RB3w z;i~nsgwK}z+ai9K2Z{zE0WFs)iUufuv=8<2_l}C6WVs+H$a1}~BGPibccgbjjQ3XI zoeM*Q!=j_SBP>^iZuO1`p{NvFy9MzfUQVlQ6GFFcTD>sL+j-5RaG$k{BYc-c`mK-h zw~yYiJSK2OY>RoCxwU$~;&7me!W2kl15^63rg?f)#Pc5aUQtwmt)G}%;wSihrO{X?e zE2s}C2WkdoMLAM-)CZIkwTiN(KB6X2o2b>)LTVQE78Oekr-G?BDGO>a6-teuhEQ)) zrj!{qlp03)Q-7mavWbNRXNo3&+xS`(EV^g1NKA|C`@PdIw%^zNUHX4736k8Qx6)@B zOD2xF`^Kg>jt-bKpk`pdfnN+-IOxYW0|t*995VRCkl-OFOsAV>m?E9h_Dg-+i$<^_;$g_p(EXYMqYZy=ABdA zJJJEai#)Ar2LEnSl0$)k|IHwJa$n5rq|D=@1Ngm?!M}^&zH$)^$jQJj(u(-GJSgT&WmCQA$`urRMa(Cl9XDP0r-DI$Tk{orfx)T}+9v!e(Kxd^4_DRul`q_#wvEy+3zneMuchS{Z zw^Lit&Tpz)L~sxJJrMK#_)%iC8)ji}64_?CCf(6pd;_ z14>GgL7tJNOqFvPF`?FDfmt=}02+tJe9?Wm@F>K$Nnb{PS|AT^!~cyXe|7EpPin8mtyD>r@nnK@z0O(=*brDYiDpqtHfqZgw7MEJ~`Yb`z9mk+7_T)sPJ9 z$cjq(G?b@Rha(rPH^)nHw#!Ou5(0|=x=nooYTyu*!WrSLn{(1zpa|4ZR8oN^A}@1f zjgtyf2u0<87LXj5=%pmDzhflLA<#p&ku<9zsW7&YAxAj>sQm^1Tlu3m#VEgL9Gk9H zszZUn)&aGWK8B~$;jsCA0`xw07wE|7f_=iv--iP_DX*thDx~SfdC9pcWnfVXni5S3 zD(DfLtCanF&%VqK$#t@eGi2nzb+R~`o~I~om-1DAbbC(mRj$^6KbC}nLY@(ixAlHv zPFV9~cnV3RGkVlYws#wS{ZM?M$AAx=H&0^kW}(`-@LU;*UZBbDHh>-tTDrp7P-?8Pkd}WXW8QSUJwUbct$S* zew3JhpUzvd`Gq+-P{35kAd$o0No06#{}xH!)7m!F4;Uno;Jv*j8EFayq*){sLnViv zN~+Mt{y~yd%*46kAq38WLS7D=Po=i-qx1qH_uUioa^%ke@QAU2p{UM%4K=dZ;#n7q}`mgnEQ| zxy8E!)0c6ndS0qW-krj$S}%*yO#!?YIp$0I?R3#Pl3kf$u@z?VkRRVeLr)#lw;7~% zG@4M<-#{--&p#;Tf1+)AKVyk{Wp9fO^>U4L0ax&%j{;u9=)f;b3*U~m@lVu!LkfqYKRNX<;ci*c1X zc0`?7`6Ms$E$a4ypguE5Uf9D1h=h&Cyf_NlOl>fV!w<~yhF9DYWbq_?@`_s@Ly19( zoajI9hERNYs~BbXOkq>Xl&V;A`ndsrdPx-&fL5WCtCSGO^p^iys^`=E;@-!FvK)C4 zSX4q$m6YE{>)^l>qfEL$I2kVBCLHYvYz~+9+K?TX{O;BsW9S)6wD>8X-zx5L?3u$> zKv8mrQkk5_IW6$rwfx`*V1Zq+HJ(BKbwhLU4CIcikqNRugNvXrF-4x0s+6XG<4M?b z;V58c;`K*R3#vuSPJjOZG0X6Lom7>s$|wV-67s91eGI@32K0fRAK4=4Zp%F}s=zbY zJ{g@&cR3wS-%hwY44FJ4d^3ChNBrj2b*YX{(z7%kFUaxdnoJLAulJvdtPNk!*6lvj zeh!$c=Vy{sq8HAZenM2#h~JM7Reb-D7QUt@nAl z46-20BCZgsIX;;rYAs3BbS#aYh}RKPEEcNx9G@*DX5(9gm}Nf|_vEAdEON!u(JZ1U zoA6XT8@u2w=p#G@tw#>%Lo^M!arimD!4fb=eT#BYI(q-c&xk^!KO$M2kH<_OE!2z; zq%RG}J$~8~@%}$oG*bzGT87?3R%jL4h~Gz(@lq)s{TtUOSN!%DYDP=0!TG?>O`q6+ zB{+ijbg;f>^1v7r*54+D;FZnYzfGs7lA_M81Y77e+y ze|K}e6fgRBMb#D+vycdx+roWTJ8bg@X0F{mazx1&UtRy|z?=<#f_5&_3l&9VKnlI+ z=H(y05hHtkG>Zlq@DS8ra`)iA&WgfpWiA(=mX!d>On7yiuCc0Gx7VY|Vg9s@mK^Rk zJK!e1{Bjq&)W@J6PLaeuPj(SY+bW882=xBEkl={6H={EGl<3M+F#-HMi&jX`5H#@m zvqz)u;W5%)@v9ntR`ox$;xrjKaQk%~lA|&fY5RbEDnT}YMQ-kZO|Z@Dx1BJc<{iW- zBA*s<&oZM~498Y6^YAjln(=*Z5mh{-AD0DxC~ZO7AjyYG!Q(h9lp^U1*k}ow12t=^ z@Cc?w5`tp;_uhTAzw%eXe?s^tsy4k%V5B-lS1uzlNnJZ1k~r{X3!;9=$;?hohbShf zK1o|&Q_<8GsCQrC?ra~IT$Bb^f9?sJvprn7h^noXF2IblUGlMu&aWm`8Xb`yNc7uN z8&sR%nB=(?T$zPG+aq&ihD;7$?+)w;sN~kRIKy~g@_%6`!4I|V8eO?oT3M$rX$0mw z_#oORD|{PyP-tLAJTP5&KHG?f!`zMYT*r;I+237Laq6aUpbpcuBut$Kf3(*aCifQN z>3gi%-b??AvXKR!5p}<8)b~JoB9ygBQPy|#qmrN*ebJjK3mnf)LOCy@XCXl!LA6~a z9!{c1LR3G(l+@U<4I=198Qo&U^RtYyo+XFGL{6bhOOu0=7_rRU#Nv=*H^LFiAe+sb z+C$WG>F(gV?9XIfX;+hAe<`yy+;#H%A=i#3bJ?XzV)vOuNRN|ZQ#uh+OY>B!>MBm7 zDK6D$_IY+Gbb@AgUjFnz$lvk6T4{QYeNi?9<-63tZl<}m<9pOkGdnbgQ>Ew2^MR>& zT@8#5T<`<`WWuMr+6TsSO7uX|C;LY7^p^gAxp48D6&GXl83uGfe~-EhLrJcldHQ4X z@L|b(2>On_rv2dr++iN$VPE0#9KQY+>3Y)0-an)(0(w{%8Y=k$3_khkO@YKjECoB* z(&4k$=Xh2VFt@ZfoAaPFF$q#Kl+r9azvxh6$20fGqhT2*QZHhYRtD1*#Q2~*3FuVC z_3A>^cF+Rz4Jj0Oe=HWy^%eA5R5g7HF>G%d&@8R!n=5E!ix{mI^lZEVk4JVv66F-n z36tbZ=r>qL<2SyE-~ZX}(_eDOgErDjf_%J}!JP`y0ExzqF*Rm08id3oqs7RP?`4~! z8UsSYqXPY!VsvdaO*#%+;nl>VeNvc7vbXYe_8y0FV)su&f13d7ifqj;DNoUTK_xZH zs#yf*(4%u=l*E(rUhZ-j&M=>yJa-o@sKYb8HC#@LDx>rT6^JDgD4MR2r(|$`_M48a zEZ;!tz`*HK-?Q24Q5`4U;cG}oRK%Uwa=F2;Z5;_bRNc2BZz9?^S`4A2^5(ra^JdB# zK14)|P-#)AB%)2_eJ!-_%PT2mDJ9yCY!#(dr3ihcUDAT01?hiY8a4O*eZSxLtJ^*2 zo^$Tm&z&(a@v?r*KI0B)UDtORxy5j{$x)-b&f(4;j{P0lkCi)oXC?+s4mzCkGUi9m z8%H%A3UVTvZau00TAs}2EQq(8?Ah_j>v?|O9=_pG@lTp`%a(NvsqC?NK)Y^PYM*9% z20ECpajwi04jdzF)Z?bxgyjlBn~m+WaG>Ov-| zN4G1!r>3!?DsbE&dpvvhIeo?``_@vS)1%^btFryK{d}Z(qP#A1MDyp}RFSRosGzBC zUA`qk0k~YWh4vw_AembDkHe5$NJ95I^^pd^}y7&C|H1;=Z zDz#vI`-vlGZ1X#0x^$}68Zu1JxpcE$>3=<~EbkwlJ$m~=iRVH4@^{+KgTD6pv}?|c zAi{ryYv71*lYXmpL#;M7kBKZz{1`Qo*)hy60eb3|X+xW6+oF#=~zI_CIPVvMN!yls-*L7$AmUM73tCNzlI1r@9G_(YZgbd^B6> ze%rf5rTBv$M|3vVx<5Me?9(G5 z^EEc+ACrmtehoDrb=L-+PVirNuuDw`(USQqZQ8xF+gexkJmKl~8)SFguEATr_e!`m z$XI7lYGhC*Jb9az{8->=5Iv>)1@_` zu={(zL(JoK5nuK1F@*tD9`^CibGGcQ-aqiw%^99LvkvFIkJns#HO{Lt;R3!Q(sf%!>Zk; zYzTT2VP@Im9JBJv<2}7zsyA+w@6S6?{65&+@oSoT?7{4Rj|8OW2Ol_E*6sa{o;iE%^Mu^6zX-R4eZ71)$x9CoJ*6aF72X%fj1{-7Ut#WtoJFZys zefh|PFP#hx*1paSJ$LgswJtJj>4J%B&3e_eV{A^=x^3-FPPEJSoA~+1g_ZW9v#%Ix zF1Ye2?o}4G&3jG5c9Vqa{EwYXH(hH?|Jc5{)0xJFLpM0>Uyd1{ZGh+YGglu@8MW9= zlz3_qegDXb4_#NzaY)tPVE|uMZ{l*scS_I?oAD-(yZYEfOkTPgf9ev{(e$6=y3R`l zV{i6P_O*Ou;cK~S#p)HSn+!*+u$b5FmHUUP<(_eo$$LNKM(han{G_>Vobik~qwGSb zpG`d`w$U%`b!fBUo4fzkZAx%@uH}5abPiFCQ|*(-+a5Q`a!Pfsh&28xN!i#Pm=KHX)bV^aI%?0bW zx@&{;Y!}m!YiF!9H1pnY^lSLExmGK$yLU($;QZQ! zbE(geDyHD>s2jV-^?IE&x_<(DXrQ>@Zohcr@GIp*3pZpqZ*W8$!J`>=)dVZ42&ml`1-(pvYA%V1r5E_gynCZ z|7S$&O=|yg(2CHBQ_a2&q@yyfX)M!_U(%XzVL(-u&pt;H<6n1v+>j3jiKlB<9`iji zdH<>a|1V7jgu`t|>z4wUIRD7@Yo|ZIFfzYOe7)1wJyln)uVSv}F7fkP-0}XY>$aB@ zy3d?*Gsw?T-OZt2nC7}I?K-4t&YwGY@SR&Px0U$*d|SkBtLf2j@?-VG_0J4$t`Pmx zry)Ah_dB~dX0}z>lDmvN?sntrg%Lp;0vV^NtKM~~N{-&J_~4@9vhFUm0|U3L4z|?G zc>jE5|HNfqLoyeiUvy~_rlY@De`C*}kcC@bblP~)zpv=fiv3n|Vqd5oo3}OdVtROz z{PD@?`$n%cbh^ODX_yoyfQ>G;^>ezsg+5WQf}z{bG+ z4h!UmXC3KWec!j_-l6HI9i>A1wQJigDcQ3-srV!~Q=3y(E8Y5aiT|&X{<7p{q+Rgl z@8!pr-A~d@>$+m(kKQBFZ|QH_`t&#%8alamZrO=xq3~(p zbRyC4gOljQ)QW;Ki)GOT`}X_wvtAgI`K;11WzM~upRdH9Tkp}6jfurfI~EFh+!DV$ zJv86rNtgVE6>L!~X2w(pTds8+JY$kUf=Pzu@xC28Ews|;yLp-3qQH_x+drnwzA!8~ z-@9IXg?Q*|;<~JCeW&*~PWHN>KixNPj@^&=yb(Wo$JeKv-`r3#X4}`~*-e+218dE{ zHtsy1Z>F)Z;N%ydRhPPns~?jko!aCVdbS~_h#5I_ zLre>^Hl^mw`nNXq)Ru2KMq%qC{XFjom%nJ@fGb$V~az ztl@X1uko9lF%gv^jmGtsvb)a)E9YUdpqwp{}APt($4wh#==>aGXvvCbkAQJF1L51)Oe5nOct{_ykZ!4{8BUp#9UZ_q)y*3|XZt&!2Q zHw#asEM`6uMN*2sR@sz$-;*FW-~7ss@vVBNo$<}2I_H@A+vWSR0^i&nurRJ7cH5gV z;+uAh%igVhxH*63#^rsaw@dof@BA2$L-d?-?sG8`S2ZLU09h{T-^JU6wukz&G zlS^VV+R%G@k8#hME1z{>v%6hfs)O%;Mg1o9NO>`A%cOCPmmofKht5Vn;hF#XK6k?DysJqy34sO=2tCBK1-7$SMBvrBusbbvEkVb!b54^MpLe2 zIMjP9y8737D+Y!ijG3VDy{i*n`F%N)rm((q)Ng6D^}v8N9`?)18>}}ZHSVBFitjIZ z^6<#(OB1GkvG#H)TKAJK_>etd`u24ZP4gNrR8-V`3qNy1du!5;gbmucX5qNlNGh4& zwPnOcqtf`jQtfnNTkm_-{XZO{>!NK}r;gPQ-x=53`-h8YPs`WscH9h~oRvyQ8H>lm zti#rR)C30yHXt5*%C_AKvyKS~Scl)MiogUcT+mj{<>0;FqYj$=nFyl}Hz!v+2Tz6V z5lmaaZcYNI$w#s7oyPAQ-_HZ1inQ{LM{8bQH=1326dNxL{PsM2(&c>i*-^}tIbr%Z z?(Fa^x6orZQhua%@}L`{zrB6-3RG&MTBEZUj837{6)3hn^bvk-uNFos^4@u z6M4eq>MPApMrHQ>`tQFn%+u-NPQy$(evjX{ASYsO=p7so;YsD;{oCWn!B_9nfa}q_N9ZP z|N9th78YVBt<;4{^{!+W{OGi@Z;!84(J9R-2e0WJnE3BJt9zx1j-Hk< zXt%u22v(d@B%U|!6Lnqt-y`tFn(^tgyj%q~L$Vk6y4ao4U1S@2)vkVW?1kLy>34stDdg-Qt`}M{ARSj*E5aN#+|fnR$PDh?wxRG`3ffZS<~VvW|PLaMhXKSepAcp zUai+>Ytw-6lW}YM-dY-y`EBk^kDyw$VeHJU=Jq|xYC~@Ks9Y3%>)nPsKVF|beLD0_ z{zLQ3lL6;H4%1pVGJSOJgD#(EtJ!IGk51ZI-RIxK2Ew9s;g55ha~sZ7w+&9pXzE_^ zEGCgjteRDCwd~lEB1V1p2rJ*0Z8pwmGwka0l8idj_OotGZuY9))Ku|)_+0j>BJGrj zX}r2K*MIc3;IY$ivy~a<<0h<+v>d(1i*0Vd2zpfLTRONhQ~MdV zCAH2Xz-K{X#b=+|l!nj4r?mH)b8e^^QP-T|8Bo>aov9=1FUx-6xmo|c-SgBvOC~IN zus|!ko9Xy|O;w2jd8cZ(1*~J=n+Ev(mu8@yH_<(;@>5Ut>2XZA|M?}WE;iLAn|+EE z7Zq!!2km&JEt&Lo&d?bTHhgL~JR;)TtGR6NWNe5}*RLAnOTFJ{x67d(EQQz2gfyZpYInUS|9v_HWIM8=rh@#`%9H z)h?m*dIoeZc)s)cjaA~XU3aF9`SOm9OUA6VIyPh1YEoZbk1%52B}4Q}E}3{Yv2fy* zMSU{dK40iq)?R;#N%nxVx#Id|~w z(&l$LUuQbt0Q)oIc}Z-{CdJ2|%a~hR>5GELm+tO7FlO$F`DK#^qz=1fXPoYGd{p_4 zOYZ-gJ=BkQ%kJ&$ICO7$zuU*i>uwf<%GS-VUGZ;KWY(`?SZ705|O zvaf6V;No5P$SCopL6%|mx|KtpN44KxemtizH}CtVPseNAt7{!^O*2`YecQj+Ieja= z-WD+nF28;d^sRttEbLsb^Rc3S^1`q9ndeo35%Xttnxfw`rK)CF@8!eyw{2L)JLtg zon3vLMzU(D*c*268RfKDr>1WGr<(f;t&^Ceplyh2WZPeGJtf?4ljnYs1WC!^+YtP@ zKT;IUo?e6vz#J^%LN%Ul`U)xLzxyLv2m5 zBK}qR*${32aqTh|BETq8M9ZWKt306p z_bXz>oU7P0bX?_C zkB7GdoA>}*EudM`B5a+IkclL6u@-x&2otgQim-OfMokz6NL<~#M^8{#VL}~&npn<`5(?*o)U$=c zJ_7RSBcV|3_u~%5Gfkla_B%T}xO*!O=m=wg|CR?F)}4j>)Rn)VrM#OkK^+@8!o}Wo zf?{1S;Ti$lo{pXnbVwoA6RN8*QbG%F{Siqe5>g_XDf+cW;y4Yu@#|kjK`m<(C84=r z2E+X**9f_smLvN(SXzqglM!-&Qh{a9_7V1CWXLMKWg&2h>P`}u%PC}yA|xaQPxJq# zh9oG0La8B0IhdWwKG;POE$1?=tN__E^bl?h)L8|X6jO4PJy;__{Z;l+gjgyUtF93; z5|^ql-0l|)0JDXCg6_DULEJCP*=@x(~Rar6?@uyciV*DJP}K)lgtw z#P7Aqtq0?{oDWRVas-$pDN2e;7pNimj1xG;Uhc=|5r@rkRK|o1=gFO*r8LSng^MYa zZy=pUWCn64m5RYAd4z-Eic|%O;}Td@T_Yuw6i0Z3HG)KhOOY}{hBAVKI;)<+;6M!} zM=0bDM%5YYNQQDk0z%Ye0G||<0tYKchz7yPWjKRyhl|A|Dnbb%CJ=QdC1ROUgh~lg za4wBV0f^yg3DAt=N~tox-3cxRUeJRni3FvZq$FY~dha9!9}`0uk;(}PLJTRD$OQEvhckneTi zWQkIQzaxI05ddl{wb5zpy=n&(I5Td+p* zye_zLrERquAt`|fg75`vqzt`rh#x3IPJd991V$vhO9P_is`%g%2nc3~6i6A4qeckY zEa7=LLM9fY_CeDWdN4_Y2Ua~8@Y7a{<{HMB)0)HYwEFIRQ zyzotc(^8(HG(w0GIECJwTuP&Uks=5wx<<<6|3`u{8JZ7JVmWBOD$xvFumo39^IM-` zjTgQtPA`#t6fWb7mCHF$$xwt`HQIv9$Hm~z5hDbpk)mz~^aK2kD%Aij!;v*WNTX>3 z;N$s94))KLOl(Q1AoPLXQ9T3@$_T`&0ihgKRt}a#ln^ID*kZQU7{V-q7L-IRL2d!I z6JkVlaFWJ(28lz2M)>BG4$adzSfw0WEgUE1VxD{8TpV&RAf&j@T5>uZToC9Y zV$C=O+3N3vP6;~(7QyNf3#TYCP9q1C;OJ1*0b-=6dP4qEYr^F(G$lnn7ETcSKq%p9 zBo44B-#DllnpOizB$^=rNpddl`xQT01;oWhgcuy2*z=N6xEhp43L;r+R95EraI6@? zM~P|rFPSmF3Ite`pj1;N4dPY3LEuD!t`RbjEqc@3$8dI)AOsJhy2b&cK0pjf2CC^CK2%zO z56yTOsOG@x5RS#*Qb-=h5G9a(fKZOQZw^+1FalwkmvR7s1cj!~oU=vqG!7UI$51wd zF{(-i5Q67YT?2dspEFXfHWD6fE+9u55%CBs2%}6Xe_A` z$N)kK8aOy$0^v?9rh#QuU&JfmkK>{eG(Zqu5JCZ1Y0E=dZ&}oBAMO9jW5AhJ1cXo@@dyO_R9)j>|MVz+Uoq6< zXud$=jD&YjKq0s|6rl|K6tV`@5$b$^KoT`E0$d83{foIWmUCvD{FUN|{78aEJ3vVB zMaZcaN(@*SVi91)yfzHrQ!zz?i|Ifi_*N9*|8X=DFh-hPI8YS}VXB zudM<^{GZ;xn3rjBu&7Bx!Odl9zx1|MavVZ5kpTiBheDWwMk|`S0UJ_OnE@X-ZdF)9 zPJp14Yf8TX37Ht#2$?-}D3u#qln)Tf(VPGfLfBN@$HAg4Mo7n?>`~oEGSK-)Yd=89 zQ$7wD&4R>SDvl5hlLVe*03Q@2st0qhoO@UC8)BI5ph^k|$(9uRkAee2UU3Sra^96d z?u!!5;rmOsTKone-_oRvt zvO^i#;iX8Jnjrgt7zy60TrE07$f3oF#0xG6^Zf=CTdfI2Yc!PdL=6aeK~4;?sM`ju zBv1zk1k!&K{p7C9zi}5G<5-dU{xvv>Op@K zZU*t#uqMITON6i+I_HJ#3|a*$C^!rf^d1Q)4$))NfxzujJ$KAwdadpmJ~$h{uf7LqZOOYC5Eh6zbVv4W2%zB7_kSuZzkNgO>k53=}6y*x$JzmwcfERG1a=A{ro+ z^7;f2YS8qZgXOjHULqzoWL>qVfDH?aqV&~Z{y{o5_UOav|OfIu3}mS9K%4ILgV zxDX^4ghw;HqLf33*eqx;r2A-W09bS$Oh91fcUm9|`r{6jxgZS_2!uia=9wZ_#31{C zK#1W8ER1{5krdR5VqRS!VW4_NG!rs6h|fHPkc=a1@IVC3ptz?@e$5(P9T zfZPVUl*qwgOsK*EKBzvBeNaQ8z5+59hBvu{@iM&cQ3VEskkYBH5s-NBI`06BrriW& z=co(j@U;Z2zj8riY&@+Y{-J7P|NkT(Sb z0%fRVI9SvNz@rvO7*wSN_@F#hT?2=SgZ?9n0L+W!FfBki;Si#wHz4F$6BHCsgP~`% z1}v9W?FWQ38l3~J5Nny&>}z_ERgiOWcbTS zA)kBto6r?O+V8R6zIJyy@ z`=RlTdrpN;^|-fP$SXCNA8`*D5dxt{$5UAdWCYrj=iXg`@IcG|h!FBe-VBs`Aj3ll zjei~^U{gE-A)>U}g)*T6uPH_27WWtibt5pbq0mB%doO@mGdwKdO$50P0qTeuu8EE+ z2sb1D+v{@D;BpwW=H;pxbY#hO8~(q Xi`WQfVIOTMIOXv1AY%vjf3*GwLc<^H diff --git a/doc/footer.html b/doc/footer.html index fe5338c1..a1895ac8 100644 --- a/doc/footer.html +++ b/doc/footer.html @@ -2,3 +2,9 @@ Code by Tom
Docs using doxygen + + diff --git a/doc/header.html b/doc/header.html index 426d4e3c..231475d1 100644 --- a/doc/header.html +++ b/doc/header.html @@ -4,3 +4,9 @@ + + diff --git a/genlist.sh b/genlist.sh index 73daa1d6..832e8e79 100644 --- a/genlist.sh +++ b/genlist.sh @@ -4,3 +4,7 @@ export a=`echo -n "src/ciphers/aes/aes_enc.o *(MPIOBJECT) " ; find . -type f | s perl ./parsenames.pl OBJECTS "$a" export a=`find . -type f | grep [.]/src | grep [.]h | sed -e 'se\./ee' | xargs` perl ./parsenames.pl HEADERS "$a" + +# $Source: /cvs/libtom/libtomcrypt/genlist.sh,v $ +# $Revision: 1.3 $ +# $Date: 2005/05/05 14:49:27 $ diff --git a/makefile b/makefile index b38aa17c..d3681f2c 100644 --- a/makefile +++ b/makefile @@ -4,7 +4,7 @@ # Modified by Clay Culver # The version -VERSION=1.02 +VERSION=1.03 # Compiler and Linker Names #CC=gcc @@ -21,6 +21,8 @@ CFLAGS += -c -I./testprof/ -I./src/headers/ -Wall -Wsign-compare -W -Wshadow -Wn #CFLAGS += -Wsystem-headers -Wdeclaration-after-statement -Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wmissing-prototypes \ # -Wmissing-declarations -Wpointer-arith +ifndef IGNORE_SPEED + # optimize for SPEED CFLAGS += -O3 -funroll-loops @@ -30,6 +32,8 @@ CFLAGS += -fomit-frame-pointer # optimize for SIZE #CFLAGS += -Os -DLTC_SMALL_CODE +endif + # older GCCs can't handle the "rotate with immediate" ROLc/RORc/etc macros # define this to help #CFLAGS += -DLTC_NO_ROLC @@ -58,13 +62,24 @@ INCPATH=/usr/include DATAPATH=/usr/share/doc/libtomcrypt/pdf #Who do we install as? +ifdef INSTALL_USER +USER=$(INSTALL_USER) +else USER=root +endif + +ifdef INSTALL_GROUP +GROUP=$(INSTALL_GROUP) +else GROUP=wheel +endif #List of objects to compile. #Leave MPI built-in or force developer to link against libtommath? +ifndef IGNORE_MPI MPIOBJECT=src/misc/mpi/mpi.o +endif OBJECTS=src/ciphers/aes/aes_enc.o $(MPIOBJECT) src/ciphers/aes/aes.o src/ciphers/anubis.o \ src/ciphers/blowfish.o src/ciphers/cast5.o src/ciphers/des.o src/ciphers/khazad.o src/ciphers/noekeon.o \ @@ -115,29 +130,40 @@ src/modes/ctr/ctr_getiv.o src/modes/ctr/ctr_setiv.o src/modes/ctr/ctr_start.o \ src/modes/ecb/ecb_decrypt.o src/modes/ecb/ecb_done.o src/modes/ecb/ecb_encrypt.o \ src/modes/ecb/ecb_start.o src/modes/ofb/ofb_decrypt.o src/modes/ofb/ofb_done.o \ src/modes/ofb/ofb_encrypt.o src/modes/ofb/ofb_getiv.o src/modes/ofb/ofb_setiv.o \ -src/modes/ofb/ofb_start.o src/pk/asn1/der/der_decode_integer.o src/pk/asn1/der/der_encode_integer.o \ -src/pk/asn1/der/der_get_multi_integer.o src/pk/asn1/der/der_length_integer.o \ -src/pk/asn1/der/der_put_multi_integer.o src/pk/dh/dh.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o \ -src/pk/dsa/dsa_import.o src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_sign_hash.o \ +src/modes/ofb/ofb_start.o src/pk/asn1/der/bit/der_decode_bit_string.o \ +src/pk/asn1/der/bit/der_encode_bit_string.o src/pk/asn1/der/bit/der_length_bit_string.o \ +src/pk/asn1/der/ia5/der_decode_ia5_string.o src/pk/asn1/der/ia5/der_encode_ia5_string.o \ +src/pk/asn1/der/ia5/der_length_ia5_string.o src/pk/asn1/der/integer/der_decode_integer.o \ +src/pk/asn1/der/integer/der_encode_integer.o src/pk/asn1/der/integer/der_length_integer.o \ +src/pk/asn1/der/object_identifier/der_decode_object_identifier.o \ +src/pk/asn1/der/object_identifier/der_encode_object_identifier.o \ +src/pk/asn1/der/object_identifier/der_length_object_identifier.o \ +src/pk/asn1/der/octet/der_decode_octet_string.o src/pk/asn1/der/octet/der_encode_octet_string.o \ +src/pk/asn1/der/octet/der_length_octet_string.o \ +src/pk/asn1/der/printable_string/der_decode_printable_string.o \ +src/pk/asn1/der/printable_string/der_encode_printable_string.o \ +src/pk/asn1/der/printable_string/der_length_printable_string.o \ +src/pk/asn1/der/sequence/der_decode_sequence.o src/pk/asn1/der/sequence/der_decode_sequence_multi.o \ +src/pk/asn1/der/sequence/der_encode_sequence.o src/pk/asn1/der/sequence/der_encode_sequence_multi.o \ +src/pk/asn1/der/sequence/der_length_sequence.o \ +src/pk/asn1/der/short_integer/der_decode_short_integer.o \ +src/pk/asn1/der/short_integer/der_encode_short_integer.o \ +src/pk/asn1/der/short_integer/der_length_short_integer.o src/pk/dh/dh.o src/pk/dsa/dsa_export.o \ +src/pk/dsa/dsa_free.o src/pk/dsa/dsa_import.o src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_sign_hash.o \ src/pk/dsa/dsa_verify_hash.o src/pk/dsa/dsa_verify_key.o src/pk/ecc/ecc.o src/pk/packet_store_header.o \ src/pk/packet_valid_header.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o \ src/pk/pkcs1/pkcs_1_oaep_decode.o src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o \ -src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/pkcs1/pkcs_1_v15_es_decode.o \ -src/pk/pkcs1/pkcs_1_v15_es_encode.o src/pk/pkcs1/pkcs_1_v15_sa_decode.o \ -src/pk/pkcs1/pkcs_1_v15_sa_encode.o src/pk/rsa/rsa_decrypt_key.o src/pk/rsa/rsa_encrypt_key.o \ -src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_free.o src/pk/rsa/rsa_import.o \ -src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_sign_hash.o src/pk/rsa/rsa_v15_decrypt_key.o \ -src/pk/rsa/rsa_v15_encrypt_key.o src/pk/rsa/rsa_v15_sign_hash.o src/pk/rsa/rsa_v15_verify_hash.o \ +src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/rsa/rsa_decrypt_key.o \ +src/pk/rsa/rsa_encrypt_key.o src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_free.o \ +src/pk/rsa/rsa_import.o src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_sign_hash.o \ src/pk/rsa/rsa_verify_hash.o src/prngs/fortuna.o src/prngs/rc4.o src/prngs/rng_get_bytes.o \ src/prngs/rng_make_prng.o src/prngs/sober128.o src/prngs/sprng.o src/prngs/yarrow.o -HEADERS=src/headers/tommath_superclass.h src/headers/tomcrypt_cfg.h \ -src/headers/tomcrypt_mac.h src/headers/tomcrypt_macros.h \ -src/headers/tomcrypt_custom.h src/headers/tomcrypt_argchk.h \ -src/headers/tomcrypt_cipher.h src/headers/tomcrypt_pk.h \ -src/headers/tommath_class.h src/headers/ltc_tommath.h src/headers/tomcrypt_hash.h \ -src/headers/tomcrypt_misc.h src/headers/tomcrypt.h src/headers/tomcrypt_pkcs.h \ -src/headers/tomcrypt_prng.h testprof/tomcrypt_test.h +HEADERS=src/headers/tommath_superclass.h src/headers/tomcrypt_cfg.h src/headers/tomcrypt_mac.h \ +src/headers/tomcrypt_macros.h src/headers/tomcrypt_custom.h src/headers/tomcrypt_argchk.h \ +src/headers/tomcrypt_cipher.h src/headers/tomcrypt_pk.h src/headers/tommath_class.h \ +src/headers/ltc_tommath.h src/headers/tomcrypt_hash.h src/headers/tomcrypt_misc.h \ +src/headers/tomcrypt.h src/headers/tomcrypt_pkcs.h src/headers/tomcrypt_prng.h testprof/tomcrypt_test.h TESTOBJECTS=demos/test.o HASHOBJECTS=demos/hashsum.o @@ -171,7 +197,7 @@ src/hashes/sha2/sha512.o: src/hashes/sha2/sha512.c src/hashes/sha2/sha384.c src/hashes/sha2/sha256.o: src/hashes/sha2/sha256.c src/hashes/sha2/sha224.c #This rule makes the libtomcrypt library. -library: $(LIBTEST) $(LIBNAME) +library: $(LIBNAME) $(LIBTEST): cd testprof ; CFLAGS="$(CFLAGS)" make @@ -193,15 +219,15 @@ small: library $(SMALLOBJECTS) $(CC) $(SMALLOBJECTS) $(LIBNAME) -o $(SMALL) $(WARN) tv_gen: library $(TVS) - $(CC) $(TVS) $(LIBNAME) $(EXTRALIBS) -o $(TV) + $(CC) $(TVS) $(LIBNAME) -o $(TV) multi: library $(MULTIS) $(CC) $(MULTIS) $(LIBNAME) -o $(MULTI) -timing: library $(TIMINGS) - $(CC) $(TIMINGS) $(LIBTEST) $(LIBNAME) -o $(TIMING) +timing: library $(LIBTEST) $(TIMINGS) + $(CC) $(TIMINGS) $(LIBTEST) $(LIBNAME) $(EXTRALIBS) -o $(TIMING) -test: library $(TESTS) +test: library $(LIBTEST) $(TESTS) $(CC) $(TESTS) $(LIBTEST) $(LIBNAME) -o $(TEST) @@ -216,11 +242,17 @@ install: library docs install -g $(GROUP) -o $(USER) $(HEADERS) $(DESTDIR)$(INCPATH) install -g $(GROUP) -o $(USER) doc/crypt.pdf $(DESTDIR)$(DATAPATH) -install_lib: library +install_test: $(LIBTEST) install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(LIBPATH) install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(INCPATH) - install -g $(GROUP) -o $(USER) $(LIBNAME) $(DESTDIR)$(LIBPATH) - install -g $(GROUP) -o $(USER) $(HEADERS) $(DESTDIR)$(INCPATH) + install -g $(GROUP) -o $(USER) $(LIBTEST) $(DESTDIR)$(LIBPATH) + +profile: + CFLAGS="$(CFLAGS) -fprofile-generate" make timing EXTRALIBS=-lgcov + ./timing + rm -f timing `find . -type f | grep [.][ao] | xargs` + CFLAGS="$(CFLAGS) -fprofile-use" make timing EXTRALIBS=-lgcov + #This rule cleans the source tree of all compiled code, not including the pdf #documentation. @@ -242,6 +274,7 @@ clean: rm -f $(TV) $(PROF) $(SMALL) $(CRYPT) $(HASHSUM) $(MULTI) $(TIMING) $(TEST) rm -rf doc/doxygen rm -f doc/*.pdf + rm -f *.txt #build the doxy files (requires Doxygen, tetex and patience) doxy: @@ -274,6 +307,8 @@ docdvi: crypt.tex #zipup the project (take that!) no_oops: clean cd .. ; cvs commit + echo Scanning for scratch/dirty files + find . -type f | grep -v CVS | xargs -n 1 bash mess.sh zipup: no_oops docs cd .. ; rm -rf crypt* libtomcrypt-$(VERSION) ; mkdir libtomcrypt-$(VERSION) ; \ @@ -283,3 +318,8 @@ zipup: no_oops docs zip -9r crypt-$(VERSION).zip libtomcrypt-$(VERSION) ; \ gpg -b -a crypt-$(VERSION).tar.bz2 ; gpg -b -a crypt-$(VERSION).zip ; \ mv -fv crypt* ~ ; rm -rf libtomcrypt-$(VERSION) + + +# $Source: /cvs/libtom/libtomcrypt/makefile,v $ +# $Revision: 1.67 $ +# $Date: 2005/06/09 00:39:26 $ diff --git a/makefile.icc b/makefile.icc index 41848dcc..e7fcc1a7 100644 --- a/makefile.icc +++ b/makefile.icc @@ -22,7 +22,7 @@ CC=icc #ARFLAGS=r # Compilation flags. Note the += does not write over the user's CFLAGS! -CFLAGS += -c -I./src/headers/ -DINTEL_CC +CFLAGS += -c -Isrc/headers/ -Itestprof/ -DINTEL_CC #The default rule for make builds the libtomcrypt library. default:library @@ -41,7 +41,13 @@ default:library # B - Blend of P4 and PM [mobile] # # Default to just generic max opts +ifdef LTC_SMALL +CFLAGS += -O2 -xP -ip +endif + +ifndef IGNORE_SPEED CFLAGS += -O3 -xP -ip +endif # want to see stuff? #CFLAGS += -opt_report @@ -122,29 +128,40 @@ src/modes/ctr/ctr_getiv.o src/modes/ctr/ctr_setiv.o src/modes/ctr/ctr_start.o \ src/modes/ecb/ecb_decrypt.o src/modes/ecb/ecb_done.o src/modes/ecb/ecb_encrypt.o \ src/modes/ecb/ecb_start.o src/modes/ofb/ofb_decrypt.o src/modes/ofb/ofb_done.o \ src/modes/ofb/ofb_encrypt.o src/modes/ofb/ofb_getiv.o src/modes/ofb/ofb_setiv.o \ -src/modes/ofb/ofb_start.o src/pk/asn1/der/der_decode_integer.o src/pk/asn1/der/der_encode_integer.o \ -src/pk/asn1/der/der_get_multi_integer.o src/pk/asn1/der/der_length_integer.o \ -src/pk/asn1/der/der_put_multi_integer.o src/pk/dh/dh.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o \ -src/pk/dsa/dsa_import.o src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_sign_hash.o \ +src/modes/ofb/ofb_start.o src/pk/asn1/der/bit/der_decode_bit_string.o \ +src/pk/asn1/der/bit/der_encode_bit_string.o src/pk/asn1/der/bit/der_length_bit_string.o \ +src/pk/asn1/der/ia5/der_decode_ia5_string.o src/pk/asn1/der/ia5/der_encode_ia5_string.o \ +src/pk/asn1/der/ia5/der_length_ia5_string.o src/pk/asn1/der/integer/der_decode_integer.o \ +src/pk/asn1/der/integer/der_encode_integer.o src/pk/asn1/der/integer/der_length_integer.o \ +src/pk/asn1/der/object_identifier/der_decode_object_identifier.o \ +src/pk/asn1/der/object_identifier/der_encode_object_identifier.o \ +src/pk/asn1/der/object_identifier/der_length_object_identifier.o \ +src/pk/asn1/der/octet/der_decode_octet_string.o src/pk/asn1/der/octet/der_encode_octet_string.o \ +src/pk/asn1/der/octet/der_length_octet_string.o \ +src/pk/asn1/der/printable_string/der_decode_printable_string.o \ +src/pk/asn1/der/printable_string/der_encode_printable_string.o \ +src/pk/asn1/der/printable_string/der_length_printable_string.o \ +src/pk/asn1/der/sequence/der_decode_sequence.o src/pk/asn1/der/sequence/der_decode_sequence_multi.o \ +src/pk/asn1/der/sequence/der_encode_sequence.o src/pk/asn1/der/sequence/der_encode_sequence_multi.o \ +src/pk/asn1/der/sequence/der_length_sequence.o \ +src/pk/asn1/der/short_integer/der_decode_short_integer.o \ +src/pk/asn1/der/short_integer/der_encode_short_integer.o \ +src/pk/asn1/der/short_integer/der_length_short_integer.o src/pk/dh/dh.o src/pk/dsa/dsa_export.o \ +src/pk/dsa/dsa_free.o src/pk/dsa/dsa_import.o src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_sign_hash.o \ src/pk/dsa/dsa_verify_hash.o src/pk/dsa/dsa_verify_key.o src/pk/ecc/ecc.o src/pk/packet_store_header.o \ src/pk/packet_valid_header.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o \ src/pk/pkcs1/pkcs_1_oaep_decode.o src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o \ -src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/pkcs1/pkcs_1_v15_es_decode.o \ -src/pk/pkcs1/pkcs_1_v15_es_encode.o src/pk/pkcs1/pkcs_1_v15_sa_decode.o \ -src/pk/pkcs1/pkcs_1_v15_sa_encode.o src/pk/rsa/rsa_decrypt_key.o src/pk/rsa/rsa_encrypt_key.o \ -src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_free.o src/pk/rsa/rsa_import.o \ -src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_sign_hash.o src/pk/rsa/rsa_v15_decrypt_key.o \ -src/pk/rsa/rsa_v15_encrypt_key.o src/pk/rsa/rsa_v15_sign_hash.o src/pk/rsa/rsa_v15_verify_hash.o \ +src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/rsa/rsa_decrypt_key.o \ +src/pk/rsa/rsa_encrypt_key.o src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_free.o \ +src/pk/rsa/rsa_import.o src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_sign_hash.o \ src/pk/rsa/rsa_verify_hash.o src/prngs/fortuna.o src/prngs/rc4.o src/prngs/rng_get_bytes.o \ src/prngs/rng_make_prng.o src/prngs/sober128.o src/prngs/sprng.o src/prngs/yarrow.o -HEADERS=src/headers/tommath_superclass.h src/headers/tomcrypt_cfg.h \ -src/headers/tomcrypt_mac.h src/headers/tomcrypt_macros.h \ -src/headers/tomcrypt_custom.h src/headers/tomcrypt_argchk.h \ -src/headers/tomcrypt_cipher.h src/headers/tomcrypt_pk.h \ -src/headers/tommath_class.h src/headers/ltc_tommath.h src/headers/tomcrypt_hash.h \ -src/headers/tomcrypt_misc.h src/headers/tomcrypt.h src/headers/tomcrypt_pkcs.h \ -src/headers/tomcrypt_prng.h testprof/tomcrypt_test.h +HEADERS=src/headers/tommath_superclass.h src/headers/tomcrypt_cfg.h src/headers/tomcrypt_mac.h \ +src/headers/tomcrypt_macros.h src/headers/tomcrypt_custom.h src/headers/tomcrypt_argchk.h \ +src/headers/tomcrypt_cipher.h src/headers/tomcrypt_pk.h src/headers/tommath_class.h \ +src/headers/ltc_tommath.h src/headers/tomcrypt_hash.h src/headers/tomcrypt_misc.h \ +src/headers/tomcrypt.h src/headers/tomcrypt_pkcs.h src/headers/tomcrypt_prng.h testprof/tomcrypt_test.h #ciphers come in two flavours... enc+dec and enc aes_enc.o: aes.c aes_tab.c @@ -214,4 +231,9 @@ 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 $(LIBTEST) $(DESTDIR)$(LIBPATH) install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH) + +# $Source: /cvs/libtom/libtomcrypt/makefile.icc,v $ +# $Revision: 1.32 $ +# $Date: 2005/05/23 03:12:44 $ diff --git a/makefile.msvc b/makefile.msvc index 16d4b8d2..9db1e8fc 100644 --- a/makefile.msvc +++ b/makefile.msvc @@ -57,29 +57,42 @@ src/modes/ctr/ctr_getiv.obj src/modes/ctr/ctr_setiv.obj src/modes/ctr/ctr_start. src/modes/ecb/ecb_decrypt.obj src/modes/ecb/ecb_done.obj src/modes/ecb/ecb_encrypt.obj \ src/modes/ecb/ecb_start.obj src/modes/ofb/ofb_decrypt.obj src/modes/ofb/ofb_done.obj \ src/modes/ofb/ofb_encrypt.obj src/modes/ofb/ofb_getiv.obj src/modes/ofb/ofb_setiv.obj \ -src/modes/ofb/ofb_start.obj src/pk/asn1/der/der_decode_integer.obj src/pk/asn1/der/der_encode_integer.obj \ -src/pk/asn1/der/der_get_multi_integer.obj src/pk/asn1/der/der_length_integer.obj \ -src/pk/asn1/der/der_put_multi_integer.obj src/pk/dh/dh.obj src/pk/dsa/dsa_export.obj src/pk/dsa/dsa_free.obj \ -src/pk/dsa/dsa_import.obj src/pk/dsa/dsa_make_key.obj src/pk/dsa/dsa_sign_hash.obj \ +src/modes/ofb/ofb_start.obj src/pk/asn1/der/bit/der_decode_bit_string.obj \ +src/pk/asn1/der/bit/der_encode_bit_string.obj src/pk/asn1/der/bit/der_length_bit_string.obj \ +src/pk/asn1/der/ia5/der_decode_ia5_string.obj src/pk/asn1/der/ia5/der_encode_ia5_string.obj \ +src/pk/asn1/der/ia5/der_length_ia5_string.obj src/pk/asn1/der/integer/der_decode_integer.obj \ +src/pk/asn1/der/integer/der_encode_integer.obj src/pk/asn1/der/integer/der_length_integer.obj \ +src/pk/asn1/der/object_identifier/der_decode_object_identifier.obj \ +src/pk/asn1/der/object_identifier/der_encode_object_identifier.obj \ +src/pk/asn1/der/object_identifier/der_length_object_identifier.obj \ +src/pk/asn1/der/octet/der_decode_octet_string.obj src/pk/asn1/der/octet/der_encode_octet_string.obj \ +src/pk/asn1/der/octet/der_length_octet_string.obj \ +src/pk/asn1/der/printable_string/der_decode_printable_string.obj \ +src/pk/asn1/der/printable_string/der_encode_printable_string.obj \ +src/pk/asn1/der/printable_string/der_length_printable_string.obj \ +src/pk/asn1/der/sequence/der_decode_sequence.obj src/pk/asn1/der/sequence/der_decode_sequence_multi.obj \ +src/pk/asn1/der/sequence/der_encode_sequence.obj src/pk/asn1/der/sequence/der_encode_sequence_multi.obj \ +src/pk/asn1/der/sequence/der_length_sequence.obj \ +src/pk/asn1/der/short_integer/der_decode_short_integer.obj \ +src/pk/asn1/der/short_integer/der_encode_short_integer.obj \ +src/pk/asn1/der/short_integer/der_length_short_integer.obj src/pk/dh/dh.obj src/pk/dsa/dsa_export.obj \ +src/pk/dsa/dsa_free.obj src/pk/dsa/dsa_import.obj src/pk/dsa/dsa_make_key.obj src/pk/dsa/dsa_sign_hash.obj \ src/pk/dsa/dsa_verify_hash.obj src/pk/dsa/dsa_verify_key.obj src/pk/ecc/ecc.obj src/pk/packet_store_header.obj \ src/pk/packet_valid_header.obj src/pk/pkcs1/pkcs_1_i2osp.obj src/pk/pkcs1/pkcs_1_mgf1.obj \ src/pk/pkcs1/pkcs_1_oaep_decode.obj src/pk/pkcs1/pkcs_1_oaep_encode.obj src/pk/pkcs1/pkcs_1_os2ip.obj \ -src/pk/pkcs1/pkcs_1_pss_decode.obj src/pk/pkcs1/pkcs_1_pss_encode.obj src/pk/pkcs1/pkcs_1_v15_es_decode.obj \ -src/pk/pkcs1/pkcs_1_v15_es_encode.obj src/pk/pkcs1/pkcs_1_v15_sa_decode.obj \ -src/pk/pkcs1/pkcs_1_v15_sa_encode.obj src/pk/rsa/rsa_decrypt_key.obj src/pk/rsa/rsa_encrypt_key.obj \ -src/pk/rsa/rsa_export.obj src/pk/rsa/rsa_exptmod.obj src/pk/rsa/rsa_free.obj src/pk/rsa/rsa_import.obj \ -src/pk/rsa/rsa_make_key.obj src/pk/rsa/rsa_sign_hash.obj src/pk/rsa/rsa_v15_decrypt_key.obj \ -src/pk/rsa/rsa_v15_encrypt_key.obj src/pk/rsa/rsa_v15_sign_hash.obj src/pk/rsa/rsa_v15_verify_hash.obj \ +src/pk/pkcs1/pkcs_1_pss_decode.obj src/pk/pkcs1/pkcs_1_pss_encode.obj src/pk/rsa/rsa_decrypt_key.obj \ +src/pk/rsa/rsa_encrypt_key.obj src/pk/rsa/rsa_export.obj src/pk/rsa/rsa_exptmod.obj src/pk/rsa/rsa_free.obj \ +src/pk/rsa/rsa_import.obj src/pk/rsa/rsa_make_key.obj src/pk/rsa/rsa_sign_hash.obj \ src/pk/rsa/rsa_verify_hash.obj src/prngs/fortuna.obj src/prngs/rc4.obj src/prngs/rng_get_bytes.obj \ src/prngs/rng_make_prng.obj src/prngs/sober128.obj src/prngs/sprng.obj src/prngs/yarrow.obj -HEADERS=src/headers/tommath_superclass.h src/headers/tomcrypt_cfg.h \ -src/headers/tomcrypt_mac.h src/headers/tomcrypt_macros.h \ -src/headers/tomcrypt_custom.h src/headers/tomcrypt_argchk.h \ -src/headers/tomcrypt_cipher.h src/headers/tomcrypt_pk.h \ -src/headers/tommath_class.h src/headers/ltc_tommath.h src/headers/tomcrypt_hash.h \ -src/headers/tomcrypt_misc.h src/headers/tomcrypt.h src/headers/tomcrypt_pkcs.h \ -src/headers/tomcrypt_prng.h testprof/tomcrypt_test.h +HEADERS=src/headers/tommath_superclass.h src/headers/tomcrypt_cfg.h src/headers/tomcrypt_mac.h \ +src/headers/tomcrypt_macros.h src/headers/tomcrypt_custom.h src/headers/tomcrypt_argchk.h \ +src/headers/tomcrypt_cipher.h src/headers/tomcrypt_pk.h src/headers/tommath_class.h \ +src/headers/ltc_tommath.h src/headers/tomcrypt_hash.h src/headers/tomcrypt_misc.h \ +src/headers/tomcrypt.h src/headers/tomcrypt_pkcs.h src/headers/tomcrypt_prng.h testprof/tomcrypt_test.h + + #ciphers come in two flavours... enc+dec and enc src/ciphers/aes/aes_enc.obj: src/ciphers/aes/aes.c src/ciphers/aes/aes_tab.c @@ -102,3 +115,7 @@ test: demos/test.c library timing: demos/timing.c library cl $(CFLAGS) demos/timing.c testprof/tomcrypt_prof.lib tomcrypt.lib advapi32.lib + +# $Source: /cvs/libtom/libtomcrypt/makefile.msvc,v $ +# $Revision: 1.14 $ +# $Date: 2005/06/08 23:37:40 $ diff --git a/makefile.shared b/makefile.shared index 207ceeaa..aa653daa 100644 --- a/makefile.shared +++ b/makefile.shared @@ -6,7 +6,7 @@ # Tom St Denis # The version -VERSION=0:102 +VERSION=0:103 # Compiler and Linker Names CC=libtool --mode=compile gcc @@ -18,14 +18,18 @@ CFLAGS += -c -I./src/headers/ -Wall -Wsign-compare -W -Wshadow #CFLAGS += -Wsystem-headers -Wdeclaration-after-statement -Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wmissing-prototypes \ # -Wmissing-declarations -Wpointer-arith +ifndef IGNORE_SPEED + # optimize for SPEED -CFLAGS += -O3 -funroll-all-loops +CFLAGS += -O3 -funroll-loops # add -fomit-frame-pointer. hinders debugging! CFLAGS += -fomit-frame-pointer # optimize for SIZE -#CFLAGS += -Os +#CFLAGS += -Os -DLTC_SMALL_CODE + +endif # compile for DEBUGING (required for ccmalloc checking!!!) #CFLAGS += -g3 @@ -45,7 +49,6 @@ TV=tv_gen TEST=test TIMING=timing - #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. @@ -55,16 +58,27 @@ INCPATH=/usr/include DATAPATH=/usr/share/doc/libtomcrypt/pdf #Who do we install as? +ifdef INSTALL_USER +USER=$(INSTALL_USER) +else USER=root -GROUP=wheel +endif + +ifdef INSTALL_GROUP +GROUP=$(INSTALL_GROUP) +else +GROUP=wheel +endif #List of objects to compile. #Leave MPI built-in or force developer to link against libtommath? +ifndef IGNORE_MPI MPIOBJECT=src/misc/mpi/mpi.o - +else #If you don't want mpi.o then add this -#MPISHARED=$(LIBPATH)/libtommath.la +MPISHARED=$(LIBPATH)/libtommath.la +endif OBJECTS=src/ciphers/aes/aes_enc.o $(MPIOBJECT) src/ciphers/aes/aes.o src/ciphers/anubis.o \ src/ciphers/blowfish.o src/ciphers/cast5.o src/ciphers/des.o src/ciphers/khazad.o src/ciphers/noekeon.o \ @@ -115,29 +129,40 @@ src/modes/ctr/ctr_getiv.o src/modes/ctr/ctr_setiv.o src/modes/ctr/ctr_start.o \ src/modes/ecb/ecb_decrypt.o src/modes/ecb/ecb_done.o src/modes/ecb/ecb_encrypt.o \ src/modes/ecb/ecb_start.o src/modes/ofb/ofb_decrypt.o src/modes/ofb/ofb_done.o \ src/modes/ofb/ofb_encrypt.o src/modes/ofb/ofb_getiv.o src/modes/ofb/ofb_setiv.o \ -src/modes/ofb/ofb_start.o src/pk/asn1/der/der_decode_integer.o src/pk/asn1/der/der_encode_integer.o \ -src/pk/asn1/der/der_get_multi_integer.o src/pk/asn1/der/der_length_integer.o \ -src/pk/asn1/der/der_put_multi_integer.o src/pk/dh/dh.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o \ -src/pk/dsa/dsa_import.o src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_sign_hash.o \ +src/modes/ofb/ofb_start.o src/pk/asn1/der/bit/der_decode_bit_string.o \ +src/pk/asn1/der/bit/der_encode_bit_string.o src/pk/asn1/der/bit/der_length_bit_string.o \ +src/pk/asn1/der/ia5/der_decode_ia5_string.o src/pk/asn1/der/ia5/der_encode_ia5_string.o \ +src/pk/asn1/der/ia5/der_length_ia5_string.o src/pk/asn1/der/integer/der_decode_integer.o \ +src/pk/asn1/der/integer/der_encode_integer.o src/pk/asn1/der/integer/der_length_integer.o \ +src/pk/asn1/der/object_identifier/der_decode_object_identifier.o \ +src/pk/asn1/der/object_identifier/der_encode_object_identifier.o \ +src/pk/asn1/der/object_identifier/der_length_object_identifier.o \ +src/pk/asn1/der/octet/der_decode_octet_string.o src/pk/asn1/der/octet/der_encode_octet_string.o \ +src/pk/asn1/der/octet/der_length_octet_string.o \ +src/pk/asn1/der/printable_string/der_decode_printable_string.o \ +src/pk/asn1/der/printable_string/der_encode_printable_string.o \ +src/pk/asn1/der/printable_string/der_length_printable_string.o \ +src/pk/asn1/der/sequence/der_decode_sequence.o src/pk/asn1/der/sequence/der_decode_sequence_multi.o \ +src/pk/asn1/der/sequence/der_encode_sequence.o src/pk/asn1/der/sequence/der_encode_sequence_multi.o \ +src/pk/asn1/der/sequence/der_length_sequence.o \ +src/pk/asn1/der/short_integer/der_decode_short_integer.o \ +src/pk/asn1/der/short_integer/der_encode_short_integer.o \ +src/pk/asn1/der/short_integer/der_length_short_integer.o src/pk/dh/dh.o src/pk/dsa/dsa_export.o \ +src/pk/dsa/dsa_free.o src/pk/dsa/dsa_import.o src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_sign_hash.o \ src/pk/dsa/dsa_verify_hash.o src/pk/dsa/dsa_verify_key.o src/pk/ecc/ecc.o src/pk/packet_store_header.o \ src/pk/packet_valid_header.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o \ src/pk/pkcs1/pkcs_1_oaep_decode.o src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o \ -src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/pkcs1/pkcs_1_v15_es_decode.o \ -src/pk/pkcs1/pkcs_1_v15_es_encode.o src/pk/pkcs1/pkcs_1_v15_sa_decode.o \ -src/pk/pkcs1/pkcs_1_v15_sa_encode.o src/pk/rsa/rsa_decrypt_key.o src/pk/rsa/rsa_encrypt_key.o \ -src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_free.o src/pk/rsa/rsa_import.o \ -src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_sign_hash.o src/pk/rsa/rsa_v15_decrypt_key.o \ -src/pk/rsa/rsa_v15_encrypt_key.o src/pk/rsa/rsa_v15_sign_hash.o src/pk/rsa/rsa_v15_verify_hash.o \ +src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/rsa/rsa_decrypt_key.o \ +src/pk/rsa/rsa_encrypt_key.o src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_free.o \ +src/pk/rsa/rsa_import.o src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_sign_hash.o \ src/pk/rsa/rsa_verify_hash.o src/prngs/fortuna.o src/prngs/rc4.o src/prngs/rng_get_bytes.o \ src/prngs/rng_make_prng.o src/prngs/sober128.o src/prngs/sprng.o src/prngs/yarrow.o -HEADERS=src/headers/tommath_superclass.h src/headers/tomcrypt_cfg.h \ -src/headers/tomcrypt_mac.h src/headers/tomcrypt_macros.h \ -src/headers/tomcrypt_custom.h src/headers/tomcrypt_argchk.h \ -src/headers/tomcrypt_cipher.h src/headers/tomcrypt_pk.h \ -src/headers/tommath_class.h src/headers/ltc_tommath.h src/headers/tomcrypt_hash.h \ -src/headers/tomcrypt_misc.h src/headers/tomcrypt.h src/headers/tomcrypt_pkcs.h \ -src/headers/tomcrypt_prng.h testprof/tomcrypt_test.h +HEADERS=src/headers/tommath_superclass.h src/headers/tomcrypt_cfg.h src/headers/tomcrypt_mac.h \ +src/headers/tomcrypt_macros.h src/headers/tomcrypt_custom.h src/headers/tomcrypt_argchk.h \ +src/headers/tomcrypt_cipher.h src/headers/tomcrypt_pk.h src/headers/tommath_class.h \ +src/headers/ltc_tommath.h src/headers/tomcrypt_hash.h src/headers/tomcrypt_misc.h \ +src/headers/tomcrypt.h src/headers/tomcrypt_pkcs.h src/headers/tomcrypt_prng.h testprof/tomcrypt_test.h TESTOBJECTS=demos/test.o HASHOBJECTS=demos/hashsum.o @@ -164,7 +189,7 @@ src/hashes/sha2/sha512.o: src/hashes/sha2/sha512.c src/hashes/sha2/sha384.c src/hashes/sha2/sha256.o: src/hashes/sha2/sha256.c src/hashes/sha2/sha224.c #This rule makes the libtomcrypt library. -library: $(LIBTEST) $(LIBNAME) +library: $(LIBNAME) $(LIBTEST): cd testprof ; CFLAGS="$(CFLAGS)" GROUP=$(GROUP) USER=$(USER) VERSION=$(VERSION) LIBPATH=$(LIBPATH) LIBNAME=$(LIBTEST) make -f makefile.shared @@ -180,19 +205,22 @@ $(LIBNAME): $(OBJECTS) #This rule makes the hash program included with libtomcrypt hashsum: library gcc $(CFLAGS) demos/hashsum.c -o hashsum.o - gcc -o hashsum hashsum.o -ltomcrypt_prof -ltomcrypt $(MPISHARED) + gcc -o hashsum hashsum.o -ltomcrypt $(MPISHARED) #makes the crypt program crypt: library gcc $(CFLAGS) demos/encrypt.c -o encrypt.o - gcc -o crypt encrypt.o -ltomcrypt_prof -ltomcrypt $(MPISHARED) + gcc -o crypt encrypt.o -ltomcrypt $(MPISHARED) tv_gen: library $(TVS) - gcc -o tv_gen $(TVS) -ltomcrypt_prof -ltomcrypt $(MPISHARED) + gcc -o tv_gen $(TVS) -ltomcrypt $(MPISHARED) -test: library $(TESTS) +test: library $(LIBTEST) $(TESTS) gcc -o $(TEST) $(TESTS) -ltomcrypt_prof -ltomcrypt $(MPISHARED) -timing: library $(TIMINGS) +timing: library $(LIBTEST) $(TIMINGS) gcc -o $(TIMING) $(TIMINGS) -ltomcrypt_prof -ltomcrypt $(MPISHARED) +# $Source: /cvs/libtom/libtomcrypt/makefile.shared,v $ +# $Revision: 1.16 $ +# $Date: 2005/06/08 23:37:40 $ diff --git a/mess.sh b/mess.sh new file mode 100644 index 00000000..bf639ce3 --- /dev/null +++ b/mess.sh @@ -0,0 +1,4 @@ +#!/bin/bash +if cvs log $1 >/dev/null 2>/dev/null; then exit 0; else echo "$1 shouldn't be here" ; exit 1; fi + + diff --git a/notes/etc/saferp_optimizer.c b/notes/etc/saferp_optimizer.c index 664661ad..feb58bc9 100644 --- a/notes/etc/saferp_optimizer.c +++ b/notes/etc/saferp_optimizer.c @@ -171,3 +171,7 @@ printf(" }\n}\n\n"); return 0; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/notes/etc/whirlgen.c b/notes/etc/whirlgen.c index 2880d3f5..f64650ba 100644 --- a/notes/etc/whirlgen.c +++ b/notes/etc/whirlgen.c @@ -89,3 +89,7 @@ int main(void) } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/notes/etc/whirltest.c b/notes/etc/whirltest.c index 9184f770..cf2e87cd 100644 --- a/notes/etc/whirltest.c +++ b/notes/etc/whirltest.c @@ -13,3 +13,7 @@ int main(void) } } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/notes/tech0005.txt b/notes/tech0005.txt new file mode 100644 index 00000000..8f393d50 --- /dev/null +++ b/notes/tech0005.txt @@ -0,0 +1,18 @@ +Tech Note 0005 +Minimizing Code Space +Tom St Denis + +Introduction +------------ + +Tweaking... + +You can disable whole classes of algorithms on the command line with the LTC_NO_* defines. From there you can manually turn on what you want to enable. + +The following build with GCC 3.4.3 on an AMD64 box gets you AES, CTR mode, SHA-256, HMAC, Yarrow, full RSA PKCS #1, PKCS #5, ASN.1 DER and MPI in +roughly 80KB of code. + +CFLAGS="-DSC_RSA_1 -DLTC_NO_CIPHERS -DLTC_NO_HASHES -DLTC_NO_PRNGS -DLTC_NO_MACS -DLTC_NO_MODES -DLTC_NO_PK -DRIJNDAEL -DCTR -DSHA256 \ +-DHMAC -DYARROW -DMRSA -DMPI -Os -fomit-frame-pointer" make IGNORE_SPEED=1 + +Neato eh? diff --git a/parsenames.pl b/parsenames.pl index d6466c5b..761f0362 100644 --- a/parsenames.pl +++ b/parsenames.pl @@ -20,3 +20,7 @@ foreach my $obj (@a) { if ($ARGV[0] eq "HEADERS") { print "testprof/tomcrypt_test.h"; } print "\n\n"; + +# $Source: /cvs/libtom/libtomcrypt/parsenames.pl,v $ +# $Revision: 1.3 $ +# $Date: 2005/05/05 14:49:27 $ diff --git a/run.sh b/run.sh new file mode 100644 index 00000000..b652110f --- /dev/null +++ b/run.sh @@ -0,0 +1,35 @@ +#!/bin/bash +bash build.sh " $1" "$2 -O2" "$3 IGNORE_SPEED=1" +if [ -a testok.txt ] && [ -f testok.txt ]; then + echo +else + echo + echo "Test failed" + exit 1 +fi + +rm -f testok.txt +bash build.sh " $1" "$2 -Os" " $3 IGNORE_SPEED=1 LTC_SMALL=1" +if [ -a testok.txt ] && [ -f testok.txt ]; then + echo +else + echo + echo "Test failed" + exit 1 +fi + +rm -f testok.txt +bash build.sh " $1" " $2" " $3" +if [ -a testok.txt ] && [ -f testok.txt ]; then + echo +else + echo + echo "Test failed" + exit 1 +fi + +exit 0 + +# $Source: /cvs/libtom/libtomcrypt/run.sh,v $ +# $Revision: 1.13 $ +# $Date: 2005/05/11 18:59:53 $ diff --git a/src/ciphers/aes/aes.c b/src/ciphers/aes/aes.c index e698efd7..584cd1ee 100644 --- a/src/ciphers/aes/aes.c +++ b/src/ciphers/aes/aes.c @@ -127,7 +127,7 @@ int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *s #endif LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); - + if (keylen != 16 && keylen != 24 && keylen != 32) { return CRYPT_INVALID_KEYSIZE; } @@ -747,3 +747,7 @@ int ECB_KS(int *keysize) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/aes/aes_tab.c b/src/ciphers/aes/aes_tab.c index 0ad1dfe0..ee639d89 100644 --- a/src/ciphers/aes/aes_tab.c +++ b/src/ciphers/aes/aes_tab.c @@ -1018,3 +1018,7 @@ static const ulong32 rcon[] = { 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, 0x1B000000UL, 0x36000000UL, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/anubis.c b/src/ciphers/anubis.c index 7e2af60b..84f7ae13 100644 --- a/src/ciphers/anubis.c +++ b/src/ciphers/anubis.c @@ -1548,3 +1548,7 @@ int anubis_keysize(int *keysize) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/blowfish.c b/src/ciphers/blowfish.c index 2f0385d4..44189b29 100644 --- a/src/ciphers/blowfish.c +++ b/src/ciphers/blowfish.c @@ -581,3 +581,7 @@ int blowfish_keysize(int *keysize) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/cast5.c b/src/ciphers/cast5.c index 2b8e4a56..654b6ef7 100644 --- a/src/ciphers/cast5.c +++ b/src/ciphers/cast5.c @@ -709,3 +709,7 @@ int cast5_keysize(int *keysize) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/des.c b/src/ciphers/des.c index d42c5faa..4d3629b7 100644 --- a/src/ciphers/des.c +++ b/src/ciphers/des.c @@ -1888,3 +1888,7 @@ int des3_keysize(int *keysize) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/khazad.c b/src/ciphers/khazad.c index 46269237..d8e69021 100644 --- a/src/ciphers/khazad.c +++ b/src/ciphers/khazad.c @@ -845,3 +845,7 @@ int khazad_keysize(int *keysize) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/noekeon.c b/src/ciphers/noekeon.c index 194cdbe6..0a54a22b 100644 --- a/src/ciphers/noekeon.c +++ b/src/ciphers/noekeon.c @@ -290,3 +290,7 @@ int noekeon_keysize(int *keysize) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/rc2.c b/src/ciphers/rc2.c index 6382941b..47b7276e 100644 --- a/src/ciphers/rc2.c +++ b/src/ciphers/rc2.c @@ -348,3 +348,7 @@ int rc2_keysize(int *keysize) + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/rc5.c b/src/ciphers/rc5.c index 32f666fe..070ff5a3 100644 --- a/src/ciphers/rc5.c +++ b/src/ciphers/rc5.c @@ -308,3 +308,7 @@ int rc5_keysize(int *keysize) + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/rc6.c b/src/ciphers/rc6.c index 996c0153..7a4558e7 100644 --- a/src/ciphers/rc6.c +++ b/src/ciphers/rc6.c @@ -337,3 +337,7 @@ int rc6_keysize(int *keysize) #endif /*RC6*/ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/safer/safer.c b/src/ciphers/safer/safer.c index e6e073ad..6c276792 100644 --- a/src/ciphers/safer/safer.c +++ b/src/ciphers/safer/safer.c @@ -481,3 +481,7 @@ int safer_sk128_test(void) + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/safer/safer_tab.c b/src/ciphers/safer/safer_tab.c index f63ba6cf..6c9abe9b 100644 --- a/src/ciphers/safer/safer_tab.c +++ b/src/ciphers/safer/safer_tab.c @@ -62,3 +62,7 @@ const unsigned char safer_lbox[256] = { #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/safer/saferp.c b/src/ciphers/safer/saferp.c index 17112f43..84747841 100644 --- a/src/ciphers/safer/saferp.c +++ b/src/ciphers/safer/saferp.c @@ -549,3 +549,7 @@ int saferp_keysize(int *keysize) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/skipjack.c b/src/ciphers/skipjack.c index e2431afb..7635042a 100644 --- a/src/ciphers/skipjack.c +++ b/src/ciphers/skipjack.c @@ -329,3 +329,7 @@ int skipjack_keysize(int *keysize) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/twofish/twofish.c b/src/ciphers/twofish/twofish.c index 7dbe9b75..bd71d035 100644 --- a/src/ciphers/twofish/twofish.c +++ b/src/ciphers/twofish/twofish.c @@ -576,7 +576,7 @@ void twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_k b = RORc(b ^ (t2 + t1 + k[3]), 1); t2 = g1_func(b, skey); - t1 = g_func(a, key) + t2; + t1 = g_func(a, skey) + t2; c = ROLc(c, 1) ^ (t1 + k[0]); d = RORc(d ^ (t2 + t1 + k[1]), 1); k -= 4; @@ -700,3 +700,7 @@ int twofish_keysize(int *keysize) + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/twofish/twofish_tab.c b/src/ciphers/twofish/twofish_tab.c index 0bffade7..b3d0272a 100644 --- a/src/ciphers/twofish/twofish_tab.c +++ b/src/ciphers/twofish/twofish_tab.c @@ -490,3 +490,7 @@ static const ulong32 rs_tab7[256] = { #endif /* TWOFISH_ALL_TABLES */ #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/ciphers/xtea.c b/src/ciphers/xtea.c index 98546df8..2712f874 100644 --- a/src/ciphers/xtea.c +++ b/src/ciphers/xtea.c @@ -201,3 +201,7 @@ int xtea_keysize(int *keysize) + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/ccm/ccm_memory.c b/src/encauth/ccm/ccm_memory.c index 34a254d9..abca36a9 100644 --- a/src/encauth/ccm/ccm_memory.c +++ b/src/encauth/ccm/ccm_memory.c @@ -293,7 +293,6 @@ int ccm_memory(int cipher, #ifdef LTC_CLEAN_STACK zeromem(skey, sizeof(*skey)); - zeromem(B, sizeof(B)); zeromem(PAD, sizeof(PAD)); zeromem(CTRPAD, sizeof(CTRPAD)); #endif @@ -304,3 +303,7 @@ int ccm_memory(int cipher, } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/ccm/ccm_test.c b/src/encauth/ccm/ccm_test.c index ee78523c..fb8e9a19 100644 --- a/src/encauth/ccm/ccm_test.c +++ b/src/encauth/ccm/ccm_test.c @@ -168,3 +168,7 @@ int ccm_test(void) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/eax/eax_addheader.c b/src/encauth/eax/eax_addheader.c index 30040252..8323258a 100644 --- a/src/encauth/eax/eax_addheader.c +++ b/src/encauth/eax/eax_addheader.c @@ -32,3 +32,7 @@ int eax_addheader(eax_state *eax, const unsigned char *header, } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/eax/eax_decrypt.c b/src/encauth/eax/eax_decrypt.c index 8711d2d1..c7af001e 100644 --- a/src/encauth/eax/eax_decrypt.c +++ b/src/encauth/eax/eax_decrypt.c @@ -44,3 +44,7 @@ int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/eax/eax_decrypt_verify_memory.c b/src/encauth/eax/eax_decrypt_verify_memory.c index 3fcab46b..34fba822 100644 --- a/src/encauth/eax/eax_decrypt_verify_memory.c +++ b/src/encauth/eax/eax_decrypt_verify_memory.c @@ -102,3 +102,7 @@ LBL_ERR: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/eax/eax_done.c b/src/encauth/eax/eax_done.c index 1d436517..50b0957f 100644 --- a/src/encauth/eax/eax_done.c +++ b/src/encauth/eax/eax_done.c @@ -88,3 +88,7 @@ LBL_ERR: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/eax/eax_encrypt.c b/src/encauth/eax/eax_encrypt.c index da23a8ce..19014e3b 100644 --- a/src/encauth/eax/eax_encrypt.c +++ b/src/encauth/eax/eax_encrypt.c @@ -45,3 +45,7 @@ int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/eax/eax_encrypt_authenticate_memory.c b/src/encauth/eax/eax_encrypt_authenticate_memory.c index 8a601cf8..67c1ee28 100644 --- a/src/encauth/eax/eax_encrypt_authenticate_memory.c +++ b/src/encauth/eax/eax_encrypt_authenticate_memory.c @@ -76,3 +76,7 @@ LBL_ERR: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/eax/eax_init.c b/src/encauth/eax/eax_init.c index 5a20db04..517f2397 100644 --- a/src/encauth/eax/eax_init.c +++ b/src/encauth/eax/eax_init.c @@ -108,11 +108,9 @@ int eax_init(eax_state *eax, int cipher, /* 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) { + if ((err = ctr_start(cipher, eax->N, key, keylen, 0, CTR_COUNTER_BIG_ENDIAN, &eax->ctr)) != CRYPT_OK) { goto LBL_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) { @@ -140,3 +138,7 @@ LBL_ERR: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/eax/eax_test.c b/src/encauth/eax/eax_test.c index 777dea1a..879d43e8 100644 --- a/src/encauth/eax/eax_test.c +++ b/src/encauth/eax/eax_test.c @@ -276,3 +276,7 @@ int eax_test(void) } #endif /* EAX_MODE */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/gcm/gcm_add_aad.c b/src/encauth/gcm/gcm_add_aad.c index cdcc0d90..585dd87d 100644 --- a/src/encauth/gcm/gcm_add_aad.c +++ b/src/encauth/gcm/gcm_add_aad.c @@ -27,8 +27,11 @@ int gcm_add_aad(gcm_state *gcm, const unsigned char *adata, unsigned long adatalen) { - unsigned long x, y; + unsigned long x; int err; +#ifdef LTC_FAST + unsigned long y; +#endif LTC_ARGCHK(gcm != NULL); if (adatalen > 0) { @@ -115,3 +118,7 @@ int gcm_add_aad(gcm_state *gcm, } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/gcm/gcm_add_iv.c b/src/encauth/gcm/gcm_add_iv.c index 7faf4c02..7b7633f1 100644 --- a/src/encauth/gcm/gcm_add_iv.c +++ b/src/encauth/gcm/gcm_add_iv.c @@ -88,3 +88,7 @@ int gcm_add_iv(gcm_state *gcm, #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/gcm/gcm_done.c b/src/encauth/gcm/gcm_done.c index 8b3a6ddd..c0656f5c 100644 --- a/src/encauth/gcm/gcm_done.c +++ b/src/encauth/gcm/gcm_done.c @@ -75,3 +75,7 @@ int gcm_done(gcm_state *gcm, #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/gcm/gcm_gf_mult.c b/src/encauth/gcm/gcm_gf_mult.c index a870c910..f48e6643 100644 --- a/src/encauth/gcm/gcm_gf_mult.c +++ b/src/encauth/gcm/gcm_gf_mult.c @@ -31,6 +31,7 @@ static void gcm_rightshift(unsigned char *a) static const unsigned char mask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; static const unsigned char poly[] = { 0x00, 0xE1 }; + /** GCM GF multiplier (internal use only) @param a First value @@ -87,3 +88,7 @@ void gcm_mult_h(gcm_state *gcm, unsigned char *I) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/gcm/gcm_init.c b/src/encauth/gcm/gcm_init.c index 35a5ab8f..417532fd 100644 --- a/src/encauth/gcm/gcm_init.c +++ b/src/encauth/gcm/gcm_init.c @@ -17,6 +17,46 @@ #ifdef GCM_MODE +#ifdef GCM_TABLES + +/* this is x*2^128 mod p(x) ... the results are 16 bytes each stored in a packed format. Since only the + * lower 16 bits are not zero'ed I removed the upper 14 bytes */ +static const unsigned char gcm_shift_table[256*2] = { +0x00, 0x00, 0x01, 0xc2, 0x03, 0x84, 0x02, 0x46, 0x07, 0x08, 0x06, 0xca, 0x04, 0x8c, 0x05, 0x4e, +0x0e, 0x10, 0x0f, 0xd2, 0x0d, 0x94, 0x0c, 0x56, 0x09, 0x18, 0x08, 0xda, 0x0a, 0x9c, 0x0b, 0x5e, +0x1c, 0x20, 0x1d, 0xe2, 0x1f, 0xa4, 0x1e, 0x66, 0x1b, 0x28, 0x1a, 0xea, 0x18, 0xac, 0x19, 0x6e, +0x12, 0x30, 0x13, 0xf2, 0x11, 0xb4, 0x10, 0x76, 0x15, 0x38, 0x14, 0xfa, 0x16, 0xbc, 0x17, 0x7e, +0x38, 0x40, 0x39, 0x82, 0x3b, 0xc4, 0x3a, 0x06, 0x3f, 0x48, 0x3e, 0x8a, 0x3c, 0xcc, 0x3d, 0x0e, +0x36, 0x50, 0x37, 0x92, 0x35, 0xd4, 0x34, 0x16, 0x31, 0x58, 0x30, 0x9a, 0x32, 0xdc, 0x33, 0x1e, +0x24, 0x60, 0x25, 0xa2, 0x27, 0xe4, 0x26, 0x26, 0x23, 0x68, 0x22, 0xaa, 0x20, 0xec, 0x21, 0x2e, +0x2a, 0x70, 0x2b, 0xb2, 0x29, 0xf4, 0x28, 0x36, 0x2d, 0x78, 0x2c, 0xba, 0x2e, 0xfc, 0x2f, 0x3e, +0x70, 0x80, 0x71, 0x42, 0x73, 0x04, 0x72, 0xc6, 0x77, 0x88, 0x76, 0x4a, 0x74, 0x0c, 0x75, 0xce, +0x7e, 0x90, 0x7f, 0x52, 0x7d, 0x14, 0x7c, 0xd6, 0x79, 0x98, 0x78, 0x5a, 0x7a, 0x1c, 0x7b, 0xde, +0x6c, 0xa0, 0x6d, 0x62, 0x6f, 0x24, 0x6e, 0xe6, 0x6b, 0xa8, 0x6a, 0x6a, 0x68, 0x2c, 0x69, 0xee, +0x62, 0xb0, 0x63, 0x72, 0x61, 0x34, 0x60, 0xf6, 0x65, 0xb8, 0x64, 0x7a, 0x66, 0x3c, 0x67, 0xfe, +0x48, 0xc0, 0x49, 0x02, 0x4b, 0x44, 0x4a, 0x86, 0x4f, 0xc8, 0x4e, 0x0a, 0x4c, 0x4c, 0x4d, 0x8e, +0x46, 0xd0, 0x47, 0x12, 0x45, 0x54, 0x44, 0x96, 0x41, 0xd8, 0x40, 0x1a, 0x42, 0x5c, 0x43, 0x9e, +0x54, 0xe0, 0x55, 0x22, 0x57, 0x64, 0x56, 0xa6, 0x53, 0xe8, 0x52, 0x2a, 0x50, 0x6c, 0x51, 0xae, +0x5a, 0xf0, 0x5b, 0x32, 0x59, 0x74, 0x58, 0xb6, 0x5d, 0xf8, 0x5c, 0x3a, 0x5e, 0x7c, 0x5f, 0xbe, +0xe1, 0x00, 0xe0, 0xc2, 0xe2, 0x84, 0xe3, 0x46, 0xe6, 0x08, 0xe7, 0xca, 0xe5, 0x8c, 0xe4, 0x4e, +0xef, 0x10, 0xee, 0xd2, 0xec, 0x94, 0xed, 0x56, 0xe8, 0x18, 0xe9, 0xda, 0xeb, 0x9c, 0xea, 0x5e, +0xfd, 0x20, 0xfc, 0xe2, 0xfe, 0xa4, 0xff, 0x66, 0xfa, 0x28, 0xfb, 0xea, 0xf9, 0xac, 0xf8, 0x6e, +0xf3, 0x30, 0xf2, 0xf2, 0xf0, 0xb4, 0xf1, 0x76, 0xf4, 0x38, 0xf5, 0xfa, 0xf7, 0xbc, 0xf6, 0x7e, +0xd9, 0x40, 0xd8, 0x82, 0xda, 0xc4, 0xdb, 0x06, 0xde, 0x48, 0xdf, 0x8a, 0xdd, 0xcc, 0xdc, 0x0e, +0xd7, 0x50, 0xd6, 0x92, 0xd4, 0xd4, 0xd5, 0x16, 0xd0, 0x58, 0xd1, 0x9a, 0xd3, 0xdc, 0xd2, 0x1e, +0xc5, 0x60, 0xc4, 0xa2, 0xc6, 0xe4, 0xc7, 0x26, 0xc2, 0x68, 0xc3, 0xaa, 0xc1, 0xec, 0xc0, 0x2e, +0xcb, 0x70, 0xca, 0xb2, 0xc8, 0xf4, 0xc9, 0x36, 0xcc, 0x78, 0xcd, 0xba, 0xcf, 0xfc, 0xce, 0x3e, +0x91, 0x80, 0x90, 0x42, 0x92, 0x04, 0x93, 0xc6, 0x96, 0x88, 0x97, 0x4a, 0x95, 0x0c, 0x94, 0xce, +0x9f, 0x90, 0x9e, 0x52, 0x9c, 0x14, 0x9d, 0xd6, 0x98, 0x98, 0x99, 0x5a, 0x9b, 0x1c, 0x9a, 0xde, +0x8d, 0xa0, 0x8c, 0x62, 0x8e, 0x24, 0x8f, 0xe6, 0x8a, 0xa8, 0x8b, 0x6a, 0x89, 0x2c, 0x88, 0xee, +0x83, 0xb0, 0x82, 0x72, 0x80, 0x34, 0x81, 0xf6, 0x84, 0xb8, 0x85, 0x7a, 0x87, 0x3c, 0x86, 0xfe, +0xa9, 0xc0, 0xa8, 0x02, 0xaa, 0x44, 0xab, 0x86, 0xae, 0xc8, 0xaf, 0x0a, 0xad, 0x4c, 0xac, 0x8e, +0xa7, 0xd0, 0xa6, 0x12, 0xa4, 0x54, 0xa5, 0x96, 0xa0, 0xd8, 0xa1, 0x1a, 0xa3, 0x5c, 0xa2, 0x9e, +0xb5, 0xe0, 0xb4, 0x22, 0xb6, 0x64, 0xb7, 0xa6, 0xb2, 0xe8, 0xb3, 0x2a, 0xb1, 0x6c, 0xb0, 0xae, +0xbb, 0xf0, 0xba, 0x32, 0xb8, 0x74, 0xb9, 0xb6, 0xbc, 0xf8, 0xbd, 0x3a, 0xbf, 0x7c, 0xbe, 0xbe }; + +#endif + /** Initialize a GCM state @param gcm The GCM state to initialize @@ -31,7 +71,7 @@ int gcm_init(gcm_state *gcm, int cipher, int err; unsigned char B[16]; #ifdef GCM_TABLES - int x, y; + int x, y, z, t; #endif LTC_ARGCHK(gcm != NULL); @@ -72,17 +112,34 @@ int gcm_init(gcm_state *gcm, int cipher, #ifdef GCM_TABLES /* setup tables */ + + /* generate the first table as it has no shifting (from which we make the other tables) */ zeromem(B, 16); - for (x = 0; x < 16; x++) { - for (y = 0; y < 256; y++) { - B[x] = y; - gcm_gf_mult(gcm->H, B, &gcm->PC[x][y][0]); - } - B[x] = 0; + for (y = 0; y < 256; y++) { + B[0] = y; + gcm_gf_mult(gcm->H, B, &gcm->PC[0][y][0]); } + + /* now generate the rest of the tables based the previous table */ + for (x = 1; x < 16; x++) { + for (y = 0; y < 256; y++) { + /* now shift it right by 8 bits */ + t = gcm->PC[x-1][y][15]; + for (z = 15; z > 0; z--) { + gcm->PC[x][y][z] = gcm->PC[x-1][y][z-1]; + } + gcm->PC[x][y][0] = gcm_shift_table[t<<1]; + gcm->PC[x][y][1] ^= gcm_shift_table[(t<<1)+1]; + } + } + #endif return CRYPT_OK; } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/gcm/gcm_memory.c b/src/encauth/gcm/gcm_memory.c index e062413d..47b72066 100644 --- a/src/encauth/gcm/gcm_memory.c +++ b/src/encauth/gcm/gcm_memory.c @@ -87,3 +87,7 @@ LTC_ERR: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/gcm/gcm_process.c b/src/encauth/gcm/gcm_process.c index 577967bb..a24eefbe 100644 --- a/src/encauth/gcm/gcm_process.c +++ b/src/encauth/gcm/gcm_process.c @@ -141,3 +141,7 @@ int gcm_process(gcm_state *gcm, #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/gcm/gcm_reset.c b/src/encauth/gcm/gcm_reset.c index e73bf66c..affdc1b2 100644 --- a/src/encauth/gcm/gcm_reset.c +++ b/src/encauth/gcm/gcm_reset.c @@ -38,3 +38,7 @@ int gcm_reset(gcm_state *gcm) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/gcm/gcm_test.c b/src/encauth/gcm/gcm_test.c index bc6ad7e3..3e45705d 100644 --- a/src/encauth/gcm/gcm_test.c +++ b/src/encauth/gcm/gcm_test.c @@ -281,7 +281,6 @@ int gcm_test(void) }; int idx, err; unsigned long x, y; - gcm_state gcm; unsigned char out[2][64], T[2][16]; /* find aes */ @@ -363,3 +362,7 @@ int gcm_test(void) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/ocb/ocb_decrypt.c b/src/encauth/ocb/ocb_decrypt.c index d3bf4802..9551aa7d 100644 --- a/src/encauth/ocb/ocb_decrypt.c +++ b/src/encauth/ocb/ocb_decrypt.c @@ -71,3 +71,7 @@ int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/ocb/ocb_decrypt_verify_memory.c b/src/encauth/ocb/ocb_decrypt_verify_memory.c index 378a8af4..d33550ab 100644 --- a/src/encauth/ocb/ocb_decrypt_verify_memory.c +++ b/src/encauth/ocb/ocb_decrypt_verify_memory.c @@ -80,3 +80,7 @@ LBL_ERR: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/ocb/ocb_done_decrypt.c b/src/encauth/ocb/ocb_done_decrypt.c index 9f8b1b9f..a28909c1 100644 --- a/src/encauth/ocb/ocb_done_decrypt.c +++ b/src/encauth/ocb/ocb_done_decrypt.c @@ -74,3 +74,7 @@ LBL_ERR: #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/ocb/ocb_done_encrypt.c b/src/encauth/ocb/ocb_done_encrypt.c index 1a075691..10062fe6 100644 --- a/src/encauth/ocb/ocb_done_encrypt.c +++ b/src/encauth/ocb/ocb_done_encrypt.c @@ -40,3 +40,7 @@ int ocb_done_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned long ptle #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/ocb/ocb_encrypt.c b/src/encauth/ocb/ocb_encrypt.c index ba39c60f..a3356c6f 100644 --- a/src/encauth/ocb/ocb_encrypt.c +++ b/src/encauth/ocb/ocb_encrypt.c @@ -64,3 +64,7 @@ int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/ocb/ocb_encrypt_authenticate_memory.c b/src/encauth/ocb/ocb_encrypt_authenticate_memory.c index bcc9cfbc..e963267d 100644 --- a/src/encauth/ocb/ocb_encrypt_authenticate_memory.c +++ b/src/encauth/ocb/ocb_encrypt_authenticate_memory.c @@ -78,3 +78,7 @@ LBL_ERR: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/ocb/ocb_init.c b/src/encauth/ocb/ocb_init.c index 57e04afc..84f113a1 100644 --- a/src/encauth/ocb/ocb_init.c +++ b/src/encauth/ocb/ocb_init.c @@ -127,3 +127,7 @@ int ocb_init(ocb_state *ocb, int cipher, } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/ocb/ocb_ntz.c b/src/encauth/ocb/ocb_ntz.c index 4ffe7e8a..3862579b 100644 --- a/src/encauth/ocb/ocb_ntz.c +++ b/src/encauth/ocb/ocb_ntz.c @@ -36,3 +36,7 @@ int ocb_ntz(unsigned long x) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/ocb/ocb_shift_xor.c b/src/encauth/ocb/ocb_shift_xor.c index b63b0227..2b9364be 100644 --- a/src/encauth/ocb/ocb_shift_xor.c +++ b/src/encauth/ocb/ocb_shift_xor.c @@ -33,3 +33,7 @@ void ocb_shift_xor(ocb_state *ocb, unsigned char *Z) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/ocb/ocb_test.c b/src/encauth/ocb/ocb_test.c index d6cb14b4..a6ac51b3 100644 --- a/src/encauth/ocb/ocb_test.c +++ b/src/encauth/ocb/ocb_test.c @@ -231,3 +231,7 @@ int ocb_test(void) -- hard to stream [you can't emit ciphertext until full block] -- The setup is somewhat complicated... */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/encauth/ocb/s_ocb_done.c b/src/encauth/ocb/s_ocb_done.c index 6f6e63dd..4a0d5bef 100644 --- a/src/encauth/ocb/s_ocb_done.c +++ b/src/encauth/ocb/s_ocb_done.c @@ -138,3 +138,7 @@ int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/chc/chc.c b/src/hashes/chc/chc.c index 67dd0902..cb7fde43 100644 --- a/src/hashes/chc/chc.c +++ b/src/hashes/chc/chc.c @@ -291,3 +291,7 @@ int chc_test(void) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/helper/hash_file.c b/src/hashes/helper/hash_file.c index 78c290a3..8354d8df 100644 --- a/src/hashes/helper/hash_file.c +++ b/src/hashes/helper/hash_file.c @@ -51,3 +51,7 @@ int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *ou #endif } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/helper/hash_filehandle.c b/src/hashes/helper/hash_filehandle.c index c02c5a78..db850634 100644 --- a/src/hashes/helper/hash_filehandle.c +++ b/src/hashes/helper/hash_filehandle.c @@ -64,3 +64,7 @@ int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outle #endif } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/helper/hash_memory.c b/src/hashes/helper/hash_memory.c index 9786948f..37eaf19c 100644 --- a/src/hashes/helper/hash_memory.c +++ b/src/hashes/helper/hash_memory.c @@ -62,3 +62,7 @@ LBL_ERR: return err; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/helper/hash_memory_multi.c b/src/hashes/helper/hash_memory_multi.c index ce22283f..bd23d610 100644 --- a/src/hashes/helper/hash_memory_multi.c +++ b/src/hashes/helper/hash_memory_multi.c @@ -80,3 +80,7 @@ LBL_ERR: va_end(args); return err; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/md2.c b/src/hashes/md2.c index 5381771f..82640b6d 100644 --- a/src/hashes/md2.c +++ b/src/hashes/md2.c @@ -24,11 +24,9 @@ const struct ltc_hash_descriptor md2_desc = 16, 16, - /* DER encoding */ - { 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x02, 0x05, 0x00, - 0x04, 0x10 }, - 18, + /* OID */ + { 1, 2, 840, 113549, 2, 2, }, + 6, &md2_init, &md2_process, @@ -246,3 +244,7 @@ int md2_test(void) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/md4.c b/src/hashes/md4.c index 477f5b08..790729a8 100644 --- a/src/hashes/md4.c +++ b/src/hashes/md4.c @@ -24,9 +24,9 @@ const struct ltc_hash_descriptor md4_desc = 16, 64, - /* DER encoding (not yet supported) */ - { 0x00 }, - 0, + /* OID */ + { 1, 2, 840, 113549, 2, 4, }, + 6, &md4_init, &md4_process, @@ -300,3 +300,7 @@ int md4_test(void) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/md5.c b/src/hashes/md5.c index e2e5c741..65950765 100644 --- a/src/hashes/md5.c +++ b/src/hashes/md5.c @@ -25,11 +25,9 @@ const struct ltc_hash_descriptor md5_desc = 16, 64, - /* DER identifier */ - { 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, - 0x04, 0x10 }, - 18, + /* OID */ + { 1, 2, 840, 113549, 2, 5, }, + 6, &md5_init, &md5_process, @@ -363,3 +361,7 @@ int md5_test(void) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/rmd128.c b/src/hashes/rmd128.c index 1c304a1c..d4f90e27 100644 --- a/src/hashes/rmd128.c +++ b/src/hashes/rmd128.c @@ -30,9 +30,9 @@ const struct ltc_hash_descriptor rmd128_desc = 16, 64, - /* DER identifier (not supported) */ - { 0x00 }, - 0, + /* OID */ + { 1, 0, 10118, 3, 0, 50 }, + 6, &rmd128_init, &rmd128_process, @@ -403,3 +403,7 @@ int rmd128_test(void) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/rmd160.c b/src/hashes/rmd160.c index a6171529..bdd1265e 100644 --- a/src/hashes/rmd160.c +++ b/src/hashes/rmd160.c @@ -30,10 +30,9 @@ const struct ltc_hash_descriptor rmd160_desc = 20, 64, - /* DER identifier */ - { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, - 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }, - 15, + /* OID */ + { 1, 3, 36, 3, 2, 1, }, + 6, &rmd160_init, &rmd160_process, @@ -463,3 +462,7 @@ int rmd160_test(void) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/sha1.c b/src/hashes/sha1.c index 267729bc..b297c995 100644 --- a/src/hashes/sha1.c +++ b/src/hashes/sha1.c @@ -25,10 +25,9 @@ const struct ltc_hash_descriptor sha1_desc = 20, 64, - /* DER identifier */ - { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, - 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 }, - 15, + /* OID */ + { 1, 3, 14, 3, 2, 26, }, + 6, &sha1_init, &sha1_process, @@ -282,3 +281,7 @@ int sha1_test(void) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/sha2/sha224.c b/src/hashes/sha2/sha224.c index 8c0dcde4..639c5ec6 100644 --- a/src/hashes/sha2/sha224.c +++ b/src/hashes/sha2/sha224.c @@ -20,9 +20,9 @@ const struct ltc_hash_descriptor sha224_desc = 28, 64, - /* DER identifier (not supported) */ - { 0x00 }, - 0, + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 4, }, + 9, &sha224_init, &sha256_process, @@ -118,3 +118,7 @@ int sha224_test(void) #endif } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/sha2/sha256.c b/src/hashes/sha2/sha256.c index 85eba2a3..59c211e7 100644 --- a/src/hashes/sha2/sha256.c +++ b/src/hashes/sha2/sha256.c @@ -24,11 +24,9 @@ const struct ltc_hash_descriptor sha256_desc = 32, 64, - /* DER identifier */ - { 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, - 0x00, 0x04, 0x20 }, - 19, + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 1, }, + 9, &sha256_init, &sha256_process, @@ -335,3 +333,7 @@ int sha256_test(void) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/sha2/sha384.c b/src/hashes/sha2/sha384.c index 912145c3..78bda807 100644 --- a/src/hashes/sha2/sha384.c +++ b/src/hashes/sha2/sha384.c @@ -20,11 +20,9 @@ const struct ltc_hash_descriptor sha384_desc = 48, 128, - /* DER identifier */ - { 0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, - 0x00, 0x04, 0x30 }, - 19, + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 2, }, + 9, &sha384_init, &sha512_process, @@ -130,3 +128,7 @@ int sha384_test(void) + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/sha2/sha512.c b/src/hashes/sha2/sha512.c index 3238f2b0..346a1b0d 100644 --- a/src/hashes/sha2/sha512.c +++ b/src/hashes/sha2/sha512.c @@ -24,11 +24,9 @@ const struct ltc_hash_descriptor sha512_desc = 64, 128, - /* DER identifier */ - { 0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, - 0x00, 0x04, 0x40 }, - 19, + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 3, }, + 9, &sha512_init, &sha512_process, @@ -314,3 +312,7 @@ int sha512_test(void) + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/tiger.c b/src/hashes/tiger.c index a1cd8883..978cd718 100644 --- a/src/hashes/tiger.c +++ b/src/hashes/tiger.c @@ -25,11 +25,9 @@ const struct ltc_hash_descriptor tiger_desc = 24, 64, - /* DER identifier */ - { 0x30, 0x29, 0x30, 0x0D, 0x06, 0x09, 0x2B, 0x06, - 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0C, 0x02, 0x05, - 0x00, 0x04, 0x18 }, - 19, + /* OID */ + { 1, 3, 6, 1, 4, 1, 11591, 12, 2, }, + 9, &tiger_init, &tiger_process, @@ -809,3 +807,7 @@ Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFG + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/whirl/whirl.c b/src/hashes/whirl/whirl.c index ff0b4367..3cd946e1 100644 --- a/src/hashes/whirl/whirl.c +++ b/src/hashes/whirl/whirl.c @@ -25,9 +25,9 @@ const struct ltc_hash_descriptor whirlpool_desc = 64, 64, - /* DER encoding (not yet supported) */ - { 0x00 }, - 0, + /* OID */ + { 1, 0, 10118, 3, 0, 55 }, + 6, &whirlpool_init, &whirlpool_process, @@ -307,3 +307,7 @@ int whirlpool_test(void) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/hashes/whirl/whirltab.c b/src/hashes/whirl/whirltab.c index fb99bea8..d38ef7c9 100644 --- a/src/hashes/whirl/whirltab.c +++ b/src/hashes/whirl/whirltab.c @@ -577,3 +577,7 @@ CONST64(0xca2dbf07ad5a8333), CONST64(0x6302aa71c81949d9), }; + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/headers/ltc_tommath.h b/src/headers/ltc_tommath.h index 05212e51..07d439ef 100644 --- a/src/headers/ltc_tommath.h +++ b/src/headers/ltc_tommath.h @@ -575,3 +575,7 @@ extern const char *mp_s_rmap; #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/headers/tomcrypt.h b/src/headers/tomcrypt.h index 0d34c745..a5c15482 100644 --- a/src/headers/tomcrypt.h +++ b/src/headers/tomcrypt.h @@ -16,8 +16,8 @@ extern "C" { #endif /* version */ -#define CRYPT 0x0102 -#define SCRYPT "1.02" +#define CRYPT 0x0103 +#define SCRYPT "1.03" /* max size of either a cipher/hash block or symmetric key [largest of the two] */ #define MAXBLOCKSIZE 128 @@ -79,3 +79,7 @@ enum { #endif /* TOMCRYPT_H_ */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/headers/tomcrypt_argchk.h b/src/headers/tomcrypt_argchk.h index 5c8759db..8de8af33 100644 --- a/src/headers/tomcrypt_argchk.h +++ b/src/headers/tomcrypt_argchk.h @@ -19,3 +19,7 @@ void crypt_argchk(char *v, char *s, int d); #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/headers/tomcrypt_cfg.h b/src/headers/tomcrypt_cfg.h index a0022d13..3b198fee 100644 --- a/src/headers/tomcrypt_cfg.h +++ b/src/headers/tomcrypt_cfg.h @@ -106,3 +106,7 @@ int XMEMCMP(const void *s1, const void *s2, size_t n); #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/headers/tomcrypt_cipher.h b/src/headers/tomcrypt_cipher.h index af184c28..d162a2a7 100644 --- a/src/headers/tomcrypt_cipher.h +++ b/src/headers/tomcrypt_cipher.h @@ -32,7 +32,7 @@ struct saferp_key { #ifdef RIJNDAEL struct rijndael_key { - ulong32 eK[64], dK[64]; + ulong32 eK[60], dK[60]; int Nr; }; #endif @@ -599,8 +599,15 @@ int cbc_done(symmetric_CBC *cbc); #endif #ifdef CTR -int ctr_start(int cipher, const unsigned char *IV, const unsigned char *key, - int keylen, int num_rounds, symmetric_CTR *ctr); + +#define CTR_COUNTER_LITTLE_ENDIAN 0 +#define CTR_COUNTER_BIG_ENDIAN 1 + +int ctr_start( int cipher, + const unsigned char *IV, + const unsigned char *key, int keylen, + int num_rounds, int ctr_mode, + symmetric_CTR *ctr); int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr); int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr); int ctr_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr); @@ -617,3 +624,7 @@ int unregister_cipher(const struct ltc_cipher_descriptor *cipher); int cipher_is_valid(int idx); + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/headers/tomcrypt_custom.h b/src/headers/tomcrypt_custom.h index d786f0bf..abf5bc2f 100644 --- a/src/headers/tomcrypt_custom.h +++ b/src/headers/tomcrypt_custom.h @@ -1,6 +1,3 @@ -/* This header is meant to be included before mycrypt.h in projects where - * you don't want to throw all the defines in a makefile. - */ #ifndef TOMCRYPT_CUSTOM_H_ #define TOMCRYPT_CUSTOM_H_ @@ -20,7 +17,9 @@ /* #define LTC_SMALL_CODE */ /* Enable self-test test vector checking */ -#define LTC_TEST +#ifndef LTC_NO_TEST + #define LTC_TEST +#endif /* clean the stack of functions which put private information on stack */ /* #define LTC_CLEAN_STACK */ @@ -38,6 +37,8 @@ /* #define LTC_NO_BSWAP */ /* ---> Symmetric Block Ciphers <--- */ +#ifndef LTC_NO_CIPHERS + #define BLOWFISH #define RC2 #define RC5 @@ -48,8 +49,12 @@ /* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */ #define TWOFISH -#define TWOFISH_TABLES -/* #define TWOFISH_ALL_TABLES */ +#ifndef LTC_NO_TABLES + #define TWOFISH_TABLES + /* #define TWOFISH_ALL_TABLES */ +#else + #define TWOFISH_SMALL +#endif /* #define TWOFISH_SMALL */ /* DES includes EDE triple-DES */ #define DES @@ -61,15 +66,23 @@ #define ANUBIS #define ANUBIS_TWEAK +#endif /* LTC_NO_CIPHERS */ + /* ---> Block Cipher Modes of Operation <--- */ +#ifndef LTC_NO_MODES + #define CFB #define OFB #define ECB #define CBC #define CTR +#endif /* LTC_NO_MODES */ + /* ---> One-Way Hash Functions <--- */ +#ifndef LTC_NO_HASHES + #define CHC_HASH #define WHIRLPOOL #define SHA512 @@ -84,7 +97,11 @@ #define RIPEMD128 #define RIPEMD160 +#endif /* LTC_NO_HASHES */ + /* ---> MAC functions <--- */ +#ifndef LTC_NO_MACS + #define HMAC #define OMAC #define PMAC @@ -95,6 +112,7 @@ #endif /* ---> Encrypt + Authenticate Modes <--- */ + #define EAX_MODE #if defined(EAX_MODE) && !(defined(CTR) && defined(OMAC)) #error EAX_MODE requires CTR and OMAC mode @@ -104,13 +122,20 @@ #define CCM_MODE #define GCM_MODE + /* Use 64KiB tables */ -#define GCM_TABLES +#ifndef LTC_NO_TABLES + #define GCM_TABLES +#endif + +#endif /* LTC_NO_MACS */ /* Various tidbits of modern neatoness */ #define BASE64 /* --> Pseudo Random Number Generators <--- */ +#ifndef LTC_NO_PRNGS + /* Yarrow */ #define YARROW /* which descriptor of AES to use? */ @@ -142,7 +167,11 @@ /* try /dev/urandom before trying /dev/random */ #define TRY_URANDOM_FIRST +#endif /* LTC_NO_PRNGS */ + /* ---> Public Key Crypto <--- */ +#ifndef LTC_NO_PK + #define MRSA /* Digital Signature Algorithm */ @@ -168,7 +197,6 @@ /* ECC */ #define MECC /* Supported Key Sizes */ -#define ECC160 #define ECC192 #define ECC224 #define ECC256 @@ -178,7 +206,11 @@ /* Include the MPI functionality? (required by the PK algorithms) */ #define MPI +#endif /* LTC_NO_PK */ + /* PKCS #1 (RSA) and #5 (Password Handling) stuff */ +#ifndef LTC_NO_PKCS + #define PKCS_1 #define PKCS_5 @@ -192,5 +224,11 @@ #error RSA/DSA requires ASN.1 DER functionality, make sure LTC_DER is enabled #endif +#endif /* LTC_NO_PKCS */ + #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/headers/tomcrypt_hash.h b/src/headers/tomcrypt_hash.h index d295a598..f92f2d67 100644 --- a/src/headers/tomcrypt_hash.h +++ b/src/headers/tomcrypt_hash.h @@ -132,10 +132,11 @@ extern struct ltc_hash_descriptor { unsigned long hashsize; /** Input block size in octets */ unsigned long blocksize; - /** ASN.1 DER identifier */ - unsigned char DER[64]; + /** ASN.1 OID */ + unsigned long OID[16]; /** Length of DER encoding */ - unsigned long DERlen; + unsigned long OIDlen; + /** Init a hash state @param hash The hash to initialize @return CRYPT_OK if successful @@ -292,29 +293,29 @@ int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) { \ unsigned long n; \ int err; \ - LTC_ARGCHK(md != NULL); \ - LTC_ARGCHK(in != NULL); \ + LTC_ARGCHK(md != NULL); \ + LTC_ARGCHK(in != NULL); \ if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \ return CRYPT_INVALID_ARG; \ } \ - while (inlen > 0) { \ - if (md-> state_var .curlen == 0 && inlen >= block_size) { \ - if ((err = compress_name (md, (unsigned char *)in)) != CRYPT_OK) { \ - return err; \ - } \ + while (inlen > 0) { \ + if (md-> state_var .curlen == 0 && inlen >= block_size) { \ + if ((err = compress_name (md, (unsigned char *)in)) != CRYPT_OK) { \ + return err; \ + } \ md-> state_var .length += block_size * 8; \ - in += block_size; \ - inlen -= block_size; \ + in += block_size; \ + inlen -= block_size; \ } else { \ - n = MIN(inlen, (block_size - md-> state_var .curlen)); \ - memcpy(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n); \ + n = MIN(inlen, (block_size - md-> state_var .curlen)); \ + memcpy(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n); \ md-> state_var .curlen += n; \ - in += n; \ - inlen -= n; \ + in += n; \ + inlen -= n; \ if (md-> state_var .curlen == block_size) { \ - if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) {\ - return err; \ - } \ + if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) { \ + return err; \ + } \ md-> state_var .length += 8*block_size; \ md-> state_var .curlen = 0; \ } \ @@ -322,3 +323,7 @@ int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) } \ return CRYPT_OK; \ } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/headers/tomcrypt_mac.h b/src/headers/tomcrypt_mac.h index 6b5e1ce5..0ffbd450 100644 --- a/src/headers/tomcrypt_mac.h +++ b/src/headers/tomcrypt_mac.h @@ -295,3 +295,7 @@ int pelican_memory(const unsigned char *key, unsigned long keylen, unsigned char *out); #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/headers/tomcrypt_macros.h b/src/headers/tomcrypt_macros.h index f083984a..b0d15332 100644 --- a/src/headers/tomcrypt_macros.h +++ b/src/headers/tomcrypt_macros.h @@ -132,7 +132,7 @@ asm __volatile__ ( \ #ifdef ENDIAN_32BITWORD #define STORE32L(x, y) \ - { unsigned long __t = (x); memcpy(y, &__t, 4); } + { ulong32 __t = (x); memcpy(y, &__t, 4); } #define LOAD32L(x, y) \ memcpy(&(x), y, 4); @@ -152,7 +152,7 @@ asm __volatile__ ( \ #else /* 64-bit words then */ #define STORE32L(x, y) \ - { unsigned long __t = (x); memcpy(y, &__t, 4); } + { ulong32 __t = (x); memcpy(y, &__t, 4); } #define LOAD32L(x, y) \ { memcpy(&(x), y, 4); x &= 0xFFFFFFFF; } @@ -193,7 +193,7 @@ asm __volatile__ ( \ #ifdef ENDIAN_32BITWORD #define STORE32H(x, y) \ - { unsigned long __t = (x); memcpy(y, &__t, 4); } + { ulong32 __t = (x); memcpy(y, &__t, 4); } #define LOAD32H(x, y) \ memcpy(&(x), y, 4); @@ -213,7 +213,7 @@ asm __volatile__ ( \ #else /* 64-bit words then */ #define STORE32H(x, y) \ - { unsigned long __t = (x); memcpy(y, &__t, 4); } + { ulong32 __t = (x); memcpy(y, &__t, 4); } #define LOAD32H(x, y) \ { memcpy(&(x), y, 4); x &= 0xFFFFFFFF; } @@ -371,3 +371,7 @@ static inline unsigned long ROR64c(unsigned long word, const int i) #else #define byte(x, n) (((x) >> (8 * (n))) & 255) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/headers/tomcrypt_misc.h b/src/headers/tomcrypt_misc.h index bed5015f..358e80ee 100644 --- a/src/headers/tomcrypt_misc.h +++ b/src/headers/tomcrypt_misc.h @@ -15,3 +15,7 @@ const char *error_to_string(int err); int mpi_to_ltc_error(int err); extern const char *crypt_build_settings; + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/headers/tomcrypt_pk.h b/src/headers/tomcrypt_pk.h index 065ca996..08b16ff1 100644 --- a/src/headers/tomcrypt_pk.h +++ b/src/headers/tomcrypt_pk.h @@ -84,9 +84,6 @@ int packet_valid_header(unsigned char *src, int section, int subsection); #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, p, q, qP, dP, dQ; @@ -123,26 +120,6 @@ int rsa_verify_hash(const unsigned char *sig, unsigned long siglen, int hash_idx, unsigned long saltlen, int *stat, rsa_key *key); -/* these use PKCS #1 v1.5 padding */ -int rsa_v15_encrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int prng_idx, - rsa_key *key); - -int rsa_v15_decrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long outlen, - int *stat, rsa_key *key); - -int rsa_v15_sign_hash(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *siglen, - int hash_idx, rsa_key *key); - -int rsa_v15_verify_hash(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long hashlen, - int hash_idx, int *stat, - rsa_key *key); - - /* PKCS #1 import/export */ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key); int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key); @@ -244,10 +221,19 @@ typedef struct { int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key); void dsa_free(dsa_key *key); + +int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen, + mp_int *r, mp_int *s, + prng_state *prng, int wprng, dsa_key *key); + 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); +int dsa_verify_hash_raw( mp_int *r, mp_int *s, + const unsigned char *hash, unsigned long hashlen, + int *stat, dsa_key *key); + int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int *stat, dsa_key *key); @@ -262,9 +248,104 @@ int dsa_verify_key(dsa_key *key, int *stat); #ifdef LTC_DER /* DER handling */ + +enum { + LTC_ASN1_EOL, + LTC_ASN1_INTEGER, + LTC_ASN1_SHORT_INTEGER, + LTC_ASN1_BIT_STRING, + LTC_ASN1_OCTET_STRING, + LTC_ASN1_NULL, + LTC_ASN1_OBJECT_IDENTIFIER, + LTC_ASN1_IA5_STRING, + LTC_ASN1_PRINTABLE_STRING, + + LTC_ASN1_SEQUENCE +}; + +typedef struct { + int type; + void *data; + unsigned long size; +} ltc_asn1_list; + +#define LTC_SET_ASN1(list, index, Type, Data, Size) \ + do { \ + int LTC_MACRO_temp = (index); \ + ltc_asn1_list *LTC_MACRO_list = (list); \ + LTC_MACRO_list[LTC_MACRO_temp].type = (Type); \ + LTC_MACRO_list[LTC_MACRO_temp].data = (Data); \ + LTC_MACRO_list[LTC_MACRO_temp].size = (Size); \ + } while (0); + +/* SEQUENCE */ +int der_encode_sequence(ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_decode_sequence(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *list, unsigned long outlen); + +int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, + unsigned long *outlen); + +/* VA list handy helpers */ +int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...); +int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...); + +/* INTEGER */ int der_encode_integer(mp_int *num, unsigned char *out, unsigned long *outlen); -int der_decode_integer(const unsigned char *in, unsigned long *inlen, mp_int *num); +int der_decode_integer(const unsigned char *in, unsigned long inlen, mp_int *num); int der_length_integer(mp_int *num, unsigned long *len); -int der_put_multi_integer(unsigned char *dst, unsigned long *outlen, mp_int *num, ...); -int der_get_multi_integer(const unsigned char *src, unsigned long *inlen, mp_int *num, ...); + +/* INTEGER -- handy for 0..2^32-1 values */ +int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num); +int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen); +int der_length_short_integer(unsigned long num, unsigned long *outlen); + +/* BIT STRING */ +int der_encode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_bit_string(unsigned long nbits, unsigned long *outlen); + +/* OCTET STRING */ +int der_encode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_octet_string(unsigned long noctets, unsigned long *outlen); + +/* OBJECT IDENTIFIER */ +int der_encode_object_identifier(unsigned long *words, unsigned long nwords, + unsigned char *out, unsigned long *outlen); +int der_decode_object_identifier(const unsigned char *in, unsigned long inlen, + unsigned long *words, unsigned long *outlen); +int der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen); +unsigned long der_object_identifier_bits(unsigned long x); + +/* IA5 STRING */ +int der_encode_ia5_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_ia5_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); + +int der_ia5_char_encode(int c); +int der_ia5_value_decode(int v); + +/* Printable STRING */ +int der_encode_printable_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_printable_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); + +int der_printable_char_encode(int c); +int der_printable_value_decode(int v); + #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/headers/tomcrypt_pkcs.h b/src/headers/tomcrypt_pkcs.h index 9fd0581a..b44544ab 100644 --- a/src/headers/tomcrypt_pkcs.h +++ b/src/headers/tomcrypt_pkcs.h @@ -10,7 +10,7 @@ int pkcs_1_mgf1(const unsigned char *seed, unsigned long seedlen, 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); -/* *** v2.0 padding */ +/* *** v2.1 padding */ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, const unsigned char *lparam, unsigned long lparamlen, unsigned long modulus_bitlen, prng_state *prng, @@ -34,32 +34,6 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, unsigned long saltlen, int hash_idx, unsigned long modulus_bitlen, int *res); -/* *** v1.5 padding */ -/* encryption padding */ -int pkcs_1_v15_es_encode(const unsigned char *msg, unsigned long msglen, - unsigned long modulus_bitlen, - prng_state *prng, int prng_idx, - unsigned char *out, unsigned long *outlen); - -/* note "outlen" is fixed, you have to tell this decoder how big - * the original message was. Unlike the OAEP decoder it cannot auto-detect it. - */ -int pkcs_1_v15_es_decode(const unsigned char *msg, unsigned long msglen, - unsigned long modulus_bitlen, - unsigned char *out, unsigned long outlen, - int *res); - -/* signature padding */ -int pkcs_1_v15_sa_encode(const unsigned char *msghash, unsigned long msghashlen, - int hash_idx, unsigned long modulus_bitlen, - unsigned char *out, unsigned long *outlen); - -int pkcs_1_v15_sa_decode(const unsigned char *msghash, unsigned long msghashlen, - const unsigned char *sig, unsigned long siglen, - int hash_idx, unsigned long modulus_bitlen, - int *res); - - #endif /* PKCS_1 */ /* ===> PKCS #5 -- Password Based Cryptography <=== */ @@ -78,3 +52,7 @@ int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, unsigned char *out, unsigned long *outlen); #endif /* PKCS_5 */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/headers/tomcrypt_prng.h b/src/headers/tomcrypt_prng.h index 2ae5749e..a257f4c2 100644 --- a/src/headers/tomcrypt_prng.h +++ b/src/headers/tomcrypt_prng.h @@ -188,3 +188,7 @@ unsigned long rng_get_bytes(unsigned char *out, int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void)); + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/headers/tommath_class.h b/src/headers/tommath_class.h index 6d05b7b7..653e3114 100644 --- a/src/headers/tommath_class.h +++ b/src/headers/tommath_class.h @@ -992,3 +992,7 @@ #else #define LTM_LAST #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/headers/tommath_superclass.h b/src/headers/tommath_superclass.h index b50ecb09..eb8b862f 100644 --- a/src/headers/tommath_superclass.h +++ b/src/headers/tommath_superclass.h @@ -1,10 +1,14 @@ /* super class file for PK algos */ /* default ... include all MPI */ +#ifndef SC_RSA_1 + #define LTM_ALL +#endif + /* RSA only (does not support DH/DSA/ECC) */ -// #define SC_RSA_1 +/* #define SC_RSA_1 */ /* For reference.... On an Athlon64 optimizing for speed... @@ -70,3 +74,7 @@ #endif #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/hmac/hmac_done.c b/src/mac/hmac/hmac_done.c index fdf20be9..3803ab45 100644 --- a/src/mac/hmac/hmac_done.c +++ b/src/mac/hmac/hmac_done.c @@ -103,3 +103,7 @@ LBL_ERR: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/hmac/hmac_file.c b/src/mac/hmac/hmac_file.c index edbb6a60..b7b39143 100644 --- a/src/mac/hmac/hmac_file.c +++ b/src/mac/hmac/hmac_file.c @@ -87,3 +87,7 @@ int hmac_file(int hash, const char *fname, #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/hmac/hmac_init.c b/src/mac/hmac/hmac_init.c index d060a5b4..e5d7f904 100644 --- a/src/mac/hmac/hmac_init.c +++ b/src/mac/hmac/hmac_init.c @@ -106,3 +106,7 @@ done: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/hmac/hmac_memory.c b/src/mac/hmac/hmac_memory.c index 036ee369..2a84745b 100644 --- a/src/mac/hmac/hmac_memory.c +++ b/src/mac/hmac/hmac_memory.c @@ -71,3 +71,7 @@ LBL_ERR: #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/hmac/hmac_memory_multi.c b/src/mac/hmac/hmac_memory_multi.c index 4a5b9be6..13f0e43b 100644 --- a/src/mac/hmac/hmac_memory_multi.c +++ b/src/mac/hmac/hmac_memory_multi.c @@ -86,3 +86,7 @@ LBL_ERR: #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/hmac/hmac_process.c b/src/mac/hmac/hmac_process.c index 30e64c37..dd4a3b21 100644 --- a/src/mac/hmac/hmac_process.c +++ b/src/mac/hmac/hmac_process.c @@ -37,3 +37,7 @@ int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/hmac/hmac_test.c b/src/mac/hmac/hmac_test.c index 0d542d43..44c61563 100644 --- a/src/mac/hmac/hmac_test.c +++ b/src/mac/hmac/hmac_test.c @@ -310,3 +310,7 @@ Key First" #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/omac/omac_done.c b/src/mac/omac/omac_done.c index 0a91a141..7291884d 100644 --- a/src/mac/omac/omac_done.c +++ b/src/mac/omac/omac_done.c @@ -78,3 +78,7 @@ int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/omac/omac_file.c b/src/mac/omac/omac_file.c index 1e3d2f6b..4f0cdc01 100644 --- a/src/mac/omac/omac_file.c +++ b/src/mac/omac/omac_file.c @@ -77,3 +77,7 @@ int omac_file(int cipher, } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/omac/omac_init.c b/src/mac/omac/omac_init.c index d39219d8..dc0678b9 100644 --- a/src/mac/omac/omac_init.c +++ b/src/mac/omac/omac_init.c @@ -39,7 +39,7 @@ int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned l } #ifdef LTC_FAST - if (16 % sizeof(LTC_FAST_TYPE)) { + if (cipher_descriptor[cipher].block_length % sizeof(LTC_FAST_TYPE)) { return CRYPT_INVALID_ARG; } #endif @@ -93,3 +93,7 @@ int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned l } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/omac/omac_memory.c b/src/mac/omac/omac_memory.c index 51d0ce24..ff3315ae 100644 --- a/src/mac/omac/omac_memory.c +++ b/src/mac/omac/omac_memory.c @@ -69,3 +69,7 @@ LBL_ERR: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/omac/omac_memory_multi.c b/src/mac/omac/omac_memory_multi.c index 76e4eb08..5278fe80 100644 --- a/src/mac/omac/omac_memory_multi.c +++ b/src/mac/omac/omac_memory_multi.c @@ -84,3 +84,7 @@ LBL_ERR: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/omac/omac_process.c b/src/mac/omac/omac_process.c index 6b603f79..6491165e 100644 --- a/src/mac/omac/omac_process.c +++ b/src/mac/omac/omac_process.c @@ -27,7 +27,8 @@ */ int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen) { - int err, n, x; + unsigned long n, x; + int err; LTC_ARGCHK(omac != NULL); LTC_ARGCHK(in != NULL); @@ -57,7 +58,7 @@ int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen) while (inlen != 0) { /* ok if the block is full we xor in prev, encrypt and replace prev */ if (omac->buflen == omac->blklen) { - for (x = 0; x < omac->blklen; x++) { + for (x = 0; x < (unsigned long)omac->blklen; x++) { omac->block[x] ^= omac->prev[x]; } cipher_descriptor[omac->cipher_idx].ecb_encrypt(omac->block, omac->prev, &omac->key); @@ -77,3 +78,7 @@ int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/omac/omac_test.c b/src/mac/omac/omac_test.c index 42e42bd1..da9a2de6 100644 --- a/src/mac/omac/omac_test.c +++ b/src/mac/omac/omac_test.c @@ -104,3 +104,7 @@ int omac_test(void) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/pelican/pelican.c b/src/mac/pelican/pelican.c index fb7ce58c..45ed7e8e 100644 --- a/src/mac/pelican/pelican.c +++ b/src/mac/pelican/pelican.c @@ -102,6 +102,12 @@ int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned lon LTC_ARGCHK(pelmac != NULL); LTC_ARGCHK(in != NULL); + + /* check range */ + if (pelmac->buflen < 0 || pelmac->buflen > 15) { + return CRYPT_INVALID_ARG; + } + #ifdef LTC_FAST if (pelmac->buflen == 0) { while (inlen & ~15) { @@ -136,6 +142,12 @@ int pelican_done(pelican_state *pelmac, unsigned char *out) { LTC_ARGCHK(pelmac != NULL); LTC_ARGCHK(out != NULL); + + /* check range */ + if (pelmac->buflen < 0 || pelmac->buflen > 16) { + return CRYPT_INVALID_ARG; + } + if (pelmac->buflen == 16) { four_rounds(pelmac); pelmac->buflen = 0; @@ -147,3 +159,7 @@ int pelican_done(pelican_state *pelmac, unsigned char *out) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/pelican/pelican_memory.c b/src/mac/pelican/pelican_memory.c index 9e0fc7b3..19240315 100644 --- a/src/mac/pelican/pelican_memory.c +++ b/src/mac/pelican/pelican_memory.c @@ -53,3 +53,7 @@ int pelican_memory(const unsigned char *key, unsigned long keylen, #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/pelican/pelican_test.c b/src/mac/pelican/pelican_test.c index e694f61a..90248039 100644 --- a/src/mac/pelican/pelican_test.c +++ b/src/mac/pelican/pelican_test.c @@ -114,3 +114,7 @@ int pelican_test(void) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/pmac/pmac_done.c b/src/mac/pmac/pmac_done.c index 610e433a..f6a08ce4 100644 --- a/src/mac/pmac/pmac_done.c +++ b/src/mac/pmac/pmac_done.c @@ -66,3 +66,7 @@ int pmac_done(pmac_state *state, unsigned char *out, unsigned long *outlen) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/pmac/pmac_file.c b/src/mac/pmac/pmac_file.c index 5b7dd242..79cc2e22 100644 --- a/src/mac/pmac/pmac_file.c +++ b/src/mac/pmac/pmac_file.c @@ -78,3 +78,7 @@ int pmac_file(int cipher, } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/pmac/pmac_init.c b/src/mac/pmac/pmac_init.c index a02b20c5..1b21e505 100644 --- a/src/mac/pmac/pmac_init.c +++ b/src/mac/pmac/pmac_init.c @@ -138,3 +138,7 @@ int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned l } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/pmac/pmac_memory.c b/src/mac/pmac/pmac_memory.c index a04cd78f..88036ec6 100644 --- a/src/mac/pmac/pmac_memory.c +++ b/src/mac/pmac/pmac_memory.c @@ -68,3 +68,7 @@ LBL_ERR: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/pmac/pmac_memory_multi.c b/src/mac/pmac/pmac_memory_multi.c index 289d2e0c..bc42b8c0 100644 --- a/src/mac/pmac/pmac_memory_multi.c +++ b/src/mac/pmac/pmac_memory_multi.c @@ -83,3 +83,7 @@ LBL_ERR: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/pmac/pmac_ntz.c b/src/mac/pmac/pmac_ntz.c index 97f0a15a..2c166481 100644 --- a/src/mac/pmac/pmac_ntz.c +++ b/src/mac/pmac/pmac_ntz.c @@ -33,3 +33,7 @@ int pmac_ntz(unsigned long x) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/pmac/pmac_process.c b/src/mac/pmac/pmac_process.c index 5cee5ecc..81fbc8c5 100644 --- a/src/mac/pmac/pmac_process.c +++ b/src/mac/pmac/pmac_process.c @@ -90,3 +90,7 @@ int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/pmac/pmac_shift_xor.c b/src/mac/pmac/pmac_shift_xor.c index 18c6141e..f0c367e7 100644 --- a/src/mac/pmac/pmac_shift_xor.c +++ b/src/mac/pmac/pmac_shift_xor.c @@ -38,3 +38,7 @@ void pmac_shift_xor(pmac_state *pmac) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/mac/pmac/pmac_test.c b/src/mac/pmac/pmac_test.c index 6c610f9f..30f606c3 100644 --- a/src/mac/pmac/pmac_test.c +++ b/src/mac/pmac/pmac_test.c @@ -159,3 +159,7 @@ int pmac_test(void) + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/base64/base64_decode.c b/src/misc/base64/base64_decode.c index ac6db57e..320f201c 100644 --- a/src/misc/base64/base64_decode.c +++ b/src/misc/base64/base64_decode.c @@ -98,3 +98,7 @@ int base64_decode(const unsigned char *in, unsigned long inlen, #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/base64/base64_encode.c b/src/misc/base64/base64_encode.c index 047980c9..6173cb90 100644 --- a/src/misc/base64/base64_encode.c +++ b/src/misc/base64/base64_encode.c @@ -74,3 +74,7 @@ int base64_encode(const unsigned char *in, unsigned long inlen, #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/burn_stack.c b/src/misc/burn_stack.c index 3bc69ab1..c7edc037 100644 --- a/src/misc/burn_stack.c +++ b/src/misc/burn_stack.c @@ -28,3 +28,7 @@ void burn_stack(unsigned long len) } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt.c b/src/misc/crypt/crypt.c index 83f1414a..99c07a88 100644 --- a/src/misc/crypt/crypt.c +++ b/src/misc/crypt/crypt.c @@ -295,8 +295,18 @@ const char *crypt_build_settings = #endif #if defined(LTC_NO_ASM) " LTC_NO_ASM " +#endif +#if defined(LTC_NO_TEST) + " LTC_NO_TEST " +#endif +#if defined(LTC_NO_TABLES) + " LTC_NO_TABLES " #endif "\n" "\n\n\n" ; + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_argchk.c b/src/misc/crypt/crypt_argchk.c index d345c8d0..2ba8a859 100644 --- a/src/misc/crypt/crypt_argchk.c +++ b/src/misc/crypt/crypt_argchk.c @@ -24,3 +24,7 @@ void crypt_argchk(char *v, char *s, int d) (void)raise(SIGABRT); } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_cipher_descriptor.c b/src/misc/crypt/crypt_cipher_descriptor.c index e2744496..a255ec6e 100644 --- a/src/misc/crypt/crypt_cipher_descriptor.c +++ b/src/misc/crypt/crypt_cipher_descriptor.c @@ -19,3 +19,7 @@ struct ltc_cipher_descriptor cipher_descriptor[TAB_SIZE] = { { NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } }; + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_cipher_is_valid.c b/src/misc/crypt/crypt_cipher_is_valid.c index b1794025..d5db7bc6 100644 --- a/src/misc/crypt/crypt_cipher_is_valid.c +++ b/src/misc/crypt/crypt_cipher_is_valid.c @@ -27,3 +27,7 @@ int cipher_is_valid(int idx) } return CRYPT_OK; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_find_cipher.c b/src/misc/crypt/crypt_find_cipher.c index b83109c1..230b9081 100644 --- a/src/misc/crypt/crypt_find_cipher.c +++ b/src/misc/crypt/crypt_find_cipher.c @@ -32,3 +32,7 @@ int find_cipher(const char *name) return -1; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_find_cipher_any.c b/src/misc/crypt/crypt_find_cipher_any.c index 42e59c05..fe669f34 100644 --- a/src/misc/crypt/crypt_find_cipher_any.c +++ b/src/misc/crypt/crypt_find_cipher_any.c @@ -41,3 +41,7 @@ int find_cipher_any(const char *name, int blocklen, int keylen) } return -1; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_find_cipher_id.c b/src/misc/crypt/crypt_find_cipher_id.c index 986baf58..766fb01b 100644 --- a/src/misc/crypt/crypt_find_cipher_id.c +++ b/src/misc/crypt/crypt_find_cipher_id.c @@ -30,3 +30,7 @@ int find_cipher_id(unsigned char ID) } return -1; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_find_hash.c b/src/misc/crypt/crypt_find_hash.c index d66201c1..c5801031 100644 --- a/src/misc/crypt/crypt_find_hash.c +++ b/src/misc/crypt/crypt_find_hash.c @@ -31,3 +31,7 @@ int find_hash(const char *name) } return -1; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_find_hash_any.c b/src/misc/crypt/crypt_find_hash_any.c index 0d6d430f..98c277eb 100644 --- a/src/misc/crypt/crypt_find_hash_any.c +++ b/src/misc/crypt/crypt_find_hash_any.c @@ -41,3 +41,7 @@ } return z; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_find_hash_id.c b/src/misc/crypt/crypt_find_hash_id.c index 8628d537..7c23864d 100644 --- a/src/misc/crypt/crypt_find_hash_id.c +++ b/src/misc/crypt/crypt_find_hash_id.c @@ -30,3 +30,7 @@ int find_hash_id(unsigned char ID) } return -1; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_find_prng.c b/src/misc/crypt/crypt_find_prng.c index c01a023a..554083e7 100644 --- a/src/misc/crypt/crypt_find_prng.c +++ b/src/misc/crypt/crypt_find_prng.c @@ -32,3 +32,7 @@ int find_prng(const char *name) return -1; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_hash_descriptor.c b/src/misc/crypt/crypt_hash_descriptor.c index cbd6d03e..969ff836 100644 --- a/src/misc/crypt/crypt_hash_descriptor.c +++ b/src/misc/crypt/crypt_hash_descriptor.c @@ -18,3 +18,7 @@ struct ltc_hash_descriptor hash_descriptor[TAB_SIZE] = { { NULL, 0, 0, 0, { 0 }, 0, NULL, NULL, NULL, NULL } }; + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_hash_is_valid.c b/src/misc/crypt/crypt_hash_is_valid.c index c9784b84..103f71b9 100644 --- a/src/misc/crypt/crypt_hash_is_valid.c +++ b/src/misc/crypt/crypt_hash_is_valid.c @@ -27,3 +27,7 @@ int hash_is_valid(int idx) } return CRYPT_OK; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_prng_descriptor.c b/src/misc/crypt/crypt_prng_descriptor.c index 8a995104..8b8ad344 100644 --- a/src/misc/crypt/crypt_prng_descriptor.c +++ b/src/misc/crypt/crypt_prng_descriptor.c @@ -17,3 +17,7 @@ struct ltc_prng_descriptor prng_descriptor[TAB_SIZE] = { { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } }; + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_prng_is_valid.c b/src/misc/crypt/crypt_prng_is_valid.c index 7795bbb9..f8ccbcf1 100644 --- a/src/misc/crypt/crypt_prng_is_valid.c +++ b/src/misc/crypt/crypt_prng_is_valid.c @@ -27,3 +27,7 @@ int prng_is_valid(int idx) } return CRYPT_OK; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_register_cipher.c b/src/misc/crypt/crypt_register_cipher.c index 74349e66..4fea824e 100644 --- a/src/misc/crypt/crypt_register_cipher.c +++ b/src/misc/crypt/crypt_register_cipher.c @@ -44,3 +44,7 @@ int register_cipher(const struct ltc_cipher_descriptor *cipher) /* no spot */ return -1; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_register_hash.c b/src/misc/crypt/crypt_register_hash.c index d5cf5b83..3ece4f7a 100644 --- a/src/misc/crypt/crypt_register_hash.c +++ b/src/misc/crypt/crypt_register_hash.c @@ -44,3 +44,7 @@ int register_hash(const struct ltc_hash_descriptor *hash) /* no spot */ return -1; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_register_prng.c b/src/misc/crypt/crypt_register_prng.c index 6a1be779..59eb456d 100644 --- a/src/misc/crypt/crypt_register_prng.c +++ b/src/misc/crypt/crypt_register_prng.c @@ -44,3 +44,7 @@ int register_prng(const struct ltc_prng_descriptor *prng) /* no spot */ return -1; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_unregister_cipher.c b/src/misc/crypt/crypt_unregister_cipher.c index 0511de54..f8fdac92 100644 --- a/src/misc/crypt/crypt_unregister_cipher.c +++ b/src/misc/crypt/crypt_unregister_cipher.c @@ -36,3 +36,7 @@ int unregister_cipher(const struct ltc_cipher_descriptor *cipher) } return CRYPT_ERROR; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_unregister_hash.c b/src/misc/crypt/crypt_unregister_hash.c index 25e36f20..51f3eac5 100644 --- a/src/misc/crypt/crypt_unregister_hash.c +++ b/src/misc/crypt/crypt_unregister_hash.c @@ -35,3 +35,7 @@ int unregister_hash(const struct ltc_hash_descriptor *hash) } return CRYPT_ERROR; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/crypt/crypt_unregister_prng.c b/src/misc/crypt/crypt_unregister_prng.c index 55cc5543..5e90832a 100644 --- a/src/misc/crypt/crypt_unregister_prng.c +++ b/src/misc/crypt/crypt_unregister_prng.c @@ -35,3 +35,7 @@ int unregister_prng(const struct ltc_prng_descriptor *prng) } return CRYPT_ERROR; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/error_to_string.c b/src/misc/error_to_string.c index 3a325a29..4958b5df 100644 --- a/src/misc/error_to_string.c +++ b/src/misc/error_to_string.c @@ -68,3 +68,7 @@ const char *error_to_string(int err) } } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/mpi/is_prime.c b/src/misc/mpi/is_prime.c index f58391fc..2fb7be5d 100644 --- a/src/misc/mpi/is_prime.c +++ b/src/misc/mpi/is_prime.c @@ -30,3 +30,7 @@ int is_prime(mp_int *N, int *result) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/mpi/mpi.c b/src/misc/mpi/mpi.c index ba3a7ed5..83486508 100644 --- a/src/misc/mpi/mpi.c +++ b/src/misc/mpi/mpi.c @@ -9042,3 +9042,7 @@ int KARATSUBA_MUL_CUTOFF = 74, /* Min. number of digits before Karatsub /* EOF */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/mpi/mpi_to_ltc_error.c b/src/misc/mpi/mpi_to_ltc_error.c index 3a4ea176..c0a55f23 100644 --- a/src/misc/mpi/mpi_to_ltc_error.c +++ b/src/misc/mpi/mpi_to_ltc_error.c @@ -42,3 +42,7 @@ int mpi_to_ltc_error(int err) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/mpi/rand_prime.c b/src/misc/mpi/rand_prime.c index 97ddf731..90d9ac15 100644 --- a/src/misc/mpi/rand_prime.c +++ b/src/misc/mpi/rand_prime.c @@ -64,3 +64,7 @@ int rand_prime(mp_int *N, long len, prng_state *prng, int wprng) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/pkcs5/pkcs_5_1.c b/src/misc/pkcs5/pkcs_5_1.c index ec473721..fd1a80f8 100644 --- a/src/misc/pkcs5/pkcs_5_1.c +++ b/src/misc/pkcs5/pkcs_5_1.c @@ -100,3 +100,7 @@ LBL_ERR: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/pkcs5/pkcs_5_2.c b/src/misc/pkcs5/pkcs_5_2.c index aac811ba..aad0ae34 100644 --- a/src/misc/pkcs5/pkcs_5_2.c +++ b/src/misc/pkcs5/pkcs_5_2.c @@ -123,3 +123,7 @@ LBL_ERR: #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/zeromem.c b/src/misc/zeromem.c index c640bb4d..9145f822 100644 --- a/src/misc/zeromem.c +++ b/src/misc/zeromem.c @@ -28,3 +28,7 @@ void zeromem(void *out, size_t outlen) *mem++ = 0; } } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/cbc/cbc_decrypt.c b/src/modes/cbc/cbc_decrypt.c index c79631c3..509c4b3f 100644 --- a/src/modes/cbc/cbc_decrypt.c +++ b/src/modes/cbc/cbc_decrypt.c @@ -89,3 +89,7 @@ int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, s } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/cbc/cbc_done.c b/src/modes/cbc/cbc_done.c index daa91103..8efe10a7 100644 --- a/src/modes/cbc/cbc_done.c +++ b/src/modes/cbc/cbc_done.c @@ -36,3 +36,7 @@ int cbc_done(symmetric_CBC *cbc) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/cbc/cbc_encrypt.c b/src/modes/cbc/cbc_encrypt.c index 00ca05f1..32664883 100644 --- a/src/modes/cbc/cbc_encrypt.c +++ b/src/modes/cbc/cbc_encrypt.c @@ -90,3 +90,7 @@ int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/cbc/cbc_getiv.c b/src/modes/cbc/cbc_getiv.c index 0f5c3e43..952a75e1 100644 --- a/src/modes/cbc/cbc_getiv.c +++ b/src/modes/cbc/cbc_getiv.c @@ -39,3 +39,7 @@ int cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/cbc/cbc_setiv.c b/src/modes/cbc/cbc_setiv.c index f2e8b31c..7dcae1f8 100644 --- a/src/modes/cbc/cbc_setiv.c +++ b/src/modes/cbc/cbc_setiv.c @@ -38,3 +38,7 @@ int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/cbc/cbc_start.c b/src/modes/cbc/cbc_start.c index 680faabe..79c75552 100644 --- a/src/modes/cbc/cbc_start.c +++ b/src/modes/cbc/cbc_start.c @@ -56,3 +56,7 @@ int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key, } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/cfb/cfb_decrypt.c b/src/modes/cfb/cfb_decrypt.c index 8b788986..6675df14 100644 --- a/src/modes/cfb/cfb_decrypt.c +++ b/src/modes/cfb/cfb_decrypt.c @@ -59,3 +59,7 @@ int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, s #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/cfb/cfb_done.c b/src/modes/cfb/cfb_done.c index 04e775c3..804a7be5 100644 --- a/src/modes/cfb/cfb_done.c +++ b/src/modes/cfb/cfb_done.c @@ -36,3 +36,7 @@ int cfb_done(symmetric_CFB *cfb) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/cfb/cfb_encrypt.c b/src/modes/cfb/cfb_encrypt.c index b9603687..681d8cdb 100644 --- a/src/modes/cfb/cfb_encrypt.c +++ b/src/modes/cfb/cfb_encrypt.c @@ -57,3 +57,7 @@ int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/cfb/cfb_getiv.c b/src/modes/cfb/cfb_getiv.c index e59c1e4a..73d1a824 100644 --- a/src/modes/cfb/cfb_getiv.c +++ b/src/modes/cfb/cfb_getiv.c @@ -39,3 +39,7 @@ int cfb_getiv(unsigned char *IV, unsigned long *len, symmetric_CFB *cfb) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/cfb/cfb_setiv.c b/src/modes/cfb/cfb_setiv.c index e475ad9e..4eedaa88 100644 --- a/src/modes/cfb/cfb_setiv.c +++ b/src/modes/cfb/cfb_setiv.c @@ -47,3 +47,7 @@ int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/cfb/cfb_start.c b/src/modes/cfb/cfb_start.c index 7157fc38..e07fc0ce 100644 --- a/src/modes/cfb/cfb_start.c +++ b/src/modes/cfb/cfb_start.c @@ -61,3 +61,7 @@ int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/ctr/ctr_decrypt.c b/src/modes/ctr/ctr_decrypt.c index daa78a80..8e5c6f70 100644 --- a/src/modes/ctr/ctr_decrypt.c +++ b/src/modes/ctr/ctr_decrypt.c @@ -36,3 +36,7 @@ int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, s #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/ctr/ctr_done.c b/src/modes/ctr/ctr_done.c index 88508baa..b87baadc 100644 --- a/src/modes/ctr/ctr_done.c +++ b/src/modes/ctr/ctr_done.c @@ -36,3 +36,7 @@ int ctr_done(symmetric_CTR *ctr) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/ctr/ctr_encrypt.c b/src/modes/ctr/ctr_encrypt.c index a96b8068..cf46216e 100644 --- a/src/modes/ctr/ctr_encrypt.c +++ b/src/modes/ctr/ctr_encrypt.c @@ -60,7 +60,7 @@ int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s /* is the pad empty? */ if (ctr->padlen == ctr->blocklen) { /* increment counter */ - if (ctr->mode == 0) { + if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) { /* little-endian */ for (x = 0; x < ctr->blocklen; x++) { ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; @@ -102,3 +102,7 @@ int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/ctr/ctr_getiv.c b/src/modes/ctr/ctr_getiv.c index 3997033d..10cdf8e2 100644 --- a/src/modes/ctr/ctr_getiv.c +++ b/src/modes/ctr/ctr_getiv.c @@ -39,3 +39,7 @@ int ctr_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/ctr/ctr_setiv.c b/src/modes/ctr/ctr_setiv.c index 2aab190d..e533b6e7 100644 --- a/src/modes/ctr/ctr_setiv.c +++ b/src/modes/ctr/ctr_setiv.c @@ -52,3 +52,7 @@ int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/ctr/ctr_start.c b/src/modes/ctr/ctr_start.c index db8c464e..47431d28 100644 --- a/src/modes/ctr/ctr_start.c +++ b/src/modes/ctr/ctr_start.c @@ -21,19 +21,23 @@ /** Initialize a CTR context @param cipher The index of the cipher desired - @param count The initial vector + @param IV The initial vector @param key The secret key @param keylen The length of the secret key (octets) @param num_rounds Number of rounds in the cipher desired (0 for default) + @param ctr_mode The counter mode (CTR_COUNTER_LITTLE_ENDIAN or CTR_COUNTER_BIG_ENDIAN) @param ctr The CTR state to initialize @return CRYPT_OK if successful */ -int ctr_start(int cipher, const unsigned char *count, const unsigned char *key, int keylen, - int num_rounds, symmetric_CTR *ctr) +int ctr_start( int cipher, + const unsigned char *IV, + const unsigned char *key, int keylen, + int num_rounds, int ctr_mode, + symmetric_CTR *ctr) { int x, err; - LTC_ARGCHK(count != NULL); + LTC_ARGCHK(IV != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(ctr != NULL); @@ -51,12 +55,16 @@ int ctr_start(int cipher, const unsigned char *count, const unsigned char *key, ctr->blocklen = cipher_descriptor[cipher].block_length; ctr->cipher = cipher; ctr->padlen = 0; - ctr->mode = 0; + ctr->mode = ctr_mode; for (x = 0; x < ctr->blocklen; x++) { - ctr->ctr[x] = count[x]; + ctr->ctr[x] = IV[x]; } cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key); return CRYPT_OK; } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/ecb/ecb_decrypt.c b/src/modes/ecb/ecb_decrypt.c index 8db4d370..97eeb70c 100644 --- a/src/modes/ecb/ecb_decrypt.c +++ b/src/modes/ecb/ecb_decrypt.c @@ -53,3 +53,7 @@ int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, s } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/ecb/ecb_done.c b/src/modes/ecb/ecb_done.c index 31a42fae..a52be38e 100644 --- a/src/modes/ecb/ecb_done.c +++ b/src/modes/ecb/ecb_done.c @@ -18,7 +18,7 @@ #ifdef ECB /** Terminate the chain - @param rcb The ECB chain to terminate + @param ecb The ECB chain to terminate @return CRYPT_OK on success */ int ecb_done(symmetric_ECB *ecb) @@ -36,3 +36,7 @@ int ecb_done(symmetric_ECB *ecb) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/ecb/ecb_encrypt.c b/src/modes/ecb/ecb_encrypt.c index dc045e9d..74adb0be 100644 --- a/src/modes/ecb/ecb_encrypt.c +++ b/src/modes/ecb/ecb_encrypt.c @@ -53,3 +53,7 @@ int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/ecb/ecb_start.c b/src/modes/ecb/ecb_start.c index a8b6d450..0bae3fe7 100644 --- a/src/modes/ecb/ecb_start.c +++ b/src/modes/ecb/ecb_start.c @@ -42,3 +42,7 @@ int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/ofb/ofb_decrypt.c b/src/modes/ofb/ofb_decrypt.c index f7254102..c69caba8 100644 --- a/src/modes/ofb/ofb_decrypt.c +++ b/src/modes/ofb/ofb_decrypt.c @@ -37,3 +37,7 @@ int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, s #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/ofb/ofb_done.c b/src/modes/ofb/ofb_done.c index ff72ddc1..169832fc 100644 --- a/src/modes/ofb/ofb_done.c +++ b/src/modes/ofb/ofb_done.c @@ -36,3 +36,7 @@ int ofb_done(symmetric_OFB *ofb) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/ofb/ofb_encrypt.c b/src/modes/ofb/ofb_encrypt.c index 4409ac8d..78e254d9 100644 --- a/src/modes/ofb/ofb_encrypt.c +++ b/src/modes/ofb/ofb_encrypt.c @@ -52,3 +52,7 @@ int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/ofb/ofb_getiv.c b/src/modes/ofb/ofb_getiv.c index eb8ef1e4..4cb75fd2 100644 --- a/src/modes/ofb/ofb_getiv.c +++ b/src/modes/ofb/ofb_getiv.c @@ -39,3 +39,7 @@ int ofb_getiv(unsigned char *IV, unsigned long *len, symmetric_OFB *ofb) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/ofb/ofb_setiv.c b/src/modes/ofb/ofb_setiv.c index 96b3f1cb..bf422227 100644 --- a/src/modes/ofb/ofb_setiv.c +++ b/src/modes/ofb/ofb_setiv.c @@ -47,3 +47,7 @@ int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/modes/ofb/ofb_start.c b/src/modes/ofb/ofb_start.c index 977e6a3a..9a40a44b 100644 --- a/src/modes/ofb/ofb_start.c +++ b/src/modes/ofb/ofb_start.c @@ -54,3 +54,7 @@ int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/bit/der_decode_bit_string.c b/src/pk/asn1/der/bit/der_decode_bit_string.c new file mode 100644 index 00000000..133d7432 --- /dev/null +++ b/src/pk/asn1/der/bit/der_decode_bit_string.c @@ -0,0 +1,101 @@ +/* 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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_bit_string.c + ASN.1 DER, encode a BIT STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a BIT STRING + @param in The DER encoded BIT STRING + @param inlen The size of the DER BIT STRING + @param out [out] The array of bits stored (one per char) + @param outlen [in/out] The number of bits stored + @return CRYPT_OK if successful +*/ +int der_decode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long dlen, blen, x, y; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* packet must be at least 4 bytes */ + if (inlen < 4) { + return CRYPT_INVALID_ARG; + } + + /* check for 0x03 */ + if ((in[0]&0x1F) != 0x03) { + return CRYPT_INVALID_PACKET; + } + + /* offset in the data */ + x = 1; + + /* get the length of the data */ + if (in[x] & 0x80) { + /* long format get number of length bytes */ + y = in[x++] & 127; + + /* invalid if 0 or > 2 */ + if (y == 0 || y > 2) { + return CRYPT_INVALID_PACKET; + } + + /* read the data len */ + dlen = 0; + while (y--) { + dlen = (dlen << 8) | (unsigned long)in[x++]; + } + } else { + /* short format */ + dlen = in[x++] & 127; + } + + /* is the data len too long or too short? */ + if ((dlen == 0) || (dlen + x > inlen)) { + return CRYPT_INVALID_PACKET; + } + + /* get padding count */ + blen = ((dlen - 1) << 3) - (in[x++] & 7); + + /* too many bits? */ + if (blen > *outlen) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* decode/store the bits */ + for (y = 0; y < blen; y++) { + out[y] = (in[x] & (1 << (7 - (y & 7)))) ? 1 : 0; + if ((y & 7) == 7) { + ++x; + } + } + + /* we done */ + *outlen = blen; + return CRYPT_OK; +} + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/bit/der_encode_bit_string.c b/src/pk/asn1/der/bit/der_encode_bit_string.c new file mode 100644 index 00000000..497b317d --- /dev/null +++ b/src/pk/asn1/der/bit/der_encode_bit_string.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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_bit_string.c + ASN.1 DER, encode a BIT STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a BIT STRING + @param in The array of bits to store (one per char) + @param inlen The number of bits tostore + @param out [out] The destination for the DER encoded BIT STRING + @param outlen [in/out] The max size and resulting size of the DER BIT STRING + @return CRYPT_OK if successful +*/ +int der_encode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long len, x, y, buf; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* avoid overflows */ + if ((err = der_length_bit_string(inlen, &len)) != CRYPT_OK) { + return err; + } + + if (len > *outlen) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* store header (include bit padding count in length) */ + x = 0; + y = (inlen >> 3) + ((inlen&7) ? 1 : 0) + 1; + + out[x++] = 0x03; + if (y < 128) { + out[x++] = y; + } else if (y < 256) { + out[x++] = 0x81; + out[x++] = y; + } else if (y < 65536) { + out[x++] = 0x82; + out[x++] = (y>>8)&255; + out[x++] = y&255; + } + + /* store number of zero padding bits */ + out[x++] = (8 - inlen) & 7; + + /* store the bits in big endian format */ + for (y = buf = 0; y < inlen; y++) { + buf |= (in[y] ? 1 : 0) << (7 - (y & 7)); + if ((y & 7) == 7) { + out[x++] = buf; + buf = 0; + } + } + /* store last byte */ + if (inlen & 7) { + out[x++] = buf; + } + *outlen = x; + return CRYPT_OK; +} + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/bit/der_length_bit_string.c b/src/pk/asn1/der/bit/der_length_bit_string.c new file mode 100644 index 00000000..bf3a614a --- /dev/null +++ b/src/pk/asn1/der/bit/der_length_bit_string.c @@ -0,0 +1,54 @@ +/* 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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_length_bit_string.c + ASN.1 DER, get length of BIT STRING, Tom St Denis +*/ + +#ifdef LTC_DER +/** + Gets length of DER encoding of BIT STRING + @param nbits The number of bits in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_bit_string(unsigned long nbits, unsigned long *outlen) +{ + unsigned long nbytes; + LTC_ARGCHK(outlen != NULL); + + /* get the number of the bytes */ + nbytes = (nbits >> 3) + ((nbits & 7) ? 1 : 0) + 1; + + if (nbytes < 128) { + /* 03 LL PP DD DD DD ... */ + *outlen = 2 + nbytes; + } else if (nbytes < 256) { + /* 03 81 LL PP DD DD DD ... */ + *outlen = 3 + nbytes; + } else if (nbytes < 65536) { + /* 03 82 LL LL PP DD DD DD ... */ + *outlen = 4 + nbytes; + } else { + return CRYPT_INVALID_ARG; + } + + return CRYPT_OK; +} + +#endif + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/der_get_multi_integer.c b/src/pk/asn1/der/der_get_multi_integer.c deleted file mode 100644 index 75ae0bc7..00000000 --- a/src/pk/asn1/der/der_get_multi_integer.c +++ /dev/null @@ -1,67 +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 - * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org - */ -#include -#include "tomcrypt.h" - -/** - @file der_get_multi_integer.c - ASN.1 DER, read multiple integers, Tom St Denis -*/ - - -#ifdef LTC_DER - -/* will read multiple DER INTEGER encoded mp_ints from src - * of upto [inlen] bytes. It will store the number of bytes - * read back into [inlen]. - */ -/** - Read multiple mp_int integers one after another - @param src The DER encoded integers - @param inlen [in] The length of the src buffer, [out] the amount of bytes read - @param num The first mp_int to decode - @param ... A NULL terminated list of mp_ints to decode - @return CRYPT_OK if successful -*/ -int der_get_multi_integer(const unsigned char *src, unsigned long *inlen, - mp_int *num, ...) -{ - va_list args; - mp_int *next; - unsigned long wrote, len; - int err; - - LTC_ARGCHK(src != NULL); - LTC_ARGCHK(inlen != NULL); - - /* setup va list */ - next = num; - len = *inlen; - wrote = 0; - va_start(args, num); - - while (next != NULL) { - if ((err = der_decode_integer(src, inlen, next)) != CRYPT_OK) { - va_end(args); - return err; - } - wrote += *inlen; - src += *inlen; - len -= *inlen; - *inlen = len; - next = va_arg(args, mp_int*); - } - va_end(args); - *inlen = wrote; - return CRYPT_OK; -} - -#endif diff --git a/src/pk/asn1/der/der_put_multi_integer.c b/src/pk/asn1/der/der_put_multi_integer.c deleted file mode 100644 index af2ca888..00000000 --- a/src/pk/asn1/der/der_put_multi_integer.c +++ /dev/null @@ -1,67 +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 - * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org - */ -#include -#include "tomcrypt.h" - -/** - @file der_put_multi_integer.c - ASN.1 DER, store multiple integers, Tom St Denis -*/ - - -#ifdef LTC_DER - -/* store multiple mp_ints in DER INTEGER format to the out, will not - * overflow the length you give it [outlen] and store the number of - * bytes used in [outlen] - */ -/** - Store multiple mp_int integers one after another - @param out [out] The destination for the DER encoded integers - @param outlen [in/out] The max size and resulting size of the DER encoded integers - @param num The first mp_int to encode - @param ... A NULL terminated list of mp_ints to encode - @return CRYPT_OK if successful -*/ -int der_put_multi_integer(unsigned char *out, unsigned long *outlen, - mp_int *num, ...) -{ - va_list args; - mp_int *next; - unsigned long wrote, len; - int err; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* setup va list */ - next = num; - len = *outlen; - wrote = 0; - va_start(args, num); - - while (next != NULL) { - if ((err = der_encode_integer(next, out, outlen)) != CRYPT_OK) { - va_end(args); - return err; - } - wrote += *outlen; - out += *outlen; - len -= *outlen; - *outlen = len; - next = va_arg(args, mp_int*); - } - va_end(args); - *outlen = wrote; - return CRYPT_OK; -} - -#endif diff --git a/src/pk/asn1/der/ia5/der_decode_ia5_string.c b/src/pk/asn1/der/ia5/der_decode_ia5_string.c new file mode 100644 index 00000000..3f9870dd --- /dev/null +++ b/src/pk/asn1/der/ia5/der_decode_ia5_string.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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_ia5_string.c + ASN.1 DER, encode a IA5 STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a IA5 STRING + @param in The DER encoded IA5 STRING + @param inlen The size of the DER IA5 STRING + @param out [out] The array of octets stored (one per char) + @param outlen [in/out] The number of octets stored + @return CRYPT_OK if successful +*/ +int der_decode_ia5_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + int t; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* must have header at least */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check for 0x16 */ + if ((in[0] & 0x1F) != 0x16) { + return CRYPT_INVALID_PACKET; + } + x = 1; + + /* decode the length */ + if (in[x] & 0x80) { + /* valid # of bytes in length are 1,2,3 */ + y = in[x] & 0x7F; + if ((y == 0) || (y > 3) || ((x + y) > inlen)) { + return CRYPT_INVALID_PACKET; + } + + /* read the length in */ + len = 0; + ++x; + while (y--) { + len = (len << 8) | in[x++]; + } + } else { + len = in[x++] & 0x7F; + } + + /* is it too long? */ + if (len > *outlen) { + return CRYPT_BUFFER_OVERFLOW; + } + + if (len + x > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* read the data */ + for (y = 0; y < len; y++) { + t = der_ia5_value_decode(in[x++]); + if (t == -1) { + return CRYPT_INVALID_ARG; + } + out[y] = t; + } + + *outlen = y; + + return CRYPT_OK; +} + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/ia5/der_encode_ia5_string.c b/src/pk/asn1/der/ia5/der_encode_ia5_string.c new file mode 100644 index 00000000..bf25b20b --- /dev/null +++ b/src/pk/asn1/der/ia5/der_encode_ia5_string.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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_ia5_string.c + ASN.1 DER, encode a IA5 STRING, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Store an IA5 STRING + @param in The array of IA5 to store (one per char) + @param inlen The number of IA5 to store + @param out [out] The destination for the DER encoded IA5 STRING + @param outlen [in/out] The max size and resulting size of the DER IA5 STRING + @return CRYPT_OK if successful +*/ +int der_encode_ia5_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get the size */ + if ((err = der_length_ia5_string(in, inlen, &len)) != CRYPT_OK) { + return err; + } + + /* too big? */ + if (len > *outlen) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* encode the header+len */ + x = 0; + out[x++] = 0x16; + if (inlen < 128) { + out[x++] = inlen; + } else if (inlen < 256) { + out[x++] = 0x81; + out[x++] = inlen; + } else if (inlen < 65536UL) { + out[x++] = 0x82; + out[x++] = (inlen>>8)&255; + out[x++] = inlen&255; + } else if (inlen < 16777216UL) { + out[x++] = 0x83; + out[x++] = (inlen>>16)&255; + out[x++] = (inlen>>8)&255; + out[x++] = inlen&255; + } else { + return CRYPT_INVALID_ARG; + } + + /* store octets */ + for (y = 0; y < inlen; y++) { + out[x++] = der_ia5_char_encode(in[y]); + } + + /* retun length */ + *outlen = x; + + return CRYPT_OK; +} + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/ia5/der_length_ia5_string.c b/src/pk/asn1/der/ia5/der_length_ia5_string.c new file mode 100644 index 00000000..40e6b97b --- /dev/null +++ b/src/pk/asn1/der/ia5/der_length_ia5_string.c @@ -0,0 +1,194 @@ +/* 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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_length_ia5_string.c + ASN.1 DER, get length of IA5 STRING, Tom St Denis +*/ + +#ifdef LTC_DER + +static const struct { + int code, value; +} ia5_table[] = { +{ '\0', 0 }, +{ '\a', 7 }, +{ '\b', 8 }, +{ '\t', 9 }, +{ '\n', 10 }, +{ '\f', 12 }, +{ '\r', 13 }, +{ ' ', 32 }, +{ '!', 33 }, +{ '"', 34 }, +{ '#', 35 }, +{ '$', 36 }, +{ '%', 37 }, +{ '&', 38 }, +{ '\'', 39 }, +{ '(', 40 }, +{ ')', 41 }, +{ '*', 42 }, +{ '+', 43 }, +{ ',', 44 }, +{ '-', 45 }, +{ '.', 46 }, +{ '/', 47 }, +{ '0', 48 }, +{ '1', 49 }, +{ '2', 50 }, +{ '3', 51 }, +{ '4', 52 }, +{ '5', 53 }, +{ '6', 54 }, +{ '7', 55 }, +{ '8', 56 }, +{ '9', 57 }, +{ ':', 58 }, +{ ';', 59 }, +{ '<', 60 }, +{ '=', 61 }, +{ '>', 62 }, +{ '?', 63 }, +{ '@', 64 }, +{ 'A', 65 }, +{ 'B', 66 }, +{ 'C', 67 }, +{ 'D', 68 }, +{ 'E', 69 }, +{ 'F', 70 }, +{ 'G', 71 }, +{ 'H', 72 }, +{ 'I', 73 }, +{ 'J', 74 }, +{ 'K', 75 }, +{ 'L', 76 }, +{ 'M', 77 }, +{ 'N', 78 }, +{ 'O', 79 }, +{ 'P', 80 }, +{ 'Q', 81 }, +{ 'R', 82 }, +{ 'S', 83 }, +{ 'T', 84 }, +{ 'U', 85 }, +{ 'V', 86 }, +{ 'W', 87 }, +{ 'X', 88 }, +{ 'Y', 89 }, +{ 'Z', 90 }, +{ '[', 91 }, +{ '\\', 92 }, +{ ']', 93 }, +{ '^', 94 }, +{ '_', 95 }, +{ '`', 96 }, +{ 'a', 97 }, +{ 'b', 98 }, +{ 'c', 99 }, +{ 'd', 100 }, +{ 'e', 101 }, +{ 'f', 102 }, +{ 'g', 103 }, +{ 'h', 104 }, +{ 'i', 105 }, +{ 'j', 106 }, +{ 'k', 107 }, +{ 'l', 108 }, +{ 'm', 109 }, +{ 'n', 110 }, +{ 'o', 111 }, +{ 'p', 112 }, +{ 'q', 113 }, +{ 'r', 114 }, +{ 's', 115 }, +{ 't', 116 }, +{ 'u', 117 }, +{ 'v', 118 }, +{ 'w', 119 }, +{ 'x', 120 }, +{ 'y', 121 }, +{ 'z', 122 }, +{ '{', 123 }, +{ '|', 124 }, +{ '}', 125 }, +{ '~', 126 } +}; + +int der_ia5_char_encode(int c) +{ + int x; + for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) { + if (ia5_table[x].code == c) { + return ia5_table[x].value; + } + } + return -1; +} + +int der_ia5_value_decode(int v) +{ + int x; + for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) { + if (ia5_table[x].value == v) { + return ia5_table[x].code; + } + } + return -1; +} + +/** + Gets length of DER encoding of IA5 STRING + @param octets The values you want to encode + @param noctets The number of octets in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) +{ + unsigned long x; + + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(octets != NULL); + + /* scan string for validity */ + for (x = 0; x < noctets; x++) { + if (der_ia5_char_encode(octets[x]) == -1) { + return CRYPT_INVALID_ARG; + } + } + + if (noctets < 128) { + /* 16 LL DD DD DD ... */ + *outlen = 2 + noctets; + } else if (noctets < 256) { + /* 16 81 LL DD DD DD ... */ + *outlen = 3 + noctets; + } else if (noctets < 65536UL) { + /* 16 82 LL LL DD DD DD ... */ + *outlen = 4 + noctets; + } else if (noctets < 16777216UL) { + /* 16 83 LL LL LL DD DD DD ... */ + *outlen = 5 + noctets; + } else { + return CRYPT_INVALID_ARG; + } + + return CRYPT_OK; +} + +#endif + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/der_decode_integer.c b/src/pk/asn1/der/integer/der_decode_integer.c similarity index 54% rename from src/pk/asn1/der/der_decode_integer.c rename to src/pk/asn1/der/integer/der_decode_integer.c index b798bd45..c8d6999d 100644 --- a/src/pk/asn1/der/der_decode_integer.c +++ b/src/pk/asn1/der/integer/der_decode_integer.c @@ -18,81 +18,93 @@ #ifdef LTC_DER -/* decodes a DER INTEGER in [in]. You have to tell this function - * how many bytes are available [inlen]. It will then attempt to - * read the INTEGER. If all goes well it stores the number of bytes - * read in [inlen] and the number in [num]. - */ /** Read a mp_int integer @param in The DER encoded data - @param inlen [in] Size of the in data, [out] number of bytes read + @param inlen Size of DER encoded data @param num The first mp_int to decode @return CRYPT_OK if successful */ -int der_decode_integer(const unsigned char *in, unsigned long *inlen, mp_int *num) +int der_decode_integer(const unsigned char *in, unsigned long inlen, mp_int *num) { - unsigned long tmplen, y, z; + unsigned long x, y, z; + int err; LTC_ARGCHK(num != NULL); LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen != NULL); - - /* save copy of max output size */ - tmplen = *inlen; - *inlen = 0; /* min DER INTEGER is 0x02 01 00 == 0 */ - if (tmplen < (1 + 1 + 1)) { + if (inlen < (1 + 1 + 1)) { return CRYPT_INVALID_PACKET; } - /* ok expect 0x02 when we AND with 0011 1111 [3F] */ - if ((*in++ & 0x3F) != 0x02) { + /* ok expect 0x02 when we AND with 0001 1111 [1F] */ + x = 0; + if ((in[x++] & 0x1F) != 0x02) { return CRYPT_INVALID_PACKET; } - ++(*inlen); /* now decode the len stuff */ - z = *in++; - ++(*inlen); + z = in[x++]; if ((z & 0x80) == 0x00) { /* short form */ /* will it overflow? */ - if (*inlen + z > tmplen) { + if (x + z > inlen) { return CRYPT_INVALID_PACKET; } /* no so read it */ - (*inlen) += z; - return mpi_to_ltc_error(mp_read_unsigned_bin(num, (unsigned char *)in, z)); + if ((err = mpi_to_ltc_error(mp_read_unsigned_bin(num, (unsigned char *)in + x, z))) != CRYPT_OK) { + return err; + } } else { /* long form */ z &= 0x7F; /* will number of length bytes overflow? (or > 4) */ - if (((*inlen + z) > tmplen) || (z > 4)) { + if (((x + z) > inlen) || (z > 4) || (z == 0)) { return CRYPT_INVALID_PACKET; } /* now read it in */ y = 0; while (z--) { - y = ((unsigned long)(*in++)) | (y << 8); - ++(*inlen); + y = ((unsigned long)(in[x++])) | (y << 8); } /* now will reading y bytes overrun? */ - if ((*inlen + y) > tmplen) { + if ((x + y) > inlen) { return CRYPT_INVALID_PACKET; } /* no so read it */ - (*inlen) += y; - return mpi_to_ltc_error(mp_read_unsigned_bin(num, (unsigned char *)in, y)); + if ((err = mpi_to_ltc_error(mp_read_unsigned_bin(num, (unsigned char *)in + x, y))) != CRYPT_OK) { + return err; + } } + + /* see if it's negative */ + if (in[x] & 0x80) { + mp_int tmp; + if (mp_init(&tmp) != MP_OKAY) { + return CRYPT_MEM; + } + + if (mp_2expt(&tmp, mp_count_bits(num)) != MP_OKAY || mp_sub(num, &tmp, num) != MP_OKAY) { + mp_clear(&tmp); + return CRYPT_MEM; + } + mp_clear(&tmp); + } + + return CRYPT_OK; + } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/der_encode_integer.c b/src/pk/asn1/der/integer/der_encode_integer.c similarity index 55% rename from src/pk/asn1/der/der_encode_integer.c rename to src/pk/asn1/der/integer/der_encode_integer.c index c5c5267b..2b44fe5f 100644 --- a/src/pk/asn1/der/der_encode_integer.c +++ b/src/pk/asn1/der/integer/der_encode_integer.c @@ -28,7 +28,7 @@ */ int der_encode_integer(mp_int *num, unsigned char *out, unsigned long *outlen) { - unsigned long tmplen, x, y, z; + unsigned long tmplen, y; int err, leading_zero; LTC_ARGCHK(num != NULL); @@ -44,48 +44,43 @@ int der_encode_integer(mp_int *num, unsigned char *out, unsigned long *outlen) return CRYPT_BUFFER_OVERFLOW; } - /* we only need a leading zero if the msb of the first byte is one */ - if ((mp_count_bits(num) & 7) == 7 || mp_iszero(num) == MP_YES) { - leading_zero = 1; + if (mp_cmp_d(num, 0) != MP_LT) { + /* we only need a leading zero if the msb of the first byte is one */ + if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == MP_YES) { + leading_zero = 1; + } else { + leading_zero = 0; + } + + /* get length of num in bytes (plus 1 since we force the msbyte to zero) */ + y = mp_unsigned_bin_size(num) + leading_zero; } else { leading_zero = 0; - } + y = mp_count_bits(num); + y = y + (8 - (y & 7)); + y = y >> 3; - /* get length of num in bytes (plus 1 since we force the msbyte to zero) */ - y = mp_unsigned_bin_size(num) + leading_zero; + } /* now store initial data */ *out++ = 0x02; if (y < 128) { /* short form */ *out++ = (unsigned char)y; + } else if (y < 256) { + *out++ = 0x81; + *out++ = y; + } else if (y < 65536UL) { + *out++ = 0x82; + *out++ = (y>>8)&255; + *out++ = y; + } else if (y < 16777216UL) { + *out++ = 0x83; + *out++ = (y>>16)&255; + *out++ = (y>>8)&255; + *out++ = y; } else { - /* long form (relies on y != 0) */ - - /* get length of length... ;-) */ - x = y; - z = 0; - while (x) { - ++z; - x >>= 8; - } - - /* store length of length */ - *out++ = 0x80 | ((unsigned char)z); - - /* now store length */ - - /* first shift length up so msbyte != 0 */ - x = y; - while ((x & 0xFF000000) == 0) { - x <<= 8; - } - - /* now store length */ - while (z--) { - *out++ = (unsigned char)((x >> 24) & 0xFF); - x <<= 8; - } + return CRYPT_INVALID_ARG; } /* now store msbyte of zero if num is non-zero */ @@ -94,11 +89,31 @@ int der_encode_integer(mp_int *num, unsigned char *out, unsigned long *outlen) } /* if it's not zero store it as big endian */ - if (mp_iszero(num) == MP_NO) { + if (mp_cmp_d(num, 0) == MP_GT) { /* now store the mpint */ if ((err = mp_to_unsigned_bin(num, out)) != MP_OKAY) { return mpi_to_ltc_error(err); } + } else if (mp_iszero(num) != MP_YES) { + mp_int tmp; + /* negative */ + if (mp_init(&tmp) != MP_OKAY) { + return CRYPT_MEM; + } + + /* 2^roundup and subtract */ + y = mp_count_bits(num); + y = y + (8 - (y & 7)); + if (mp_2expt(&tmp, y) != MP_OKAY || mp_add(&tmp, num, &tmp) != MP_OKAY) { + mp_clear(&tmp); + return CRYPT_MEM; + } + + if ((err = mp_to_unsigned_bin(&tmp, out)) != MP_OKAY) { + mp_clear(&tmp); + return mpi_to_ltc_error(err); + } + mp_clear(&tmp); } /* we good */ @@ -107,3 +122,7 @@ int der_encode_integer(mp_int *num, unsigned char *out, unsigned long *outlen) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/der_length_integer.c b/src/pk/asn1/der/integer/der_length_integer.c similarity index 60% rename from src/pk/asn1/der/der_length_integer.c rename to src/pk/asn1/der/integer/der_length_integer.c index f86738ad..4d9960e4 100644 --- a/src/pk/asn1/der/der_length_integer.c +++ b/src/pk/asn1/der/integer/der_length_integer.c @@ -31,25 +31,33 @@ int der_length_integer(mp_int *num, unsigned long *outlen) LTC_ARGCHK(num != NULL); LTC_ARGCHK(outlen != NULL); - /* we only need a leading zero if the msb of the first byte is one */ - if ((mp_count_bits(num) & 7) == 7 || mp_iszero(num) == MP_YES) { - leading_zero = 1; + if (mp_cmp_d(num, 0) != MP_LT) { + /* positive */ + + /* we only need a leading zero if the msb of the first byte is one */ + if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == MP_YES) { + leading_zero = 1; + } else { + leading_zero = 0; + } + + /* size for bignum */ + z = len = leading_zero + mp_unsigned_bin_size(num); } else { + /* it's negative */ + /* find power of 2 that is a multiple of eight and greater than count bits */ leading_zero = 0; + z = mp_count_bits(num); + z = z + (8 - (z & 7)); + len = z = z >> 3; } - /* size for bignum */ - z = len = leading_zero + mp_unsigned_bin_size(num); - - /* we need a 0x02 */ - ++len; - /* now we need a length */ if (z < 128) { /* short form */ ++len; } else { - /* long form (relies on z != 0) */ + /* long form (relies on z != 0), assumes length bytes < 128 */ ++len; while (z) { @@ -58,8 +66,16 @@ int der_length_integer(mp_int *num, unsigned long *outlen) } } + /* we need a 0x02 to indicate it's INTEGER */ + ++len; + + /* return length */ *outlen = len; return CRYPT_OK; } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c b/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c new file mode 100644 index 00000000..7c6db26b --- /dev/null +++ b/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c @@ -0,0 +1,99 @@ +/* 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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_object_identifier.c + ASN.1 DER, Decode Object Identifier, Tom St Denis +*/ + +#ifdef LTC_DER +/** + Decode OID data and store the array of integers in words + @param in The OID DER encoded data + @param inlen The length of the OID data + @param words [out] The destination of the OID words + @param outlen [in/out] The number of OID words + @return CRYPT_OK if successful +*/ +int der_decode_object_identifier(const unsigned char *in, unsigned long inlen, + unsigned long *words, unsigned long *outlen) +{ + unsigned long x, y, t, len; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(words != NULL); + LTC_ARGCHK(outlen != NULL); + + /* header is at least 3 bytes */ + if (inlen < 3) { + return CRYPT_INVALID_PACKET; + } + + /* must be room for at least two words */ + if (*outlen < 2) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* decode the packet header */ + x = 0; + if ((in[x++] & 0x1F) != 0x06) { + return CRYPT_INVALID_PACKET; + } + + /* get the length */ + if (in[x] < 128) { + len = in[x++]; + } else { + if (in[x] < 0x81 || in[x] > 0x82) { + return CRYPT_INVALID_PACKET; + } + y = in[x++] & 0x7F; + len = 0; + while (y--) { + len = (len << 8) | (unsigned long)in[x++]; + } + } + + if (len < 1 || (len + x) > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* decode word1 and word2 */ + --len; + t = in[x++]; + words[0] = t/40; + words[1] = t%40; + + /* decode rest */ + y = 2; + t = 0; + while (len--) { + t = (t << 7) | (in[x] & 0x7F); + if (!(in[x++] & 0x80)) { + /* store t */ + if (y >= *outlen) { + return CRYPT_BUFFER_OVERFLOW; + } + words[y++] = t; + t = 0; + } + } + + *outlen = y; + return CRYPT_OK; +} + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c b/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c new file mode 100644 index 00000000..4247d78e --- /dev/null +++ b/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c @@ -0,0 +1,103 @@ +/* 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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_object_identifier.c + ASN.1 DER, Encode Object Identifier, Tom St Denis +*/ + +#ifdef LTC_DER +/** + Encode an OID + @param words The words to encode (upto 32-bits each) + @param nwords The number of words in the OID + @param out [out] Destination of OID data + @param outlen [in/out] The max and resulting size of the OID + @return CRYPT_OK if successful +*/ +int der_encode_object_identifier(unsigned long *words, unsigned long nwords, + unsigned char *out, unsigned long *outlen) +{ + unsigned long i, x, y, z, t, mask; + int err; + + LTC_ARGCHK(words != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* check length */ + if ((err = der_length_object_identifier(words, nwords, &x)) != CRYPT_OK) { + return err; + } + if (x > *outlen) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* compute length to store OID data */ + z = 1; + for (y = 2; y < nwords; y++) { + t = der_object_identifier_bits(words[y]); + z += t/7 + ((t%7) ? 1 : 0); + } + + /* store header + length */ + x = 0; + out[x++] = 0x06; + if (z < 128) { + out[x++] = z; + } else if (z < 256) { + out[x++] = 0x81; + out[x++] = z; + } else if (z < 65536UL) { + out[x++] = 0x82; + out[x++] = (z>>8)&255; + out[x++] = z&255; + } else { + return CRYPT_INVALID_ARG; + } + + /* store first byte */ + out[x++] = words[0] * 40 + words[1]; + + for (i = 2; i < nwords; i++) { + /* store 7 bit words in little endian */ + t = words[i] & 0xFFFFFFFF; + if (t) { + y = x; + mask = 0; + while (t) { + out[x++] = (t & 0x7F) | mask; + t >>= 7; + mask |= 0x80; /* upper bit is set on all but the last byte */ + } + /* now swap bytes y...x-1 */ + z = x - 1; + while (y < z) { + t = out[y]; out[y] = out[z]; out[z] = t; + ++y; + --z; + } + } else { + /* zero word */ + out[x++] = 0x00; + } + } + + *outlen = x; + return CRYPT_OK; +} + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/object_identifier/der_length_object_identifier.c b/src/pk/asn1/der/object_identifier/der_length_object_identifier.c new file mode 100644 index 00000000..5c07bc22 --- /dev/null +++ b/src/pk/asn1/der/object_identifier/der_length_object_identifier.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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_length_object_identifier.c + ASN.1 DER, get length of Object Identifier, Tom St Denis +*/ + +#ifdef LTC_DER + +unsigned long der_object_identifier_bits(unsigned long x) +{ + unsigned long c; + x &= 0xFFFFFFFF; + c = 0; + while (x) { + ++c; + x >>= 1; + } + return c; +} + + +/** + Gets length of DER encoding of Object Identifier + @param nwords The number of OID words + @param words The actual OID words to get the size of + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen) +{ + unsigned long y, z, t; + + LTC_ARGCHK(words != NULL); + LTC_ARGCHK(outlen != NULL); + + + /* must be >= 2 words */ + if (nwords < 2) { + return CRYPT_INVALID_ARG; + } + + /* word1 = 0,1,2 and word2 0..39 */ + if (words[0] > 2 || words[1] > 39) { + return CRYPT_INVALID_ARG; + } + + /* leading byte of first two words */ + z = 1; + for (y = 2; y < nwords; y++) { + t = der_object_identifier_bits(words[y]); + z += t/7 + ((t%7) ? 1 : 0); + } + + /* now depending on the length our length encoding changes */ + if (z < 128) { + z += 2; + } else if (z < 256) { + z += 3; + } else if (z < 65536UL) { + z += 4; + } else { + return CRYPT_INVALID_ARG; + } + + *outlen = z; + return CRYPT_OK; +} + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/octet/der_decode_octet_string.c b/src/pk/asn1/der/octet/der_decode_octet_string.c new file mode 100644 index 00000000..185e6deb --- /dev/null +++ b/src/pk/asn1/der/octet/der_decode_octet_string.c @@ -0,0 +1,90 @@ +/* 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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_octet_string.c + ASN.1 DER, encode a OCTET STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a OCTET STRING + @param in The DER encoded OCTET STRING + @param inlen The size of the DER OCTET STRING + @param out [out] The array of octets stored (one per char) + @param outlen [in/out] The number of octets stored + @return CRYPT_OK if successful +*/ +int der_decode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* must have header at least */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check for 0x04 */ + if ((in[0] & 0x1F) != 0x04) { + return CRYPT_INVALID_PACKET; + } + x = 1; + + /* decode the length */ + if (in[x] & 0x80) { + /* valid # of bytes in length are 1,2,3 */ + y = in[x] & 0x7F; + if ((y == 0) || (y > 3) || ((x + y) > inlen)) { + return CRYPT_INVALID_PACKET; + } + + /* read the length in */ + len = 0; + ++x; + while (y--) { + len = (len << 8) | in[x++]; + } + } else { + len = in[x++] & 0x7F; + } + + /* is it too long? */ + if (len > *outlen) { + return CRYPT_BUFFER_OVERFLOW; + } + + if (len + x > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* read the data */ + for (y = 0; y < len; y++) { + out[y] = in[x++]; + } + + *outlen = y; + + return CRYPT_OK; +} + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/octet/der_encode_octet_string.c b/src/pk/asn1/der/octet/der_encode_octet_string.c new file mode 100644 index 00000000..bd882b68 --- /dev/null +++ b/src/pk/asn1/der/octet/der_encode_octet_string.c @@ -0,0 +1,85 @@ +/* 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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_octet_string.c + ASN.1 DER, encode a OCTET STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store an OCTET STRING + @param in The array of OCTETS to store (one per char) + @param inlen The number of OCTETS to store + @param out [out] The destination for the DER encoded OCTET STRING + @param outlen [in/out] The max size and resulting size of the DER OCTET STRING + @return CRYPT_OK if successful +*/ +int der_encode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get the size */ + if ((err = der_length_octet_string(inlen, &len)) != CRYPT_OK) { + return err; + } + + /* too big? */ + if (len > *outlen) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* encode the header+len */ + x = 0; + out[x++] = 0x04; + if (inlen < 128) { + out[x++] = inlen; + } else if (inlen < 256) { + out[x++] = 0x81; + out[x++] = inlen; + } else if (inlen < 65536UL) { + out[x++] = 0x82; + out[x++] = (inlen>>8)&255; + out[x++] = inlen&255; + } else if (inlen < 16777216UL) { + out[x++] = 0x83; + out[x++] = (inlen>>16)&255; + out[x++] = (inlen>>8)&255; + out[x++] = inlen&255; + } else { + return CRYPT_INVALID_ARG; + } + + /* store octets */ + for (y = 0; y < inlen; y++) { + out[x++] = in[y]; + } + + /* retun length */ + *outlen = x; + + return CRYPT_OK; +} + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/octet/der_length_octet_string.c b/src/pk/asn1/der/octet/der_length_octet_string.c new file mode 100644 index 00000000..72874544 --- /dev/null +++ b/src/pk/asn1/der/octet/der_length_octet_string.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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_length_octet_string.c + ASN.1 DER, get length of OCTET STRING, Tom St Denis +*/ + +#ifdef LTC_DER +/** + Gets length of DER encoding of OCTET STRING + @param noctets The number of octets in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_octet_string(unsigned long noctets, unsigned long *outlen) +{ + LTC_ARGCHK(outlen != NULL); + + if (noctets < 128) { + /* 04 LL DD DD DD ... */ + *outlen = 2 + noctets; + } else if (noctets < 256) { + /* 04 81 LL DD DD DD ... */ + *outlen = 3 + noctets; + } else if (noctets < 65536UL) { + /* 04 82 LL LL DD DD DD ... */ + *outlen = 4 + noctets; + } else if (noctets < 16777216UL) { + /* 04 83 LL LL LL DD DD DD ... */ + *outlen = 5 + noctets; + } else { + return CRYPT_INVALID_ARG; + } + + return CRYPT_OK; +} + +#endif + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/printable_string/der_decode_printable_string.c b/src/pk/asn1/der/printable_string/der_decode_printable_string.c new file mode 100644 index 00000000..e967740d --- /dev/null +++ b/src/pk/asn1/der/printable_string/der_decode_printable_string.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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_printable_string.c + ASN.1 DER, encode a printable STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a printable STRING + @param in The DER encoded printable STRING + @param inlen The size of the DER printable STRING + @param out [out] The array of octets stored (one per char) + @param outlen [in/out] The number of octets stored + @return CRYPT_OK if successful +*/ +int der_decode_printable_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + int t; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* must have header at least */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check for 0x13 */ + if ((in[0] & 0x1F) != 0x13) { + return CRYPT_INVALID_PACKET; + } + x = 1; + + /* decode the length */ + if (in[x] & 0x80) { + /* valid # of bytes in length are 1,2,3 */ + y = in[x] & 0x7F; + if ((y == 0) || (y > 3) || ((x + y) > inlen)) { + return CRYPT_INVALID_PACKET; + } + + /* read the length in */ + len = 0; + ++x; + while (y--) { + len = (len << 8) | in[x++]; + } + } else { + len = in[x++] & 0x7F; + } + + /* is it too long? */ + if (len > *outlen) { + return CRYPT_BUFFER_OVERFLOW; + } + + if (len + x > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* read the data */ + for (y = 0; y < len; y++) { + t = der_printable_value_decode(in[x++]); + if (t == -1) { + return CRYPT_INVALID_ARG; + } + out[y] = t; + } + + *outlen = y; + + return CRYPT_OK; +} + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/printable_string/der_encode_printable_string.c b/src/pk/asn1/der/printable_string/der_encode_printable_string.c new file mode 100644 index 00000000..82bab8e5 --- /dev/null +++ b/src/pk/asn1/der/printable_string/der_encode_printable_string.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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_printable_string.c + ASN.1 DER, encode a printable STRING, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Store an printable STRING + @param in The array of printable to store (one per char) + @param inlen The number of printable to store + @param out [out] The destination for the DER encoded printable STRING + @param outlen [in/out] The max size and resulting size of the DER printable STRING + @return CRYPT_OK if successful +*/ +int der_encode_printable_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get the size */ + if ((err = der_length_printable_string(in, inlen, &len)) != CRYPT_OK) { + return err; + } + + /* too big? */ + if (len > *outlen) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* encode the header+len */ + x = 0; + out[x++] = 0x13; + if (inlen < 128) { + out[x++] = inlen; + } else if (inlen < 256) { + out[x++] = 0x81; + out[x++] = inlen; + } else if (inlen < 65536UL) { + out[x++] = 0x82; + out[x++] = (inlen>>8)&255; + out[x++] = inlen&255; + } else if (inlen < 16777216UL) { + out[x++] = 0x83; + out[x++] = (inlen>>16)&255; + out[x++] = (inlen>>8)&255; + out[x++] = inlen&255; + } else { + return CRYPT_INVALID_ARG; + } + + /* store octets */ + for (y = 0; y < inlen; y++) { + out[x++] = der_printable_char_encode(in[y]); + } + + /* retun length */ + *outlen = x; + + return CRYPT_OK; +} + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/printable_string/der_length_printable_string.c b/src/pk/asn1/der/printable_string/der_length_printable_string.c new file mode 100644 index 00000000..b8aaab3b --- /dev/null +++ b/src/pk/asn1/der/printable_string/der_length_printable_string.c @@ -0,0 +1,166 @@ +/* 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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_length_printable_string.c + ASN.1 DER, get length of Printable STRING, Tom St Denis +*/ + +#ifdef LTC_DER + +static const struct { + int code, value; +} printable_table[] = { +{ ' ', 32 }, +{ '\'', 39 }, +{ '(', 40 }, +{ ')', 41 }, +{ '+', 43 }, +{ ',', 44 }, +{ '-', 45 }, +{ '.', 46 }, +{ '/', 47 }, +{ '0', 48 }, +{ '1', 49 }, +{ '2', 50 }, +{ '3', 51 }, +{ '4', 52 }, +{ '5', 53 }, +{ '6', 54 }, +{ '7', 55 }, +{ '8', 56 }, +{ '9', 57 }, +{ ':', 58 }, +{ '=', 61 }, +{ '?', 63 }, +{ 'A', 65 }, +{ 'B', 66 }, +{ 'C', 67 }, +{ 'D', 68 }, +{ 'E', 69 }, +{ 'F', 70 }, +{ 'G', 71 }, +{ 'H', 72 }, +{ 'I', 73 }, +{ 'J', 74 }, +{ 'K', 75 }, +{ 'L', 76 }, +{ 'M', 77 }, +{ 'N', 78 }, +{ 'O', 79 }, +{ 'P', 80 }, +{ 'Q', 81 }, +{ 'R', 82 }, +{ 'S', 83 }, +{ 'T', 84 }, +{ 'U', 85 }, +{ 'V', 86 }, +{ 'W', 87 }, +{ 'X', 88 }, +{ 'Y', 89 }, +{ 'Z', 90 }, +{ 'a', 97 }, +{ 'b', 98 }, +{ 'c', 99 }, +{ 'd', 100 }, +{ 'e', 101 }, +{ 'f', 102 }, +{ 'g', 103 }, +{ 'h', 104 }, +{ 'i', 105 }, +{ 'j', 106 }, +{ 'k', 107 }, +{ 'l', 108 }, +{ 'm', 109 }, +{ 'n', 110 }, +{ 'o', 111 }, +{ 'p', 112 }, +{ 'q', 113 }, +{ 'r', 114 }, +{ 's', 115 }, +{ 't', 116 }, +{ 'u', 117 }, +{ 'v', 118 }, +{ 'w', 119 }, +{ 'x', 120 }, +{ 'y', 121 }, +{ 'z', 122 }, +}; + +int der_printable_char_encode(int c) +{ + int x; + for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) { + if (printable_table[x].code == c) { + return printable_table[x].value; + } + } + return -1; +} + +int der_printable_value_decode(int v) +{ + int x; + for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) { + if (printable_table[x].value == v) { + return printable_table[x].code; + } + } + return -1; +} + +/** + Gets length of DER encoding of Printable STRING + @param octets The values you want to encode + @param noctets The number of octets in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) +{ + unsigned long x; + + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(octets != NULL); + + /* scan string for validity */ + for (x = 0; x < noctets; x++) { + if (der_printable_char_encode(octets[x]) == -1) { + return CRYPT_INVALID_ARG; + } + } + + if (noctets < 128) { + /* 16 LL DD DD DD ... */ + *outlen = 2 + noctets; + } else if (noctets < 256) { + /* 16 81 LL DD DD DD ... */ + *outlen = 3 + noctets; + } else if (noctets < 65536UL) { + /* 16 82 LL LL DD DD DD ... */ + *outlen = 4 + noctets; + } else if (noctets < 16777216UL) { + /* 16 83 LL LL LL DD DD DD ... */ + *outlen = 5 + noctets; + } else { + return CRYPT_INVALID_ARG; + } + + return CRYPT_OK; +} + +#endif + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/sequence/der_decode_sequence.c b/src/pk/asn1/der/sequence/der_decode_sequence.c new file mode 100644 index 00000000..7228497d --- /dev/null +++ b/src/pk/asn1/der/sequence/der_decode_sequence.c @@ -0,0 +1,215 @@ +/* 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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" +#include + + +/** + @file der_decode_sequence.c + ASN.1 DER, decode a SEQUENCE, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Decode a SEQUENCE + @param in The DER encoded input + @param inlen The size of the input + @param list The list of items to decode + @param outlen The number of items in the list + @return CRYPT_OK on success +*/ +int der_decode_sequence(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *list, unsigned long outlen) +{ + int err, type; + unsigned long size, x, y, z, i, blksize; + void *data; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(list != NULL); + + /* get blk size */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* sequence type? */ + x = 0; + if (in[x++] != 0x30) { + return CRYPT_INVALID_PACKET; + } + + if (in[x] < 128) { + blksize = in[x++]; + } else if (in[x] & 0x80) { + if (in[x] < 0x81 || in[x] > 0x83) { + return CRYPT_INVALID_PACKET; + } + y = in[x++] & 0x7F; + + /* would reading the len bytes overrun? */ + if (x + y > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* read len */ + blksize = 0; + while (y--) { + blksize = (blksize << 8) | (unsigned long)in[x++]; + } + } + + /* would this blksize overflow? */ + if (x + blksize > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* ok read data */ + inlen = blksize; + for (i = 0; i < outlen; i++) { + type = list[i].type; + size = list[i].size; + data = list[i].data; + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_INTEGER: + z = inlen; + if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = der_length_integer(data, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + inlen -= z; + break; + + + case LTC_ASN1_SHORT_INTEGER: + z = inlen; + if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = der_length_short_integer(size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + inlen -= z; + break; + + case LTC_ASN1_BIT_STRING: + z = inlen; + if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) { + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + inlen -= z; + break; + + case LTC_ASN1_OCTET_STRING: + z = inlen; + if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) { + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + inlen -= z; + break; + + case LTC_ASN1_NULL: + if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + x += 2; + inlen -= 2; + break; + + case LTC_ASN1_OBJECT_IDENTIFIER: + z = inlen; + if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) { + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + inlen -= z; + break; + + case LTC_ASN1_IA5_STRING: + z = inlen; + if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) { + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + inlen -= z; + break; + + + case LTC_ASN1_PRINTABLE_STRING: + z = inlen; + if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) { + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + inlen -= z; + break; + + case LTC_ASN1_SEQUENCE: + z = inlen; + if ((err = der_decode_sequence(in + x, z, data, size)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + inlen -= z; + break; + + default: + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + } + err = CRYPT_OK; + +LBL_ERR: + return err; +} + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/sequence/der_decode_sequence_multi.c b/src/pk/asn1/der/sequence/der_decode_sequence_multi.c new file mode 100644 index 00000000..539f310a --- /dev/null +++ b/src/pk/asn1/der/sequence/der_decode_sequence_multi.c @@ -0,0 +1,120 @@ +/* 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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" +#include + + +/** + @file der_decode_sequence_multi.c + ASN.1 DER, decode a SEQUENCE, Tom St Denis +*/ + +#ifdef LTC_DER + +int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) +{ + int err, type; + unsigned long size, x; + void *data; + va_list args; + ltc_asn1_list *list; + + LTC_ARGCHK(in != NULL); + + /* get size of output that will be required */ + va_start(args, inlen); + x = 0; + for (;;) { + type = va_arg(args, int); + size = va_arg(args, unsigned long); + data = va_arg(args, void*); + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_INTEGER: + case LTC_ASN1_SHORT_INTEGER: + case LTC_ASN1_BIT_STRING: + case LTC_ASN1_OCTET_STRING: + case LTC_ASN1_NULL: + case LTC_ASN1_OBJECT_IDENTIFIER: + case LTC_ASN1_IA5_STRING: + case LTC_ASN1_PRINTABLE_STRING: + case LTC_ASN1_SEQUENCE: + ++x; + break; + + default: + va_end(args); + return CRYPT_INVALID_ARG; + } + } + va_end(args); + + /* allocate structure for x elements */ + if (x == 0) { + return CRYPT_NOP; + } + + list = XCALLOC(sizeof(*list), x); + if (list == NULL) { + return CRYPT_MEM; + } + + /* fill in the structure */ + va_start(args, inlen); + x = 0; + for (;;) { + type = va_arg(args, int); + size = va_arg(args, unsigned long); + data = va_arg(args, void*); + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_INTEGER: + case LTC_ASN1_SHORT_INTEGER: + case LTC_ASN1_BIT_STRING: + case LTC_ASN1_OCTET_STRING: + case LTC_ASN1_NULL: + case LTC_ASN1_OBJECT_IDENTIFIER: + case LTC_ASN1_IA5_STRING: + case LTC_ASN1_PRINTABLE_STRING: + case LTC_ASN1_SEQUENCE: + list[x].type = type; + list[x].size = size; + list[x++].data = data; + break; + + default: + va_end(args); + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + } + va_end(args); + + err = der_decode_sequence(in, inlen, list, x); +LBL_ERR: + XFREE(list); + return err; +} + +#endif + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/sequence/der_encode_sequence.c b/src/pk/asn1/der/sequence/der_encode_sequence.c new file mode 100644 index 00000000..6f86a4a6 --- /dev/null +++ b/src/pk/asn1/der/sequence/der_encode_sequence.c @@ -0,0 +1,265 @@ +/* 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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" +#include + + +/** + @file der_encode_sequence.c + ASN.1 DER, encode a SEQUENCE, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Encode a SEQUENCE + @param list The list of items to encode + @param inlen The number of items in the list + @param out [out] The destination + @param outlen [in/out] The size of the output + @return CRYPT_OK on success +*/ +int der_encode_sequence(ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + int err, type; + unsigned long size, x, y, z, i; + void *data; + + LTC_ARGCHK(list != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get size of output that will be required */ + y = 0; + for (i = 0; i < inlen; i++) { + type = list[i].type; + size = list[i].size; + data = list[i].data; + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_INTEGER: + if ((err = der_length_integer(data, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_SHORT_INTEGER: + if ((err = der_length_short_integer(*((unsigned long*)data), &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_BIT_STRING: + if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_OCTET_STRING: + if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_NULL: + y += 2; + break; + + case LTC_ASN1_OBJECT_IDENTIFIER: + if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_IA5_STRING: + if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_PRINTABLE_STRING: + if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_SEQUENCE: + if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + + default: + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + } + + /* calc header size */ + z = y; + if (y < 128) { + y += 2; + } else if (y < 256) { + /* 0x30 0x81 LL */ + y += 3; + } else if (y < 65536UL) { + /* 0x30 0x82 LL LL */ + y += 4; + } else if (y < 16777216UL) { + /* 0x30 0x83 LL LL LL */ + y += 5; + } else { + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + + /* too big ? */ + if (*outlen < y) { + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + /* store header */ + x = 0; + out[x++] = 0x30; + if (z < 128) { + out[x++] = z; + } else if (z < 256) { + out[x++] = 0x81; + out[x++] = z; + } else if (z < 65536UL) { + out[x++] = 0x82; + out[x++] = (z>>8UL)&255; + out[x++] = z&255; + } else if (z < 16777216UL) { + out[x++] = 0x83; + out[x++] = (z>>16UL)&255; + out[x++] = (z>>8UL)&255; + out[x++] = z&255; + } + + /* store data */ + *outlen -= x; + for (i = 0; i < inlen; i++) { + type = list[i].type; + size = list[i].size; + data = list[i].data; + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_INTEGER: + z = *outlen; + if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_SHORT_INTEGER: + z = *outlen; + if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_BIT_STRING: + z = *outlen; + if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_OCTET_STRING: + z = *outlen; + if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_NULL: + out[x++] = 0x05; + out[x++] = 0x00; + *outlen -= 2; + break; + + case LTC_ASN1_OBJECT_IDENTIFIER: + z = *outlen; + if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_IA5_STRING: + z = *outlen; + if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_PRINTABLE_STRING: + z = *outlen; + if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + case LTC_ASN1_SEQUENCE: + z = *outlen; + if ((err = der_encode_sequence(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + x += z; + *outlen -= z; + break; + + default: + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + } + *outlen = x; + err = CRYPT_OK; + +LBL_ERR: + return err; +} + +#endif diff --git a/src/pk/asn1/der/sequence/der_encode_sequence_multi.c b/src/pk/asn1/der/sequence/der_encode_sequence_multi.c new file mode 100644 index 00000000..1b7fccbb --- /dev/null +++ b/src/pk/asn1/der/sequence/der_encode_sequence_multi.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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" +#include + + +/** + @file der_encode_sequence_multi.c + ASN.1 DER, encode a SEQUENCE, Tom St Denis +*/ + +#ifdef LTC_DER + +int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) +{ + int err, type; + unsigned long size, x; + void *data; + va_list args; + ltc_asn1_list *list; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get size of output that will be required */ + va_start(args, outlen); + x = 0; + for (;;) { + type = va_arg(args, int); + size = va_arg(args, unsigned long); + data = va_arg(args, void*); + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_INTEGER: + case LTC_ASN1_SHORT_INTEGER: + case LTC_ASN1_BIT_STRING: + case LTC_ASN1_OCTET_STRING: + case LTC_ASN1_NULL: + case LTC_ASN1_OBJECT_IDENTIFIER: + case LTC_ASN1_IA5_STRING: + case LTC_ASN1_PRINTABLE_STRING: + case LTC_ASN1_SEQUENCE: + ++x; + break; + + default: + va_end(args); + return CRYPT_INVALID_ARG; + } + } + va_end(args); + + /* allocate structure for x elements */ + if (x == 0) { + return CRYPT_NOP; + } + + list = XCALLOC(sizeof(*list), x); + if (list == NULL) { + return CRYPT_MEM; + } + + /* fill in the structure */ + va_start(args, outlen); + x = 0; + for (;;) { + type = va_arg(args, int); + size = va_arg(args, unsigned long); + data = va_arg(args, void*); + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_INTEGER: + case LTC_ASN1_SHORT_INTEGER: + case LTC_ASN1_BIT_STRING: + case LTC_ASN1_OCTET_STRING: + case LTC_ASN1_NULL: + case LTC_ASN1_OBJECT_IDENTIFIER: + case LTC_ASN1_IA5_STRING: + case LTC_ASN1_PRINTABLE_STRING: + case LTC_ASN1_SEQUENCE: + list[x].type = type; + list[x].size = size; + list[x++].data = data; + break; + + default: + va_end(args); + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + } + va_end(args); + + err = der_encode_sequence(list, x, out, outlen); +LBL_ERR: + XFREE(list); + return err; +} + +#endif + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/sequence/der_length_sequence.c b/src/pk/asn1/der/sequence/der_length_sequence.c new file mode 100644 index 00000000..91204519 --- /dev/null +++ b/src/pk/asn1/der/sequence/der_length_sequence.c @@ -0,0 +1,144 @@ +/* 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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" +#include + + +/** + @file der_length_sequence.c + ASN.1 DER, length a SEQUENCE, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Get the length of a DER sequence + @param list The sequences of items in the SEQUENCE + @param inlen The number of items + @param outlen [out] The length required in octets to store it + @return CRYPT_OK on success +*/ +int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, + unsigned long *outlen) +{ + int err, type; + unsigned long size, x, y, z, i; + void *data; + + LTC_ARGCHK(list != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get size of output that will be required */ + y = 0; + for (i = 0; i < inlen; i++) { + type = list[i].type; + size = list[i].size; + data = list[i].data; + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_INTEGER: + if ((err = der_length_integer(data, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_SHORT_INTEGER: + if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_BIT_STRING: + if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_OCTET_STRING: + if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_NULL: + y += 2; + break; + + case LTC_ASN1_OBJECT_IDENTIFIER: + if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_IA5_STRING: + if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_PRINTABLE_STRING: + if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_SEQUENCE: + if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + + default: + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + } + + /* calc header size */ + z = y; + if (y < 128) { + y += 2; + } else if (y < 256) { + /* 0x30 0x81 LL */ + y += 3; + } else if (y < 65536UL) { + /* 0x30 0x82 LL LL */ + y += 4; + } else if (y < 16777216UL) { + /* 0x30 0x83 LL LL LL */ + y += 5; + } else { + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + + /* store size */ + *outlen = y; + err = CRYPT_OK; + +LBL_ERR: + return err; +} + +#endif diff --git a/src/pk/asn1/der/short_integer/der_decode_short_integer.c b/src/pk/asn1/der/short_integer/der_decode_short_integer.c new file mode 100644 index 00000000..6e731e10 --- /dev/null +++ b/src/pk/asn1/der/short_integer/der_decode_short_integer.c @@ -0,0 +1,68 @@ +/* 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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_short_integer.c + ASN.1 DER, decode an integer, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Read a mp_int integer + @param in The DER encoded data + @param inlen Size of data + @param num [out] The integer to decode + @return CRYPT_OK if successful +*/ +int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num) +{ + unsigned long len, x, y; + + LTC_ARGCHK(num != NULL); + LTC_ARGCHK(in != NULL); + + /* check length */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check header */ + x = 0; + if ((in[x++] & 0x1F) != 0x02) { + return CRYPT_INVALID_PACKET; + } + + /* get the packet len */ + len = in[x++]; + + if (x + len > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* read number */ + y = 0; + while (len--) { + y = (y<<8) | (unsigned long)in[x++]; + } + *num = y; + + return CRYPT_OK; + +} + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/short_integer/der_encode_short_integer.c b/src/pk/asn1/der/short_integer/der_encode_short_integer.c new file mode 100644 index 00000000..51f45f78 --- /dev/null +++ b/src/pk/asn1/der/short_integer/der_encode_short_integer.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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_encode_short_integer.c + ASN.1 DER, encode an integer, Tom St Denis +*/ + + +#ifdef LTC_DER + +/* Exports a positive integer as DER format (upto 32-bits in size) */ +/** + Store a mp_int integer + @param num The integer to encode + @param out [out] The destination for the DER encoded integers + @param outlen [in/out] The max size and resulting size of the DER encoded integers + @return CRYPT_OK if successful +*/ +int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen) +{ + unsigned long len, x, y, z; + int err; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* force to 32 bits */ + num &= 0xFFFFFFFFUL; + + /* find out how big this will be */ + if ((err = der_length_short_integer(num, &len)) != CRYPT_OK) { + return err; + } + + if (*outlen < len) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* get len of output */ + z = 0; + y = num; + while (y) { + ++z; + y >>= 8; + } + + /* handle zero */ + if (z == 0) { + z = 1; + } + + /* see if msb is set */ + z += (num&(1UL<<((z<<3) - 1))) ? 1 : 0; + + /* adjust the number so the msB is non-zero */ + for (x = 0; (z <= 4) && (x < (4 - z)); x++) { + num <<= 8; + } + + /* store header */ + x = 0; + out[x++] = 0x02; + out[x++] = z; + + /* if 31st bit is set output a leading zero and decrement count */ + if (z == 5) { + out[x++] = 0; + --z; + } + + /* store values */ + for (y = 0; y < z; y++) { + out[x++] = (num >> 24) & 0xFF; + num <<= 8; + } + + /* we good */ + *outlen = x; + + return CRYPT_OK; +} + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/short_integer/der_length_short_integer.c b/src/pk/asn1/der/short_integer/der_length_short_integer.c new file mode 100644 index 00000000..4d7f4ab2 --- /dev/null +++ b/src/pk/asn1/der/short_integer/der_length_short_integer.c @@ -0,0 +1,69 @@ +/* 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@gmail.com, http://libtomcrypt.org + */ +#include "tomcrypt.h" + +/** + @file der_length_short_integer.c + ASN.1 DER, get length of encoding, Tom St Denis +*/ + + +#ifdef LTC_DER +/** + Gets length of DER encoding of num + @param num The integer to get the size of + @param outlen [out] The length of the DER encoding for the given integer + @return CRYPT_OK if successful +*/ +int der_length_short_integer(unsigned long num, unsigned long *outlen) +{ + unsigned long z, y, len; + + LTC_ARGCHK(outlen != NULL); + + /* force to 32 bits */ + num &= 0xFFFFFFFFUL; + + /* get the number of bytes */ + z = 0; + y = num; + while (y) { + ++z; + y >>= 8; + } + + /* handle zero */ + if (z == 0) { + z = 1; + } + + /* we need a 0x02 to indicate it's INTEGER */ + len = 1; + + /* length byte */ + ++len; + + /* bytes in value */ + len += z; + + /* see if msb is set */ + len += (num&(1UL<<((z<<3) - 1))) ? 1 : 0; + + /* return length */ + *outlen = len; + return CRYPT_OK; +} + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/dh/dh.c b/src/pk/dh/dh.c index c2085a6a..9782f4f3 100644 --- a/src/pk/dh/dh.c +++ b/src/pk/dh/dh.c @@ -518,3 +518,7 @@ done: #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/dh/dh_sys.c b/src/pk/dh/dh_sys.c index 801f85ac..a6614d7b 100644 --- a/src/pk/dh/dh_sys.c +++ b/src/pk/dh/dh_sys.c @@ -493,3 +493,7 @@ done: return err; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/dsa/dsa_export.c b/src/pk/dsa/dsa_export.c index 773023ea..ee785b7c 100644 --- a/src/pk/dsa/dsa_export.c +++ b/src/pk/dsa/dsa_export.c @@ -27,18 +27,13 @@ */ int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key) { - unsigned long y, z; - int err; + unsigned char flags[1]; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_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; } @@ -47,29 +42,31 @@ int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key return CRYPT_INVALID_ARG; } - /* store header */ - packet_store_header(out, PACKET_SECT_DSA, PACKET_SUB_KEY); - y = PACKET_SIZE; + flags[0] = (type != PK_PUBLIC) ? 1 : 0; - /* 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); + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, &key->g, + LTC_ASN1_INTEGER, 1UL, &key->p, + LTC_ASN1_INTEGER, 1UL, &key->q, + LTC_ASN1_INTEGER, 1UL, &key->y, + LTC_ASN1_INTEGER, 1UL, &key->x, + LTC_ASN1_EOL, 0UL, NULL); + } else { + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, &key->g, + LTC_ASN1_INTEGER, 1UL, &key->p, + LTC_ASN1_INTEGER, 1UL, &key->q, + LTC_ASN1_INTEGER, 1UL, &key->y, + LTC_ASN1_EOL, 0UL, NULL); } - - *outlen = y; - return CRYPT_OK; } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/dsa/dsa_free.c b/src/pk/dsa/dsa_free.c index 862a2dd5..0bde19f5 100644 --- a/src/pk/dsa/dsa_free.c +++ b/src/pk/dsa/dsa_free.c @@ -28,3 +28,7 @@ void dsa_free(dsa_key *key) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/dsa/dsa_import.c b/src/pk/dsa/dsa_import.c index 6de56e3c..b2e1776d 100644 --- a/src/pk/dsa/dsa_import.c +++ b/src/pk/dsa/dsa_import.c @@ -26,46 +26,64 @@ */ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) { - unsigned long x, y; + unsigned char flags[1]; int err; LTC_ARGCHK(in != NULL); LTC_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); + /* get key type */ + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto error; } - return CRYPT_OK; + if (flags[0] == 1) { + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, &key->g, + LTC_ASN1_INTEGER, 1UL, &key->p, + LTC_ASN1_INTEGER, 1UL, &key->q, + LTC_ASN1_INTEGER, 1UL, &key->y, + LTC_ASN1_INTEGER, 1UL, &key->x, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto error; + } + key->type = PK_PRIVATE; + } else { + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, &key->g, + LTC_ASN1_INTEGER, 1UL, &key->p, + LTC_ASN1_INTEGER, 1UL, &key->q, + LTC_ASN1_INTEGER, 1UL, &key->y, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto error; + } + key->type = PK_PUBLIC; + } + key->qord = mp_unsigned_bin_size(&key->q); + + if (key->qord >= MDSA_MAX_GROUP || key->qord <= 15 || + key->qord >= mp_unsigned_bin_size(&key->p) || (mp_unsigned_bin_size(&key->p) - key->qord) >= MDSA_DELTA) { + err = CRYPT_INVALID_PACKET; + goto error; + } + + return CRYPT_OK; error: mp_clear_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL); return err; } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/dsa/dsa_make_key.c b/src/pk/dsa/dsa_make_key.c index 60683a0c..a43da125 100644 --- a/src/pk/dsa/dsa_make_key.c +++ b/src/pk/dsa/dsa_make_key.c @@ -140,3 +140,7 @@ done: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/dsa/dsa_sign_hash.c b/src/pk/dsa/dsa_sign_hash.c index da92a825..05e11ca1 100644 --- a/src/pk/dsa/dsa_sign_hash.c +++ b/src/pk/dsa/dsa_sign_hash.c @@ -21,26 +21,25 @@ Sign a hash with DSA @param in The hash to sign @param inlen The length of the hash to sign - @param out [out] Where to store the signature - @param outlen [in/out] The max size and resulting size of the signature + @param r The "r" integer of the signature (caller must initialize with mp_init() first) + @param s The "s" integer of the signature (caller must initialize with mp_init() first) @param prng An active PRNG state @param wprng The index of the PRNG desired @param key A private DSA key @return CRYPT_OK if successful */ -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) +int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen, + mp_int *r, mp_int *s, + prng_state *prng, int wprng, dsa_key *key) { - mp_int k, kinv, tmp, r, s; + mp_int k, kinv, tmp; unsigned char *buf; int err; - unsigned long out1, out2; - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(r != NULL); + LTC_ARGCHK(s != NULL); + LTC_ARGCHK(key != NULL); if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; @@ -60,7 +59,7 @@ int dsa_sign_hash(const unsigned char *in, unsigned long inlen, } /* Init our temps */ - if ((err = mp_init_multi(&k, &kinv, &r, &s, &tmp, NULL)) != MP_OKAY) { goto error; } + if ((err = mp_init_multi(&k, &kinv, &tmp, NULL)) != MP_OKAY) { goto error; } retry: @@ -85,37 +84,26 @@ retry: 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 ((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; } + 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 ((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; } + if (mp_iszero(s) == MP_YES) { goto retry; } - /* now store em both */ - - /* first check that we have enough room */ - if ((err = der_length_integer(&s, &out1)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = der_length_integer(&r, &out2)) != CRYPT_OK) { goto LBL_ERR; } - if (*outlen < (out1+out2)) { - err = CRYPT_BUFFER_OVERFLOW; - goto LBL_ERR; - } - - /* store ints */ - err = der_put_multi_integer(out, outlen, &r, &s, NULL); + err = CRYPT_OK; goto LBL_ERR; error: err = mpi_to_ltc_error(err); LBL_ERR: - mp_clear_multi(&k, &kinv, &r, &s, &tmp, NULL); + mp_clear_multi(&k, &kinv, &tmp, NULL); #ifdef LTC_CLEAN_STACK zeromem(buf, MDSA_MAX_GROUP); #endif @@ -123,4 +111,49 @@ LBL_ERR: return err; } +/** + Sign a hash with DSA + @param in The hash to sign + @param inlen The length of the hash to sign + @param out [out] Where to store the signature + @param outlen [in/out] The max size and resulting size of the signature + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param key A private DSA key + @return CRYPT_OK if successful +*/ +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 r, s; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + if (mp_init_multi(&r, &s, NULL) != MP_OKAY) { + return CRYPT_MEM; + } + + if ((err = dsa_sign_hash_raw(in, inlen, &r, &s, prng, wprng, key)) != CRYPT_OK) { + goto LBL_ERR; + } + + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_INTEGER, 1UL, &r, + LTC_ASN1_INTEGER, 1UL, &s, + LTC_ASN1_EOL, 0UL, NULL); + +LBL_ERR: + mp_clear_multi(&r, &s, NULL); + return err; +} + #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/dsa/dsa_verify_hash.c b/src/pk/dsa/dsa_verify_hash.c index 140f0e20..1d7ed56d 100644 --- a/src/pk/dsa/dsa_verify_hash.c +++ b/src/pk/dsa/dsa_verify_hash.c @@ -18,6 +18,71 @@ #ifdef MDSA +/** + Verify a DSA signature + @param r DSA "r" parameter + @param s DSA "s" parameter + @param hash The hash that was signed + @param hashlen The length of the hash that was signed + @param stat [out] The result of the signature verification, 1==valid, 0==invalid + @param key The corresponding public DH key + @return CRYPT_OK if successful (even if the signature is invalid) +*/ +int dsa_verify_hash_raw( mp_int *r, mp_int *s, + const unsigned char *hash, unsigned long hashlen, + int *stat, dsa_key *key) +{ + mp_int w, v, u1, u2; + int err; + + LTC_ARGCHK(r != NULL); + LTC_ARGCHK(s != NULL); + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(key != NULL); + + /* default to invalid signature */ + *stat = 0; + + /* init our variables */ + if ((err = mp_init_multi(&w, &v, &u1, &u2, NULL)) != MP_OKAY) { + return mpi_to_ltc_error(err); + } + + /* neither r or s can be null or >q*/ + if (mp_iszero(r) == MP_YES || mp_iszero(s) == MP_YES || mp_cmp(r, &key->q) != MP_LT || mp_cmp(s, &key->q) != MP_LT) { + err = CRYPT_INVALID_PACKET; + goto done; + } + + /* 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, hashlen)) != 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(&w, &v, &u1, &u2, NULL); + return err; +} + /** Verify a DSA signature @param sig The signature @@ -32,59 +97,32 @@ int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int *stat, dsa_key *key) { - mp_int r, s, w, v, u1, u2; - int err; + int err; + mp_int r, s; - LTC_ARGCHK(sig != NULL); - LTC_ARGCHK(hash != NULL); - LTC_ARGCHK(stat != NULL); - LTC_ARGCHK(key != NULL); - - /* default to invalid signature */ - *stat = 0; - - /* init our variables */ - if ((err = mp_init_multi(&r, &s, &w, &v, &u1, &u2, NULL)) != MP_OKAY) { - return mpi_to_ltc_error(err); + if ((err = mp_init_multi(&r, &s, NULL)) != CRYPT_OK) { + return CRYPT_MEM; } - /* read in r followed by s */ - if ((err = der_get_multi_integer(sig, &siglen, &r, &s, NULL)) != CRYPT_OK) { goto done; } - - /* neither r or s can be null */ - if (mp_iszero(&r) == MP_YES || mp_iszero(&s) == MP_YES) { - err = CRYPT_INVALID_PACKET; - goto done; - } - - /* 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, hashlen)) != 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; + /* decode the sequence */ + if ((err = der_decode_sequence_multi(sig, siglen, + LTC_ASN1_INTEGER, 1UL, &r, + LTC_ASN1_INTEGER, 1UL, &s, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; } - err = CRYPT_OK; - goto done; + /* do the op */ + err = dsa_verify_hash_raw(&r, &s, hash, hashlen, stat, key); -error : err = mpi_to_ltc_error(err); -done : mp_clear_multi(&r, &s, &w, &v, &u1, &u2, NULL); +LBL_ERR: + mp_clear_multi(&r, &s, NULL); return err; } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/dsa/dsa_verify_key.c b/src/pk/dsa/dsa_verify_key.c index 3e842614..8eed7f14 100644 --- a/src/pk/dsa/dsa_verify_key.c +++ b/src/pk/dsa/dsa_verify_key.c @@ -96,3 +96,7 @@ done : mp_clear_multi(&tmp, &tmp2, NULL); return err; } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/ecc/ecc.c b/src/pk/ecc/ecc.c index b5e088b0..605b0fbd 100644 --- a/src/pk/ecc/ecc.c +++ b/src/pk/ecc/ecc.c @@ -24,7 +24,7 @@ #ifdef MECC /* size of our temp buffers for exported keys */ -#define ECC_BUF_SIZE 160 +#define ECC_BUF_SIZE 256 /* max private key size */ #define ECC_MAXSIZE 66 @@ -34,22 +34,6 @@ static const struct { int size; char *name, *prime, *B, *order, *Gx, *Gy; } sets[] = { -#ifdef ECC160 -{ - 20, - "ECC-160", - /* prime */ - "G00000000000000000000000007", - /* B */ - "1oUV2vOaSlWbxr6", - /* order */ - "G0000000000004sCQUtDxaqDUN5", - /* Gx */ - "jpqOf1BHus6Yd/pyhyVpP", - /* Gy */ - "D/wykuuIFfr+vPyx7kQEPu8MixO", -}, -#endif #ifdef ECC192 { 24, @@ -165,70 +149,6 @@ static const struct { } }; -#if 0 - -/* you plug in a prime and B value and it finds a pseudo-random base point */ -void ecc_find_base(void) -{ - static char *prime = "26959946667150639794667015087019630673637144422540572481103610249951"; - static char *order = "26959946667150639794667015087019637467111563745054605861463538557247"; - static char *b = "9538957348957353489587"; - mp_int pp, p, r, B, tmp1, tmp2, tx, ty, x, y; - char buf[4096]; - int i; - - mp_init_multi(&tx, &ty, &x, &y, &p, &pp, &r, &B, &tmp1, &tmp2, NULL); - mp_read_radix(&p, prime, 10); - mp_read_radix(&r, order, 10); - mp_read_radix(&B, b, 10); - - /* get (p+1)/4 */ - mp_add_d(&p, 1, &pp); - mp_div_2(&pp, &pp); - mp_div_2(&pp, &pp); - - buf[0] = 0; - do { - printf("."); fflush(stdout); - /* make a random value of x */ - for (i = 0; i < 16; i++) buf[i+1] = rand() & 255; - mp_read_raw(&x, buf, 17); - mp_copy(&x, &tx); - - /* now compute x^3 - 3x + b */ - mp_expt_d(&x, 3, &tmp1); - mp_mul_d(&x, 3, &tmp2); - mp_sub(&tmp1, &tmp2, &tmp1); - mp_add(&tmp1, &B, &tmp1); - mp_mod(&tmp1, &p, &tmp1); - - /* now compute sqrt via x^((p+1)/4) */ - mp_exptmod(&tmp1, &pp, &p, &tmp2); - mp_copy(&tmp2, &ty); - - /* now square it */ - mp_sqrmod(&tmp2, &p, &tmp2); - - /* tmp2 should equal tmp1 */ - } while (mp_cmp(&tmp1, &tmp2)); - - /* now output values in way that libtomcrypt wants */ - mp_todecimal(&p, buf); - printf("\n\np==%s\n", buf); - mp_tohex(&B, buf); - printf("b==%s\n", buf); - mp_todecimal(&r, buf); - printf("r==%s\n", buf); - mp_tohex(&tx, buf); - printf("Gx==%s\n", buf); - mp_tohex(&ty, buf); - printf("Gy==%s\n", buf); - - mp_clear_multi(&tx, &ty, &x, &y, &p, &pp, &r, &B, &tmp1, &tmp2, NULL); -} - -#endif - static int is_valid_idx(int n) { int x; @@ -263,7 +183,7 @@ static void del_point(ecc_point *p) } } -static int ecc_map(ecc_point *P, mp_int *modulus, mp_int *mu) +static int ecc_map(ecc_point *P, mp_int *modulus, mp_digit mp) { mp_int t1, t2; int err; @@ -272,20 +192,23 @@ static int ecc_map(ecc_point *P, mp_int *modulus, mp_int *mu) return CRYPT_MEM; } + /* first map z back to normal */ + if ((err = mp_montgomery_reduce(&P->z, modulus, mp)) != MP_OKAY) { goto error; } + /* get 1/z */ - if ((err = mp_invmod(&P->z, modulus, &t1)) != MP_OKAY) { goto error; } + if ((err = mp_invmod(&P->z, modulus, &t1)) != MP_OKAY) { goto error; } /* get 1/z^2 and 1/z^3 */ - if ((err = mp_sqr(&t1, &t2)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&t2, modulus, mu)) != MP_OKAY) { goto error; } - if ((err = mp_mul(&t1, &t2, &t1)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_sqr(&t1, &t2)) != MP_OKAY) { goto error; } + if ((err = mp_mod(&t2, modulus, &t2)) != MP_OKAY) { goto error; } + if ((err = mp_mul(&t1, &t2, &t1)) != MP_OKAY) { goto error; } + if ((err = mp_mod(&t1, modulus, &t1)) != MP_OKAY) { goto error; } /* multiply against x/y */ - if ((err = mp_mul(&P->x, &t2, &P->x)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&P->x, modulus, mu)) != MP_OKAY) { goto error; } - if ((err = mp_mul(&P->y, &t1, &P->y)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&P->y, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_mul(&P->x, &t2, &P->x)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&P->x, modulus, mp)) != MP_OKAY) { goto error; } + if ((err = mp_mul(&P->y, &t1, &P->y)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&P->y, modulus, mp)) != MP_OKAY) { goto error; } mp_set(&P->z, 1); err = CRYPT_OK; @@ -298,9 +221,8 @@ done: } - /* double a point R = 2P, R can be P*/ -static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus, mp_int *mu) +static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus, mp_digit mp) { mp_int t1, t2; int err; @@ -315,10 +237,10 @@ static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus, mp_int *mu) /* t1 = Z * Z */ if ((err = mp_sqr(&R->z, &t1)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; } /* Z = Y * Z */ if ((err = mp_mul(&R->z, &R->y, &R->z)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&R->z, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&R->z, modulus, mp)) != MP_OKAY) { goto error; } /* Z = 2Z */ if ((err = mp_mul_2(&R->z, &R->z)) != MP_OKAY) { goto error; } if (mp_cmp(&R->z, modulus) != MP_LT) { @@ -337,7 +259,7 @@ static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus, mp_int *mu) } /* T2 = T1 * T2 */ if ((err = mp_mul(&t1, &t2, &t2)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&t2, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&t2, modulus, mp)) != MP_OKAY) { goto error; } /* T1 = 2T2 */ if ((err = mp_mul_2(&t2, &t1)) != MP_OKAY) { goto error; } if (mp_cmp(&t1, modulus) != MP_LT) { @@ -356,10 +278,10 @@ static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus, mp_int *mu) } /* Y = Y * Y */ if ((err = mp_sqr(&R->y, &R->y)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&R->y, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&R->y, modulus, mp)) != MP_OKAY) { goto error; } /* T2 = Y * Y */ if ((err = mp_sqr(&R->y, &t2)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&t2, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&t2, modulus, mp)) != MP_OKAY) { goto error; } /* T2 = T2/2 */ if (mp_isodd(&t2)) { if ((err = mp_add(&t2, modulus, &t2)) != MP_OKAY) { goto error; } @@ -367,11 +289,11 @@ static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus, mp_int *mu) if ((err = mp_div_2(&t2, &t2)) != MP_OKAY) { goto error; } /* Y = Y * X */ if ((err = mp_mul(&R->y, &R->x, &R->y)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&R->y, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&R->y, modulus, mp)) != MP_OKAY) { goto error; } /* X = T1 * T1 */ if ((err = mp_sqr(&t1, &R->x)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&R->x, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&R->x, modulus, mp)) != MP_OKAY) { goto error; } /* X = X - Y */ if ((err = mp_sub(&R->x, &R->y, &R->x)) != MP_OKAY) { goto error; } if (mp_cmp_d(&R->x, 0) == MP_LT) { @@ -390,7 +312,7 @@ static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus, mp_int *mu) } /* Y = Y * T1 */ if ((err = mp_mul(&R->y, &t1, &R->y)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&R->y, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&R->y, modulus, mp)) != MP_OKAY) { goto error; } /* Y = Y - T2 */ if ((err = mp_sub(&R->y, &t2, &R->y)) != MP_OKAY) { goto error; } if (mp_cmp_d(&R->y, 0) == MP_LT) { @@ -407,7 +329,7 @@ done: } /* add two different points over Z/pZ, R = P + Q, note R can equal either P or Q */ -static int add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mp_int *modulus, mp_int *mu) +static int add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mp_int *modulus, mp_digit mp) { mp_int t1, t2, x, y, z; int err; @@ -420,34 +342,31 @@ static int add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mp_int *modulus, if ((err = mp_copy(&P->y, &y)) != MP_OKAY) { goto error; } if ((err = mp_copy(&P->z, &z)) != MP_OKAY) { goto error; } - /* if Z' != 1 */ - if (mp_cmp_d(&Q->z, 1) != MP_EQ) { /* T1 = Z' * Z' */ if ((err = mp_sqr(&Q->z, &t1)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; } /* X = X * T1 */ if ((err = mp_mul(&t1, &x, &x)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&x, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&x, modulus, mp)) != MP_OKAY) { goto error; } /* T1 = Z' * T1 */ if ((err = mp_mul(&Q->z, &t1, &t1)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; } /* Y = Y * T1 */ if ((err = mp_mul(&t1, &y, &y)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&y, modulus, mu)) != MP_OKAY) { goto error; } - } + if ((err = mp_montgomery_reduce(&y, modulus, mp)) != MP_OKAY) { goto error; } /* T1 = Z*Z */ if ((err = mp_sqr(&z, &t1)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; } /* T2 = X' * T1 */ if ((err = mp_mul(&Q->x, &t1, &t2)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&t2, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&t2, modulus, mp)) != MP_OKAY) { goto error; } /* T1 = Z * T1 */ if ((err = mp_mul(&z, &t1, &t1)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; } /* T1 = Y' * T1 */ if ((err = mp_mul(&Q->y, &t1, &t1)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; } /* Y = Y - T1 */ if ((err = mp_sub(&y, &t1, &y)) != MP_OKAY) { goto error; } @@ -484,28 +403,28 @@ static int add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mp_int *modulus, if (mp_cmp_d(&Q->z, 1) != MP_EQ) { /* Z = Z * Z' */ if ((err = mp_mul(&z, &Q->z, &z)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&z, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&z, modulus, mp)) != MP_OKAY) { goto error; } } /* Z = Z * X */ if ((err = mp_mul(&z, &x, &z)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&z, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&z, modulus, mp)) != MP_OKAY) { goto error; } /* T1 = T1 * X */ if ((err = mp_mul(&t1, &x, &t1)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; } /* X = X * X */ if ((err = mp_sqr(&x, &x)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&x, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&x, modulus, mp)) != MP_OKAY) { goto error; } /* T2 = T2 * x */ if ((err = mp_mul(&t2, &x, &t2)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&t2, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&t2, modulus, mp)) != MP_OKAY) { goto error; } /* T1 = T1 * X */ if ((err = mp_mul(&t1, &x, &t1)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; } /* X = Y*Y */ if ((err = mp_sqr(&y, &x)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&x, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&x, modulus, mp)) != MP_OKAY) { goto error; } /* X = X - T2 */ if ((err = mp_sub(&x, &t2, &x)) != MP_OKAY) { goto error; } if (mp_cmp_d(&x, 0) == MP_LT) { @@ -524,7 +443,7 @@ static int add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mp_int *modulus, } /* T2 = T2 * Y */ if ((err = mp_mul(&t2, &y, &t2)) != MP_OKAY) { goto error; } - if ((err = mp_reduce(&t2, modulus, mu)) != MP_OKAY) { goto error; } + if ((err = mp_montgomery_reduce(&t2, modulus, mp)) != MP_OKAY) { goto error; } /* Y = T2 - T1 */ if ((err = mp_sub(&t2, &t1, &y)) != MP_OKAY) { goto error; } if (mp_cmp_d(&y, 0) == MP_LT) { @@ -553,22 +472,25 @@ done: #define WINSIZE 4 /* perform R = kG where k == integer and G == ecc_point */ -static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus) +static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus, int map) { ecc_point *tG, *M[8]; int i, j, err; mp_int mu; - mp_digit buf; + mp_digit buf, mp; int first, bitbuf, bitcpy, bitcnt, mode, digidx; - /* init barrett reduction */ - if ((err = mp_init(&mu)) != MP_OKAY) { - return mpi_to_ltc_error(err); - } - if ((err = mp_reduce_setup(&mu, modulus)) != MP_OKAY) { + /* init montgomery reduction */ + if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) { + return CRYPT_INVALID_ARG; + } + if ((err = mp_init(&mu)) != MP_OKAY) { + return CRYPT_MEM; + } + if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) { mp_clear(&mu); - return mpi_to_ltc_error(err); - } + return CRYPT_INVALID_ARG; + } /* alloc ram for window temps */ for (i = 0; i < 8; i++) { @@ -586,20 +508,21 @@ static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus) tG = new_point(); if (tG == NULL) { err = CRYPT_MEM; goto done; } - /* tG = G */ - if ((err = mp_copy(&G->x, &tG->x)) != MP_OKAY) { goto error; } - if ((err = mp_copy(&G->y, &tG->y)) != MP_OKAY) { goto error; } - if ((err = mp_copy(&G->z, &tG->z)) != MP_OKAY) { goto error; } + /* tG = G and convert to montgomery */ + if ((err = mp_mulmod(&G->x, &mu, modulus, &tG->x)) != MP_OKAY) { goto error; } + if ((err = mp_mulmod(&G->y, &mu, modulus, &tG->y)) != MP_OKAY) { goto error; } + if ((err = mp_mulmod(&G->z, &mu, modulus, &tG->z)) != MP_OKAY) { goto error; } + mp_clear(&mu); /* calc the M tab, which holds kG for k==8..15 */ /* M[0] == 8G */ - if ((err = dbl_point(G, M[0], modulus, &mu)) != CRYPT_OK) { goto done; } - if ((err = dbl_point(M[0], M[0], modulus, &mu)) != CRYPT_OK) { goto done; } - if ((err = dbl_point(M[0], M[0], modulus, &mu)) != CRYPT_OK) { goto done; } + if ((err = dbl_point(tG, M[0], modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = dbl_point(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = dbl_point(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; } /* now find (8+k)G for k=1..7 */ for (j = 9; j < 16; j++) { - if ((err = add_point(M[j-9], G, M[j-8], modulus, &mu)) != CRYPT_OK) { goto done; } + if ((err = add_point(M[j-9], tG, M[j-8], modulus, mp)) != CRYPT_OK) { goto done; } } /* setup sliding window */ @@ -621,7 +544,7 @@ static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus) bitcnt = (int) DIGIT_BIT; } - /* grab the next msb from the multiplicand */ + /* grab the next msb from the ltiplicand */ i = (buf >> (DIGIT_BIT - 1)) & 1; buf <<= 1; @@ -632,7 +555,7 @@ static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus) /* if the bit is zero and mode == 1 then we double */ if (mode == 1 && i == 0) { - if ((err = dbl_point(R, R, modulus, &mu)) != CRYPT_OK) { goto done; } + if ((err = dbl_point(R, R, modulus, mp)) != CRYPT_OK) { goto done; } continue; } @@ -653,11 +576,11 @@ static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus) /* ok window is filled so double as required and add */ /* double first */ for (j = 0; j < WINSIZE; j++) { - if ((err = dbl_point(R, R, modulus, &mu)) != CRYPT_OK) { goto done; } + if ((err = dbl_point(R, R, modulus, mp)) != CRYPT_OK) { goto done; } } /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */ - if ((err = add_point(R, M[bitbuf-8], R, modulus, &mu)) != CRYPT_OK) { goto done; } + if ((err = add_point(R, M[bitbuf-8], R, modulus, mp)) != CRYPT_OK) { goto done; } } /* empty window and reset */ bitcpy = bitbuf = 0; @@ -671,7 +594,7 @@ static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus) for (j = 0; j < bitcpy; j++) { /* only double if we have had at least one add first */ if (first == 0) { - if ((err = dbl_point(R, R, modulus, &mu)) != CRYPT_OK) { goto done; } + if ((err = dbl_point(R, R, modulus, mp)) != CRYPT_OK) { goto done; } } bitbuf <<= 1; @@ -684,14 +607,19 @@ static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus) first = 0; } else { /* then add */ - if ((err = add_point(R, tG, R, modulus, &mu)) != CRYPT_OK) { goto done; } + if ((err = add_point(R, tG, R, modulus, mp)) != CRYPT_OK) { goto done; } } } } } /* map R back from projective space */ - err = ecc_map(R, modulus, &mu); + if (map) { + err = ecc_map(R, modulus, mp); + } else { + err = CRYPT_OK; + } + goto done; error: err = mpi_to_ltc_error(err); @@ -700,7 +628,6 @@ done: for (i = 0; i < 8; i++) { del_point(M[i]); } - mp_clear(&mu); return err; } @@ -756,7 +683,7 @@ int ecc_test(void) /* then we should have G == (order + 1)G */ if ((err = mp_add_d(&order, 1, &order)) != MP_OKAY) { goto error; } - if ((err = ecc_mulmod(&order, G, GG, &modulus)) != CRYPT_OK) { goto done; } + if ((err = ecc_mulmod(&order, G, GG, &modulus, 1)) != CRYPT_OK) { goto done; } if (mp_cmp(&G->x, &GG->x) != 0 || mp_cmp(&G->y, &GG->y) != 0) { err = CRYPT_FAIL_TESTVECTOR; goto done; @@ -855,7 +782,7 @@ int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key) if ((err = mp_read_unsigned_bin(&key->k, (unsigned char *)buf, keysize)) != MP_OKAY) { goto error; } /* make the public key */ - if ((err = ecc_mulmod(&key->k, base, &key->pubkey, &prime)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = ecc_mulmod(&key->k, base, &key->pubkey, &prime, 1)) != CRYPT_OK) { goto LBL_ERR; } key->type = PK_PRIVATE; /* shrink key */ @@ -985,46 +912,50 @@ done: */ int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key) { - unsigned long y, z; - int cp, err; + int cp, err; + unsigned char flags[2]; + unsigned long key_size; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); - /* can we store the static header? */ - if (*outlen < (PACKET_SIZE + 3)) { - return CRYPT_BUFFER_OVERFLOW; - } - /* type valid? */ if (key->type != PK_PRIVATE && type == PK_PRIVATE) { return CRYPT_PK_TYPE_MISMATCH; } - /* output type and magic byte */ - y = PACKET_SIZE; - out[y++] = (unsigned char)type; - out[y++] = (unsigned char)sets[key->idx].size; + if (is_valid_idx(key->idx) == 0) { + return CRYPT_INVALID_ARG; + } - /* output x coordinate */ - OUTPUT_BIGNUM(&(key->pubkey.x), out, y, z); - - /* compress y and output it */ + /* compress the y part */ if ((err = compress_y_point(&key->pubkey, key->idx, &cp)) != CRYPT_OK) { return err; } - out[y++] = (unsigned char)cp; + flags[1] = cp; + + /* we store the NIST byte size */ + key_size = sets[key->idx].size; if (type == PK_PRIVATE) { - OUTPUT_BIGNUM(&key->k, out, y, z); + flags[0] = 1; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_BIT_STRING, 2UL, flags, + LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, + LTC_ASN1_INTEGER, 1UL, &key->pubkey.x, + LTC_ASN1_INTEGER, 1UL, &key->k, + LTC_ASN1_EOL, 0UL, NULL); + } else { + flags[0] = 0; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_BIT_STRING, 2UL, flags, + LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, + LTC_ASN1_INTEGER, 1UL, &key->pubkey.x, + LTC_ASN1_EOL, 0UL, NULL); } - /* store header */ - packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_KEY); - *outlen = y; - - return CRYPT_OK; + return err; } /** @@ -1036,72 +967,66 @@ int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key */ int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key) { - unsigned long x, y, s; - int err; + unsigned long key_size; + unsigned char flags[2]; + int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); - /* check length */ - if ((3+PACKET_SIZE) > inlen) { - return CRYPT_INVALID_PACKET; - } - - /* check type */ - if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_KEY)) != CRYPT_OK) { - return err; - } - /* init key */ if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != MP_OKAY) { return CRYPT_MEM; } - y = PACKET_SIZE; - key->type = (int)in[y++]; - s = (unsigned long)in[y++]; - - for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size != 0); x++); - if (sets[x].size == 0) { - err = CRYPT_INVALID_KEYSIZE; + /* find out what type of key it is */ + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 2UL, &flags, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto error; } - key->idx = (int)x; - /* type check both values */ - if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE)) { + + if (flags[0] == 1) { + /* private key */ + key->type = PK_PRIVATE; + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 2UL, flags, + LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, + LTC_ASN1_INTEGER, 1UL, &key->pubkey.x, + LTC_ASN1_INTEGER, 1UL, &key->k, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto error; + } + } else { + /* public key */ + /* private key */ + key->type = PK_PUBLIC; + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 2UL, flags, + LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, + LTC_ASN1_INTEGER, 1UL, &key->pubkey.x, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto error; + } + } + + /* find the idx */ + for (key->idx = 0; sets[key->idx].size && (unsigned long)sets[key->idx].size != key_size; ++key->idx); + if (sets[key->idx].size == 0) { err = CRYPT_INVALID_PACKET; goto error; } - /* is the key idx valid? */ - if (is_valid_idx(key->idx) != 1) { - err = CRYPT_INVALID_PACKET; + /* compute y */ + if ((err = expand_y_point(&key->pubkey, key->idx, flags[1])) != CRYPT_OK) { goto error; } - /* load x coordinate */ - INPUT_BIGNUM(&key->pubkey.x, in, x, y, inlen); - - /* load y */ - x = (unsigned long)in[y++]; - if ((err = expand_y_point(&key->pubkey, key->idx, (int)x)) != CRYPT_OK) { - goto error; - } - - if (key->type == PK_PRIVATE) { - /* load private key */ - INPUT_BIGNUM(&key->k, in, x, y, inlen); - } - - /* eliminate private key if public */ - if (key->type == PK_PUBLIC) { - mp_clear(&key->k); - } - - /* z is always 1 */ + /* set z */ mp_set(&key->pubkey.z, 1); + /* we're good */ return CRYPT_OK; error: mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL); @@ -1112,14 +1037,14 @@ error: Create an ECC shared secret between two keys @param private_key The private ECC key @param public_key The public key - @param out [out] Destination of the shared secret + @param out [out] Destination of the shared secret (Conforms to EC-DH from ANSI X9.63) @param outlen [in/out] The max size and resulting size of the shared secret @return CRYPT_OK if successful */ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, unsigned char *out, unsigned long *outlen) { - unsigned long x, y; + unsigned long x; ecc_point *result; mp_int prime; int err; @@ -1134,6 +1059,10 @@ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, return CRYPT_PK_NOT_PRIVATE; } + if (is_valid_idx(private_key->idx) == 0) { + return CRYPT_INVALID_ARG; + } + if (private_key->idx != public_key->idx) { return CRYPT_PK_TYPE_MISMATCH; } @@ -1149,21 +1078,19 @@ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, return mpi_to_ltc_error(err); } - if ((err = mp_read_radix(&prime, (char *)sets[private_key->idx].prime, 64)) != MP_OKAY) { goto error; } - if ((err = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime)) != CRYPT_OK) { goto done1; } + if ((err = mp_read_radix(&prime, (char *)sets[private_key->idx].prime, 64)) != MP_OKAY) { goto error; } + if ((err = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime, 1)) != CRYPT_OK) { goto done1; } - x = (unsigned long)mp_unsigned_bin_size(&result->x); - y = (unsigned long)mp_unsigned_bin_size(&result->y); - - if (*outlen < (x+y)) { + x = (unsigned long)mp_unsigned_bin_size(&prime); + if (*outlen < x) { err = CRYPT_BUFFER_OVERFLOW; goto done1; } - *outlen = x+y; - if ((err = mp_to_unsigned_bin(&result->x, out)) != MP_OKAY) { goto error; } - if ((err = mp_to_unsigned_bin(&result->y, out+x)) != MP_OKAY) { goto error; } + zeromem(out, x); + if ((err = mp_to_unsigned_bin(&result->x, out + (x - mp_unsigned_bin_size(&result->x)))) != MP_OKAY) { goto error; } - err = CRYPT_OK; + err = CRYPT_OK; + *outlen = x; goto done1; error: err = mpi_to_ltc_error(err); @@ -1192,3 +1119,7 @@ int ecc_get_size(ecc_key *key) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/ecc/ecc_sys.c b/src/pk/ecc/ecc_sys.c index d5576f64..3cdc2416 100644 --- a/src/pk/ecc/ecc_sys.c +++ b/src/pk/ecc/ecc_sys.c @@ -33,7 +33,7 @@ int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, { unsigned char *pub_expt, *ecc_shared, *skey; ecc_key pubkey; - unsigned long x, y, z, hashsize, pubkeysize; + unsigned long x, y, pubkeysize; int err; LTC_ARGCHK(in != NULL); @@ -82,53 +82,29 @@ int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, goto LBL_ERR; } - /* now check if the out buffer is big enough */ - if (*outlen < (9 + PACKET_SIZE + pubkeysize + hash_descriptor[hash].hashsize)) { - ecc_free(&pubkey); - err = CRYPT_BUFFER_OVERFLOW; - goto LBL_ERR; - } - /* make random key */ - hashsize = hash_descriptor[hash].hashsize; - x = ECC_BUF_SIZE; + x = ECC_BUF_SIZE; if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) { ecc_free(&pubkey); goto LBL_ERR; } ecc_free(&pubkey); - z = MAXBLOCKSIZE; - if ((err = hash_memory(hash, ecc_shared, x, skey, &z)) != CRYPT_OK) { + y = MAXBLOCKSIZE; + if ((err = hash_memory(hash, ecc_shared, x, skey, &y)) != CRYPT_OK) { goto LBL_ERR; } - /* store header */ - packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY); - - /* output header */ - y = PACKET_SIZE; - - /* size of hash name and the name itself */ - out[y++] = hash_descriptor[hash].ID; - - /* length of ECC pubkey and the key itself */ - STORE32L(pubkeysize, out+y); - y += 4; - - for (x = 0; x < pubkeysize; x++, y++) { - out[y] = pub_expt[x]; + /* Encrypt key */ + for (x = 0; x < inlen; x++) { + skey[x] ^= in[x]; } - STORE32L(inlen, out+y); - y += 4; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash].OIDlen, hash_descriptor[hash].OID, + LTC_ASN1_OCTET_STRING, pubkeysize, pub_expt, + LTC_ASN1_OCTET_STRING, inlen, skey, + LTC_ASN1_EOL, 0UL, NULL); - /* Encrypt/Store the encrypted key */ - for (x = 0; x < inlen; x++, y++) { - out[y] = skey[x] ^ in[x]; - } - *outlen = y; - - err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK /* clean up */ @@ -157,10 +133,11 @@ int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, ecc_key *key) { - unsigned char *shared_secret, *skey; - unsigned long x, y, z, hashsize, keysize; + unsigned char *ecc_shared, *skey, *pub_expt; + unsigned long x, y, hashOID[32]; int hash, err; ecc_key pubkey; + ltc_asn1_list decode[3]; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); @@ -172,98 +149,93 @@ int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, return CRYPT_PK_NOT_PRIVATE; } - /* correct length ? */ - if (inlen < PACKET_SIZE+1+4+4) { - return CRYPT_INVALID_PACKET; - } else { - inlen -= PACKET_SIZE+1+4+4; - } - - /* is header correct? */ - if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY)) != CRYPT_OK) { + /* decode to find out hash */ + LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0])); + + if ((err = der_decode_sequence(in, inlen, decode, 1)) != CRYPT_OK) { return err; } + for (hash = 0; hash_descriptor[hash].name != NULL && + (hash_descriptor[hash].OIDlen != decode[0].size || + memcmp(hash_descriptor[hash].OID, hashOID, sizeof(unsigned long)*decode[0].size)); hash++); - /* now lets get the hash name */ - y = PACKET_SIZE; - hash = find_hash_id(in[y++]); - if (hash == -1) { - return CRYPT_INVALID_HASH; - } - - /* common values */ - hashsize = hash_descriptor[hash].hashsize; - - /* get public key */ - LOAD32L(x, in+y); - if (inlen < x) { + if (hash_descriptor[hash].name == NULL) { return CRYPT_INVALID_PACKET; - } else { - inlen -= x; } - y += 4; - if ((err = ecc_import(in+y, x, &pubkey)) != CRYPT_OK) { - return err; - } - y += x; + + /* we now have the hash! */ /* allocate memory */ - shared_secret = XMALLOC(ECC_BUF_SIZE); - skey = XMALLOC(MAXBLOCKSIZE); - if (shared_secret == NULL || skey == NULL) { - if (shared_secret != NULL) { - XFREE(shared_secret); + pub_expt = XMALLOC(ECC_BUF_SIZE); + ecc_shared = XMALLOC(ECC_BUF_SIZE); + skey = XMALLOC(MAXBLOCKSIZE); + if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) { + if (pub_expt != NULL) { + XFREE(pub_expt); + } + if (ecc_shared != NULL) { + XFREE(ecc_shared); } if (skey != NULL) { XFREE(skey); } - ecc_free(&pubkey); return CRYPT_MEM; } + LTC_SET_ASN1(decode, 1, LTC_ASN1_OCTET_STRING, pub_expt, ECC_BUF_SIZE); + LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE); + + /* read the structure in now */ + if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* import ECC key from packet */ + if ((err = ecc_import(decode[1].data, decode[1].size, &pubkey)) != CRYPT_OK) { + goto LBL_ERR; + } /* make shared key */ x = ECC_BUF_SIZE; - if ((err = ecc_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) { + if ((err = ecc_shared_secret(key, &pubkey, ecc_shared, &x)) != CRYPT_OK) { ecc_free(&pubkey); goto LBL_ERR; } ecc_free(&pubkey); - z = MAXBLOCKSIZE; - if ((err = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) { + y = MAXBLOCKSIZE; + if ((err = hash_memory(hash, ecc_shared, x, ecc_shared, &y)) != CRYPT_OK) { goto LBL_ERR; } - LOAD32L(keysize, in+y); - if (inlen < keysize) { + /* ensure the hash of the shared secret is at least as big as the encrypt itself */ + if (decode[2].size > y) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; - } else { - inlen -= keysize; } - y += 4; - if (*outlen < keysize) { - err = CRYPT_BUFFER_OVERFLOW; - goto LBL_ERR; + /* avoid buffer overflow */ + if (*outlen < decode[2].size) { + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; } /* Decrypt the key */ - for (x = 0; x < keysize; x++, y++) { - out[x] = skey[x] ^ in[y]; + for (x = 0; x < decode[2].size; x++) { + out[x] = skey[x] ^ ecc_shared[x]; } - - *outlen = keysize; + *outlen = x; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK - zeromem(shared_secret, ECC_BUF_SIZE); - zeromem(skey, MAXBLOCKSIZE); + zeromem(pub_expt, ECC_BUF_SIZE); + zeromem(ecc_shared, ECC_BUF_SIZE); + zeromem(skey, MAXBLOCKSIZE); #endif + XFREE(pub_expt); + XFREE(ecc_shared); XFREE(skey); - XFREE(shared_secret); return err; } @@ -284,9 +256,7 @@ int ecc_sign_hash(const unsigned char *in, unsigned long inlen, prng_state *prng, int wprng, ecc_key *key) { ecc_key pubkey; - mp_int b, p; - unsigned char *epubkey, *er; - unsigned long x, y, pubkeysize, rsize; + mp_int r, s, e, p; int err; LTC_ARGCHK(in != NULL); @@ -308,116 +278,65 @@ int ecc_sign_hash(const unsigned char *in, unsigned long inlen, return err; } - /* make up a key and export the public copy */ - if ((err = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) { - return err; - } - - /* allocate ram */ - epubkey = XMALLOC(ECC_BUF_SIZE); - er = XMALLOC(ECC_BUF_SIZE); - if (epubkey == NULL || er == NULL) { - if (epubkey != NULL) { - XFREE(epubkey); - } - if (er != NULL) { - XFREE(er); - } - ecc_free(&pubkey); - return CRYPT_MEM; - } - - pubkeysize = ECC_BUF_SIZE; - if ((err = ecc_export(epubkey, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) { - ecc_free(&pubkey); - goto LBL_ERR; - } - - /* get the hash and load it as a bignum into 'b' */ + /* get the hash and load it as a bignum into 'e' */ /* init the bignums */ - if ((err = mp_init_multi(&b, &p, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&r, &s, &p, &e, NULL)) != MP_OKAY) { ecc_free(&pubkey); err = mpi_to_ltc_error(err); goto LBL_ERR; } if ((err = mp_read_radix(&p, (char *)sets[key->idx].order, 64)) != MP_OKAY) { goto error; } - if ((err = mp_read_unsigned_bin(&b, (unsigned char *)in, (int)inlen)) != MP_OKAY) { goto error; } + if ((err = mp_read_unsigned_bin(&e, (unsigned char *)in, (int)inlen)) != MP_OKAY) { goto error; } - /* find b = (m - x)/k */ - if ((err = mp_invmod(&pubkey.k, &p, &pubkey.k)) != MP_OKAY) { goto error; } /* k = 1/k */ - if ((err = mp_submod(&b, &key->k, &p, &b)) != MP_OKAY) { goto error; } /* b = m - x */ - if ((err = mp_mulmod(&b, &pubkey.k, &p, &b)) != MP_OKAY) { goto error; } /* b = (m - x)/k */ + /* make up a key and export the public copy */ + for (;;) { + if ((err = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) { + return err; + } - /* export it */ - rsize = (unsigned long)mp_unsigned_bin_size(&b); - if (rsize > ECC_BUF_SIZE) { - err = CRYPT_BUFFER_OVERFLOW; - goto error; - } - if ((err = mp_to_unsigned_bin(&b, er)) != MP_OKAY) { goto error; } + /* find r = x1 mod n */ + if ((err = mp_mod(&pubkey.pubkey.x, &p, &r)) != MP_OKAY) { goto error; } - /* now lets check the outlen before we write */ - if (*outlen < (12 + rsize + pubkeysize)) { - err = CRYPT_BUFFER_OVERFLOW; - goto LBL_ERR; + if (mp_iszero(&r)) { + ecc_free(&pubkey); + } else { + /* find s = (e + xr)/k */ + if ((err = mp_invmod(&pubkey.k, &p, &pubkey.k)) != MP_OKAY) { goto error; } /* k = 1/k */ + if ((err = mp_mulmod(&key->k, &r, &p, &s)) != MP_OKAY) { goto error; } /* s = xr */ + if ((err = mp_addmod(&e, &s, &p, &s)) != MP_OKAY) { goto error; } /* s = e + xr */ + if ((err = mp_mulmod(&s, &pubkey.k, &p, &s)) != MP_OKAY) { goto error; } /* s = (e + xr)/k */ + + if (mp_iszero(&s)) { + ecc_free(&pubkey); + } else { + break; + } + } } - /* lets output */ - y = PACKET_SIZE; - - /* size of public key */ - STORE32L(pubkeysize, out+y); - y += 4; - - /* copy the public key */ - for (x = 0; x < pubkeysize; x++, y++) { - out[y] = epubkey[x]; - } - - /* size of 'r' */ - STORE32L(rsize, out+y); - y += 4; - - /* copy r */ - for (x = 0; x < rsize; x++, y++) { - out[y] = er[x]; - } - - /* store header */ - packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_SIGNED); - *outlen = y; - - /* all ok */ - err = CRYPT_OK; + /* store as SEQUENCE { r, s -- integer } */ + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_INTEGER, 1UL, &r, + LTC_ASN1_INTEGER, 1UL, &s, + LTC_ASN1_EOL, 0UL, NULL); goto LBL_ERR; error: err = mpi_to_ltc_error(err); LBL_ERR: - mp_clear_multi(&b, &p, NULL); + mp_clear_multi(&r, &s, &p, &e, NULL); ecc_free(&pubkey); -#ifdef LTC_CLEAN_STACK - zeromem(er, ECC_BUF_SIZE); - zeromem(epubkey, ECC_BUF_SIZE); -#endif - - XFREE(epubkey); - XFREE(er); return err; } -/* verify that mG = (bA + Y) +/* verify * - * The signatures work by making up a fresh key "a" with a public key "A". Now we want to sign so the - * public key Y = xG can verify it. - * - * b = (m - x)/k, A is the public key embedded and Y is the users public key [who signed it] - * A = kG therefore bA == ((m-x)/k)kG == (m-x)G - * - * Adding Y = xG to the bA gives us (m-x)G + xG == mG - * - * The user given only xG, kG and b cannot determine k or x which means they can't find the private key. - * + * w = s^-1 mod n + * u1 = xw + * u2 = rw + * X = u1*G + u2*Q + * v = X_x1 mod n + * accept if v == r */ /** @@ -434,10 +353,9 @@ int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int *stat, ecc_key *key) { - ecc_point *mG; - ecc_key pubkey; - mp_int b, p, m, mu; - unsigned long x, y; + ecc_point *mG, *mQ; + mp_int r, s, v, w, u1, u2, e, p, m; + mp_digit mp; int err; LTC_ARGCHK(sig != NULL); @@ -448,89 +366,81 @@ int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, /* default to invalid signature */ *stat = 0; - if (siglen < PACKET_SIZE+4+4) { - return CRYPT_INVALID_PACKET; - } else { - siglen -= PACKET_SIZE+4+4; + /* is the IDX valid ? */ + if (is_valid_idx(key->idx) != 1) { + return CRYPT_PK_INVALID_TYPE; } - /* is the message format correct? */ - if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_ECC, PACKET_SUB_SIGNED)) != CRYPT_OK) { - return err; - } - - /* get hash name */ - y = PACKET_SIZE; - - /* get size of public key */ - LOAD32L(x, sig+y); - if (siglen < x) { - return CRYPT_INVALID_PACKET; - } else { - siglen -= x; - } - y += 4; - - /* load the public key */ - if ((err = ecc_import((unsigned char*)sig+y, x, &pubkey)) != CRYPT_OK) { - return err; - } - y += x; - - /* load size of 'b' */ - LOAD32L(x, sig+y); - if (siglen < x) { - return CRYPT_INVALID_PACKET; - } else { - siglen -= x; - } - y += 4; - - /* init values */ - if ((err = mp_init_multi(&b, &m, &p, &mu, NULL)) != MP_OKAY) { - ecc_free(&pubkey); - return mpi_to_ltc_error(err); - } - - mG = new_point(); - if (mG == NULL) { - mp_clear_multi(&b, &m, &p, &mu, NULL); - ecc_free(&pubkey); + /* allocate ints */ + if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL)) != MP_OKAY) { return CRYPT_MEM; - } + } - /* load b */ - if ((err = mp_read_unsigned_bin(&b, (unsigned char *)sig+y, (int)x)) != MP_OKAY) { goto error; } - y += x; + /* allocate points */ + mG = new_point(); + mQ = new_point(); + if (mQ == NULL || mG == NULL) { + err = CRYPT_MEM; + goto done; + } - /* get m in binary a bignum */ - if ((err = mp_read_unsigned_bin(&m, (unsigned char *)hash, (int)hashlen)) != MP_OKAY) { goto error; } - - /* load prime */ - if ((err = mp_read_radix(&p, (char *)sets[key->idx].prime, 64)) != MP_OKAY) { goto error; } - - /* calculate barrett stuff */ - mp_set(&mu, 1); - mp_lshd(&mu, 2 * USED(&p)); - if ((err = mp_div(&mu, &p, &mu, NULL)) != MP_OKAY) { goto error; } + /* parse header */ + if ((err = der_decode_sequence_multi(sig, siglen, + LTC_ASN1_INTEGER, 1UL, &r, + LTC_ASN1_INTEGER, 1UL, &s, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto done; + } - /* get bA */ - if ((err = ecc_mulmod(&b, &pubkey.pubkey, &pubkey.pubkey, &p)) != CRYPT_OK) { goto done; } - - /* get bA + Y */ - if ((err = add_point(&pubkey.pubkey, &key->pubkey, &pubkey.pubkey, &p, &mu)) != CRYPT_OK) { goto done; } + /* get the order */ + if ((err = mp_read_radix(&p, (char *)sets[key->idx].order, 64)) != MP_OKAY) { goto error; } - /* we have to transform it */ - if ((err = ecc_map(&pubkey.pubkey, &p, &mu)) != CRYPT_OK) { goto done; } + /* get the modulus */ + if ((err = mp_read_radix(&m, (char *)sets[key->idx].prime, 64)) != MP_OKAY) { goto error; } - /* get mG */ + /* check for zero */ + if (mp_iszero(&r) || mp_iszero(&s) || mp_cmp(&r, &p) != MP_LT || mp_cmp(&s, &p) != MP_LT) { + err = CRYPT_INVALID_PACKET; + goto done; + } + + /* read hash */ + if ((err = mp_read_unsigned_bin(&e, (unsigned char *)hash, (int)hashlen)) != MP_OKAY) { goto error; } + + /* w = s^-1 mod n */ + if ((err = mp_invmod(&s, &p, &w)) != MP_OKAY) { goto error; } + + /* u1 = ew */ + if ((err = mp_mulmod(&e, &w, &p, &u1)) != MP_OKAY) { goto error; } + + /* u2 = rw */ + if ((err = mp_mulmod(&r, &w, &p, &u2)) != MP_OKAY) { goto error; } + + /* find mG = u1*G */ if ((err = mp_read_radix(&mG->x, (char *)sets[key->idx].Gx, 64)) != MP_OKAY) { goto error; } if ((err = mp_read_radix(&mG->y, (char *)sets[key->idx].Gy, 64)) != MP_OKAY) { goto error; } - mp_set(&mG->z, 1); - if ((err = ecc_mulmod(&m, mG, mG, &p)) != CRYPT_OK) { goto done; } + mp_set(&mG->z, 1); + if ((err = ecc_mulmod(&u1, mG, mG, &m, 0)) != CRYPT_OK) { goto done; } - /* compare mG to bA + Y */ - if (mp_cmp(&mG->x, &pubkey.pubkey.x) == MP_EQ && mp_cmp(&mG->y, &pubkey.pubkey.y) == MP_EQ) { + /* find mQ = u2*Q */ + if ((err = mp_copy(&key->pubkey.x, &mQ->x)) != MP_OKAY) { goto error; } + if ((err = mp_copy(&key->pubkey.y, &mQ->y)) != MP_OKAY) { goto error; } + if ((err = mp_copy(&key->pubkey.z, &mQ->z)) != MP_OKAY) { goto error; } + if ((err = ecc_mulmod(&u2, mQ, mQ, &m, 0)) != CRYPT_OK) { goto done; } + + /* find the montgomery mp */ + if ((err = mp_montgomery_setup(&m, &mp)) != MP_OKAY) { goto error; } + /* add them */ + if ((err = add_point(mQ, mG, mG, &m, mp)) != CRYPT_OK) { goto done; } + + /* reduce */ + if ((err = ecc_map(mG, &m, mp)) != CRYPT_OK) { goto done; } + + /* v = X_x1 mod n */ + if ((err = mp_mod(&mG->x, &p, &v)) != CRYPT_OK) { goto done; } + + /* does v == r */ + if (mp_cmp(&v, &r) == MP_EQ) { *stat = 1; } @@ -541,8 +451,12 @@ error: err = mpi_to_ltc_error(err); done: del_point(mG); - ecc_free(&pubkey); - mp_clear_multi(&p, &m, &b, &mu, NULL); + del_point(mQ); + mp_clear_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL); return err; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/packet_store_header.c b/src/pk/packet_store_header.c index a2442cc8..ca09a76d 100644 --- a/src/pk/packet_store_header.c +++ b/src/pk/packet_store_header.c @@ -27,3 +27,7 @@ void packet_store_header(unsigned char *dst, int section, int subsection) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/packet_valid_header.c b/src/pk/packet_valid_header.c index b2eb9c94..8ac83758 100644 --- a/src/pk/packet_valid_header.c +++ b/src/pk/packet_valid_header.c @@ -35,3 +35,7 @@ int packet_valid_header(unsigned char *src, int section, int subsection) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/pkcs1/pkcs_1_i2osp.c b/src/pk/pkcs1/pkcs_1_i2osp.c index 7f13626c..8ec251d9 100644 --- a/src/pk/pkcs1/pkcs_1_i2osp.c +++ b/src/pk/pkcs1/pkcs_1_i2osp.c @@ -49,3 +49,7 @@ int pkcs_1_i2osp(mp_int *n, unsigned long modulus_len, unsigned char *out) #endif /* PKCS_1 */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/pkcs1/pkcs_1_mgf1.c b/src/pk/pkcs1/pkcs_1_mgf1.c index 0fe177fd..233d7bc0 100644 --- a/src/pk/pkcs1/pkcs_1_mgf1.c +++ b/src/pk/pkcs1/pkcs_1_mgf1.c @@ -102,3 +102,7 @@ LBL_ERR: } #endif /* PKCS_1 */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/pkcs1/pkcs_1_oaep_decode.c b/src/pk/pkcs1/pkcs_1_oaep_decode.c index 82862c1e..fd368e62 100644 --- a/src/pk/pkcs1/pkcs_1_oaep_decode.c +++ b/src/pk/pkcs1/pkcs_1_oaep_decode.c @@ -63,7 +63,7 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, /* allocate ram for DB/mask/salt of size modulus_len */ DB = XMALLOC(modulus_len); mask = XMALLOC(modulus_len); - seed = XMALLOC(modulus_len); + seed = XMALLOC(hLen); if (DB == NULL || mask == NULL || seed == NULL) { if (DB != NULL) { XFREE(DB); @@ -92,14 +92,13 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, } /* now read the masked seed */ - for (x = 1, y = 0; y < hLen; y++) { - seed[y] = msg[x++]; - } + x = 1; + XMEMCPY(seed, msg + x, hLen); + x += hLen; /* now read the masked DB */ - for (y = 0; y < modulus_len - hLen - 1; y++) { - DB[y] = msg[x++]; - } + XMEMCPY(DB, msg + x, modulus_len - hLen - 1); + x += modulus_len - hLen - 1; /* compute MGF1 of maskedDB (hLen) */ if ((err = pkcs_1_mgf1(DB, modulus_len - hLen - 1, hash_idx, mask, hLen)) != CRYPT_OK) { @@ -161,9 +160,8 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, /* copy message */ *outlen = (modulus_len - hLen - 1) - x; - for (y = 0; x != (modulus_len - hLen - 1); ) { - out[y++] = DB[x++]; - } + XMEMCPY(out, DB + x, modulus_len - hLen - 1); + x += modulus_len - hLen - 1; /* valid packet */ *res = 1; @@ -172,7 +170,7 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(DB, modulus_len); - zeromem(seed, modulus_len); + zeromem(seed, hLen); zeromem(mask, modulus_len); #endif @@ -184,3 +182,7 @@ LBL_ERR: } #endif /* PKCS_1 */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/pkcs1/pkcs_1_oaep_encode.c b/src/pk/pkcs1/pkcs_1_oaep_encode.c index 7afea602..525158c0 100644 --- a/src/pk/pkcs1/pkcs_1_oaep_encode.c +++ b/src/pk/pkcs1/pkcs_1_oaep_encode.c @@ -66,7 +66,7 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, /* allocate ram for DB/mask/salt of size modulus_len */ DB = XMALLOC(modulus_len); mask = XMALLOC(modulus_len); - seed = XMALLOC(modulus_len); + seed = XMALLOC(hLen); if (DB == NULL || mask == NULL || seed == NULL) { if (DB != NULL) { XFREE(DB); @@ -97,16 +97,15 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, /* append PS then 0x01 (to lhash) */ x = hLen; y = modulus_len - msglen - 2*hLen - 2; - while (y--) { - DB[x++] = 0x00; - } + XMEMSET(DB+x, 0, y); + x += y; + + /* 0x01 byte */ DB[x++] = 0x01; - /* message */ - y = msglen; - while (y--) { - DB[x++] = *msg++; - } + /* message (length = msglen) */ + XMEMCPY(DB+x, msg, msglen); + x += msglen; /* now choose a random seed */ if (prng_descriptor[prng_idx].read(seed, hLen, prng) != hLen) { @@ -143,19 +142,18 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, /* 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]; - } + XMEMCPY(out+x, seed, hLen); + x += hLen; + XMEMCPY(out+x, DB, modulus_len - hLen - 1); + x += modulus_len - hLen - 1; + *outlen = x; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(DB, modulus_len); - zeromem(seed, modulus_len); + zeromem(seed, hLen); zeromem(mask, modulus_len); #endif @@ -168,3 +166,7 @@ LBL_ERR: #endif /* PKCS_1 */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/pkcs1/pkcs_1_os2ip.c b/src/pk/pkcs1/pkcs_1_os2ip.c index db6b58c7..42627cae 100644 --- a/src/pk/pkcs1/pkcs_1_os2ip.c +++ b/src/pk/pkcs1/pkcs_1_os2ip.c @@ -35,3 +35,7 @@ int pkcs_1_os2ip(mp_int *n, unsigned char *in, unsigned long inlen) #endif /* PKCS_1 */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/pkcs1/pkcs_1_pss_decode.c b/src/pk/pkcs1/pkcs_1_pss_decode.c index a19e7d8c..98c71608 100644 --- a/src/pk/pkcs1/pkcs_1_pss_decode.c +++ b/src/pk/pkcs1/pkcs_1_pss_decode.c @@ -87,14 +87,13 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, } /* copy out the DB */ - for (x = 0; x < modulus_len - hLen - 1; x++) { - DB[x] = sig[x]; - } + x = 0; + XMEMCPY(DB, sig + x, modulus_len - hLen - 1); + x += modulus_len - hLen - 1; /* copy out the hash */ - for (y = 0; y < hLen; y++) { - hash[y] = sig[x++]; - } + XMEMCPY(hash, sig + x, hLen); + x += hLen; /* check the MSB */ if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)))) != 0) { @@ -172,3 +171,7 @@ LBL_ERR: } #endif /* PKCS_1 */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/pkcs1/pkcs_1_pss_encode.c b/src/pk/pkcs1/pkcs_1_pss_encode.c index 58a03d52..a086e389 100644 --- a/src/pk/pkcs1/pkcs_1_pss_encode.c +++ b/src/pk/pkcs1/pkcs_1_pss_encode.c @@ -110,13 +110,12 @@ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, } /* 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; - } + x = 0; + XMEMSET(DB + x, 0, modulus_len - saltlen - hLen - 2); + x += modulus_len - saltlen - hLen - 2; DB[x++] = 0x01; - for (y = 0; y < saltlen; y++) { - DB[x++] = salt[y]; - } + XMEMCPY(DB + x, salt, saltlen); + x += saltlen; /* 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) { @@ -134,14 +133,15 @@ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, goto LBL_ERR; } - /* DB */ - for (y = x = 0; x < modulus_len - hLen - 1; x++) { - out[y++] = DB[x]; - } + /* DB len = modulus_len - hLen - 1 */ + y = 0; + XMEMCPY(out + y, DB, modulus_len - hLen - 1); + y += modulus_len - hLen - 1; + /* hash */ - for (x = 0; x < hLen; x++) { - out[y++] = hash[x]; - } + XMEMCPY(out + y, hash, hLen); + y += hLen; + /* 0xBC */ out[y] = 0xBC; @@ -168,3 +168,7 @@ LBL_ERR: } #endif /* PKCS_1 */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/pkcs1/pkcs_1_v15_es_decode.c b/src/pk/pkcs1/pkcs_1_v15_es_decode.c deleted file mode 100644 index fc548459..00000000 --- a/src/pk/pkcs1/pkcs_1_v15_es_decode.c +++ /dev/null @@ -1,74 +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 - * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org - */ -#include "tomcrypt.h" - -/** - @file pkcs_1_v15_es_decode.c - PKCS #1 v1.5 Encryption Padding, Tom St Denis -*/ - -#ifdef PKCS_1 - -/** - PKCS #1 v1.5 Encryption Decoding - @param msg The padded data - @param msglen The length of the padded data (octets) - @param modulus_bitlen The bit length of the RSA modulus - @param out [out] Where to store the decoded data - @param outlen The length of the decoded data - @param res [out] Result of the decoding, 1==valid, 0==invalid - @return CRYPT_OK if successful -*/ -int pkcs_1_v15_es_decode(const unsigned char *msg, unsigned long msglen, - unsigned long modulus_bitlen, - unsigned char *out, unsigned long outlen, - int *res) -{ - unsigned long x, modulus_bytelen; - - LTC_ARGCHK(msg != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(res != NULL); - - /* default to failed */ - *res = 0; - - modulus_bytelen = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); - - /* must be at least modulus_bytelen bytes long */ - if (msglen != modulus_bytelen) { - return CRYPT_INVALID_ARG; - } - - /* should start with 0x00 0x02 */ - if (msg[0] != 0x00 || msg[1] != 0x02) { - return CRYPT_OK; - } - - /* skip over PS */ - x = 2 + (modulus_bytelen - outlen - 3); - - /* should be 0x00 */ - if (msg[x++] != 0x00) { - return CRYPT_OK; - } - - /* the message is left */ - if (x + outlen > modulus_bytelen) { - return CRYPT_PK_INVALID_SIZE; - } - XMEMCPY(out, msg + x, outlen); - *res = 1; - return CRYPT_OK; -} - -#endif - diff --git a/src/pk/pkcs1/pkcs_1_v15_es_encode.c b/src/pk/pkcs1/pkcs_1_v15_es_encode.c deleted file mode 100644 index b6ac4298..00000000 --- a/src/pk/pkcs1/pkcs_1_v15_es_encode.c +++ /dev/null @@ -1,69 +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 - * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org - */ -#include "tomcrypt.h" - -/** - @file pkcs_1_v15_es_encode.c - v1.5 Encryption Padding for PKCS #1, Tom St Denis -*/ - -#ifdef PKCS_1 - -/** - PKCS #1 v1.5 Encryption Padding - @param msg The data to encode - @param msglen The length of the data (octets) - @param modulus_bitlen The bit length of the RSA modulus - @param prng An active PRNG - @param prng_idx The index of the PRNG desired - @param out [out] The destination of the padding - @param outlen [in/out] The max size and resulting size of the padding - @return CRYPT_OK if successful -*/ -int pkcs_1_v15_es_encode(const unsigned char *msg, unsigned long msglen, - unsigned long modulus_bitlen, - prng_state *prng, int prng_idx, - unsigned char *out, unsigned long *outlen) -{ - unsigned long modulus_bytelen, x, y; - - LTC_ARGCHK(msg != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - /* get modulus len */ - modulus_bytelen = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); - if (modulus_bytelen < 12) { - return CRYPT_INVALID_ARG; - } - - /* verify length */ - if (msglen > (modulus_bytelen - 11) || *outlen < modulus_bytelen) { - return CRYPT_PK_INVALID_SIZE; - } - - /* 0x00 0x02 PS 0x00 M */ - x = 0; - out[x++] = 0x00; - out[x++] = 0x02; - y = modulus_bytelen - msglen - 3; - if (prng_descriptor[prng_idx].read(out+x, y, prng) != y) { - return CRYPT_ERROR_READPRNG; - } - x += y; - out[x++] = 0x00; - XMEMCPY(out+x, msg, msglen); - *outlen = modulus_bytelen; - - return CRYPT_OK; -} - -#endif /* PKCS_1 */ diff --git a/src/pk/pkcs1/pkcs_1_v15_sa_decode.c b/src/pk/pkcs1/pkcs_1_v15_sa_decode.c deleted file mode 100644 index 7cad021a..00000000 --- a/src/pk/pkcs1/pkcs_1_v15_sa_decode.c +++ /dev/null @@ -1,91 +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 - * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org - */ -#include "tomcrypt.h" - -/** - @file pkcs_1_v15_sa_decode.c - PKCS #1 v1.5 Signature Padding, Tom St Denis -*/ - -#ifdef PKCS_1 - -/** - Perform PKCS #1 v1.5 Signature Decoding - @param msghash The hash that was signed - @param msghashlen The length of the hash - @param sig The signature [padded data] - @param siglen The length of the signature - @param hash_idx The index of the hash used - @param modulus_bitlen The bit length of the RSA modulus - @param res [out] Result of comparison, 1==valid, 0==invalid - @return CRYPT_OK if successful -*/ -int pkcs_1_v15_sa_decode(const unsigned char *msghash, unsigned long msghashlen, - const unsigned char *sig, unsigned long siglen, - int hash_idx, unsigned long modulus_bitlen, - int *res) -{ - unsigned long x, y, modulus_bytelen, derlen; - int err; - - LTC_ARGCHK(msghash != NULL); - LTC_ARGCHK(sig != NULL); - LTC_ARGCHK(res != NULL); - - /* default to invalid */ - *res = 0; - - /* valid hash ? */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - - /* get derlen */ - derlen = hash_descriptor[hash_idx].DERlen; - - /* get modulus len */ - modulus_bytelen = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); - - /* valid sizes? */ - if ((msghashlen + 3 + derlen > modulus_bytelen) || (siglen != modulus_bytelen)) { - return CRYPT_PK_INVALID_SIZE; - } - - /* packet is 0x00 0x01 PS 0x00 T, where PS == 0xFF repeated modulus_bytelen - 3 - derlen - msghashlen times, T == DER || hash */ - x = 0; - if (sig[x++] != 0x00 || sig[x++] != 0x01) { - return CRYPT_OK; - } - - /* now follows (modulus_bytelen - 3 - derlen - msghashlen) 0xFF bytes */ - for (y = 0; y < (modulus_bytelen - 3 - derlen - msghashlen); y++) { - if (sig[x++] != 0xFF) { - return CRYPT_OK; - } - } - - if (sig[x++] != 0x00) { - return CRYPT_OK; - } - - for (y = 0; y < derlen; y++) { - if (sig[x++] != hash_descriptor[hash_idx].DER[y]) { - return CRYPT_OK; - } - } - - if (memcmp(msghash, sig+x, msghashlen) == 0) { - *res = 1; - } - return CRYPT_OK; -} - -#endif diff --git a/src/pk/pkcs1/pkcs_1_v15_sa_encode.c b/src/pk/pkcs1/pkcs_1_v15_sa_encode.c deleted file mode 100644 index 60c77ef0..00000000 --- a/src/pk/pkcs1/pkcs_1_v15_sa_encode.c +++ /dev/null @@ -1,84 +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 - * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org - */ -#include "tomcrypt.h" - -/** - @file pkcs_1_v15_sa_encode.c - PKCS #1 v1.5 Signature Padding, Tom St Denis -*/ - -#ifdef PKCS_1 - -/** - Perform PKCS #1 v1.5 Signature Padding - @param msghash The hash you wish to incorporate in the padding - @param msghashlen The length of the hash - @param hash_idx The index of the hash used - @param modulus_bitlen The length of the RSA modulus that will sign this (bits) - @param out [out] Where to store the padded data - @param outlen [in/out] Max size and resulting size of the padded data - @return CRYPT_OK if successful -*/ -int pkcs_1_v15_sa_encode(const unsigned char *msghash, unsigned long msghashlen, - int hash_idx, unsigned long modulus_bitlen, - unsigned char *out, unsigned long *outlen) -{ - unsigned long derlen, modulus_bytelen, x, y; - int err; - - LTC_ARGCHK(msghash != NULL) - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - - /* hack, to detect any hash without a DER OID */ - if (hash_descriptor[hash_idx].DERlen == 0) { - return CRYPT_INVALID_ARG; - } - - /* get modulus len */ - modulus_bytelen = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); - - /* get der len ok? Forgive my lame German accent.... */ - derlen = hash_descriptor[hash_idx].DERlen; - - /* valid sizes? */ - if (msghashlen + 3 + derlen > modulus_bytelen) { - return CRYPT_PK_INVALID_SIZE; - } - - if (*outlen < modulus_bytelen) { - return CRYPT_BUFFER_OVERFLOW; - } - - /* packet is 0x00 0x01 PS 0x00 T, where PS == 0xFF repeated modulus_bytelen - 3 - derlen - msghashlen times, T == DER || hash */ - x = 0; - out[x++] = 0x00; - out[x++] = 0x01; - for (y = 0; y < (modulus_bytelen - 3 - derlen - msghashlen); y++) { - out[x++] = 0xFF; - } - out[x++] = 0x00; - for (y = 0; y < derlen; y++) { - out[x++] = hash_descriptor[hash_idx].DER[y]; - } - for (y = 0; y < msghashlen; y++) { - out[x++] = msghash[y]; - } - - *outlen = modulus_bytelen; - return CRYPT_OK; -} - -#endif /* PKCS_1 */ diff --git a/src/pk/rsa/rsa_decrypt_key.c b/src/pk/rsa/rsa_decrypt_key.c index 3117715b..ba2a076a 100644 --- a/src/pk/rsa/rsa_decrypt_key.c +++ b/src/pk/rsa/rsa_decrypt_key.c @@ -87,3 +87,7 @@ int rsa_decrypt_key(const unsigned char *in, unsigned long inlen, + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/rsa/rsa_encrypt_key.c b/src/pk/rsa/rsa_encrypt_key.c index 891b43e0..88efb3d2 100644 --- a/src/pk/rsa/rsa_encrypt_key.c +++ b/src/pk/rsa/rsa_encrypt_key.c @@ -74,3 +74,7 @@ int rsa_encrypt_key(const unsigned char *in, unsigned long inlen, } #endif /* MRSA */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/rsa/rsa_export.c b/src/pk/rsa/rsa_export.c index 951be702..f7f42bf4 100644 --- a/src/pk/rsa/rsa_export.c +++ b/src/pk/rsa/rsa_export.c @@ -27,7 +27,8 @@ */ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key) { - int err, x; + int err; + unsigned long zero=0; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); @@ -37,62 +38,39 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key if (!(key->type == PK_PRIVATE) && (type == PK_PRIVATE)) { return CRYPT_PK_INVALID_TYPE; } - if (*outlen < 4) { - return CRYPT_BUFFER_OVERFLOW; - } - - /* Mental Note: push space for the header 0x30 0x82 LL LL (LL = length of packet EXcluding 4 bytes) - * we assume LL > 255 which is true since the smallest RSA key has a 128-byte modulus (1024-bit) - */ - *outlen -= 4; if (type == PK_PRIVATE) { /* private key */ - mp_int zero; - - /* first INTEGER == 0 to signify two-prime RSA */ - if ((err = mp_init(&zero)) != MP_OKAY) { - return mpi_to_ltc_error(err); - } - /* output is Version, n, e, d, p, q, d mod (p-1), d mod (q - 1), 1/q mod p */ - if ((err = der_put_multi_integer( - out+4, outlen, &zero, &key->N, &key->e, - &key->d, &key->p, &key->q, &key->dP, - &key->dQ, &key->qP, NULL)) != CRYPT_OK) { - mp_clear(&zero); + if ((err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &zero, + LTC_ASN1_INTEGER, 1UL, &key->N, + LTC_ASN1_INTEGER, 1UL, &key->e, + LTC_ASN1_INTEGER, 1UL, &key->d, + LTC_ASN1_INTEGER, 1UL, &key->p, + LTC_ASN1_INTEGER, 1UL, &key->q, + LTC_ASN1_INTEGER, 1UL, &key->dP, + LTC_ASN1_INTEGER, 1UL, &key->dQ, + LTC_ASN1_INTEGER, 1UL, &key->qP, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { return err; } /* clear zero and return */ - mp_clear(&zero); + return CRYPT_OK; } else { /* public key */ - if ((err = der_put_multi_integer(out+4, outlen, &key->N, &key->e, NULL)) != CRYPT_OK) { - return err; - } + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_INTEGER, 1UL, &key->N, + LTC_ASN1_INTEGER, 1UL, &key->e, + LTC_ASN1_EOL, 0UL, NULL); } - - /* store the header */ - out[0] = 0x30; - if (*outlen < 256) { - /* shift the output up one byte if the header is only 3 bytes */ - for (x = 0; x < *outlen; x++) { - out[x+3] = out[x+4]; - } - out[1] = 0x81; - out[2] = (*outlen & 255); - *outlen += 3; - } else { - out[1] = 0x82; - out[2] = (*outlen >> 8) & 255; - out[3] = (*outlen & 255); - *outlen += 4; - } - return err; } #endif /* MRSA */ +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/rsa/rsa_exptmod.c b/src/pk/rsa/rsa_exptmod.c index fda6cbb5..b7bfebd3 100644 --- a/src/pk/rsa/rsa_exptmod.c +++ b/src/pk/rsa/rsa_exptmod.c @@ -103,3 +103,7 @@ done: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/rsa/rsa_free.c b/src/pk/rsa/rsa_free.c index 85ade97d..a6114609 100644 --- a/src/pk/rsa/rsa_free.c +++ b/src/pk/rsa/rsa_free.c @@ -29,3 +29,7 @@ void rsa_free(rsa_key *key) } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/rsa/rsa_import.c b/src/pk/rsa/rsa_import.c index 5408df06..d89ed973 100644 --- a/src/pk/rsa/rsa_import.c +++ b/src/pk/rsa/rsa_import.c @@ -18,7 +18,7 @@ #ifdef MRSA /** - Import an RSAPublicKey or RSAPrivateKey [two-prime only, defined in PKCS #1 v2.1] + Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in PKCS #1 v2.1] @param in The packet to import from @param inlen It's length (octets) @param key [out] Destination for newly imported key @@ -26,65 +26,39 @@ */ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) { - unsigned long x, y; - int err; + int err; + mp_int zero; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); /* init key */ - if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, - &key->p, &key->q, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&zero, &key->e, &key->d, &key->N, &key->dQ, + &key->dP, &key->qP, &key->p, &key->q, NULL)) != MP_OKAY) { return mpi_to_ltc_error(err); } - /* check the header */ - if (inlen < 4) { - return CRYPT_INVALID_PACKET; - } - - /* should be 0x30 0x8{1|2} LL LL */ - if ((in[0] != 0x30) || ((in[1] != 0x81) && (in[1] != 0x82))) { - return CRYPT_INVALID_PACKET; - } - - /* ok all the ASN.1 params are fine so far, let's move up */ - x = ((unsigned long)in[2]); - y = 0; - if ((in[1] & ~0x80) == 2) { - x = (x << 8) + ((unsigned long)in[3]) + 1; - in += 1; - y = 1; - } - in += 3; /* advance input */ - x += 3; /* size of packet according to header */ - y += 3; /* used input */ - - if (x != inlen) { - return CRYPT_INVALID_PACKET; - } - - /* decrement inlen by the header size */ - inlen -= y; - - /* read first number, it's either N or 0 [0 == private key] */ - x = inlen; - if ((err = der_get_multi_integer(in, &x, &key->N, NULL)) != CRYPT_OK) { + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_INTEGER, 1UL, &key->N, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto LBL_ERR; } - /* advance */ - inlen -= x; - in += x; - if (mp_cmp_d(&key->N, 0) == MP_EQ) { /* it's a private key */ - if ((err = der_get_multi_integer(in, &inlen, &key->N, &key->e, - &key->d, &key->p, &key->q, &key->dP, - &key->dQ, &key->qP, NULL)) != CRYPT_OK) { + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_INTEGER, 1UL, &zero, + LTC_ASN1_INTEGER, 1UL, &key->N, + LTC_ASN1_INTEGER, 1UL, &key->e, + LTC_ASN1_INTEGER, 1UL, &key->d, + LTC_ASN1_INTEGER, 1UL, &key->p, + LTC_ASN1_INTEGER, 1UL, &key->q, + LTC_ASN1_INTEGER, 1UL, &key->dP, + LTC_ASN1_INTEGER, 1UL, &key->dQ, + LTC_ASN1_INTEGER, 1UL, &key->qP, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto LBL_ERR; } - key->type = PK_PRIVATE; } else if (mp_cmp_d(&key->N, 1) == MP_EQ) { /* we don't support multi-prime RSA */ @@ -92,21 +66,27 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) goto LBL_ERR; } else { /* it's a public key and we lack e */ - if ((err = der_get_multi_integer(in, &inlen, &key->e, NULL)) != CRYPT_OK) { + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_INTEGER, 1UL, &key->N, + LTC_ASN1_INTEGER, 1UL, &key->e, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto LBL_ERR; } /* free up some ram */ mp_clear_multi(&key->p, &key->q, &key->qP, &key->dP, &key->dQ, NULL); - key->type = PK_PUBLIC; } return CRYPT_OK; LBL_ERR: - mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP, + mp_clear_multi(&zero, &key->d, &key->e, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL); return err; } #endif /* MRSA */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/rsa/rsa_make_key.c b/src/pk/rsa/rsa_make_key.c index 9d49e3ce..34a94d34 100644 --- a/src/pk/rsa/rsa_make_key.c +++ b/src/pk/rsa/rsa_make_key.c @@ -119,3 +119,7 @@ done: } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/rsa/rsa_sign_hash.c b/src/pk/rsa/rsa_sign_hash.c index b86ad64f..010ee3cf 100644 --- a/src/pk/rsa/rsa_sign_hash.c +++ b/src/pk/rsa/rsa_sign_hash.c @@ -73,3 +73,7 @@ int rsa_sign_hash(const unsigned char *in, unsigned long inlen, } #endif /* MRSA */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/rsa/rsa_v15_decrypt_key.c b/src/pk/rsa/rsa_v15_decrypt_key.c deleted file mode 100644 index eb5fe7d9..00000000 --- a/src/pk/rsa/rsa_v15_decrypt_key.c +++ /dev/null @@ -1,73 +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 - * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org - */ -#include "tomcrypt.h" - -/** - @file rsa_v15_decrypt_key.c - RSA PKCS v1.5 Decryption, Tom St Denis -*/ - -#ifdef MRSA - -/** - RSA decrypt then PKCS #1 v1.5 depad - @param in The ciphertext - @param inlen The length of the ciphertext (octets) - @param out [out] The plaintext - @param outlen The length of the plaintext (you have to tell this function as it's not part of PKCS #1 v1.0 padding!) - @param stat [out] Status of decryption, 1==valid, 0==invalid - @param key The corresponding private RSA key - @return CRYPT_OK if successful (even if invalid) -*/ -int rsa_v15_decrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long outlen, - int *stat, rsa_key *key) -{ - unsigned long modulus_bitlen, modulus_bytelen, x; - int err; - unsigned char *tmp; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(stat != NULL); - - /* default to invalid */ - *stat = 0; - - /* get modulus len in bits */ - modulus_bitlen = mp_count_bits(&(key->N)); - - /* outlen must be at least the size of the modulus */ - modulus_bytelen = mp_unsigned_bin_size(&(key->N)); - if (modulus_bytelen != inlen) { - return CRYPT_INVALID_PACKET; - } - - /* allocate ram */ - tmp = XMALLOC(inlen); - if (tmp == NULL) { - return CRYPT_MEM; - } - - /* rsa decode the packet */ - x = inlen; - if ((err = rsa_exptmod(in, inlen, tmp, &x, PK_PRIVATE, key)) != CRYPT_OK) { - XFREE(tmp); - return err; - } - - /* PKCS #1 v1.5 depad */ - err = pkcs_1_v15_es_decode(tmp, x, modulus_bitlen, out, outlen, stat); - XFREE(tmp); - return err; -} - -#endif diff --git a/src/pk/rsa/rsa_v15_encrypt_key.c b/src/pk/rsa/rsa_v15_encrypt_key.c deleted file mode 100644 index d422f67b..00000000 --- a/src/pk/rsa/rsa_v15_encrypt_key.c +++ /dev/null @@ -1,68 +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 - * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org - */ -#include "tomcrypt.h" - -/** - @file rsa_v15_encrypt_key.c - RSA PKCS v1.5 Encryption, Tom St Denis -*/ - -#ifdef MRSA - -/** - PKCS #1 v1.5 pad then encrypt - @param in The plaintext - @param inlen The length of the plaintext (octets) - @param out [out] The ciphertext - @param outlen [in/out] The max size and resulting size of the ciphertext - @param prng An active PRNG - @param prng_idx The index of the desired PRNG - @param key The public RSA key - @return CRYPT_OK if successful -*/ -int rsa_v15_encrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int prng_idx, - rsa_key *key) -{ - unsigned long modulus_bitlen, modulus_bytelen, x; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - - /* valid prng? */ - if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { - return err; - } - - /* get modulus len in bits */ - modulus_bitlen = mp_count_bits(&(key->N)); - - /* outlen must be at least the size of the modulus */ - modulus_bytelen = mp_unsigned_bin_size(&(key->N)); - if (modulus_bytelen > *outlen) { - return CRYPT_BUFFER_OVERFLOW; - } - - /* pad it */ - x = *outlen; - if ((err = pkcs_1_v15_es_encode(in, inlen, modulus_bitlen, prng, prng_idx, out, &x)) != CRYPT_OK) { - return err; - } - - /* encrypt it */ - return rsa_exptmod(out, x, out, outlen, PK_PUBLIC, key); -} - -#endif diff --git a/src/pk/rsa/rsa_v15_sign_hash.c b/src/pk/rsa/rsa_v15_sign_hash.c deleted file mode 100644 index 7e9b3505..00000000 --- a/src/pk/rsa/rsa_v15_sign_hash.c +++ /dev/null @@ -1,66 +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 - * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org - */ -#include "tomcrypt.h" - -/** - @file rsa_v15_sign_hash.c - RSA PKCS v1.5 Signature, Tom St Denis -*/ - -#ifdef MRSA - -/** - PKCS #1 v1.5 pad then sign - @param in The hash to sign - @param inlen The length of the message hash (octets) - @param out [out] The signature - @param siglen [in/out] The max size and resulting size of the signature - @param hash_idx The index of the hash desired - @param key The private RSA key to perform the signature with - @return CRYPT_OK if successful -*/ -int rsa_v15_sign_hash(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *siglen, - int hash_idx, rsa_key *key) -{ - unsigned long modulus_bitlen, modulus_bytelen, x; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(siglen != NULL); - LTC_ARGCHK(key != NULL); - - /* valid hash ? */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - - /* get modulus len in bits */ - modulus_bitlen = mp_count_bits(&(key->N)); - - /* outlen must be at least the size of the modulus */ - modulus_bytelen = mp_unsigned_bin_size(&(key->N)); - if (modulus_bytelen > *siglen) { - return CRYPT_BUFFER_OVERFLOW; - } - - /* PKCS #1 v1.5 pad the key */ - x = *siglen; - if ((err = pkcs_1_v15_sa_encode(in, inlen, hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) { - return err; - } - - /* RSA encode it */ - return rsa_exptmod(out, x, out, siglen, PK_PRIVATE, key); -} - -#endif diff --git a/src/pk/rsa/rsa_v15_verify_hash.c b/src/pk/rsa/rsa_v15_verify_hash.c deleted file mode 100644 index e742cba0..00000000 --- a/src/pk/rsa/rsa_v15_verify_hash.c +++ /dev/null @@ -1,81 +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 - * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org - */ -#include "tomcrypt.h" - -/** - @file rsa_v15_verify_hash.c - RSA PKCS v1.5 Signature verification, Tom St Denis -*/ - -#ifdef MRSA - -/** - RSA de-sign then PKCS v1.5 signature depad - @param sig The signature data - @param siglen The length of the signature (octets) - @param hash The hash of the message that was signed - @param hashlen The length of the hash of the message that was signed (octets) - @param hash_idx The index of the desired hash - @param stat [out] The result of the signature comparison, 1==valid, 0==invalid - @param key The corresponding public RSA key that performed the signature - @return CRYPT_OK if successful (even if the signature is invalid) -*/ -int rsa_v15_verify_hash(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long hashlen, - int hash_idx, int *stat, - rsa_key *key) -{ - unsigned long modulus_bitlen, modulus_bytelen, x; - int err; - unsigned char *tmpbuf; - - LTC_ARGCHK(hash != NULL); - LTC_ARGCHK(sig != NULL); - LTC_ARGCHK(stat != NULL); - LTC_ARGCHK(key != NULL); - - /* default to invalid */ - *stat = 0; - - /* valid hash ? */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - - /* get modulus len in bits */ - modulus_bitlen = mp_count_bits(&(key->N)); - - /* outlen must be at least the size of the modulus */ - modulus_bytelen = mp_unsigned_bin_size(&(key->N)); - if (modulus_bytelen != siglen) { - return CRYPT_INVALID_PACKET; - } - - /* allocate temp buffer for decoded sig */ - tmpbuf = XMALLOC(siglen); - if (tmpbuf == NULL) { - return CRYPT_MEM; - } - - /* RSA decode it */ - x = siglen; - if ((err = rsa_exptmod(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) { - XFREE(tmpbuf); - return err; - } - - /* PSS decode it */ - err = pkcs_1_v15_sa_decode(hash, hashlen, tmpbuf, x, hash_idx, modulus_bitlen, stat); - XFREE(tmpbuf); - return err; -} - -#endif diff --git a/src/pk/rsa/rsa_verify_hash.c b/src/pk/rsa/rsa_verify_hash.c index 7072083d..ab5b2f82 100644 --- a/src/pk/rsa/rsa_verify_hash.c +++ b/src/pk/rsa/rsa_verify_hash.c @@ -80,3 +80,7 @@ int rsa_verify_hash(const unsigned char *sig, unsigned long siglen, } #endif /* MRSA */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/prngs/fortuna.c b/src/prngs/fortuna.c index 4548a901..cdb67bf2 100644 --- a/src/prngs/fortuna.c +++ b/src/prngs/fortuna.c @@ -384,3 +384,7 @@ int fortuna_test(void) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/prngs/rc4.c b/src/prngs/rc4.c index 750c38b5..feddf1cb 100644 --- a/src/prngs/rc4.c +++ b/src/prngs/rc4.c @@ -258,3 +258,7 @@ int rc4_test(void) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/prngs/rng_get_bytes.c b/src/prngs/rng_get_bytes.c index 8519e0af..bd0972c9 100644 --- a/src/prngs/rng_get_bytes.c +++ b/src/prngs/rng_get_bytes.c @@ -138,3 +138,7 @@ unsigned long rng_get_bytes(unsigned char *out, unsigned long outlen, #endif return 0; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/prngs/rng_make_prng.c b/src/prngs/rng_make_prng.c index 94132e71..ce410e61 100644 --- a/src/prngs/rng_make_prng.c +++ b/src/prngs/rng_make_prng.c @@ -63,3 +63,7 @@ int rng_make_prng(int bits, int wprng, prng_state *prng, return CRYPT_OK; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/prngs/sober128.c b/src/prngs/sober128.c index 48667bd2..f5094749 100644 --- a/src/prngs/sober128.c +++ b/src/prngs/sober128.c @@ -489,3 +489,7 @@ int sober128_test(void) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/prngs/sober128tab.c b/src/prngs/sober128tab.c index e25e2719..a5754c72 100644 --- a/src/prngs/sober128tab.c +++ b/src/prngs/sober128tab.c @@ -156,3 +156,7 @@ static const ulong32 Sbox[256] = { 0x45f0b24f, 0x51fda998, 0xc0d52d71, 0xfa0896a8, 0xf9e6053f, 0xa4b0d300, 0xd499cbcc, 0xb95e3d40, }; + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/prngs/sprng.c b/src/prngs/sprng.c index dce83478..dc826679 100644 --- a/src/prngs/sprng.c +++ b/src/prngs/sprng.c @@ -130,3 +130,7 @@ int sprng_test(void) + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/prngs/yarrow.c b/src/prngs/yarrow.c index 1582856e..4abaf733 100644 --- a/src/prngs/yarrow.c +++ b/src/prngs/yarrow.c @@ -186,6 +186,7 @@ int yarrow_ready(prng_state *prng) prng->yarrow.pool, /* IV */ prng->yarrow.pool, ks, /* KEY and key size */ 0, /* number of rounds */ + CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */ &prng->yarrow.ctr)) != CRYPT_OK) { return err; } @@ -310,3 +311,7 @@ int yarrow_test(void) #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/testbuild.sh b/testbuild.sh new file mode 100644 index 00000000..a17c6775 --- /dev/null +++ b/testbuild.sh @@ -0,0 +1,11 @@ +#!/bin/bash +echo "$1 (Build Only, $2, $3)..." +make clean 1>/dev/null 2>/dev/null +echo -n "building..." +touch testok.txt +CFLAGS="$2" make -f $3 test tv_gen 1>gcc_1.txt 2>gcc_2.txt || (echo "build $1 failed see gcc_2.txt for more information" && cat gcc_2.txt && rm -f testok.txt && exit 1) +if find testok.txt -type f 1>/dev/null 2>/dev/null ; then + echo "successful" + exit 0 +fi +exit 1 diff --git a/testme.sh b/testme.sh new file mode 100644 index 00000000..da0f97b1 --- /dev/null +++ b/testme.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# date +echo "date="`date` + +# output version +echo "Testing verion" `grep "^VERSION=" makefile | sed "s/.*=//"` +#grep "VERSION=" makefile | perl -e "@a = split('=', <>); print @a[1];"` + +# get uname +echo "uname="`uname -a` +echo + +# stock build +bash run.sh "STOCK" " " $1 || exit 1 + +# SMALL code +bash run.sh "SMALL" "-DLTC_SMALL_CODE" $1 || exit 1 + +# NOTABLES +bash run.sh "NOTABLES" "-DLTC_NO_TABLES" $1 || exit 1 + +# SMALL+NOTABLES +bash run.sh "SMALL+NOTABLES" "-DLTC_SMALL_CODE -DLTC_NO_TABLES" $1 || exit 1 + +# CLEANSTACK +bash run.sh "CLEANSTACK" "-DLTC_CLEAN_STACK" $1 || exit 1 + +# CLEANSTACK + SMALL +bash run.sh "CLEANSTACK+SMALL" "-DLTC_SMALL_CODE -DLTC_CLEAN_STACK" $1 || exit 1 + +# CLEANSTACK + NOTABLES +bash run.sh "CLEANSTACK+NOTABLES" "-DLTC_NO_TABLES -DLTC_CLEAN_STACK" $1 || exit 1 + +# CLEANSTACK + NOTABLES + SMALL +bash run.sh "CLEANSTACK+NOTABLES+SMALL" "-DLTC_NO_TABLES -DLTC_CLEAN_STACK -DLTC_SMALL_CODE" $1 || exit 1 + +# NO_FAST +bash run.sh "NO_FAST" "-DLTC_NO_FAST" $1 || exit 1 + +# NO_ASM +bash run.sh "NO_ASM" "-DLTC_NO_ASM" $1 || exit 1 + +# test build with no testing +bash testbuild.sh "NOTEST" "-DLTC_NO_TEST" $1 || exit 1 + +# test build with no file routines +bash testbuild.sh "NOFILE" "-DLTC_NO_FILE" $1 || exit 1 + +# $Source: /cvs/libtom/libtomcrypt/testme.sh,v $ +# $Revision: 1.16 $ +# $Date: 2005/05/11 18:59:53 $ diff --git a/testprof/base64_test.c b/testprof/base64_test.c index e93ebefa..5ce55dd5 100644 --- a/testprof/base64_test.c +++ b/testprof/base64_test.c @@ -12,9 +12,13 @@ int base64_test(void) l2 = sizeof(tmp); DO(base64_decode(out, l1, tmp, &l2)); if (l2 != x || memcmp(tmp, in, x)) { - printf("base64 failed %lu %lu %lu", x, l1, l2); + fprintf(stderr, "base64 failed %lu %lu %lu", x, l1, l2); return 1; } } return 0; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/testprof/cipher_hash_test.c b/testprof/cipher_hash_test.c index d2f3bfca..666d9139 100644 --- a/testprof/cipher_hash_test.c +++ b/testprof/cipher_hash_test.c @@ -39,3 +39,7 @@ int cipher_hash_test(void) return 0; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/testprof/der_tests.c b/testprof/der_tests.c index fe8eb000..95f33485 100644 --- a/testprof/der_tests.c +++ b/testprof/der_tests.c @@ -4,7 +4,7 @@ int der_tests(void) { - printf("NOP"); + fprintf(stderr, "NOP"); return 0; } @@ -12,83 +12,219 @@ int der_tests(void) int der_tests(void) { - unsigned long x, y, z, zz; - unsigned char buf[2][4096]; + unsigned long x, y, z, zz, oid[2][32]; + unsigned char buf[3][2048]; mp_int a, b, c, d, e, f, g; + static const unsigned char rsa_oid_der[] = { 0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d }; + static const unsigned long rsa_oid[] = { 1, 2, 840, 113549 }; + + static const unsigned char rsa_ia5[] = "test1@rsa.com"; + static const unsigned char rsa_ia5_der[] = { 0x16, 0x0d, 0x74, 0x65, 0x73, 0x74, 0x31, + 0x40, 0x72, 0x73, 0x61, 0x2e, 0x63, 0x6f, 0x6d }; + + static const unsigned char rsa_printable[] = "Test User 1"; + static const unsigned char rsa_printable_der[] = { 0x13, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, + 0x73, 0x65, 0x72, 0x20, 0x31 }; + DO(mpi_to_ltc_error(mp_init_multi(&a, &b, &c, &d, &e, &f, &g, NULL))); for (zz = 0; zz < 16; zz++) { for (z = 0; z < 1024; z++) { if (yarrow_read(buf[0], z, &yarrow_prng) != z) { - printf("Failed to read %lu bytes from yarrow\n", z); + fprintf(stderr, "Failed to read %lu bytes from yarrow\n", z); return 1; } DO(mpi_to_ltc_error(mp_read_unsigned_bin(&a, buf[0], z))); + if (mp_iszero(&a) == MP_NO) { a.sign = buf[0][0] & 1 ? MP_ZPOS : MP_NEG; } x = sizeof(buf[0]); DO(der_encode_integer(&a, buf[0], &x)); - y = x; + DO(der_length_integer(&a, &y)); + if (y != x) { fprintf(stderr, "DER INTEGER size mismatch\n"); return 1; } mp_zero(&b); - DO(der_decode_integer(buf[0], &y, &b)); + DO(der_decode_integer(buf[0], y, &b)); if (y != x || mp_cmp(&a, &b) != MP_EQ) { - printf("%lu: %lu vs %lu\n", z, x, y); + fprintf(stderr, "%lu: %lu vs %lu\n", z, x, y); #ifdef BN_MP_TORADIX_C mp_todecimal(&a, buf[0]); mp_todecimal(&b, buf[1]); - printf("a == %s\nb == %s\n", buf[0], buf[1]); + fprintf(stderr, "a == %s\nb == %s\n", buf[0], buf[1]); #endif mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL); return 1; } } } - -/* test the multi */ - mp_set(&a, 1); - x = sizeof(buf[0]); - DO(der_put_multi_integer(buf[0], &x, &a, NULL)); - y = x; - mp_zero(&a); - DO(der_get_multi_integer(buf[0], &y, &a, NULL)); - if (x != y || mp_cmp_d(&a, 1)) { - printf("%lu, %lu, %d\n", x, y, mp_cmp_d(&a, 1)); - mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL); - return 1; - } +/* test short integer */ + for (zz = 0; zz < 256; zz++) { + for (z = 1; z < 4; z++) { + if (yarrow_read(buf[0], z, &yarrow_prng) != z) { + fprintf(stderr, "Failed to read %lu bytes from yarrow\n", z); + return 1; + } + /* encode with normal */ + DO(mpi_to_ltc_error(mp_read_unsigned_bin(&a, buf[0], z))); - mp_set(&a, 1); - mp_set(&b, 2); - x = sizeof(buf[0]); - DO(der_put_multi_integer(buf[0], &x, &a, &b, NULL)); - y = x; - mp_zero(&a); - mp_zero(&b); - DO(der_get_multi_integer(buf[0], &y, &a, &b, NULL)); - if (x != y || mp_cmp_d(&a, 1) || mp_cmp_d(&b, 2)) { - printf("%lu, %lu, %d, %d\n", x, y, mp_cmp_d(&a, 1), mp_cmp_d(&b, 2)); - mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL); - return 1; - } - - mp_set(&a, 1); - mp_set(&b, 2); - mp_set(&c, 3); - x = sizeof(buf[0]); - DO(der_put_multi_integer(buf[0], &x, &a, &b, &c, NULL)); - y = x; - mp_zero(&a); - mp_zero(&b); - mp_zero(&c); - DO(der_get_multi_integer(buf[0], &y, &a, &b, &c, NULL)); - if (x != y || mp_cmp_d(&a, 1) || mp_cmp_d(&b, 2) || mp_cmp_d(&c, 3)) { - printf("%lu, %lu, %d, %d, %d\n", x, y, mp_cmp_d(&a, 1), mp_cmp_d(&b, 2), mp_cmp_d(&c, 3)); - mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL); - return 1; - } + x = sizeof(buf[0]); + DO(der_encode_integer(&a, buf[0], &x)); + /* encode with short */ + y = sizeof(buf[1]); + DO(der_encode_short_integer(mp_get_int(&a), buf[1], &y)); + if (x != y || memcmp(buf[0], buf[1], x)) { + fprintf(stderr, "DER INTEGER short encoding failed, %lu, %lu\n", x, y); + for (z = 0; z < x; z++) fprintf(stderr, "%02x ", buf[0][z]); fprintf(stderr, "\n"); + for (z = 0; z < y; z++) fprintf(stderr, "%02x ", buf[1][z]); fprintf(stderr, "\n"); + mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL); + return 1; + } + /* decode it */ + x = 0; + DO(der_decode_short_integer(buf[1], y, &x)); + if (x != mp_get_int(&a)) { + fprintf(stderr, "DER INTEGER short decoding failed, %lu, %lu\n", x, mp_get_int(&a)); + mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL); + return 1; + } + } + } mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL); + + +/* Test bit string */ + for (zz = 1; zz < 1536; zz++) { + yarrow_read(buf[0], zz, &yarrow_prng); + for (z = 0; z < zz; z++) { + buf[0][z] &= 0x01; + } + x = sizeof(buf[1]); + DO(der_encode_bit_string(buf[0], zz, buf[1], &x)); + DO(der_length_bit_string(zz, &y)); + if (y != x) { + fprintf(stderr, "\nDER BIT STRING length of encoded not match expected : %lu, %lu, %lu\n", z, x, y); + return 1; + } + + y = sizeof(buf[2]); + DO(der_decode_bit_string(buf[1], x, buf[2], &y)); + if (y != zz || memcmp(buf[0], buf[2], zz)) { + fprintf(stderr, "%lu, %lu, %d\n", y, zz, memcmp(buf[0], buf[2], zz)); + return 1; + } + } + +/* Test octet string */ + for (zz = 1; zz < 1536; zz++) { + yarrow_read(buf[0], zz, &yarrow_prng); + x = sizeof(buf[1]); + DO(der_encode_octet_string(buf[0], zz, buf[1], &x)); + DO(der_length_octet_string(zz, &y)); + if (y != x) { + fprintf(stderr, "\nDER OCTET STRING length of encoded not match expected : %lu, %lu, %lu\n", z, x, y); + return 1; + } + y = sizeof(buf[2]); + DO(der_decode_octet_string(buf[1], x, buf[2], &y)); + if (y != zz || memcmp(buf[0], buf[2], zz)) { + fprintf(stderr, "%lu, %lu, %d\n", y, zz, memcmp(buf[0], buf[2], zz)); + return 1; + } + } + +/* test OID */ + x = sizeof(buf[0]); + DO(der_encode_object_identifier(rsa_oid, sizeof(rsa_oid)/sizeof(rsa_oid[0]), buf[0], &x)); + if (x != sizeof(rsa_oid_der) || memcmp(rsa_oid_der, buf[0], x)) { + fprintf(stderr, "rsa_oid_der encode failed to match, %lu, ", x); + for (y = 0; y < x; y++) fprintf(stderr, "%02x ", buf[0][y]); + fprintf(stderr, "\n"); + return 1; + } + + y = sizeof(oid[0])/sizeof(oid[0][0]); + DO(der_decode_object_identifier(buf[0], x, oid[0], &y)); + if (y != sizeof(rsa_oid)/sizeof(rsa_oid[0]) || memcmp(rsa_oid, oid[0], sizeof(rsa_oid))) { + fprintf(stderr, "rsa_oid_der decode failed to match, %lu, ", y); + for (z = 0; z < y; z++) fprintf(stderr, "%lu ", oid[0][z]); + fprintf(stderr, "\n"); + return 1; + } + + /* do random strings */ + for (zz = 0; zz < 5000; zz++) { + /* pick a random number of words */ + yarrow_read(buf[0], 4, &yarrow_prng); + LOAD32L(z, buf[0]); + z = 2 + (z % ((sizeof(oid[0])/sizeof(oid[0][0])) - 2)); + + /* fill them in */ + oid[0][0] = buf[0][0] % 3; + oid[0][1] = buf[0][1] % 40; + + for (y = 2; y < z; y++) { + yarrow_read(buf[0], 4, &yarrow_prng); + LOAD32L(oid[0][y], buf[0]); + } + + /* encode it */ + x = sizeof(buf[0]); + DO(der_encode_object_identifier(oid[0], z, buf[0], &x)); + DO(der_length_object_identifier(oid[0], z, &y)); + if (x != y) { + fprintf(stderr, "Random OID %lu test failed, length mismatch: %lu, %lu\n", z, x, y); + for (x = 0; x < z; x++) fprintf(stderr, "%lu\n", oid[0][x]); + return 1; + } + + /* decode it */ + y = sizeof(oid[0])/sizeof(oid[0][0]); + DO(der_decode_object_identifier(buf[0], x, oid[1], &y)); + if (y != z) { + fprintf(stderr, "Random OID %lu test failed, decode length mismatch: %lu, %lu\n", z, x, y); + return 1; + } + if (memcmp(oid[0], oid[1], sizeof(oid[0][0]) * z)) { + fprintf(stderr, "Random OID %lu test failed, decoded values wrong\n", z); + for (x = 0; x < z; x++) fprintf(stderr, "%lu\n", oid[0][x]); fprintf(stderr, "\n\n Got \n\n"); + for (x = 0; x < z; x++) fprintf(stderr, "%lu\n", oid[1][x]); + return 1; + } + } + +/* IA5 string */ + x = sizeof(buf[0]); + DO(der_encode_ia5_string(rsa_ia5, strlen(rsa_ia5), buf[0], &x)); + if (x != sizeof(rsa_ia5_der) || memcmp(buf[0], rsa_ia5_der, x)) { + fprintf(stderr, "IA5 encode failed: %lu, %lu\n", x, (unsigned long)sizeof(rsa_ia5_der)); + return 1; + } + y = sizeof(buf[1]); + DO(der_decode_ia5_string(buf[0], x, buf[1], &y)); + if (y != strlen(rsa_ia5) || memcmp(buf[1], rsa_ia5, strlen(rsa_ia5))) { + fprintf(stderr, "DER IA5 failed test vector\n"); + return 1; + } + +/* Printable string */ + x = sizeof(buf[0]); + DO(der_encode_printable_string(rsa_printable, strlen(rsa_printable), buf[0], &x)); + if (x != sizeof(rsa_printable_der) || memcmp(buf[0], rsa_printable_der, x)) { + fprintf(stderr, "PRINTABLE encode failed: %lu, %lu\n", x, (unsigned long)sizeof(rsa_printable_der)); + return 1; + } + y = sizeof(buf[1]); + DO(der_decode_printable_string(buf[0], x, buf[1], &y)); + if (y != strlen(rsa_printable) || memcmp(buf[1], rsa_printable, strlen(rsa_printable))) { + fprintf(stderr, "DER printable failed test vector\n"); + return 1; + } + return 0; } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/testprof/dh_tests.c b/testprof/dh_tests.c index feb74acf..e644b061 100644 --- a/testprof/dh_tests.c +++ b/testprof/dh_tests.c @@ -22,11 +22,11 @@ int dh_tests (void) y = 4096; DO(dh_shared_secret (&userb, &usera, buf[1], &y)); if (y != x) { - printf ("DH Shared keys are not same size.\n"); + fprintf(stderr, "DH Shared keys are not same size.\n"); return 1; } if (memcmp (buf[0], buf[1], x)) { - printf ("DH Shared keys not same contents.\n"); + fprintf(stderr, "DH Shared keys not same contents.\n"); return 1; } @@ -41,11 +41,11 @@ int dh_tests (void) DO(dh_shared_secret (&usera, &userb, buf[2], &z)); if (z != x) { - printf ("failed. Size don't match?\n"); + fprintf(stderr, "failed. Size don't match?\n"); return 1; } if (memcmp (buf[0], buf[2], x)) { - printf ("Failed. Content didn't match.\n"); + fprintf(stderr, "Failed. Content didn't match.\n"); return 1; } dh_free (&usera); @@ -62,12 +62,12 @@ int dh_tests (void) x = sizeof (buf[0]); DO(dh_decrypt_key (buf[1], y, buf[0], &x, &usera)); if (x != 16) { - printf ("Failed (length)\n"); + fprintf(stderr, "Failed (length)\n"); return 1; } for (x = 0; x < 16; x++) if (buf[0][x] != x) { - printf ("Failed (contents)\n"); + fprintf(stderr, "Failed (contents)\n"); return 1; } @@ -81,7 +81,7 @@ int dh_tests (void) buf[0][0] ^= 1; DO(dh_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera)); if (!(stat == 1 && stat2 == 0)) { - printf("dh_sign/verify_hash %d %d", stat, stat2); + fprintf(stderr, "dh_sign/verify_hash %d %d", stat, stat2); return 1; } dh_free (&usera); @@ -92,8 +92,12 @@ int dh_tests (void) int dh_tests(void) { - printf("NOP"); + fprintf(stderr, "NOP"); return 0; } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/testprof/dsa_test.c b/testprof/dsa_test.c index cd2e89a3..6724feb4 100644 --- a/testprof/dsa_test.c +++ b/testprof/dsa_test.c @@ -14,7 +14,7 @@ int dsa_test(void) /* verify it */ DO(dsa_verify_key(&key, &stat1)); - if (stat1 == 0) { printf("dsa_verify_key "); return 1; } + if (stat1 == 0) { fprintf(stderr, "dsa_verify_key "); return 1; } /* sign the message */ x = sizeof(out); @@ -27,7 +27,7 @@ int dsa_test(void) msg[0] ^= 1; DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat2, &key)); msg[0] ^= 1; - if (!(stat1 == 1 && stat2 == 0)) { printf("dsa_verify %d %d", stat1, stat2); return 1; } + if (!(stat1 == 1 && stat2 == 0)) { fprintf(stderr, "dsa_verify %d %d", stat1, stat2); return 1; } /* test exporting it */ x = sizeof(out2); @@ -36,16 +36,17 @@ int dsa_test(void) /* verify a signature with it */ DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2)); - if (stat1 == 0) { printf("dsa_verify (import private) %d ", stat1); return 1; } + if (stat1 == 0) { fprintf(stderr, "dsa_verify (import private) %d ", stat1); return 1; } dsa_free(&key2); /* export as public now */ x = sizeof(out2); DO(dsa_export(out2, &x, PK_PUBLIC, &key)); + DO(dsa_import(out2, x, &key2)); /* verify a signature with it */ DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2)); - if (stat1 == 0) { printf("dsa_verify (import public) %d ", stat1); return 1; } + if (stat1 == 0) { fprintf(stderr, "dsa_verify (import public) %d ", stat1); return 1; } dsa_free(&key2); dsa_free(&key); @@ -56,8 +57,12 @@ int dsa_test(void) int dsa_test(void) { - printf("NOP"); + fprintf(stderr, "NOP"); return 0; } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/testprof/ecc_test.c b/testprof/ecc_test.c index 0b37ba2f..4ec3e8a7 100644 --- a/testprof/ecc_test.c +++ b/testprof/ecc_test.c @@ -2,102 +2,123 @@ #ifdef MECC +static int sizes[] = { +#ifdef ECC192 +24, +#endif +#ifdef ECC224 +28, +#endif +#ifdef ECC256 +32, +#endif +#ifdef ECC384 +48, +#endif +#ifdef ECC512 +65 +#endif +}; + int ecc_tests (void) { unsigned char buf[4][4096]; - unsigned long x, y, z; + unsigned long x, y, z, s; int stat, stat2; ecc_key usera, userb, pubKey, privKey; DO(ecc_test ()); - /* make up two keys */ - DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), 65, &usera)); - DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), 65, &userb)); + for (s = 0; s < (int)(sizeof(sizes)/sizeof(sizes[0])); s++) { + /* make up two keys */ + DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &usera)); + DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &userb)); - /* make the shared secret */ - x = 4096; - DO(ecc_shared_secret (&usera, &userb, buf[0], &x)); + /* make the shared secret */ + x = 4096; + DO(ecc_shared_secret (&usera, &userb, buf[0], &x)); - y = 4096; - DO(ecc_shared_secret (&userb, &usera, buf[1], &y)); + y = 4096; + DO(ecc_shared_secret (&userb, &usera, buf[1], &y)); - if (y != x) { - printf ("ecc Shared keys are not same size."); - return 1; + if (y != x) { + fprintf(stderr, "ecc Shared keys are not same size."); + return 1; + } + + if (memcmp (buf[0], buf[1], x)) { + fprintf(stderr, "ecc Shared keys not same contents."); + return 1; + } + + /* now export userb */ + y = 4096; + DO(ecc_export (buf[1], &y, PK_PUBLIC, &userb)); + ecc_free (&userb); + + /* import and make the shared secret again */ + DO(ecc_import (buf[1], y, &userb)); + + z = 4096; + DO(ecc_shared_secret (&usera, &userb, buf[2], &z)); + + if (z != x) { + fprintf(stderr, "failed. Size don't match?"); + return 1; + } + if (memcmp (buf[0], buf[2], x)) { + fprintf(stderr, "Failed. Content didn't match."); + return 1; + } + ecc_free (&usera); + ecc_free (&userb); + + /* test encrypt_key */ + DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &usera)); + + /* export key */ + x = sizeof(buf[0]); + DO(ecc_export(buf[0], &x, PK_PUBLIC, &usera)); + DO(ecc_import(buf[0], x, &pubKey)); + x = sizeof(buf[0]); + DO(ecc_export(buf[0], &x, PK_PRIVATE, &usera)); + DO(ecc_import(buf[0], x, &privKey)); + + for (x = 0; x < 32; x++) { + buf[0][x] = x; + } + y = sizeof (buf[1]); + DO(ecc_encrypt_key (buf[0], 32, buf[1], &y, &yarrow_prng, find_prng ("yarrow"), find_hash ("sha256"), &pubKey)); + zeromem (buf[0], sizeof (buf[0])); + x = sizeof (buf[0]); + DO(ecc_decrypt_key (buf[1], y, buf[0], &x, &privKey)); + if (x != 32) { + fprintf(stderr, "Failed (length)"); + return 1; + } + for (x = 0; x < 32; x++) { + if (buf[0][x] != x) { + fprintf(stderr, "Failed (contents)"); + return 1; + } + } + /* test sign_hash */ + for (x = 0; x < 16; x++) { + buf[0][x] = x; + } + x = sizeof (buf[1]); + DO(ecc_sign_hash (buf[0], 16, buf[1], &x, &yarrow_prng, find_prng ("yarrow"), &privKey)); + DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat, &pubKey)); + buf[0][0] ^= 1; + DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat2, &privKey)); + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "ecc_verify_hash failed %d, %d, ", stat, stat2); + return 1; + } + ecc_free (&usera); + ecc_free (&pubKey); + ecc_free (&privKey); } - - if (memcmp (buf[0], buf[1], x)) { - printf ("ecc Shared keys not same contents."); - return 1; - } - - /* now export userb */ - y = 4096; - DO(ecc_export (buf[1], &y, PK_PUBLIC, &userb)); - ecc_free (&userb); - - /* import and make the shared secret again */ - DO(ecc_import (buf[1], y, &userb)); - - z = 4096; - DO(ecc_shared_secret (&usera, &userb, buf[2], &z)); - - if (z != x) { - printf ("failed. Size don't match?"); - return 1; - } - if (memcmp (buf[0], buf[2], x)) { - printf ("Failed. Content didn't match."); - return 1; - } - ecc_free (&usera); - ecc_free (&userb); - -/* test encrypt_key */ - DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), 65, &usera)); - -/* export key */ - x = sizeof(buf[0]); - DO(ecc_export(buf[0], &x, PK_PUBLIC, &usera)); - DO(ecc_import(buf[0], x, &pubKey)); - x = sizeof(buf[0]); - DO(ecc_export(buf[0], &x, PK_PRIVATE, &usera)); - DO(ecc_import(buf[0], x, &privKey)); - - for (x = 0; x < 32; x++) { - buf[0][x] = x; - } - y = sizeof (buf[1]); - DO(ecc_encrypt_key (buf[0], 32, buf[1], &y, &yarrow_prng, find_prng ("yarrow"), find_hash ("sha256"), &pubKey)); - zeromem (buf[0], sizeof (buf[0])); - x = sizeof (buf[0]); - DO(ecc_decrypt_key (buf[1], y, buf[0], &x, &privKey)); - if (x != 32) { - printf ("Failed (length)"); - return 1; - } - for (x = 0; x < 32; x++) - if (buf[0][x] != x) { - printf ("Failed (contents)"); - return 1; - } -/* test sign_hash */ - for (x = 0; x < 16; x++) { - buf[0][x] = x; - } - x = sizeof (buf[1]); - DO(ecc_sign_hash (buf[0], 16, buf[1], &x, &yarrow_prng, find_prng ("yarrow"), &privKey)); - DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat, &pubKey)); - buf[0][0] ^= 1; - DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat2, &privKey)); - if (!(stat == 1 && stat2 == 0)) { - printf("ecc_verify_hash failed %d, %d, ", stat, stat2); - return 1; - } - ecc_free (&usera); - ecc_free (&pubKey); - ecc_free (&privKey); return 0; } @@ -105,8 +126,12 @@ int ecc_tests (void) int ecc_tests(void) { - printf("NOP"); + fprintf(stderr, "NOP"); return 0; } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/testprof/mac_test.c b/testprof/mac_test.c index b076d7b6..e22a72a3 100644 --- a/testprof/mac_test.c +++ b/testprof/mac_test.c @@ -29,3 +29,7 @@ int mac_test(void) #endif return 0; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/testprof/makefile.icc b/testprof/makefile.icc index c9226fba..ff87660f 100644 --- a/testprof/makefile.icc +++ b/testprof/makefile.icc @@ -1,4 +1,4 @@ -CFLAGS += -I../src/headers -I./ -O3 -xP -ip +CFLAGS += -I../src/headers -I./ CC=icc OBJECTS = base64_test.o cipher_hash_test.o der_tests.o dh_tests.o \ diff --git a/testprof/modes_test.c b/testprof/modes_test.c index 46beb8ab..da25f85d 100644 --- a/testprof/modes_test.c +++ b/testprof/modes_test.c @@ -19,7 +19,7 @@ int modes_test(void) /* get idx of AES handy */ cipher_idx = find_cipher("aes"); if (cipher_idx == -1) { - printf("test requires AES"); + fprintf(stderr, "test requires AES"); return 1; } @@ -30,7 +30,7 @@ int modes_test(void) l = sizeof(iv2); DO(cbc_getiv(iv2, &l, &cbc)); if (l != 16 || memcmp(iv2, iv, 16)) { - printf("cbc_getiv failed"); + fprintf(stderr, "cbc_getiv failed"); return 1; } DO(cbc_encrypt(pt, ct, 64, &cbc)); @@ -40,7 +40,7 @@ int modes_test(void) zeromem(tmp, sizeof(tmp)); DO(cbc_decrypt(ct, tmp, 64, &cbc)); if (memcmp(tmp, pt, 64) != 0) { - printf("CBC failed"); + fprintf(stderr, "CBC failed"); return 1; } #endif @@ -53,7 +53,7 @@ int modes_test(void) DO(cfb_getiv(iv2, &l, &cfb)); /* note we don't memcmp iv2/iv since cfb_start processes the IV for the first block */ if (l != 16) { - printf("cfb_getiv failed"); + fprintf(stderr, "cfb_getiv failed"); return 1; } DO(cfb_encrypt(pt, ct, 64, &cfb)); @@ -63,7 +63,7 @@ int modes_test(void) zeromem(tmp, sizeof(tmp)); DO(cfb_decrypt(ct, tmp, 64, &cfb)); if (memcmp(tmp, pt, 64) != 0) { - printf("CFB failed"); + fprintf(stderr, "CFB failed"); return 1; } #endif @@ -75,7 +75,7 @@ int modes_test(void) l = sizeof(iv2); DO(ofb_getiv(iv2, &l, &ofb)); if (l != 16 || memcmp(iv2, iv, 16)) { - printf("ofb_getiv failed"); + fprintf(stderr, "ofb_getiv failed"); return 1; } DO(ofb_encrypt(pt, ct, 64, &ofb)); @@ -85,7 +85,7 @@ int modes_test(void) zeromem(tmp, sizeof(tmp)); DO(ofb_decrypt(ct, tmp, 64, &ofb)); if (memcmp(tmp, pt, 64) != 0) { - printf("OFB failed"); + fprintf(stderr, "OFB failed"); return 1; } #endif @@ -93,11 +93,11 @@ int modes_test(void) #ifdef CTR /* test CTR mode */ /* encode the block */ - DO(ctr_start(cipher_idx, iv, key, 16, 0, &ctr)); + DO(ctr_start(cipher_idx, iv, key, 16, 0, CTR_COUNTER_LITTLE_ENDIAN, &ctr)); l = sizeof(iv2); DO(ctr_getiv(iv2, &l, &ctr)); if (l != 16 || memcmp(iv2, iv, 16)) { - printf("ctr_getiv failed"); + fprintf(stderr, "ctr_getiv failed"); return 1; } DO(ctr_encrypt(pt, ct, 57, &ctr)); @@ -107,10 +107,14 @@ int modes_test(void) zeromem(tmp, sizeof(tmp)); DO(ctr_decrypt(ct, tmp, 57, &ctr)); if (memcmp(tmp, pt, 57) != 0) { - printf("CTR failed"); + fprintf(stderr, "CTR failed"); return 1; } #endif return 0; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/testprof/pkcs_1_test.c b/testprof/pkcs_1_test.c index 40cf6306..aabf30b9 100644 --- a/testprof/pkcs_1_test.c +++ b/testprof/pkcs_1_test.c @@ -14,7 +14,7 @@ int pkcs_1_test(void) prng_idx = find_prng("yarrow"); if (hash_idx == -1 || prng_idx == -1) { - printf("pkcs_1 tests require sha1/yarrow"); + fprintf(stderr, "pkcs_1 tests require sha1/yarrow"); return 1; } @@ -29,30 +29,6 @@ int pkcs_1_test(void) /* random modulus len (v1.5 must be multiple of 8 though arbitrary sizes seem to work) */ modlen = 800 + 8 * (abs(rand()) % 28); - /* PKCS v1.5 testing (encryption) */ - l1 = sizeof(buf[1]); - DO(pkcs_1_v15_es_encode(buf[0], l3, modlen, &yarrow_prng, prng_idx, buf[1], &l1)); - DO(pkcs_1_v15_es_decode(buf[1], l1, modlen, buf[2], l3, &res1)); - if (res1 != 1 || memcmp(buf[0], buf[2], l3)) { - printf("pkcs v1.5 encrypt failed %d, %lu, %lu ", res1, l1, l3); - return 1; - } - - /* PKCS v1.5 testing (signatures) */ - l1 = sizeof(buf[1]); - DO(pkcs_1_v15_sa_encode(buf[0], l3, hash_idx, modlen, buf[1], &l1)); - DO(pkcs_1_v15_sa_decode(buf[0], l3, buf[1], l1, hash_idx, modlen, &res1)); - buf[0][i1 = abs(rand()) % l3] ^= 1; - DO(pkcs_1_v15_sa_decode(buf[0], l3, buf[1], l1, hash_idx, modlen, &res2)); - buf[0][i1] ^= 1; - buf[1][i2 = abs(rand()) % l1] ^= 1; - DO(pkcs_1_v15_sa_decode(buf[0], l3, buf[1], l1, hash_idx, modlen, &res3)); - - if (!(res1 == 1 && res2 == 0 && res3 == 0)) { - printf("pkcs v1.5 sign failed %d %d %d ", res1, res2, res3); - return 1; - } - /* pick a random lparam len [0..16] */ lparamlen = abs(rand()) % 17; @@ -71,16 +47,16 @@ int pkcs_1_test(void) DO(pkcs_1_oaep_decode(buf[1], l1, lparam, lparamlen, modlen, hash_idx, buf[2], &l2, &res1)); if (res1 != 1 || l2 != l3 || memcmp(buf[2], buf[0], l3) != 0) { - printf("Outsize == %lu, should have been %lu, res1 = %d, lparamlen = %lu, msg contents follow.\n", l2, l3, res1, lparamlen); - printf("ORIGINAL:\n"); + fprintf(stderr, "Outsize == %lu, should have been %lu, res1 = %d, lparamlen = %lu, msg contents follow.\n", l2, l3, res1, lparamlen); + fprintf(stderr, "ORIGINAL:\n"); for (x = 0; x < l3; x++) { - printf("%02x ", buf[0][x]); + fprintf(stderr, "%02x ", buf[0][x]); } - printf("\nRESULT:\n"); + fprintf(stderr, "\nRESULT:\n"); for (x = 0; x < l2; x++) { - printf("%02x ", buf[2][x]); + fprintf(stderr, "%02x ", buf[2][x]); } - printf("\n\n"); + fprintf(stderr, "\n\n"); return 1; } @@ -97,7 +73,7 @@ int pkcs_1_test(void) DO(pkcs_1_pss_decode(buf[0], l3, buf[1], l1, saltlen, hash_idx, modlen, &res3)); if (!(res1 == 1 && res2 == 0 && res3 == 0)) { - printf("PSS failed: %d, %d, %d, %lu, %lu\n", res1, res2, res3, l3, saltlen); + fprintf(stderr, "PSS failed: %d, %d, %d, %lu, %lu\n", res1, res2, res3, l3, saltlen); return 1; } } @@ -108,9 +84,13 @@ int pkcs_1_test(void) int pkcs_1_test(void) { - printf("NOP"); + fprintf(stderr, "NOP"); return 0; } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/testprof/rsa_test.c b/testprof/rsa_test.c index f114e499..f2893ee5 100644 --- a/testprof/rsa_test.c +++ b/testprof/rsa_test.c @@ -4,18 +4,125 @@ #define RSA_MSGSIZE 78 +/* These are test keys [see file test.key] that I use to test my import/export against */ +static const unsigned char openssl_private_rsa[] = { + 0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xcf, 0x9a, 0xde, 0x64, 0x8a, + 0xda, 0xc8, 0x33, 0x20, 0xa9, 0xd7, 0x83, 0x31, 0x19, 0x54, 0xb2, 0x9a, 0x85, 0xa7, 0xa1, 0xb7, + 0x75, 0x33, 0xb6, 0xa9, 0xac, 0x84, 0x24, 0xb3, 0xde, 0xdb, 0x7d, 0x85, 0x2d, 0x96, 0x65, 0xe5, + 0x3f, 0x72, 0x95, 0x24, 0x9f, 0x28, 0x68, 0xca, 0x4f, 0xdb, 0x44, 0x1c, 0x3e, 0x60, 0x12, 0x8a, + 0xdd, 0x26, 0xa5, 0xeb, 0xff, 0x0b, 0x5e, 0xd4, 0x88, 0x38, 0x49, 0x2a, 0x6e, 0x5b, 0xbf, 0x12, + 0x37, 0x47, 0xbd, 0x05, 0x6b, 0xbc, 0xdb, 0xf3, 0xee, 0xe4, 0x11, 0x8e, 0x41, 0x68, 0x7c, 0x61, + 0x13, 0xd7, 0x42, 0xc8, 0x80, 0xbe, 0x36, 0x8f, 0xdc, 0x08, 0x8b, 0x4f, 0xac, 0xa4, 0xe2, 0x76, + 0x0c, 0xc9, 0x63, 0x6c, 0x49, 0x58, 0x93, 0xed, 0xcc, 0xaa, 0xdc, 0x25, 0x3b, 0x0a, 0x60, 0x3f, + 0x8b, 0x54, 0x3a, 0xc3, 0x4d, 0x31, 0xe7, 0x94, 0xa4, 0x44, 0xfd, 0x02, 0x03, 0x01, 0x00, 0x01, + 0x02, 0x81, 0x81, 0x00, 0xc8, 0x62, 0xb9, 0xea, 0xde, 0x44, 0x53, 0x1d, 0x56, 0x97, 0xd9, 0x97, + 0x9e, 0x1a, 0xcf, 0x30, 0x1e, 0x0a, 0x88, 0x45, 0x86, 0x29, 0x30, 0xa3, 0x4d, 0x9f, 0x61, 0x65, + 0x73, 0xe0, 0xd6, 0x87, 0x8f, 0xb6, 0xf3, 0x06, 0xa3, 0x82, 0xdc, 0x7c, 0xac, 0xfe, 0x9b, 0x28, + 0x9a, 0xae, 0xfd, 0xfb, 0xfe, 0x2f, 0x0e, 0xd8, 0x97, 0x04, 0xe3, 0xbb, 0x1f, 0xd1, 0xec, 0x0d, + 0xba, 0xa3, 0x49, 0x7f, 0x47, 0xac, 0x8a, 0x44, 0x04, 0x7e, 0x86, 0xb7, 0x39, 0x42, 0x3f, 0xad, + 0x1e, 0xb7, 0x0e, 0xa5, 0x51, 0xf4, 0x40, 0x63, 0x1e, 0xfd, 0xbd, 0xea, 0x9f, 0x41, 0x9f, 0xa8, + 0x90, 0x1d, 0x6f, 0x0a, 0x5a, 0x95, 0x13, 0x11, 0x0d, 0x80, 0xaf, 0x5f, 0x64, 0x98, 0x8a, 0x2c, + 0x78, 0x68, 0x65, 0xb0, 0x2b, 0x8b, 0xa2, 0x53, 0x87, 0xca, 0xf1, 0x64, 0x04, 0xab, 0xf2, 0x7b, + 0xdb, 0x83, 0xc8, 0x81, 0x02, 0x41, 0x00, 0xf7, 0xbe, 0x5e, 0x23, 0xc3, 0x32, 0x3f, 0xbf, 0x8b, + 0x8e, 0x3a, 0xee, 0xfc, 0xfc, 0xcb, 0xe5, 0xf7, 0xf1, 0x0b, 0xbc, 0x42, 0x82, 0xae, 0xd5, 0x7a, + 0x3e, 0xca, 0xf7, 0xd5, 0x69, 0x3f, 0x64, 0x25, 0xa2, 0x1f, 0xb7, 0x75, 0x75, 0x05, 0x92, 0x42, + 0xeb, 0xb8, 0xf1, 0xf3, 0x0a, 0x05, 0xe3, 0x94, 0xd1, 0x55, 0x78, 0x35, 0xa0, 0x36, 0xa0, 0x9b, + 0x7c, 0x92, 0x84, 0x6c, 0xdd, 0xdc, 0x4d, 0x02, 0x41, 0x00, 0xd6, 0x86, 0x0e, 0x85, 0x42, 0x0b, + 0x04, 0x08, 0x84, 0x21, 0x60, 0xf0, 0x0e, 0x0d, 0x88, 0xfd, 0x1e, 0x36, 0x10, 0x65, 0x4f, 0x1e, + 0x53, 0xb4, 0x08, 0x72, 0x80, 0x5c, 0x3f, 0x59, 0x66, 0x17, 0xe6, 0x98, 0xf2, 0xe9, 0x6c, 0x7a, + 0x06, 0x4c, 0xac, 0x76, 0x3d, 0xed, 0x8c, 0xa1, 0xce, 0xad, 0x1b, 0xbd, 0xb4, 0x7d, 0x28, 0xbc, + 0xe3, 0x0e, 0x38, 0x8d, 0x99, 0xd8, 0x05, 0xb5, 0xa3, 0x71, 0x02, 0x40, 0x6d, 0xeb, 0xc3, 0x2d, + 0x2e, 0xf0, 0x5e, 0xa4, 0x88, 0x31, 0x05, 0x29, 0x00, 0x8a, 0xd1, 0x95, 0x29, 0x9b, 0x83, 0xcf, + 0x75, 0xdb, 0x31, 0xe3, 0x7a, 0x27, 0xde, 0x3a, 0x74, 0x30, 0x0c, 0x76, 0x4c, 0xd4, 0x50, 0x2a, + 0x40, 0x2d, 0x39, 0xd9, 0x99, 0x63, 0xa9, 0x5d, 0x80, 0xae, 0x53, 0xca, 0x94, 0x3f, 0x05, 0x23, + 0x1e, 0xf8, 0x05, 0x04, 0xe1, 0xb8, 0x35, 0xf2, 0x17, 0xb3, 0xa0, 0x89, 0x02, 0x41, 0x00, 0xab, + 0x90, 0x88, 0xfa, 0x60, 0x08, 0x29, 0x50, 0x9a, 0x43, 0x8b, 0xa0, 0x50, 0xcc, 0xd8, 0x5a, 0xfe, + 0x97, 0x64, 0x63, 0x71, 0x74, 0x22, 0xa3, 0x20, 0x02, 0x5a, 0xcf, 0xeb, 0xc6, 0x16, 0x95, 0x54, + 0xd1, 0xcb, 0xab, 0x8d, 0x1a, 0xc6, 0x00, 0xfa, 0x08, 0x92, 0x9c, 0x71, 0xd5, 0x52, 0x52, 0x35, + 0x96, 0x71, 0x4b, 0x8b, 0x92, 0x0c, 0xd0, 0xe9, 0xbf, 0xad, 0x63, 0x0b, 0xa5, 0xe9, 0xb1, 0x02, + 0x41, 0x00, 0xdc, 0xcc, 0x27, 0xc8, 0xe4, 0xdc, 0x62, 0x48, 0xd5, 0x9b, 0xaf, 0xf5, 0xab, 0x60, + 0xf6, 0x21, 0xfd, 0x53, 0xe2, 0xb7, 0x5d, 0x09, 0xc9, 0x1a, 0xa1, 0x04, 0xa9, 0xfc, 0x61, 0x2c, + 0x5d, 0x04, 0x58, 0x3a, 0x5a, 0x39, 0xf1, 0x4a, 0x21, 0x56, 0x67, 0xfd, 0xcc, 0x20, 0xa3, 0x8f, + 0x78, 0x18, 0x5a, 0x79, 0x3d, 0x2e, 0x8e, 0x7e, 0x86, 0x0a, 0xe6, 0xa8, 0x33, 0xc1, 0x04, 0x17, + 0x4a, 0x9f, }; + + +/*** NOTE: OpenSSL seems to have more to their public key format. I've stripped the extra headers... */ +static const unsigned char openssl_public_rsa[] = { + 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xcf, 0x9a, 0xde, + 0x64, 0x8a, 0xda, 0xc8, 0x33, 0x20, 0xa9, 0xd7, 0x83, 0x31, 0x19, 0x54, 0xb2, 0x9a, 0x85, 0xa7, + 0xa1, 0xb7, 0x75, 0x33, 0xb6, 0xa9, 0xac, 0x84, 0x24, 0xb3, 0xde, 0xdb, 0x7d, 0x85, 0x2d, 0x96, + 0x65, 0xe5, 0x3f, 0x72, 0x95, 0x24, 0x9f, 0x28, 0x68, 0xca, 0x4f, 0xdb, 0x44, 0x1c, 0x3e, 0x60, + 0x12, 0x8a, 0xdd, 0x26, 0xa5, 0xeb, 0xff, 0x0b, 0x5e, 0xd4, 0x88, 0x38, 0x49, 0x2a, 0x6e, 0x5b, + 0xbf, 0x12, 0x37, 0x47, 0xbd, 0x05, 0x6b, 0xbc, 0xdb, 0xf3, 0xee, 0xe4, 0x11, 0x8e, 0x41, 0x68, + 0x7c, 0x61, 0x13, 0xd7, 0x42, 0xc8, 0x80, 0xbe, 0x36, 0x8f, 0xdc, 0x08, 0x8b, 0x4f, 0xac, 0xa4, + 0xe2, 0x76, 0x0c, 0xc9, 0x63, 0x6c, 0x49, 0x58, 0x93, 0xed, 0xcc, 0xaa, 0xdc, 0x25, 0x3b, 0x0a, + 0x60, 0x3f, 0x8b, 0x54, 0x3a, 0xc3, 0x4d, 0x31, 0xe7, 0x94, 0xa4, 0x44, 0xfd, 0x02, 0x03, 0x01, + 0x00, 0x01, }; + +static int rsa_compat_test(void) +{ + rsa_key key; + unsigned char buf[1024]; + unsigned long len; + + /* try reading the key */ + DO(rsa_import(openssl_private_rsa, sizeof(openssl_private_rsa), &key)); + + /* now try to export private/public and compare */ + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PRIVATE, &key)); + if (len != sizeof(openssl_private_rsa) || memcmp(buf, openssl_private_rsa, len)) { + fprintf(stderr, "RSA private export failed to match OpenSSL output, %lu, %lu\n", len, sizeof(openssl_private_rsa)); + + +{ +int x; +printf("\n\n"); +for (x = 0; x < len; ) { if (buf[x] == openssl_private_rsa[x]) printf("-- "); else printf("%02x ", buf[x]^openssl_private_rsa[x]); if (!(++x & 15)) printf("\n"); } +} +printf("\n\n"); + + return 1; + } + + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PUBLIC, &key)); + if (len != sizeof(openssl_public_rsa) || memcmp(buf, openssl_public_rsa, len)) { + fprintf(stderr, "RSA(private) public export failed to match OpenSSL output\n"); + return 1; + } + rsa_free(&key); + + /* try reading the public key */ + DO(rsa_import(openssl_public_rsa, sizeof(openssl_public_rsa), &key)); + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PUBLIC, &key)); + if (len != sizeof(openssl_public_rsa) || memcmp(buf, openssl_public_rsa, len)) { + fprintf(stderr, "RSA(public) public export failed to match OpenSSL output\n"); + return 1; + } + rsa_free(&key); + + return 0; +} + int rsa_test(void) { unsigned char in[1024], out[1024], tmp[1024]; rsa_key key, privKey, pubKey; - int hash_idx, prng_idx, stat, stat2, cnt; - unsigned long rsa_msgsize, len, len2; + int hash_idx, prng_idx, stat, stat2; + unsigned long rsa_msgsize, len, len2, cnt; static unsigned char lparam[] = { 0x01, 0x02, 0x03, 0x04 }; + + if (rsa_compat_test() != 0) { + return 1; + } hash_idx = find_hash("sha1"); prng_idx = find_prng("yarrow"); if (hash_idx == -1 || prng_idx == -1) { - printf("rsa_test requires SHA1 and yarrow"); + fprintf(stderr, "rsa_test requires SHA1 and yarrow"); return 1; } @@ -23,32 +130,32 @@ int rsa_test(void) for (cnt = 0; cnt < 10; cnt++) { DO(rsa_make_key(&yarrow_prng, prng_idx, 1024/8, 65537, &key)); if (mp_count_bits(&key.N) != 1024) { - printf("rsa_1024 key modulus has %d bits\n", mp_count_bits(&key.N)); + fprintf(stderr, "rsa_1024 key modulus has %d bits\n", mp_count_bits(&key.N)); len = mp_unsigned_bin_size(&key.N); mp_to_unsigned_bin(&key.N, tmp); -printf("N == \n"); + fprintf(stderr, "N == \n"); for (cnt = 0; cnt < len; ) { - printf("%02x ", tmp[cnt]); - if (!(++cnt & 15)) printf("\n"); + fprintf(stderr, "%02x ", tmp[cnt]); + if (!(++cnt & 15)) fprintf(stderr, "\n"); } len = mp_unsigned_bin_size(&key.p); mp_to_unsigned_bin(&key.p, tmp); -printf("p == \n"); + fprintf(stderr, "p == \n"); for (cnt = 0; cnt < len; ) { - printf("%02x ", tmp[cnt]); - if (!(++cnt & 15)) printf("\n"); + fprintf(stderr, "%02x ", tmp[cnt]); + if (!(++cnt & 15)) fprintf(stderr, "\n"); } len = mp_unsigned_bin_size(&key.q); mp_to_unsigned_bin(&key.q, tmp); -printf("\nq == \n"); + fprintf(stderr, "\nq == \n"); for (cnt = 0; cnt < len; ) { - printf("%02x ", tmp[cnt]); - if (!(++cnt & 15)) printf("\n"); + fprintf(stderr, "%02x ", tmp[cnt]); + if (!(++cnt & 15)) fprintf(stderr, "\n"); } -printf("\n"); + fprintf(stderr, "\n"); return 1; @@ -57,38 +164,7 @@ printf("\n"); rsa_free(&key); } } - - /* test PKCS #1 v1.5 */ - for (cnt = 0; cnt < 4; cnt++) { - for (rsa_msgsize = 1; rsa_msgsize <= 117; rsa_msgsize++) { - /* make a random key/msg */ - yarrow_read(in, rsa_msgsize, &yarrow_prng); - - len = sizeof(out); - len2 = rsa_msgsize; - - /* encrypt */ - DO(rsa_v15_encrypt_key(in, rsa_msgsize, out, &len, &yarrow_prng, prng_idx, &key)); - DO(rsa_v15_decrypt_key(out, len, tmp, rsa_msgsize, &stat, &key)); - if (stat != 1 || memcmp(tmp, in, rsa_msgsize)) { - printf("PKCS #1 v1.5 encrypt/decrypt failure (rsa_msgsize: %lu, stat: %d)\n", rsa_msgsize, stat); - return 1; - } - } - } - - /* signature */ - len = sizeof(out); - DO(rsa_v15_sign_hash(in, 20, out, &len, hash_idx, &key)); - in[1] ^= 1; - DO(rsa_v15_verify_hash(out, len, in, 20, hash_idx, &stat, &key)); - in[1] ^= 1; - DO(rsa_v15_verify_hash(out, len, in, 20, hash_idx, &stat2, &key)); - if (!(stat == 0 && stat2 == 1)) { - printf("PKCS #1 v1.5 sign/verify failure (stat %d, stat2 %d)\n", stat, stat2); - return 1; - } - + /* encrypt the key (without lparam) */ for (cnt = 0; cnt < 4; cnt++) { for (rsa_msgsize = 1; rsa_msgsize <= 86; rsa_msgsize++) { @@ -105,35 +181,35 @@ printf("\n"); /* change a byte back */ out[8] ^= 1; if (len2 != rsa_msgsize) { - printf("\nrsa_decrypt_key mismatch len %lu (first decrypt)", len2); + fprintf(stderr, "\nrsa_decrypt_key mismatch len %lu (first decrypt)", len2); return 1; } len2 = rsa_msgsize; DO(rsa_decrypt_key(out, len, tmp, &len2, NULL, 0, hash_idx, &stat, &key)); if (!(stat == 1 && stat2 == 0)) { - printf("rsa_decrypt_key failed"); + fprintf(stderr, "rsa_decrypt_key failed"); return 1; } if (len2 != rsa_msgsize || memcmp(tmp, in, rsa_msgsize)) { unsigned long x; - printf("\nrsa_decrypt_key mismatch, len %lu (second decrypt)\n", len2); - printf("Original contents: \n"); + fprintf(stderr, "\nrsa_decrypt_key mismatch, len %lu (second decrypt)\n", len2); + fprintf(stderr, "Original contents: \n"); for (x = 0; x < rsa_msgsize; ) { - printf("%02x ", in[x]); + fprintf(stderr, "%02x ", in[x]); if (!(++x % 16)) { - printf("\n"); + fprintf(stderr, "\n"); } } - printf("\n"); - printf("Output contents: \n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Output contents: \n"); for (x = 0; x < rsa_msgsize; ) { - printf("%02x ", out[x]); + fprintf(stderr, "%02x ", out[x]); if (!(++x % 16)) { - printf("\n"); + fprintf(stderr, "\n"); } } - printf("\n"); + fprintf(stderr, "\n"); return 1; } } @@ -148,7 +224,7 @@ printf("\n"); out[8] ^= 1; DO(rsa_decrypt_key(out, len, tmp, &len2, lparam, sizeof(lparam), hash_idx, &stat2, &key)); if (len2 != rsa_msgsize) { - printf("\nrsa_decrypt_key mismatch len %lu (first decrypt)", len2); + fprintf(stderr, "\nrsa_decrypt_key mismatch len %lu (first decrypt)", len2); return 1; } /* change a byte back */ @@ -157,11 +233,11 @@ printf("\n"); len2 = rsa_msgsize; DO(rsa_decrypt_key(out, len, tmp, &len2, lparam, sizeof(lparam), hash_idx, &stat, &key)); if (!(stat == 1 && stat2 == 0)) { - printf("rsa_decrypt_key failed"); + fprintf(stderr, "rsa_decrypt_key failed"); return 1; } if (len2 != rsa_msgsize || memcmp(tmp, in, rsa_msgsize)) { - printf("rsa_decrypt_key mismatch len %lu", len2); + fprintf(stderr, "rsa_decrypt_key mismatch len %lu", len2); return 1; } } @@ -185,7 +261,7 @@ printf("\n"); DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat2, &key)); if (!(stat == 1 && stat2 == 0)) { - printf("rsa_verify_hash (unsalted, origKey) failed, %d, %d", stat, stat2); + fprintf(stderr, "rsa_verify_hash (unsalted, origKey) failed, %d, %d", stat, stat2); rsa_free(&key); rsa_free(&pubKey); rsa_free(&privKey); @@ -201,7 +277,7 @@ printf("\n"); DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat2, &privKey)); if (!(stat == 1 && stat2 == 0)) { - printf("rsa_verify_hash (unsalted, privKey) failed, %d, %d", stat, stat2); + fprintf(stderr, "rsa_verify_hash (unsalted, privKey) failed, %d, %d", stat, stat2); rsa_free(&key); rsa_free(&pubKey); rsa_free(&privKey); @@ -217,7 +293,7 @@ printf("\n"); DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat2, &pubKey)); if (!(stat == 1 && stat2 == 0)) { - printf("rsa_verify_hash (unsalted, pubkey) failed, %d, %d", stat, stat2); + fprintf(stderr, "rsa_verify_hash (unsalted, pubkey) failed, %d, %d", stat, stat2); rsa_free(&key); rsa_free(&pubKey); rsa_free(&privKey); @@ -233,7 +309,7 @@ printf("\n"); DO(rsa_verify_hash(out, len, in, 20, hash_idx, 8, &stat2, &pubKey)); if (!(stat == 1 && stat2 == 0)) { - printf("rsa_verify_hash (salted) failed, %d, %d", stat, stat2); + fprintf(stderr, "rsa_verify_hash (salted) failed, %d, %d", stat, stat2); rsa_free(&key); rsa_free(&pubKey); rsa_free(&privKey); @@ -251,8 +327,12 @@ printf("\n"); int rsa_test(void) { - printf("NOP"); + fprintf(stderr, "NOP"); return 0; } #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/testprof/store_test.c b/testprof/store_test.c index 41b2f927..71666ba1 100644 --- a/testprof/store_test.c +++ b/testprof/store_test.c @@ -3,13 +3,17 @@ /* Test store/load macros with offsets */ int store_test(void) { - unsigned char buf[24]; + unsigned char buf[256]; int y; ulong32 L, L1; ulong64 LL, LL1; +#ifdef LTC_FAST + int x, z; +#endif - L = 0x12345678UL; for (y = 0; y < 4; y++) { + L = 0x12345678UL; + L1 = 0; STORE32L(L, buf + y); LOAD32L(L1, buf + y); if (L1 != L) { @@ -24,8 +28,9 @@ int store_test(void) } } - LL = CONST64 (0x01020304050607); for (y = 0; y < 8; y++) { + LL = CONST64 (0x01020304050607); + LL1 = 0; STORE64L(LL, buf + y); LOAD64L(LL1, buf + y); if (LL1 != LL) { @@ -40,5 +45,34 @@ int store_test(void) } } +/* test LTC_FAST */ +#ifdef LTC_FAST + y = 16; + + for (z = 0; z < y; z++) { + /* fill y bytes with random */ + yarrow_read(buf+z, y, &yarrow_prng); + yarrow_read(buf+z+y, y, &yarrow_prng); + + /* now XOR it byte for byte */ + for (x = 0; x < y; x++) { + buf[2*y+z+x] = buf[z+x] ^ buf[z+y+x]; + } + + /* now XOR it word for word */ + for (x = 0; x < y; x += sizeof(LTC_FAST_TYPE)) { + *((LTC_FAST_TYPE*)(&buf[3*y+z+x])) = *((LTC_FAST_TYPE*)(&buf[z+x])) ^ *((LTC_FAST_TYPE*)(&buf[z+y+x])); + } + + if (memcmp(&buf[2*y+z], &buf[3*y+z], y)) { + fprintf(stderr, "\nLTC_FAST failed at offset %d\n", z); + return 1; + } + } +#endif return 0; } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/testprof/test.c b/testprof/test.c index 9f6df715..721a992f 100644 --- a/testprof/test.c +++ b/testprof/test.c @@ -7,3 +7,7 @@ void run_cmd(int res, int line, char *file, char *cmd) exit(EXIT_FAILURE); } } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/testprof/test.key b/testprof/test.key new file mode 100644 index 00000000..e4996c35 --- /dev/null +++ b/testprof/test.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDPmt5kitrIMyCp14MxGVSymoWnobd1M7aprIQks97bfYUtlmXl +P3KVJJ8oaMpP20QcPmASit0mpev/C17UiDhJKm5bvxI3R70Fa7zb8+7kEY5BaHxh +E9dCyIC+No/cCItPrKTidgzJY2xJWJPtzKrcJTsKYD+LVDrDTTHnlKRE/QIDAQAB +AoGBAMhiuereRFMdVpfZl54azzAeCohFhikwo02fYWVz4NaHj7bzBqOC3Hys/pso +mq79+/4vDtiXBOO7H9HsDbqjSX9HrIpEBH6GtzlCP60etw6lUfRAYx79veqfQZ+o +kB1vClqVExENgK9fZJiKLHhoZbAri6JTh8rxZASr8nvbg8iBAkEA975eI8MyP7+L +jjru/PzL5ffxC7xCgq7Vej7K99VpP2Qloh+3dXUFkkLruPHzCgXjlNFVeDWgNqCb +fJKEbN3cTQJBANaGDoVCCwQIhCFg8A4NiP0eNhBlTx5TtAhygFw/WWYX5pjy6Wx6 +Bkysdj3tjKHOrRu9tH0ovOMOOI2Z2AW1o3ECQG3rwy0u8F6kiDEFKQCK0ZUpm4PP +ddsx43on3jp0MAx2TNRQKkAtOdmZY6ldgK5TypQ/BSMe+AUE4bg18hezoIkCQQCr +kIj6YAgpUJpDi6BQzNha/pdkY3F0IqMgAlrP68YWlVTRy6uNGsYA+giSnHHVUlI1 +lnFLi5IM0Om/rWMLpemxAkEA3MwnyOTcYkjVm6/1q2D2If1T4rddCckaoQSp/GEs +XQRYOlo58UohVmf9zCCjj3gYWnk9Lo5+hgrmqDPBBBdKnw== +-----END RSA PRIVATE KEY----- diff --git a/testprof/tomcrypt_test.h b/testprof/tomcrypt_test.h index fc284304..6503b7cd 100644 --- a/testprof/tomcrypt_test.h +++ b/testprof/tomcrypt_test.h @@ -71,3 +71,7 @@ void time_encmacs(void); #endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/testprof/x86_prof.c b/testprof/x86_prof.c index bcc25f47..7fbe8e16 100644 --- a/testprof/x86_prof.c +++ b/testprof/x86_prof.c @@ -21,10 +21,10 @@ void tally_results(int type) // qsort the results qsort(results, no_results, sizeof(struct list), &sorter); - printf("\n"); + fprintf(stderr, "\n"); if (type == 0) { for (x = 0; x < no_results; x++) { - printf("%-20s: Schedule at %6lu\n", cipher_descriptor[results[x].id].name, (unsigned long)results[x].spd1); + fprintf(stderr, "%-20s: Schedule at %6lu\n", cipher_descriptor[results[x].id].name, (unsigned long)results[x].spd1); } } else if (type == 1) { for (x = 0; x < no_results; x++) { @@ -42,7 +42,7 @@ void tally_results(int type) /* RDTSC from Scott Duplichan */ ulong64 rdtsc (void) { - #if defined __GNUC__ + #if defined __GNUC__ && !defined(LTC_NO_ASM) #ifdef INTEL_CC ulong64 a; asm ( " rdtsc ":"=A"(a)); @@ -62,11 +62,11 @@ ulong64 rdtsc (void) #endif // Microsoft and Intel Windows compilers - #elif defined _M_IX86 + #elif defined _M_IX86 && !defined(LTC_NO_ASM) __asm rdtsc - #elif defined _M_AMD64 + #elif defined _M_AMD64 && !defined(LTC_NO_ASM) return __rdtsc (); - #elif defined _M_IA64 + #elif defined _M_IA64 && !defined(LTC_NO_ASM) #if defined __INTEL_COMPILER #include #endif @@ -104,7 +104,7 @@ void init_timer(void) c2 = (t2 > c2) ? t2 : c2; } skew = c2 - c1; - printf("Clock Skew: %lu\n", (unsigned long)skew); + fprintf(stderr, "Clock Skew: %lu\n", (unsigned long)skew); } void reg_algs(void) @@ -199,7 +199,7 @@ void reg_algs(void) #ifdef CHC_HASH register_hash(&chc_desc); if ((err = chc_register(register_cipher(&aes_desc))) != CRYPT_OK) { - printf("chc_register error: %s\n", error_to_string(err)); + fprintf(stderr, "chc_register error: %s\n", error_to_string(err)); exit(EXIT_FAILURE); } #endif @@ -231,7 +231,7 @@ int time_keysched(void) int (*func) (const unsigned char *, int , int , symmetric_key *); unsigned char key[MAXBLOCKSIZE]; - printf ("\n\nKey Schedule Time Trials for the Symmetric Ciphers:\n(Times are cycles per key)\n"); + fprintf(stderr, "\n\nKey Schedule Time Trials for the Symmetric Ciphers:\n(Times are cycles per key)\n"); no_results = 0; for (x = 0; cipher_descriptor[x].name != NULL; x++) { #define DO1(k) func(k, kl, 0, &skey); @@ -249,7 +249,7 @@ int time_keysched(void) t1 = c1 - skew; results[no_results].spd1 = results[no_results].avg = t1; results[no_results++].id = x; - printf("."); fflush(stdout); + fprintf(stderr, "."); fflush(stdout); #undef DO1 } @@ -266,7 +266,7 @@ int time_cipher(void) unsigned char key[MAXBLOCKSIZE], pt[4096]; int err; - printf ("\n\nECB Time Trials for the Symmetric Ciphers:\n"); + fprintf(stderr, "\n\nECB Time Trials for the Symmetric Ciphers:\n"); no_results = 0; for (x = 0; cipher_descriptor[x].name != NULL; x++) { ecb_start(x, key, cipher_descriptor[x].min_key_length, 0, &ecb); @@ -318,7 +318,7 @@ int time_cipher(void) results[no_results].spd2 = a2/(sizeof(pt)/cipher_descriptor[x].block_length); results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2; ++no_results; - printf("."); fflush(stdout); + fprintf(stderr, "."); fflush(stdout); #undef DO2 #undef DO1 @@ -337,7 +337,7 @@ int time_cipher2(void) unsigned char key[MAXBLOCKSIZE], pt[4096]; int err; - printf ("\n\nCBC Time Trials for the Symmetric Ciphers:\n"); + fprintf(stderr, "\n\nCBC Time Trials for the Symmetric Ciphers:\n"); no_results = 0; for (x = 0; cipher_descriptor[x].name != NULL; x++) { cbc_start(x, pt, key, cipher_descriptor[x].min_key_length, 0, &cbc); @@ -389,7 +389,7 @@ int time_cipher2(void) results[no_results].spd2 = a2/(sizeof(pt)/cipher_descriptor[x].block_length); results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2; ++no_results; - printf("."); fflush(stdout); + fprintf(stderr, "."); fflush(stdout); #undef DO2 #undef DO1 @@ -399,7 +399,7 @@ int time_cipher2(void) return 0; } #else -int time_cipher2(void) { printf("NO CBC\n"); return 0; } +int time_cipher2(void) { fprintf(stderr, "NO CBC\n"); return 0; } #endif #ifdef CTR @@ -411,10 +411,10 @@ int time_cipher3(void) unsigned char key[MAXBLOCKSIZE], pt[4096]; int err; - printf ("\n\nCTR Time Trials for the Symmetric Ciphers:\n"); + fprintf(stderr, "\n\nCTR Time Trials for the Symmetric Ciphers:\n"); no_results = 0; for (x = 0; cipher_descriptor[x].name != NULL; x++) { - ctr_start(x, pt, key, cipher_descriptor[x].min_key_length, 0, &ctr); + ctr_start(x, pt, key, cipher_descriptor[x].min_key_length, 0, CTR_COUNTER_LITTLE_ENDIAN, &ctr); /* sanity check on cipher */ if ((err = cipher_descriptor[x].test()) != CRYPT_OK) { @@ -463,7 +463,7 @@ int time_cipher3(void) results[no_results].spd2 = a2/(sizeof(pt)/cipher_descriptor[x].block_length); results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2; ++no_results; - printf("."); fflush(stdout); + fprintf(stderr, "."); fflush(stdout); #undef DO2 #undef DO1 @@ -473,7 +473,7 @@ int time_cipher3(void) return 0; } #else -int time_cipher3(void) { printf("NO CTR\n"); return 0; } +int time_cipher3(void) { fprintf(stderr, "NO CTR\n"); return 0; } #endif int time_hash(void) @@ -485,7 +485,7 @@ int time_hash(void) unsigned char pt[MAXBLOCKSIZE]; - printf ("\n\nHASH Time Trials for:\n"); + fprintf(stderr, "\n\nHASH Time Trials for:\n"); no_results = 0; for (x = 0; hash_descriptor[x].name != NULL; x++) { @@ -518,7 +518,7 @@ int time_hash(void) results[no_results].id = x; results[no_results].spd1 = results[no_results].avg = t1; ++no_results; - printf("."); fflush(stdout); + fprintf(stderr, "."); fflush(stdout); #undef DO2 #undef DO1 } @@ -534,7 +534,7 @@ void time_mult(void) unsigned long x, y; mp_int a, b, c; - printf("Timing Multiplying:\n"); + fprintf(stderr, "Timing Multiplying:\n"); mp_init_multi(&a,&b,&c,NULL); for (x = 128/DIGIT_BIT; x <= 1536/DIGIT_BIT; x += 128/DIGIT_BIT) { mp_rand(&a, x); @@ -551,7 +551,7 @@ void time_mult(void) t1 = (t_read() - t1)>>1; if (t1 < t2) t2 = t1; } - printf("%4lu bits: %9llu cycles\n", x*DIGIT_BIT, t2); + fprintf(stderr, "%4lu bits: %9llu cycles\n", x*DIGIT_BIT, t2); } mp_clear_multi(&a,&b,&c,NULL); @@ -565,7 +565,7 @@ void time_sqr(void) unsigned long x, y; mp_int a, b; - printf("Timing Squaring:\n"); + fprintf(stderr, "Timing Squaring:\n"); mp_init_multi(&a,&b,NULL); for (x = 128/DIGIT_BIT; x <= 1536/DIGIT_BIT; x += 128/DIGIT_BIT) { mp_rand(&a, x); @@ -581,7 +581,7 @@ void time_sqr(void) t1 = (t_read() - t1)>>1; if (t1 < t2) t2 = t1; } - printf("%4lu bits: %9llu cycles\n", x*DIGIT_BIT, t2); + fprintf(stderr, "%4lu bits: %9llu cycles\n", x*DIGIT_BIT, t2); } mp_clear_multi(&a,&b,NULL); @@ -589,8 +589,8 @@ void time_sqr(void) #undef DO2 } #else -void time_mult(void) { printf("NO MULT\n"); } -void time_sqr(void) { printf("NO SQR\n"); } +void time_mult(void) { fprintf(stderr, "NO MULT\n"); } +void time_sqr(void) { fprintf(stderr, "NO SQR\n"); } #endif void time_prng(void) @@ -601,7 +601,7 @@ void time_prng(void) unsigned long x, y; int err; - printf("Timing PRNGs (cycles/byte output, cycles add_entropy (32 bytes) :\n"); + fprintf(stderr, "Timing PRNGs (cycles/byte output, cycles add_entropy (32 bytes) :\n"); for (x = 0; prng_descriptor[x].name != NULL; x++) { /* sanity check on prng */ @@ -616,7 +616,7 @@ void time_prng(void) prng_descriptor[x].ready(&tprng); t2 = -1; -#define DO1 if (prng_descriptor[x].read(buf, 4096, &tprng) != 4096) { printf("\n\nERROR READ != 4096\n\n"); exit(EXIT_FAILURE); } +#define DO1 if (prng_descriptor[x].read(buf, 4096, &tprng) != 4096) { fprintf(stderr, "\n\nERROR READ != 4096\n\n"); exit(EXIT_FAILURE); } #define DO2 DO1 DO1 for (y = 0; y < 10000; y++) { t_start(); @@ -625,7 +625,7 @@ void time_prng(void) t1 = (t_read() - t1)>>1; if (t1 < t2) t2 = t1; } - printf("%20s: %5llu ", prng_descriptor[x].name, t2>>12); + fprintf(stderr, "%20s: %5llu ", prng_descriptor[x].name, t2>>12); #undef DO2 #undef DO1 @@ -638,7 +638,7 @@ void time_prng(void) t1 = (t_read() - t1)>>1; if (t1 < t2) t2 = t1; } - printf("%5llu\n", t2); + fprintf(stderr, "%5llu\n", t2); #undef DO2 #undef DO1 @@ -672,7 +672,7 @@ void time_rsa(void) } } t2 >>= 4; - printf("RSA-%lu make_key took %15llu cycles\n", x, t2); + fprintf(stderr, "RSA-%lu make_key took %15llu cycles\n", x, t2); t2 = 0; for (y = 0; y < 16; y++) { @@ -689,7 +689,7 @@ void time_rsa(void) t2 += t1; } t2 >>= 4; - printf("RSA-%lu encrypt_key took %15llu cycles\n", x, t2); + fprintf(stderr, "RSA-%lu encrypt_key took %15llu cycles\n", x, t2); t2 = 0; for (y = 0; y < 16; y++) { @@ -705,14 +705,14 @@ void time_rsa(void) t2 += t1; } t2 >>= 4; - printf("RSA-%lu decrypt_key took %15llu cycles\n", x, t2); + fprintf(stderr, "RSA-%lu decrypt_key took %15llu cycles\n", x, t2); rsa_free(&key); } } #else -void time_rsa(void) { printf("NO RSA\n"); } +void time_rsa(void) { fprintf(stderr, "NO RSA\n"); } #endif #ifdef MECC @@ -743,7 +743,7 @@ void time_ecc(void) } } t2 >>= 4; - printf("ECC-%lu make_key took %15llu cycles\n", x*8, t2); + fprintf(stderr, "ECC-%lu make_key took %15llu cycles\n", x*8, t2); t2 = 0; for (y = 0; y < 16; y++) { @@ -759,12 +759,12 @@ void time_ecc(void) t2 += t1; } t2 >>= 4; - printf("ECC-%lu encrypt_key took %15llu cycles\n", x*8, t2); + fprintf(stderr, "ECC-%lu encrypt_key took %15llu cycles\n", x*8, t2); ecc_free(&key); } } #else -void time_ecc(void) { printf("NO ECC\n"); } +void time_ecc(void) { fprintf(stderr, "NO ECC\n"); } #endif #ifdef MDH @@ -795,7 +795,7 @@ void time_dh(void) } } t2 >>= 4; - printf("DH-%4lu make_key took %15llu cycles\n", x*8, t2); + fprintf(stderr, "DH-%4lu make_key took %15llu cycles\n", x*8, t2); t2 = 0; for (y = 0; y < 16; y++) { @@ -811,12 +811,12 @@ void time_dh(void) t2 += t1; } t2 >>= 4; - printf("DH-%4lu encrypt_key took %15llu cycles\n", x*8, t2); + fprintf(stderr, "DH-%4lu encrypt_key took %15llu cycles\n", x*8, t2); dh_free(&key); } } #else -void time_dh(void) { printf("NO DH\n"); } +void time_dh(void) { fprintf(stderr, "NO DH\n"); } #endif void time_macs_(unsigned long MAC_SIZE) @@ -826,7 +826,7 @@ void time_macs_(unsigned long MAC_SIZE) unsigned long x, z; int err, cipher_idx, hash_idx; - printf("\nMAC Timings (cycles/byte on %dKB blocks):\n", MAC_SIZE); + fprintf(stderr, "\nMAC Timings (cycles/byte on %luKB blocks):\n", MAC_SIZE); buf = XMALLOC(MAC_SIZE*1024); if (buf == NULL) { @@ -853,7 +853,7 @@ void time_macs_(unsigned long MAC_SIZE) t1 = t_read() - t1; if (t1 < t2) t2 = t1; } - printf("OMAC-AES\t\t%9llu\n", t2/(MAC_SIZE*1024)); + fprintf(stderr, "OMAC-AES\t\t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); #endif #ifdef PMAC @@ -869,7 +869,7 @@ void time_macs_(unsigned long MAC_SIZE) t1 = t_read() - t1; if (t1 < t2) t2 = t1; } - printf("PMAC-AES\t\t%9llu\n", t2/(MAC_SIZE*1024)); + fprintf(stderr, "PMAC-AES\t\t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); #endif #ifdef PELICAN @@ -885,7 +885,7 @@ void time_macs_(unsigned long MAC_SIZE) t1 = t_read() - t1; if (t1 < t2) t2 = t1; } - printf("PELICAN \t\t%9llu\n", t2/(MAC_SIZE*1024)); + fprintf(stderr, "PELICAN \t\t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); #endif #ifdef HMAC @@ -901,7 +901,7 @@ void time_macs_(unsigned long MAC_SIZE) t1 = t_read() - t1; if (t1 < t2) t2 = t1; } - printf("HMAC-MD5\t\t%9llu\n", t2/(MAC_SIZE*1024)); + fprintf(stderr, "HMAC-MD5\t\t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); #endif XFREE(buf); @@ -921,7 +921,7 @@ void time_encmacs_(unsigned long MAC_SIZE) unsigned long x, z; int err, cipher_idx; - printf("\nENC+MAC Timings (zero byte AAD, 16 byte IV, cycles/byte on %dKB blocks):\n", MAC_SIZE); + fprintf(stderr, "\nENC+MAC Timings (zero byte AAD, 16 byte IV, cycles/byte on %luKB blocks):\n", MAC_SIZE); buf = XMALLOC(MAC_SIZE*1024); if (buf == NULL) { @@ -948,7 +948,7 @@ void time_encmacs_(unsigned long MAC_SIZE) t1 = t_read() - t1; if (t1 < t2) t2 = t1; } - printf("EAX \t\t%9llu\n", t2/(MAC_SIZE*1024)); + fprintf(stderr, "EAX \t\t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); #endif #ifdef OCB_MODE @@ -964,7 +964,7 @@ void time_encmacs_(unsigned long MAC_SIZE) t1 = t_read() - t1; if (t1 < t2) t2 = t1; } - printf("OCB \t\t%9llu\n", t2/(MAC_SIZE*1024)); + fprintf(stderr, "OCB \t\t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); #endif #ifdef CCM_MODE @@ -980,7 +980,7 @@ void time_encmacs_(unsigned long MAC_SIZE) t1 = t_read() - t1; if (t1 < t2) t2 = t1; } - printf("CCM \t\t%9llu\n", t2/(MAC_SIZE*1024)); + fprintf(stderr, "CCM \t\t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); #endif #ifdef GCM_MODE @@ -996,12 +996,12 @@ void time_encmacs_(unsigned long MAC_SIZE) t1 = t_read() - t1; if (t1 < t2) t2 = t1; } - printf("GCM (no-precomp)\t%9llu\n", t2/(MAC_SIZE*1024)); + fprintf(stderr, "GCM (no-precomp)\t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); { gcm_state gcm; - if ((err = gcm_init(&gcm, cipher_idx, key, 16)) != CRYPT_OK) { printf("gcm_init: %s\n", error_to_string(err)); exit(EXIT_FAILURE); } + if ((err = gcm_init(&gcm, cipher_idx, key, 16)) != CRYPT_OK) { fprintf(stderr, "gcm_init: %s\n", error_to_string(err)); exit(EXIT_FAILURE); } t2 = -1; for (x = 0; x < 10000; x++) { t_start(); @@ -1031,7 +1031,7 @@ void time_encmacs_(unsigned long MAC_SIZE) t1 = t_read() - t1; if (t1 < t2) t2 = t1; } - printf("GCM (precomp)\t%9llu\n", t2/(MAC_SIZE*1024)); + fprintf(stderr, "GCM (precomp)\t%9llu\n", t2/(ulong64)(MAC_SIZE*1024)); } #endif @@ -1044,3 +1044,7 @@ void time_encmacs(void) time_encmacs_(4); time_encmacs_(32); } + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */