diff --git a/authors b/authors index 7938176..525e646 100644 --- a/authors +++ b/authors @@ -25,7 +25,7 @@ tomstdenis@yahoo.com. 6) Clay Culver - Submitted a fix for "rsa.c" which cleaned up some code. + Submitted a fix for "rsa.c" which cleaned up some code. Submited some other fixes too. :-) 7) Jason Klapste diff --git a/base64.c b/base64.c index 3ab94d0..a772b80 100644 --- a/base64.c +++ b/base64.c @@ -91,7 +91,7 @@ int base64_decode(const unsigned char *in, unsigned long len, if (c == 254) { c = 0; g--; } t = (t<<6)|c; if (++y == 4) { - if (z + g > *outlen) goto error; + if (z + g > *outlen) { return CRYPT_BUFFER_OVERFLOW; } out[z++] = (unsigned char)((t>>16)&255); if (g > 1) out[z++] = (unsigned char)((t>>8)&255); if (g > 2) out[z++] = (unsigned char)(t&255); @@ -103,8 +103,6 @@ int base64_decode(const unsigned char *in, unsigned long len, } *outlen = z; return CRYPT_OK; -error: - return CRYPT_BUFFER_OVERFLOW; } #endif diff --git a/changes b/changes index 4708da3..3185e36 100644 --- a/changes +++ b/changes @@ -1,3 +1,28 @@ +Dec 14th, 2002 +v0.79 -- Change to PK code [binary and source]. I made it so you have to pass the buffer size to the *_decrypt_key and + *_verify_hash functions. This prevents malformed packets from performing buffer overflows. I've also trimmed + the packet header size [by 4 bytes]. + -- Made the test program halt on the first error it occurs. Also made it trap more errors than before. + -- Wrote the first chapter of my new book [DRAFT!], not in this package but check my website! + -- Included a perl script "config.pl" that will make "makefile.out" according to the users needs. + -- Added shell script to look for latest release + -- Merge DH and ECC key defines from mycrypt_cfg.h into the makefiles + -- updated the makefile to use BSD friendly archiving invokations + -- Changed the DH and ECC code to use base64 static key settings [e.g. the primes]. Dropped the code size by 3KB + and is ever-so-slightly faster than before. + -- added "mp_shrink" function to shrink the size of bignums. Specially useful for PK code :-) + -- Added new exptmod function that calculates a^b mod c with fewer multiplies then before [~20% for crypto + sized numbers]. Also added a "low mem" variant that doesn't use more than 20KB [upto 4096 bit nums] of + heap todo the calculation. Both are #define'able controlled + -- Added XREALLOC macro to provide realloc() functionality. + -- Added fix where in rsa_import() if you imported a public key or a non-optimized key it would free the mp_int's + not being used. + -- Fixed potential bug in the ECC code. Only would occur on platforms where char is not eight bits [which isn't + often!] + -- Fixed up the ECC point multiplication, its about 15% faster now + -- While I was at it [since the lib isn't binary backwards compatible anyways] I've fixed the PK export routines + so they export as "unsigned" types saving 1 byte per bignum outputted. Not a lot but heck why not. + Nov 28th, 2002 v0.78 -- Made the default ARGCHK macro a function call instead which reduced the code size from 264KB to 239KB. -- Fixed a bug in the XTEA keysize function which called ARGCHK incorrectly. diff --git a/config.pl b/config.pl new file mode 100644 index 0000000..fd8093c --- /dev/null +++ b/config.pl @@ -0,0 +1,143 @@ +#!/usr/bin/perl +# +# Generates a makefile based on user input +# +# Tom St Denis, tomstdenis@yahoo.com, http://tom.iahu.ca + +@settings = ( + "CC,Compiler,gcc", + "AR,Archiver,ar", + "LD,Linker,ld", + "CFLAGS,Optimizations,-Os", + "CFLAGS,Warnings,-Wall -Wsign-compare -W -Wno-unused -Werror", + "CFLAGS,Include Paths,-I./", + "CFLAGS,Other compiler options,", + "CFLAGS,XMALLOC,-DXMALLOC=malloc", + "CFLAGS,XCALLOC,-DXCALLOC=calloc", + "CFLAGS,XFREE,-DXFREE=free", + "CFLAGS,XCLOCK,-DXCLOCK=clock", + "CFLAGS,XCLOCKS_PER_SEC,-DXCLOCKS_PER_SEC=CLOCKS_PER_SEC", +); + +@opts = ( + "SMALL_CODE,Use small code where possible (slower code),y", + "NO_FILE,Avoid file I/O calls,n", + "CLEAN_STACK,Clean the stack within functions,n", + + "BLOWFISH,Include Blowfish block cipher,y", + "RC2,Include RC2 block cipher,y", + "RC5,Include RC5 block cipher,y", + "RC6,Include RC6 block cipher,y", + "SERPENT,Include Serpent block cipher,y", + "SAFERP,Include Safer+ block cipher,y", + "SAFER,Include Safer-64 block ciphers,y", + "RIJNDAEL,Include Rijndael (AES) block cipher,y", + "XTEA,Include XTEA block cipher,y", + "TWOFISH,Include Twofish block cipher,y", + "TWOFISH_SMALL,Include Use a low ram variant of Twofish,n", + "TWOFISH_TABLES,Include Use precomputed tables to speed up the low-ram variant,n", + "DES,Include DES and 3DES block ciphers,y", + "CAST5,Include CAST5 (aka CAST-128) block cipher,y", + "NOEKEON,Include Noekeon block cipher,y", + + "CFB,Include CFB block mode of operation,y", + "OFB,Include OFB block mode of operation,y", + "ECB,Include ECB block mode of operation,y", + "CBC,Include CBC block mode of operation,y", + "CTR,Include CTR block mode of operation,y", + + "SHA512,Include SHA512 one-way hash,y", + "SHA384,Include SHA384 one-way hash (requires SHA512),y", + "SHA256,Include SHA256 one-way hash,y", + "TIGER,Include TIGER one-way hash,y", + "SHA1,Include SHA1 one-way hash,y", + "MD5,Include MD5 one-way hash,y", + "MD4,Include MD4 one-way hash,y", + "MD2,Include MD2 one-way hash,y", + "HMAC,Include Hash based Message Authentication Support,y", + + "BASE64,Include Base64 encoding support,y", + + "YARROW,Include Yarrow PRNG,y", + "SPRNG,Include Secure PRNG base on RNG code,y", + "RC4,Include RC4 PRNG,y", + "DEVRANDOM,Use /dev/random or /dev/urandom if available?,y", + "TRY_URANDOM_FIRST,Try /dev/urandom before /dev/random?,n", + + "MRSA,Include RSA public key support,y", + "MDH,Include Diffie-Hellman (over Z/pZ) public key support,y", + "MECC,Include Eliptic Curve public key crypto support,y", + "MDSA,Include Digital Signature Algoritm (DSA) support\n(not required for signatures in the other three),y", + "KR,Include Keyring support (groups all three PK systems),y", + + "DH768,768-bit DH key support,y", + "DH1024,1024-bit DH key support,y", + "DH1280,1280-bit DH key support,y", + "DH1536,1280-bit DH key support,y", + "DH1792,1792-bit DH key support,y", + "DH2048,2048-bit DH key support,y", + "DH2560,2560-bit DH key support,y", + "DH3072,3072-bit DH key support,y", + "DH4096,4096-bit DH key support,y", + + "ECC160,160-bit ECC key support,y", + "ECC192,192-bit ECC key support,y", + "ECC224,224-bit ECC key support,y", + "ECC256,256-bit ECC key support,y", + "ECC384,384-bit ECC key support,y", + "ECC521,521-bit ECC key support,y", + + "DSA1024,1024-bit (160-bit) DSA key support,y", + "DSA2048,2048-bit (256-bit) DSA key support,y", + "DSA4096,4096-bit (512-bit) DSA key support,y", + + "GF,Include GF(2^w) math support (not used internally),n", + + "MPI,Include MPI big integer math support (required by the public key code),y", + "MPI_FASTEXPT,Use the faster exponentiation code (uses some heap but is faster),y", + "MPI_FASTEXPT_LOWMEM,Use the low ram variant of the fast code\nRequires the fast code to enabled,n", + + +); + +# scan for switches and make variables +for (@settings) { + @m = split(",", $_); + print "@m[1]: [@m[2]] "; + $r = <>; $r = @m[2] if ($r eq "\n"); + chomp($r); + @vars{@m[0]} = @vars{@m[0]} . $r . " "; +} + +# scan for build flags +for (@opts) { + @m = split(",", $_); + print "@m[1]: [@m[2]]"; + $r = <>; @vars{'CFLAGS'} = @vars{'CFLAGS'} . "-D" . $m[0] . " " if (($r eq "y\n") || ($r eq "\n" && @m[2] eq "y")); +} + +open(OUT,">makefile.out"); +print OUT "#makefile generated with config.pl\n#\n#Tom St Denis (tomstdenis\@yahoo.com, http://tom.iahu.ca) \n\n"; + +# output unique vars first +for (@settings) { + @m = split(",", $_); + print OUT "@m[0] = @vars{@m[0]}\n" if (@vars{@m[0]} ne "" && @m[0] ne "CFLAGS"); + print OUT "CFLAGS += @vars{@m[0]}\n" if (@vars{@m[0]} ne "" && @m[0] eq "CFLAGS"); + @vars{@m[0]} = ""; +} + +# output objects +print OUT "\ndefault: library\n\n"; +print OUT "OBJECTS = keyring.o gf.o mem.o sprng.o dsa.o ecc.o base64.o dh.o rsa.o bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o ampi.o mpi.o prime.o twofish.o packet.o hmac.o strings.o\n\n"; + +# some depends +print OUT "rsa.o: rsa_sys.c\ndh.o: dh_sys.c\necc.o: ecc_sys.c\n\n"; + +# targets +print OUT "library: \$(OBJECTS)\n\t \$(AR) rs libtomcrypt.a \$(OBJECTS)\n\n"; +print OUT "clean:\n\trm -f \$(OBJECTS) libtomcrypt.a \n\n"; + +close OUT; + +print "\n\nmakefile.out was written.\n"; \ No newline at end of file diff --git a/crypt.c b/crypt.c index 41d5eef..b200a6e 100644 --- a/crypt.c +++ b/crypt.c @@ -1,7 +1,9 @@ #include "mycrypt.h" #include -struct _cipher_descriptor cipher_descriptor[32] = { +#define TAB_SIZE 32 + +struct _cipher_descriptor cipher_descriptor[TAB_SIZE] = { { NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, { NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, { NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, @@ -35,7 +37,7 @@ struct _cipher_descriptor cipher_descriptor[32] = { { NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }, { NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL } }; -struct _hash_descriptor hash_descriptor[32] = { +struct _hash_descriptor hash_descriptor[TAB_SIZE] = { { NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, @@ -69,7 +71,7 @@ struct _hash_descriptor hash_descriptor[32] = { { NULL, 0, 0, 0, NULL, NULL, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL, NULL } }; -struct _prng_descriptor prng_descriptor[32] = { +struct _prng_descriptor prng_descriptor[TAB_SIZE] = { { NULL, NULL, NULL, NULL, NULL }, { NULL, NULL, NULL, NULL, NULL }, { NULL, NULL, NULL, NULL, NULL }, @@ -103,26 +105,27 @@ struct _prng_descriptor prng_descriptor[32] = { { NULL, NULL, NULL, NULL, NULL }, { NULL, NULL, NULL, NULL, NULL } }; -#if (ARGTYPE == 0) && defined(SMALL_CODE) - +/* ch1-01-1 */ +#if (ARGTYPE == 0) void crypt_argchk(char *v, char *s, int d) { #ifdef SONY_PS2 - printf("_ARGCHK '%s' failure on line %d of file %s\n", v, d, s); + printf("_ARGCHK '%s' failure on line %d of file %s\n", + v, d, s); #else - fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n", v, d, s); + fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n", + v, d, s); #endif - raise(SIGABRT); + raise(SIGABRT); } - #endif - +/* ch1-01-1 */ int find_cipher(const char *name) { int x; _ARGCHK(name != NULL); - for (x = 0; x < 32; x++) { + for (x = 0; x < TAB_SIZE; x++) { if (cipher_descriptor[x].name != NULL && !strcmp(cipher_descriptor[x].name, name)) { return x; } @@ -134,7 +137,7 @@ int find_hash(const char *name) { int x; _ARGCHK(name != NULL); - for (x = 0; x < 32; x++) { + for (x = 0; x < TAB_SIZE; x++) { if (hash_descriptor[x].name != NULL && !strcmp(hash_descriptor[x].name, name)) { return x; } @@ -146,7 +149,7 @@ int find_prng(const char *name) { int x; _ARGCHK(name != NULL); - for (x = 0; x < 32; x++) { + for (x = 0; x < TAB_SIZE; x++) { if ((prng_descriptor[x].name != NULL) && !strcmp(prng_descriptor[x].name, name)) { return x; } @@ -157,7 +160,7 @@ int find_prng(const char *name) int find_cipher_id(unsigned char ID) { int x; - for (x = 0; x < 32; x++) { + for (x = 0; x < TAB_SIZE; x++) { if (cipher_descriptor[x].ID == ID) { return (cipher_descriptor[x].name == NULL) ? -1 : x; } @@ -168,7 +171,7 @@ int find_cipher_id(unsigned char ID) int find_hash_id(unsigned char ID) { int x; - for (x = 0; x < 32; x++) { + for (x = 0; x < TAB_SIZE; x++) { if (hash_descriptor[x].ID == ID) { return (hash_descriptor[x].name == NULL) ? -1 : x; } @@ -186,7 +189,7 @@ int find_cipher_any(const char *name, int blocklen, int keylen) x = find_cipher(name); if (x != -1) return x; - for (x = 0; cipher_descriptor[x].name != NULL; x++) { + for (x = 0; cipher_descriptor[x].name != NULL && x < TAB_SIZE; x++) { if (blocklen <= (int)cipher_descriptor[x].block_length && keylen <= (int)cipher_descriptor[x].max_key_length) { return x; } @@ -201,14 +204,14 @@ int register_cipher(const struct _cipher_descriptor *cipher) _ARGCHK(cipher != NULL); /* is it already registered? */ - for (x = 0; x < 32; x++) { + for (x = 0; x < TAB_SIZE; x++) { if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) { return x; } } /* find a blank spot */ - for (x = 0; x < 32; x++) { + for (x = 0; x < TAB_SIZE; x++) { if (cipher_descriptor[x].name == NULL) { memcpy(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor)); return x; @@ -226,7 +229,7 @@ int unregister_cipher(const struct _cipher_descriptor *cipher) _ARGCHK(cipher != NULL); /* is it already registered? */ - for (x = 0; x < 32; x++) { + for (x = 0; x < TAB_SIZE; x++) { if (!memcmp(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor))) { cipher_descriptor[x].name = NULL; cipher_descriptor[x].ID = 255; @@ -243,14 +246,14 @@ int register_hash(const struct _hash_descriptor *hash) _ARGCHK(hash != NULL); /* is it already registered? */ - for (x = 0; x < 32; x++) { + for (x = 0; x < TAB_SIZE; x++) { if (!memcmp(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor))) { return x; } } /* find a blank spot */ - for (x = 0; x < 32; x++) { + for (x = 0; x < TAB_SIZE; x++) { if (hash_descriptor[x].name == NULL) { memcpy(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor)); return x; @@ -268,7 +271,7 @@ int unregister_hash(const struct _hash_descriptor *hash) _ARGCHK(hash != NULL); /* is it already registered? */ - for (x = 0; x < 32; x++) { + for (x = 0; x < TAB_SIZE; x++) { if (!memcmp(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor))) { hash_descriptor[x].name = NULL; return CRYPT_OK; @@ -284,14 +287,14 @@ int register_prng(const struct _prng_descriptor *prng) _ARGCHK(prng != NULL); /* is it already registered? */ - for (x = 0; x < 32; x++) { + for (x = 0; x < TAB_SIZE; x++) { if (!memcmp(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor))) { return x; } } /* find a blank spot */ - for (x = 0; x < 32; x++) { + for (x = 0; x < TAB_SIZE; x++) { if (prng_descriptor[x].name == NULL) { memcpy(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor)); return x; @@ -309,7 +312,7 @@ int unregister_prng(const struct _prng_descriptor *prng) _ARGCHK(prng != NULL); /* is it already registered? */ - for (x = 0; x < 32; x++) { + for (x = 0; x < TAB_SIZE; x++) { if (!memcmp(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor))) { prng_descriptor[x].name = NULL; return CRYPT_OK; @@ -320,7 +323,7 @@ int unregister_prng(const struct _prng_descriptor *prng) int cipher_is_valid(int idx) { - if (idx < 0 || idx > 32 || cipher_descriptor[idx].name == NULL) { + if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx].name == NULL) { return CRYPT_INVALID_CIPHER; } return CRYPT_OK; @@ -328,7 +331,7 @@ int cipher_is_valid(int idx) int hash_is_valid(int idx) { - if (idx < 0 || idx > 32 || hash_descriptor[idx].name == NULL) { + if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) { return CRYPT_INVALID_HASH; } return CRYPT_OK; @@ -336,7 +339,7 @@ int hash_is_valid(int idx) int prng_is_valid(int idx) { - if (idx < 0 || idx > 32 || prng_descriptor[idx].name == NULL) { + if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) { return CRYPT_INVALID_PRNG; } return CRYPT_OK; diff --git a/crypt.pdf b/crypt.pdf index fe3dc99..7c84a8e 100644 Binary files a/crypt.pdf and b/crypt.pdf differ diff --git a/crypt.tex b/crypt.tex index 39f6abf..a05bef6 100644 --- a/crypt.tex +++ b/crypt.tex @@ -44,7 +44,7 @@ \def\gap{\vspace{0.5ex}} \makeindex \begin{document} -\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.78} +\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.79} \author{Tom St Denis \\ Algonquin College \\ \\ @@ -192,6 +192,7 @@ I would like to give thanks to the following people (in no particular order) for \item Wayne Scott \item Andrew Tyler \item Sky Schulz + \item Christopher Imes \end{enumerate} \chapter{The Application Programming Interface (API)} @@ -1367,15 +1368,18 @@ int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen, unsigned char *outkey, unsigned long *outlen, prng_state *prng, int wprng, rsa_key *key); -int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey, - unsigned long *keylen, rsa_key *key); +int rsa_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *outkey, unsigned long *keylen, + rsa_key *key); \end{verbatim} The ``rsa\_encrypt\_key()'' function accepts a symmetric key (limited to 32 bytes) as input in ``inkey''. ``inlen'' is the size of the input key in bytes. The function will then ``rsa\_pad()'' the key and encrypt it using the RSA -algorithm. It will store the result in ``outkey'' along with the length in ``outlen''. The ``rsa\_decrypt\_key()'' function -performs the opposite. The ``in'' variable is where the RSA packet goes and it will store the original symmetric key in -the ``outkey'' variable along with its length in ``keylen''. +algorithm. It will store the result in ``outkey'' along with the length in ``outlen''. + +The ``rsa\_decrypt\_key()'' function performs the opposite. The ``in'' variable is where the RSA packet of length +``inlen'' goes and it will store the original symmetric key in the ``outkey'' variable along with its length in +``keylen''. Similarly to sign or verify a hash of a message the following two messages are provided. The idea is to hash your message then use these functions to RSA sign the hash. @@ -1384,8 +1388,8 @@ int rsa_sign_hash(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, rsa_key *key); -int rsa_verify_hash(const unsigned char *sig, const unsigned char *hash, - int *stat, rsa_key *key); +int rsa_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, int *stat, rsa_key *key); \end{verbatim} For ``rsa\_sign\_hash'' the input is intended to be the hash of a message the user wants to sign. The output is the RSA signed packet which ``rsa\_verify\_hash'' can verify. For the verification function ``sig'' is the RSA signature @@ -1633,12 +1637,13 @@ int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen, prng_state *prng, int wprng, int hash, dh_key *key); -int dh_decrypt_key(const unsigned char *in, unsigned char *outkey, - unsigned long *keylen, dh_key *key); +int dh_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *outkey, unsigned long *keylen, + dh_key *key); \end{verbatim} Where ``inkey'' is an input symmetric key of no more than 32 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 ``dh\_encrypt\_key()''. The hash must produce a message digest at least as large +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 ``dh\_encrypt\_key()''. The hash must produce a message digest at least as large as the symmetric key you are trying to share. Similar to the RSA system you can sign and verify a hash of a message. @@ -1647,9 +1652,9 @@ int dh_sign_hash(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, dh_key *key); -int dh_verify_hash(const unsigned char *sig, const unsigned char *hash, - unsigned long inlen, int *stat, - dh_key *key); +int dh_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, dh_key *key); \end{verbatim} The ``dh\_sign\_hash'' function signs the message hash in ``in'' of length ``inlen'' and forms a DH packet in ``out''. @@ -1742,8 +1747,9 @@ int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen, prng_state *prng, int wprng, int hash, ecc_key *key); -int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey, - unsigned long *keylen, ecc_key *key); +int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *outkey, unsigned long *keylen, + ecc_key *key); \end{verbatim} Where ``inkey'' is an input symmetric key of no more than 32 bytes. Essentially these routines created a random public key @@ -1757,9 +1763,9 @@ int ecc_sign_hash(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, ecc_key *key); -int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash, - unsigned long inlen, int *stat, - ecc_key *key); +int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, ecc_key *key); \end{verbatim} The ``ecc\_sign\_hash'' function signs the message hash in ``in'' of length ``inlen'' and forms a ECC packet in ``out''. diff --git a/demos/test.c b/demos/test.c index dcd4a42..c03d218 100644 --- a/demos/test.c +++ b/demos/test.c @@ -63,23 +63,23 @@ void store_tests(void) STORE32L(L, &buf[0]); L = 0; LOAD32L(L, &buf[0]); - if (L != 0x12345678UL) printf("LOAD/STORE32 Little don't work\n"); + if (L != 0x12345678UL) { printf("LOAD/STORE32 Little don't work\n"); exit(-1); } LL = CONST64(0x01020304050607); STORE64L(LL, &buf[0]); LL = 0; LOAD64L(LL, &buf[0]) - if (LL != CONST64(0x01020304050607)) printf("LOAD/STORE64 Little don't work\n"); + if (LL != CONST64(0x01020304050607)) { printf("LOAD/STORE64 Little don't work\n"); exit(-1); } L = 0x12345678UL; STORE32H(L, &buf[0]); L = 0; LOAD32H(L, &buf[0]); - if (L != 0x12345678UL) printf("LOAD/STORE32 High don't work\n"); + if (L != 0x12345678UL) { printf("LOAD/STORE32 High don't work\n"); exit(-1); } LL = CONST64(0x01020304050607); STORE64H(LL, &buf[0]); LL = 0; LOAD64H(LL, &buf[0]) - if (LL != CONST64(0x01020304050607)) printf("LOAD/STORE64 High don't work\n"); + if (LL != CONST64(0x01020304050607)) { printf("LOAD/STORE64 High don't work\n"); exit(-1); } } void cipher_tests(void) { @@ -103,10 +103,12 @@ void ecb_tests(void) for (x = 0; cipher_descriptor[x].name != NULL; x++) { printf(" %12s: ", cipher_descriptor[x].name); - if ((errno = cipher_descriptor[x].test()) != CRYPT_OK) + if ((errno = cipher_descriptor[x].test()) != CRYPT_OK) { printf(" **failed** Reason: %s\n", error_to_string(errno)); - else + exit(-1); + } else { printf("passed\n"); + } } } @@ -124,11 +126,15 @@ void cbc_tests(void) for (x = 0; x < 32; x++) blk[x] = IV[x] = x; /* now lets start a cbc session */ - if ((errno = cbc_start(find_cipher("blowfish"), IV, key, 16, 0, &cbc)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } + if ((errno = cbc_start(find_cipher("blowfish"), IV, key, 16, 0, &cbc)) != CRYPT_OK) { + printf("CBC Setup: %s\n", error_to_string(errno)); exit(-1); } /* now lets encode 32 bytes */ - for (x = 0; x < 4; x++) - cbc_encrypt(blk+8*x, ct+8*x, &cbc); + for (x = 0; x < 4; x++) { + if ((errno = cbc_encrypt(blk+8*x, ct+8*x, &cbc)) != CRYPT_OK) { + printf("CBC encrypt: %s\n", error_to_string(errno)); exit(-1); + } + } zeromem(blk, sizeof(blk)); @@ -137,11 +143,16 @@ void cbc_tests(void) for (x = 0; x < 32; x++) IV[x] = x; /* now lets start a cbc session */ - if ((errno = cbc_start(find_cipher("blowfish"), IV, key, 16, 0, &cbc)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } + if ((errno = cbc_start(find_cipher("blowfish"), IV, key, 16, 0, &cbc)) != CRYPT_OK) { + printf("CBC Setup: %s\n", error_to_string(errno)); exit(-1); } /* now lets decode 32 bytes */ - for (x = 0; x < 4; x++) - cbc_decrypt(ct+8*x, blk+8*x, &cbc); + for (x = 0; x < 4; x++) { + if ((errno = cbc_decrypt(ct+8*x, blk+8*x, &cbc)) != CRYPT_OK) { + printf("CBC decrypt: %s\n", error_to_string(errno)); exit(-1); + } + } + /* print output */ for (x = y = 0; x < 32; x++) if (blk[x] != x) y = 1; @@ -157,6 +168,7 @@ void cbc_tests(void) printf("CBC failed logical testing.\n"); for (x = 0; x < 16; x++) printf("%02x ", ct[x]); printf("\n"); + exit(-1); } else { printf("CBC passed logical testing.\n"); } @@ -178,11 +190,15 @@ void ofb_tests(void) for (x = 0; x < 32; x++) blk[x] = IV[x] = x; /* now lets start a ofb session */ - if ((errno = ofb_start(find_cipher("blowfish"), IV, key, 16, 0, &ofb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } + if ((errno = ofb_start(find_cipher("cast5"), IV, key, 16, 0, &ofb)) != CRYPT_OK) { + printf("OFB Setup: %s\n", error_to_string(errno)); exit(-1); } /* now lets encode 32 bytes */ - for (x = 0; x < 4; x++) - ofb_encrypt(blk+8*x, ct+8*x, 8, &ofb); + for (x = 0; x < 4; x++) { + if ((errno = ofb_encrypt(blk+8*x, ct+8*x, 8, &ofb)) != CRYPT_OK) { + printf("OFB encrypt: %s\n", error_to_string(errno)); exit(-1); + } + } zeromem(blk, sizeof(blk)); @@ -191,15 +207,20 @@ void ofb_tests(void) for (x = 0; x < 32; x++) IV[x] = x; /* now lets start a ofb session */ - if ((errno = ofb_start(find_cipher("blowfish"), IV, key, 16, 0, &ofb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } + if ((errno = ofb_start(find_cipher("cast5"), IV, key, 16, 0, &ofb)) != CRYPT_OK) { + printf("OFB setup: %s\n", error_to_string(errno)); exit(-1); } /* now lets decode 32 bytes */ - for (x = 0; x < 4; x++) - ofb_decrypt(ct+8*x, blk+8*x, 8, &ofb); + for (x = 0; x < 4; x++) { + if ((errno = ofb_decrypt(ct+8*x, blk+8*x, 8, &ofb)) != CRYPT_OK) { + printf("OFB decrypt: %s\n", error_to_string(errno)); exit(-1); + } + } /* print output */ for (x = y = 0; x < 32; x++) if (blk[x] != x) y = 1; printf(" %s\n", y?"failed":"passed"); + if (y) exit(-1); } #else void ofb_tests(void) { printf("OFB not compiled in\n"); } @@ -218,11 +239,15 @@ void cfb_tests(void) for (x = 0; x < 32; x++) blk[x] = IV[x] = x; /* now lets start a cfb session */ - if ((errno = cfb_start(find_cipher("blowfish"), IV, key, 16, 0, &cfb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } + if ((errno = cfb_start(find_cipher("blowfish"), IV, key, 16, 0, &cfb)) != CRYPT_OK) { + printf("CFB setup: %s\n", error_to_string(errno)); exit(-1); } /* now lets encode 32 bytes */ - for (x = 0; x < 4; x++) - cfb_encrypt(blk+8*x, ct+8*x, 8, &cfb); + for (x = 0; x < 4; x++) { + if ((errno = cfb_encrypt(blk+8*x, ct+8*x, 8, &cfb)) != CRYPT_OK) { + printf("CFB encrypt: %s\n", error_to_string(errno)); exit(-1); + } + } zeromem(blk, sizeof(blk)); @@ -231,15 +256,20 @@ void cfb_tests(void) for (x = 0; x < 32; x++) IV[x] = x; /* now lets start a cfb session */ - if ((errno = cfb_start(find_cipher("blowfish"), IV, key, 16, 0, &cfb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } + if ((errno = cfb_start(find_cipher("blowfish"), IV, key, 16, 0, &cfb)) != CRYPT_OK) { + printf("CFB Setup: %s\n", error_to_string(errno)); exit(-1); } /* now lets decode 32 bytes */ - for (x = 0; x < 4; x++) - cfb_decrypt(ct+8*x, blk+8*x, 8, &cfb); + for (x = 0; x < 4; x++) { + if ((errno = cfb_decrypt(ct+8*x, blk+8*x, 8, &cfb)) != CRYPT_OK) { + printf("CFB decrypt: %s\n", error_to_string(errno)); exit(-1); + } + } /* print output */ for (x = y = 0; x < 32; x++) if (blk[x] != x) y = 1; printf(" %s\n", y?"failed":"passed"); + if (y) exit(-1); } #else void cfb_tests(void) { printf("CFB not compiled in\n"); } @@ -259,11 +289,15 @@ void ctr_tests(void) for (x = 0; x < 32; x++) blk[x] = count[x] = x; /* now lets start a ctr session */ - if ((errno = ctr_start(find_cipher("aes"), count, key, 16, 0, &ctr)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } + if ((errno = ctr_start(find_cipher("xtea"), count, key, 16, 0, &ctr)) != CRYPT_OK) { + printf("CTR Setup: %s\n", error_to_string(errno)); exit(-1); } /* now lets encode 32 bytes */ - for (x = 0; x < 4; x++) - ctr_encrypt(blk+8*x, ct+8*x, 8, &ctr); + for (x = 0; x < 4; x++) { + if ((errno = ctr_encrypt(blk+8*x, ct+8*x, 8, &ctr)) != CRYPT_OK) { + printf("CTR encrypt: %s\n", error_to_string(errno)); exit(-1); + } + } zeromem(blk, sizeof(blk)); @@ -272,15 +306,20 @@ void ctr_tests(void) for (x = 0; x < 32; x++) count[x] = x; /* now lets start a cbc session */ - if ((errno = ctr_start(find_cipher("aes"), count, key, 16, 0, &ctr)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } + if ((errno = ctr_start(find_cipher("xtea"), count, key, 16, 0, &ctr)) != CRYPT_OK) { + printf("CTR Setup: %s\n", error_to_string(errno)); exit(-1); } /* now lets decode 32 bytes */ - for (x = 0; x < 4; x++) - ctr_decrypt(ct+8*x, blk+8*x, 8, &ctr); + for (x = 0; x < 4; x++) { + if ((errno = ctr_decrypt(ct+8*x, blk+8*x, 8, &ctr)) != CRYPT_OK) { + printf("CTR decrypt: %s\n", error_to_string(errno)); exit(-1); + } + } /* print output */ for (x = y = 0; x < 32; x++) if (blk[x] != x) y = 1; printf(" %s\n", y?"failed":"passed"); + if (y) exit(-1); /* lets actually check the bytes */ memset(count, 0, 8); count[0] = 0xFF; /* IV = FF 00 00 00 00 00 00 00 */ @@ -325,17 +364,18 @@ void pad_test(void) /* pad the message so that random filler is placed before and after it */ y = 100; - if ((errno = rsa_pad(in, 16, out, &y, find_prng("yarrow"), &prng)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } + if ((errno = rsa_pad(in, 16, out, &y, find_prng("yarrow"), &prng)) != CRYPT_OK) { + printf("Error: %s\n", error_to_string(errno)); exit(-1); } /* depad the message to get the original content */ memset(in, 0, sizeof(in)); x = 100; - if ((errno = rsa_depad(out, y, in, &x)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } + if ((errno = rsa_depad(out, y, in, &x)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); } /* check outcome */ printf("rsa_pad: "); - if (x != 16) { printf("Failed. Wrong size.\n"); return; } - for (x = 0; x < 16; x++) if (in[x] != x) { printf("Failed. Expected %02lx and got %02x.\n", x, in[x]); return; } + if (x != 16) { printf("Failed. Wrong size.\n"); exit(-1); } + for (x = 0; x < 16; x++) if (in[x] != x) { printf("Failed. Expected %02lx and got %02x.\n", x, in[x]); exit(-1); } printf("passed.\n"); } @@ -349,100 +389,40 @@ void rsa_test(void) /* ---- SINGLE ENCRYPT ---- */ /* encrypt a short 8 byte string */ - if ((errno = rsa_make_key(&prng, find_prng("yarrow"), 1024/8, 65537, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } + if ((errno = rsa_make_key(&prng, find_prng("yarrow"), 1024/8, 65537, &key)) != CRYPT_OK) { + printf("Error: %s\n", error_to_string(errno)); exit(-1); } for (x = 0; x < 8; x++) in[x] = (unsigned char)(x+1); y = sizeof(in); - if ((errno = rsa_exptmod(in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } + if ((errno = rsa_exptmod(in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { + printf("Error: %s\n", error_to_string(errno)); exit(-1); } /* decrypt it */ zeromem(in, sizeof(in)); x = sizeof(out); - if ((errno = rsa_exptmod(out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } + if ((errno = rsa_exptmod(out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { + printf("Error: %s\n", error_to_string(errno)); exit(-1); } /* compare */ printf("RSA : "); - for (x = 0; x < 8; x++) if (in[x] != (x+1)) { printf("Failed. x==%02lx, in[%ld]==%02x\n", x, x, in[x]); } + for (x = 0; x < 8; x++) if (in[x] != (x+1)) { printf("Failed. x==%02lx, in[%ld]==%02x\n", x, x, in[x]); exit(-1); } printf("passed.\n"); -#ifdef PK_PACKET - /* ---- BLOCK ENCRYPT ---- */ - /* now lets test rsa_encrypt() */ - for (x = 0; x < 8; x++) in[x] = (unsigned char)x; - x = sizeof(out); - if ((errno = rsa_encrypt(in, 8, out, &x, &prng, find_prng("yarrow"), find_cipher("aes"), &key)) != CRYPT_OK) { - printf("Error: %s\n", error_to_string(errno)); - return; - } - - /* test rsa_decrypt() */ - zeromem(in, sizeof(in)); - y = sizeof(in); - if ((errno = rsa_decrypt(out, x, in, &y, &key)) != CRYPT_OK) { - printf("Error: %s\n", error_to_string(errno)); - return; - } - printf("rsa_encrypt()/rsa_decrypt(): "); - for (y = 0; y < 8; y++) if (in[y] != y) { printf("failed.\n"); return; } - printf("Passed.\n"); - - /* ---- SIGNATURES ---- */ - x = sizeof(in); - if ((errno = rsa_sign("hello", 5, in, &x, find_hash("md5"), &key)) != CRYPT_OK) { - printf("Error: %s\n", error_to_string(errno)); - return; - } - if ((errno = rsa_verify(in, "hello", 5, &stat, &key)) != CRYPT_OK) { - printf("Error: %s\n", error_to_string(errno)); - return; - } - printf("RSA Signatures: %s, ", (stat==1)?"pass":"fail"); - if ((errno = rsa_verify(in, "abcde", 5, &stat, &key)) != CRYPT_OK) { - printf("Error: %s\n", error_to_string(errno)); - return; - } - printf("%s\n", (stat==0)?"pass":"fail"); - - /* ---- EXPORT/IMPORT ---- */ - x = sizeof(out); - if ((errno = rsa_export(out, &x, PK_PRIVATE_OPTIMIZED, &key)) != CRYPT_OK) { - printf("Error: %s\n", error_to_string(errno)); - return; - } - printf("RSA Export takes %lu bytes\n", x); - rsa_free(&key); - if ((errno = rsa_import(out, &key, x)) != CRYPT_OK) { - printf("Error: %s\n", error_to_string(errno)); - return; - } - printf("RSA Import: "); - if ((errno = rsa_verify(in, "hello", 5, &stat, &key)) != CRYPT_OK) { - printf("Error: %s\n", error_to_string(errno)); - return; - } - printf("%s, ", (stat==1)?"pass":"fail"); - if ((errno = rsa_verify(in, "abcde", 5, &stat, &key)) != CRYPT_OK) { - printf("Error: %s\n", error_to_string(errno)); - return; - } - printf("%s\n", (stat==0)?"pass":"fail"); -#endif - /* test the rsa_encrypt_key functions */ for (x = 0; x < 16; x++) in[x] = x; y = sizeof(out); if ((errno = rsa_encrypt_key(in, 16, out, &y, &prng, find_prng("yarrow"), &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } zeromem(in, sizeof(in)); x = sizeof(in); - if ((errno = rsa_decrypt_key(out, in, &x, &key)) != CRYPT_OK) { + if ((errno = rsa_decrypt_key(out, y, in, &x, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } printf("RSA en/de crypt key routines: "); - if (x != 16) { printf("Failed (length)\n"); return; } - for (x = 0; x < 16; x++) if (in[x] != x) { printf("Failed (contents)\n"); return; } + if (x != 16) { printf("Failed (length)\n"); exit(-1); } + for (x = 0; x < 16; x++) if (in[x] != x) { printf("Failed (contents)\n"); exit(-1); } printf("Passed\n"); /* test sign_hash functions */ @@ -450,24 +430,25 @@ void rsa_test(void) x = sizeof(in); if ((errno = rsa_sign_hash(in, 16, out, &x, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } printf("RSA signed hash: %lu bytes\n", x); - if ((errno = rsa_verify_hash(out, in, &stat, &key)) != CRYPT_OK) { + if ((errno = rsa_verify_hash(out, x, in, &stat, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } printf("Verify hash: %s, ", stat?"passed":"failed"); in[0] ^= 1; - if ((errno = rsa_verify_hash(out, in, &stat, &key)) != CRYPT_OK) { + if ((errno = rsa_verify_hash(out, x, in, &stat, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } printf("%s\n", (!stat)?"passed":"failed"); + if (stat) exit(-1); rsa_free(&key); /* make a RSA key */ -#ifdef SONY_PS2 +#ifdef SONY_PS2_NOPE limit = 1024; #else limit = 2048; @@ -475,21 +456,21 @@ void rsa_test(void) for (z = 1024; z <= limit; z += 512) { t = XCLOCK(); - if ((errno = rsa_make_key(&prng, find_prng("yarrow"), z/8, 65537, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } + if ((errno = rsa_make_key(&prng, find_prng("yarrow"), z/8, 65537, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); } t = XCLOCK() - t; printf("Took %.0f ms to make a %ld-bit RSA key.\n", 1000.0 * ((double)t / (double)XCLOCKS_PER_SEC), z); /* time encryption */ y = sizeof(in); t = XCLOCK(); - if ((errno = rsa_exptmod(in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } + if ((errno = rsa_exptmod(in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); } t = XCLOCK() - t; printf("Took %.0f ms to encrypt with a %ld-bit RSA key.\n", 1000.0 * ((double)t / (double)XCLOCKS_PER_SEC), z); /* time decryption */ x = sizeof(out); t = XCLOCK(); - if ((errno = rsa_exptmod(out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } + if ((errno = rsa_exptmod(out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); } t = XCLOCK() - t; printf("Took %.0f ms to decrypt with a %ld-bit RSA key.\n", 1000.0 * ((double)t / (double)XCLOCKS_PER_SEC), z); rsa_free(&key); @@ -516,19 +497,19 @@ void base64_test(void) x = 100; if (base64_encode(buf[0], 16, buf[1], &x) != CRYPT_OK) { printf(" error: %s\n", error_to_string(errno)); - return; + exit(-1); } printf(" encoded 16 bytes to %ld bytes...[%s]\n", x, buf[1]); memset(buf[0], 0, 100); y = 100; if (base64_decode(buf[1], x, buf[0], &y) != CRYPT_OK) { printf(" error: %s\n", error_to_string(errno)); - return; + exit(-1); } printf(" decoded %ld bytes to %ld bytes\n", x, y); for (x = 0; x < 16; x++) if (buf[0][x] != x) { printf(" **failed**\n"); - return; + exit(-1); } printf(" passed\n"); } @@ -642,50 +623,50 @@ void dh_tests(void) /* make up two keys */ if ((errno = dh_make_key(&prng, find_prng("yarrow"), 96, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } if ((errno = dh_make_key(&prng, find_prng("yarrow"), 96, &userb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } /* make the shared secret */ x = 4096; if ((errno = dh_shared_secret(&usera, &userb, buf[0], &x)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } y = 4096; if ((errno = dh_shared_secret(&userb, &usera, buf[1], &y)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } - if (y != x) { printf("DH Shared keys are not same size.\n"); return; } - if (memcmp(buf[0], buf[1], x)) { printf("DH Shared keys not same contents.\n"); return; } + if (y != x) { printf("DH Shared keys are not same size.\n"); exit(-1); } + if (memcmp(buf[0], buf[1], x)) { printf("DH Shared keys not same contents.\n"); exit(-1); } /* now export userb */ y = 4096; if ((errno = dh_export(buf[1], &y, PK_PUBLIC, &userb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } dh_free(&userb); /* import and make the shared secret again */ if ((errno = dh_import(buf[1], y, &userb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } z = 4096; if ((errno = dh_shared_secret(&usera, &userb, buf[2], &z)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } printf("DH routines: "); - if (z != x) { printf("failed. Size don't match?\n"); return; } - if (memcmp(buf[0], buf[2], x)) { printf("Failed. Content didn't match.\n"); return; } + if (z != x) { printf("failed. Size don't match?\n"); exit(-1); } + if (memcmp(buf[0], buf[2], x)) { printf("Failed. Content didn't match.\n"); exit(-1); } printf("Passed\n"); dh_free(&usera); dh_free(&userb); @@ -703,7 +684,7 @@ void dh_tests(void) printf("Make dh-1024 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC)); dh_free(&usera); -#ifndef SONY_PS2 +#ifndef SONY_PS2_NOPE t1 = XCLOCK(); dh_make_key(&prng, find_prng("yarrow"), 160, &usera); t1 = XCLOCK() - t1; @@ -735,71 +716,23 @@ void dh_tests(void) dh_free(&usera); #endif -#ifdef PK_PACKET -/* try dh packet stuff */ - for (x = 0; x < 16; x++) buf[0][x] = (unsigned char)x; - dh_make_key(&prng, find_prng("yarrow"), 24, &usera); - - x = 4096; - if (dh_encrypt(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), find_cipher("aes"), - find_hash("sha1"), &usera) != CRYPT_OK) { - printf("dh_encrypt says %s\n", error_to_string(errno)); - return; - } - printf("dh encrypted 16 bytes into %ld bytes!\n", x); - - y = 4096; - if ((errno = dh_decrypt(buf[1], x, buf[2], &y, &usera)) != CRYPT_OK) { - printf("dh_decrypt says %s\n", error_to_string(errno)); - return; - } - - printf("dh packet: "); - if (16 != y) { printf("Failed: Sizes different! 16 vs %ld\n", y); return; } - if (memcmp(buf[0], buf[2], 16)) { printf("Failed; Content mismatch.\n"); return; } - printf("Passed!\n"); - dh_free(&usera); - -/* try dh signatures */ - dh_make_key(&prng, find_prng("yarrow"), 96, &usera); - x = 4096; - if ((errno = dh_sign("hello", 5, buf[0], &x, find_hash("sha1"), &prng, find_prng("yarrow"), &usera)) != CRYPT_OK) { - printf("Error: %s\n", error_to_string(errno)); - return; - } - - printf("dh-768 Signature took %ld bytes\n", x); - - if ((errno = dh_verify(buf[0], "hello", 5, &stat, &usera)) != CRYPT_OK) { - printf("Error: %s\n", error_to_string(errno)); - return; - } - if ((errno = dh_verify(buf[0], "hellp", 5, &stat2, &usera)) != CRYPT_OK) { - printf("Error: %s\n", error_to_string(errno)); - return; - } - - printf("dh Signatures: %s (%d,%d)\n", ((stat==1)&&(stat2==0))?"passed":"failed", stat,stat2); - dh_free(&usera); -#endif - /* test encrypt_key */ dh_make_key(&prng, find_prng("yarrow"), 96, &usera); for (x = 0; x < 16; x++) buf[0][x] = x; y = sizeof(buf[1]); if ((errno = dh_encrypt_key(buf[0], 16, buf[1], &y, &prng, find_prng("yarrow"), find_hash("md5"), &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } zeromem(buf[0], sizeof(buf[0])); x = sizeof(buf[0]); - if ((errno = dh_decrypt_key(buf[1], buf[0], &x, &usera)) != CRYPT_OK) { + if ((errno = dh_decrypt_key(buf[1], y, buf[0], &x, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } printf("DH en/de crypt key routines: "); - if (x != 16) { printf("Failed (length)\n"); return; } - for (x = 0; x < 16; x++) if (buf[0][x] != x) { printf("Failed (contents)\n"); return; } + if (x != 16) { printf("Failed (length)\n"); exit(-1); } + for (x = 0; x < 16; x++) if (buf[0][x] != x) { printf("Failed (contents)\n"); exit(-1); } printf("Passed (size %lu)\n", y); /* test sign_hash */ @@ -807,16 +740,16 @@ void dh_tests(void) x = sizeof(buf[1]); if ((errno = dh_sign_hash(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } - if (dh_verify_hash(buf[1], buf[0], 16, &stat, &usera)) { + if (dh_verify_hash(buf[1], x, buf[0], 16, &stat, &usera)) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } buf[0][0] ^= 1; - if (dh_verify_hash(buf[1], buf[0], 16, &stat2, &usera)) { + if (dh_verify_hash(buf[1], x, buf[0], 16, &stat2, &usera)) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } printf("dh_sign/verify_hash: %s (%d,%d)\n", ((stat==1)&&(stat2==0))?"passed":"failed", stat,stat2); dh_free(&usera); @@ -868,7 +801,7 @@ void ecc_tests(void) ecc_key usera, userb; clock_t t1; - if ((errno = ecc_test()) != CRYPT_OK) printf("ecc Error: %s\n", error_to_string(errno)); + if ((errno = ecc_test()) != CRYPT_OK) { printf("ecc Error: %s\n", error_to_string(errno)); exit(-1); } ecc_sizes(&low, &high); printf("ecc Keys from %d to %d supported.\n", low*8, high*8); @@ -876,35 +809,35 @@ void ecc_tests(void) /* make up two keys */ if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 24, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 24, &userb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } /* make the shared secret */ x = 4096; if ((errno = ecc_shared_secret(&usera, &userb, buf[0], &x)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } y = 4096; if ((errno = ecc_shared_secret(&userb, &usera, buf[1], &y)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } - if (y != x) { printf("ecc Shared keys are not same size.\n"); return; } + if (y != x) { printf("ecc Shared keys are not same size.\n"); exit(-1); } - if (memcmp(buf[0], buf[1], x)) { printf("ecc Shared keys not same contents.\n"); return; } + if (memcmp(buf[0], buf[1], x)) { printf("ecc Shared keys not same contents.\n"); exit(-1); } /* now export userb */ y = 4096; if ((errno = ecc_export(buf[1], &y, PK_PUBLIC, &userb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } ecc_free(&userb); printf("ECC-192 export took %ld bytes\n", y); @@ -912,142 +845,94 @@ void ecc_tests(void) /* import and make the shared secret again */ if ((errno = ecc_import(buf[1], y, &userb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } z = 4096; if ((errno = ecc_shared_secret(&usera, &userb, buf[2], &z)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } printf("ecc routines: "); - if (z != x) { printf("failed. Size don't match?\n"); return; } - if (memcmp(buf[0], buf[2], x)) { printf("Failed. Content didn't match.\n"); return; } + if (z != x) { printf("failed. Size don't match?\n"); exit(-1); } + if (memcmp(buf[0], buf[2], x)) { printf("Failed. Content didn't match.\n"); exit(-1); } printf("Passed\n"); ecc_free(&usera); ecc_free(&userb); /* time stuff */ t1 = XCLOCK(); - ecc_make_key(&prng, find_prng("yarrow"), 20, &usera); + if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 20, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); } t1 = XCLOCK() - t1; printf("Make ECC-160 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC)); ecc_free(&usera); t1 = XCLOCK(); - ecc_make_key(&prng, find_prng("yarrow"), 24, &usera); + if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 24, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); } t1 = XCLOCK() - t1; printf("Make ECC-192 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC)); ecc_free(&usera); t1 = XCLOCK(); - ecc_make_key(&prng, find_prng("yarrow"), 28, &usera); + if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 28, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); } t1 = XCLOCK() - t1; printf("Make ECC-224 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC)); ecc_free(&usera); #ifndef SONY_PS2 t1 = XCLOCK(); - ecc_make_key(&prng, find_prng("yarrow"), 32, &usera); + if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 32, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); } t1 = XCLOCK() - t1; printf("Make ECC-256 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC)); ecc_free(&usera); t1 = XCLOCK(); - ecc_make_key(&prng, find_prng("yarrow"), 48, &usera); + if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 48, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); } t1 = XCLOCK() - t1; printf("Make ECC-384 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC)); ecc_free(&usera); t1 = XCLOCK(); - ecc_make_key(&prng, find_prng("yarrow"), 65, &usera); + if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 65, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); } t1 = XCLOCK() - t1; printf("Make ECC-521 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC)); ecc_free(&usera); #endif -#ifdef PK_PACKET -/* try ECC packet stuff */ - for (x = 0; x < 16; x++) buf[0][x] = (unsigned char)x; - ecc_make_key(&prng, find_prng("yarrow"), 20, &usera); - - x = 4096; - if (ecc_encrypt(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), find_cipher("aes"), - find_hash("tiger"), &usera) != CRYPT_OK) { - printf("ecc_encrypt says %s\n", error_to_string(errno)); - return; - } - printf("Ecc encrypted 16 bytes into %ld bytes!\n", x); - - y = 4096; - if ((errno = ecc_decrypt(buf[1], x, buf[2], &y, &usera)) != CRYPT_OK) { - printf("ecc_decrypt says %s\n", error_to_string(errno)); - return; - } - - printf("ECC packet: "); - if (16 != y) { printf("Failed: Sizes different! 16 vs %ld\n", y); return; } - if (memcmp(buf[0], buf[2], 16)) { printf("Failed; Content mismatch.\n"); return; } - printf("Passed!\n"); - ecc_free(&usera); - -/* try ECC signatures */ - ecc_make_key(&prng, find_prng("yarrow"), 20, &usera); - x = 4096; - if ((errno = ecc_sign("hello", 5, buf[0], &x, find_hash("sha1"), &prng, find_prng("yarrow"), &usera)) != CRYPT_OK) { - printf("Error: %s\n", error_to_string(errno)); - return; - } - - printf("ECC-160 Signature took %ld bytes\n", x); - - if ((errno = ecc_verify(buf[0], "hello", 5, &stat, &usera)) != CRYPT_OK) { - printf("Error: %s\n", error_to_string(errno)); - return; - } - if ((errno = ecc_verify(buf[0], "hellp", 5, &stat2, &usera)) != CRYPT_OK) { - printf("Error: %s\n", error_to_string(errno)); - return; - } - - printf("ECC Signatures: %s (%d,%d)\n", ((stat==1)&&(stat2==0))?"passed":"failed", stat,stat2); - ecc_free(&usera); -#endif - /* test encrypt_key */ ecc_make_key(&prng, find_prng("yarrow"), 32, &usera); for (x = 0; x < 16; x++) buf[0][x] = x; y = sizeof(buf[1]); if ((errno = ecc_encrypt_key(buf[0], 16, buf[1], &y, &prng, find_prng("yarrow"), find_hash("md5"), &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } zeromem(buf[0], sizeof(buf[0])); x = sizeof(buf[0]); - if ((errno = ecc_decrypt_key(buf[1],buf[0], &x, &usera)) != CRYPT_OK) { + if ((errno = ecc_decrypt_key(buf[1], y, buf[0], &x, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } printf("ECC en/de crypt key routines: "); - if (x != 16) { printf("Failed (length)\n"); return; } - for (x = 0; x < 16; x++) if (buf[0][x] != x) { printf("Failed (contents)\n"); return; } + if (x != 16) { printf("Failed (length)\n"); exit(-1); } + for (x = 0; x < 16; x++) if (buf[0][x] != x) { printf("Failed (contents)\n"); exit(-1); } printf("Passed (size: %lu)\n", y); /* test sign_hash */ for (x = 0; x < 16; x++) buf[0][x] = x; x = sizeof(buf[1]); if ((errno = ecc_sign_hash(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } - if (ecc_verify_hash(buf[1], buf[0], 16, &stat, &usera)) { + if (ecc_verify_hash(buf[1], x, buf[0], 16, &stat, &usera)) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } buf[0][0] ^= 1; - if (ecc_verify_hash(buf[1], buf[0], 16, &stat2, &usera)) { + if (ecc_verify_hash(buf[1], x, buf[0], 16, &stat2, &usera)) { printf("Error: %s\n", error_to_string(errno)); - return; + exit(-1); } printf("ecc_sign/verify_hash: %s (%d,%d)\n", ((stat==1)&&(stat2==0))?"passed":"failed", stat,stat2); ecc_free(&usera); @@ -1185,15 +1070,16 @@ void register_all_algs(void) register_cipher(&null_desc); +#ifdef SHA1 + register_hash(&sha1_desc); +#endif #ifdef SHA256 register_hash(&sha256_desc); #endif #ifdef TIGER register_hash(&tiger_desc); #endif -#ifdef SHA1 - register_hash(&sha1_desc); -#endif + #ifdef MD5 register_hash(&md5_desc); #endif @@ -1383,18 +1269,18 @@ void kr_test(void) len = sizeof(buf2); if ((errno = kr_sign_hash(kr, _kr->ID, buf, 32, buf2, &len, &prng, find_prng("yarrow"))) != CRYPT_OK) { - printf("kr_sign_hash failed, %i, %lu\n", i, len); + printf("kr_sign_hash failed, %i, %s\n", i, error_to_string(errno)); exit(-1); } printf("kr_sign_hash: "); if ((errno = kr_verify_hash(kr, buf2, buf, 32, &stat)) != CRYPT_OK) { - printf("kr_sign_hash failed, %i, %lu\n", i, len); + printf("kr_sign_hash failed, %i, %s\n", i, error_to_string(errno)); exit(-1); } printf("%s, ", stat?"passed":"failed"); buf[15] ^= 1; if ((errno = kr_verify_hash(kr, buf2, buf, 32, &stat)) != CRYPT_OK) { - printf("kr_sign_hash failed, %i, %lu\n", i, len); + printf("kr_sign_hash failed, %i, %s\n", i, error_to_string(errno)); exit(-1); } printf("%s\n", (!stat)?"passed":"failed"); @@ -1542,7 +1428,7 @@ int main(void) if ((errno = yarrow_ready(&prng)) != CRYPT_OK) { printf("yarrow_ready: %s\n", error_to_string(errno)); } - + printf(crypt_build_settings); test_errs(); diff --git a/dh.c b/dh.c index 44a237a..7683deb 100644 --- a/dh.c +++ b/dh.c @@ -12,10 +12,9 @@ static const struct { 96, "DH-768", "2", - "2893527720709661239493896562339544088620375736490408468011883030469939904368" - "0860923364582982212457078989335831907131881773994018526277492109945959747917" - "8279025394653904396221302707492255957231214118178743427870878320796645901947" - "9487" + "1tH+dRFGpEYyVLe4ydZcYyGDpeAxnChz0yk+pNCtkEXwUsOORyguBtx8spUD" + "FAjEDS8PutUBTEu2q4USqu19dUbCLj9D2jY7y3871RnSccurMBsMm35ILcyQ" + "rpN0MQKc/" }, #endif #ifdef DH1024 @@ -23,11 +22,9 @@ static const struct { 128, "DH-1024", "2", - "3477431594398766260792527967974222231775354473882066076071816639030459075912" - "0194047822362172211817327089848758298713770865641434468581617942085516098634" - "0457973820182883508387588163122354089264395604796675278966117567294812714812" - "7968205965648764507160662831267200108590414847865290564578963676831229604111" - "36319" + "Uypu+t9nfUnCj7xD+xokM+Cd6mASW4ofg1jpC2BpQasC5edtA1dJC+RjbOBZ" + "z+5mvq5VYT8Wfjmlpjm9tQxHOYB0+3Myl7gbCQ5SRljWT2oBLukLNvgFjiU4" + "wiWkmu41Ern/j6uxwKb740C+VIgDAdeUY4fA5hyfr3/+DWYb14/" }, #endif #ifdef DH1280 @@ -35,12 +32,10 @@ static const struct { 160, "DH-1280", "2", - "2618298020488323341377089635550383393554460131909411928885489146533597039863" - "5379029297773089246854323581071445272213255646852180580463169755159411503866" - "4190218001872082125570169842848154404911652982668791288605239288293106162305" - "7236093554796242806887062958692596037823904832542385180840218330924392268465" - "0197244314233248991982159235832322194332167923655574170280697353556560854901" - "280047" + "520QV4Tsq4NwK9Mt5CGR9xk4slvaikgi/ax3OPky5GERKTsoqEXOlFyMzURP" + "P8jYzCVz1izKd2zTDxbFfLxrJry0ceaQ5YZa5N4teByCPVlQh4v6iQl+944+" + "/NDlKzvWpx7HG7k8cGKhva7aFF8bP/CvLpaQhrfXlOX+X9pcmML9QH63tUjq" + "B80l8Yx9KN0dC3iNnsTV3DnqnEvFQkoqql" }, #endif #ifdef DH1536 @@ -48,13 +43,11 @@ static const struct { 192, "DH-1536", "3", - "2992593690703251306835100868059076484222548092264611010748654597096560864537" - "1704684310938824733433085888971827086341295918925237859522548192211945291282" - "1170570153374563548621496076860061698150233114892317627457427359445435608693" - "5625000902194809114890745455404045166957722404567939575618007347432055137282" - "3291711752537781447636541738638119983678441628437171377508654097130147131310" - "9209393805685590941710151477648542896503595482724205166251069428524927527085" - "2602467" + "1FTWXrPcY1w74oZ0ouIzSN8uZcRiOf6U11fx0ka6+7fqIAezPhd3Ab43QnDf" + "KFg+or/fFRGEWAxF8WIE2jx8iTOu010yNEQyH14CK0RAyy2zY4gRs2MpnU5r" + "/feWf60OkLtnPzN34+Xnlg5xf7Jl00wkHRCeJG17L3SklOidAPxWnE+Wm4BS" + "SOzdQBgiZOjlhrYS1+TIU3NP5H7BrtKFcf+ZwBULibf29L7LkDOgQbie1+43" + "lU+8SHAyBwAeGYMfZ" }, #endif #ifdef DH1792 @@ -62,14 +55,11 @@ static const struct { 224, "DH-1792", "2", - "3210090394251532205679207425273650879078185529033544241951292722086520015900" - "0402371844205168176419829949232601235193754977706171541009393172204470047690" - "6659627844880912479392592056697278305733615369406596661203184035142652643118" - "1379603333858737848321053048184938839622944591194935387992479717305577175500" - "2554620614907177847128950276247571809502831255425929468853285490357704941968" - "3407102520889651917659577334897408316217748346860775479727332331727022096550" - "7718799868459391361770854814013613619048768630587629568449528005570971478547" - "34960319" + "IPo3wjvfS7vBYnFHwJHmesA51od9fnR8Aenezif4qLE2HX+YCv1tpvHA8yLH" + "yYbKe9QfSHHtOgVjK8AYEyPirpXxlmdykGuj+dX7EiWMRGYc+v1kKkqmCn0o" + "5tU416O/1HXTpQ2Hps0buchUD+HlCMrSgnIqRxK6Fjr0ZfiCS4XgAD6sLgi0" + "BxKFMxDsVzpGMNwF5Lj2R/cJiTi0cNDDY3gn4lK/PRUsJtRKU+9sxy0q5Yof" + "aG5VO8VcHkZJVwUKhDFHkZYWMHV808TGHXM2RQ9kRa2QvS2mXxMrDSCloQ/" }, #endif #ifdef DH2048 @@ -77,15 +67,12 @@ static const struct { 256, "DH-2048", "2", - "4726642895635639316469736509812041897640060270607231273592407174543853221823" - "7979333351774907308168340693326687317443721193266215155735814510792148768576" - "4984911991227443513994894535335532038333186916782632419417062569961974604240" - "2901241901263467186228353234265630967717360250949841797609150915436003989316" - "5037637034737020327399910409885798185771003505320583967737293415979917317338" - "9858373857347474783642420203804168920566508414708692945275435973492502995396" - "8243060517332102902655554683247304860032703684578197028928889831788842751736" - "4945316709081173840186150794397479045034008257793436817683392375274635794835" - "245695887" + "5sR1VmdsQQzzjN0iridVVyveug6sAC3+/jTIHSgEoimPOREXQ05r2WJZJAF2" + "CRu8kuusiPw2ivRli+fdLr63v1uZG5nQa28uLwNxZEsu4gu6TrGjepXeXm4Z" + "CVOC1HMmi660fLZ2ruHLa4v2NWex2Zx91/y4ygPlZM+K//iy+Gft9Ma9Ayn0" + "eYwofZeUL9vJSfutPVp2ZrIEUQDBKMvMm0SRSLiUjDtzXqrH+b/wuwIFG1K4" + "var3ucsT45mDzD9qb3tBdksSPZbr6yrELV8h+qmjiBr15oHKEglS0XwSvCap" + "abUn5XPPVoaKv13+tOnG9mGgzQ8JeClVXN63Q+GGEF" }, #endif #ifdef DH2560 @@ -93,17 +80,14 @@ static const struct { 320, "DH-2560", "3", - "4364638085059577685748948703943497396233464406019459611612544400721432981520" - "4010567649104824811014627875285783993051576616744140702150122992472133564455" - "7342265864606569000117714935185566842453630868849121480179691838399545644365" - "5711067577313173717585579907818806913366955847993133136872874688941488237617" - "8558298254958618375680644901754262226787427510387748147553499120184991222267" - "0102069951687572917937634467778042874315463238062009202992087620963771759666" - "4482665328580794026699200252242206134194410697184828373996126449788399252071" - "0987084027819404215874884544513172913711709852902888677006373648742061314404" - "5836803985635654192482395882603511950547826439092832800532152534003936926017" - "6124466061356551464456206233957889787267447285030586700468858762515271223502" - "75750995227" + "G7UVKk+N6LfpGkdBP6XLB4QJ3wzee5YH/3o6tBDMwr4FS8YjCmeP6l4gu0hX" + "dzY2Rive4TYOu4Akm4naZuv32d71/2lQeNcO23BNYOEPxtn9BU8uYfaHP9Mo" + "M+m76oUCiI5uqpag5RH3BO34FyE4BiKkzjEXq9xxc8ERacG8Mo8DNiXu79p9" + "Q/0wsRz+W/lIN4gYw3w4iLMooAGnDrhcj5cZb0HysHWYfqmFo+jTBP6Egi0g" + "cmVO2qWQh2cZIQMfppaf1Ffq0XGIJpgDFyOHPl3NVxDabVK1tkVct+hathxJ" + "UTdqZmR2VFwMASXjfgj4VFdvFCUxV8Xr8JcwXkwlMjOJbAl0LoCa4M7hpYvz" + "G/0XviGCpv7qQaONKtsiQ6mHhMcyo9hBCRZXtNPkfPMZkPeV05akvaDs6Ek7" + "DZ62oKR" }, #endif #ifdef DH3072 @@ -111,19 +95,15 @@ static const struct { 384, "DH-3072", "2", - "1142416747335183639807830604262436227795642944052113706188970261176634876069" - "2206243140413411077394583180726863277012016602279290144126785129569474909173" - "5847898223419867427192303319460727303195559844849117167970588759054009995043" - "0587724584911968750902323279027363746682105257685923245298206183100977078603" - "1785669030271542286603956118755585683996118896215213488875253101894663403069" - "6777459483058938495054342017637452328957807119724320113448575216910178963168" - "6140320644942133224365885545343578400651720289418164056243357539082138421096" - "0117518650374602256601091379644034244332285065935413233557998331562749140202" - "9658442193362989700115138825649355387042894469683222814519074873620465114612" - "2132979989735099337056069750580968643878203623537213701573130477907243026098" - "6460269894522159103008260495503005267165927542949439526272736586626709581721" - "0321895327263896436255906801057848442461527026701693042037830722750891947548" - "89511973916207" + "1zsV6XgY57R/hu2RR4H/BjwRqmQL9h+Dc5rgoWOcqiTS8qpVTWafi1KFV77V" + "rUcjcer1EDgCV0tpzlemtyrC2pHpw7hr3EEl2evfWOvg05FRI6mKc2UPNv2c" + "2Bjww4LD/tdsLleX7AHHXCXFSSyd6C3qWq7BqABZriSpQeaEtXbWfeC6ytFe" + "2i3VeQsLa40XQ21UxwhPAjamjSOfYzkW7xi0fwI1e+4OQiFcWOfOuvswoaEf" + "MIICyAmVp67vjGo66dk81dMemyplipgXAWPdl7ppnDd6cEjyN4N90D7kQiNg" + "lVmJlKLecldOUtdIqMnbJCbiN/t/3/AEFaokGO9om5ckc6M9gG5PG0T7Oh1N" + "dSx/PstGdxwvs9DOwjyo5wl5C9QSLtUYJl2+GZYMj6WfsgCrb6jjRJJJQe2C" + "y7wUcBILbRsP3lYT8s14zm4xFBrfMUoLN287j3wQ1TNUXjYSCi4ZLKT1XDai" + "93345OiutLOqGGikFg6ypnymJK3yeHuul" }, #endif #ifdef DH4096 @@ -131,23 +111,18 @@ static const struct { 512, "DH-4096", "3", - "1214855636816562637502584060163403830270705000634713483015101384881871978446" - "8012247985361554068958233050354675916325310675478909486951171720769542207270" - "7568804875102242119871203284889005635784597424656074834791863005085393369779" - "2254955890439720297560693579400297062396904306270145886830719309296352765295" - "7121830407731464190228751653827780070401099576097395898755908857011261979060" - "6362013395489321661267883850754077713843779770560245371955901763398648664952" - "3611975865005712371194067612263330335590526176087004421363598470302731349138" - "7732059014477046821815179040647356365184624522427916765417252923789255682968" - "5801015185232631677751193503753101741391050692192245066693320227848902452126" - "3798482237150056835746454842662048692127173834433089016107854491097456725016" - "3277096631997382384421648431471327891537255132571679155551620949708535844479" - "9312548860769600816980737473671129700747381225627224548940589847029717873802" - "9484459690836250560495461579533254473316340608217876781986188705928270735695" - "7528308255279638383554197625162460286802809880204019145518254873499903069763" - "0409310938445143881325121105159739212749146489879740678917545306796007200859" - "0614886532333015881171367104445044718144312416815712216611576221546455968770" - "801413440778423979" + "Id8ukxZdao3hS0NGTKAXdt3c8PpiyigIyBY8lwOHjM2cqkaZgwvr1pA6OowS" + "32kJkeOqKB8gNTZZZVqOFkPXgvC4WveUgA5a7rhTj28pDidNROmMO70CCcSw" + "aHI3GLFuEMz3JJyvQKGaGwpV3C9gS70dFWTxEfNRzdYEdvIic8/SXI79VgNP" + "LGR68nzd4qxCgaLpVBnWsanRp7mfEj52S/7Kxjs14lrbAOMjCuHgN4F6THWh" + "PNhG0VXfFFIwAMW2unrfpdo+gQHNclqCf2N1FALpABzvUesgs3wIP+QTMqms" + "os/AkuulG7MusbeFl3SoCtaoW12CF038ZbqW+e+DKI1zObhtsLanvaiZm/N4" + "BsJirW7avcWNQYm1oYjZ2bR/jYqfoJ0CLXLO/vqHb8J9a5VE9nz7cqMD3/MH" + "k/g7BapsOtKuol6ipbUvxQPtf4KCwqQQ40JeqgS6amivI/aLu05S7bAxKOwE" + "Yu8YxjN6lXm3co5Wy+BmNSuRlzKhxICyHEqMfKwUtm48XHzHuPaGQzHgkn6H" + "3A+FQjQGLHewADYlbfdTF3sHYyc5k9h/9cYVkbmv7bQze53CJGr3T1hZYbN6" + "+fuz0SPnfjiKu+bWD+8RYtZpLs2+f32huMz3OqoryGfULxC2aEjL2rdBn+ZR" + "PT0+ZAUyLSAVHbsul++cawh" }, #endif { @@ -180,9 +155,8 @@ int dh_test(void) #if 0 printf("dh_test():testing size %d-bits\n", sets[x].size * 8); #endif - /* see if g^((p-1)/2) == 1 mod p. */ - if (mp_read_radix(&g, sets[x].base, 10) != MP_OKAY) { goto error; } - if (mp_read_radix(&p, sets[x].prime, 10) != MP_OKAY) { goto error; } + if (mp_read_radix(&g, sets[x].base, 64) != MP_OKAY) { goto error; } + if (mp_read_radix(&p, sets[x].prime, 64) != MP_OKAY) { goto error; } /* ensure p is prime */ if ((res = is_prime(&p, &primality)) != CRYPT_OK) { goto done; } @@ -276,18 +250,21 @@ int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key) if (mp_init_multi(&g, &p, &key->x, &key->y, NULL) != MP_OKAY) { return CRYPT_MEM; } - if (mp_read_radix(&g, sets[x].base, 10) != MP_OKAY) { goto error2; } - if (mp_read_radix(&p, sets[x].prime, 10) != MP_OKAY) { goto error2; } + if (mp_read_radix(&g, sets[key->idx].base, 64) != MP_OKAY) { goto error; } + if (mp_read_radix(&p, sets[key->idx].prime, 64) != MP_OKAY) { goto error; } /* load the x value */ mp_read_raw(&key->x, buf, keysize+1); - if (mp_exptmod(&g, &key->x, &p, &key->y) != MP_OKAY) { goto error2; } + if (mp_exptmod(&g, &key->x, &p, &key->y) != MP_OKAY) { goto error; } key->type = PK_PRIVATE; + + if (mp_shrink(&key->x) != MP_OKAY) { goto error; } + if (mp_shrink(&key->y) != MP_OKAY) { goto error; } /* free up ram */ res = CRYPT_OK; goto done2; -error2: +error: res = CRYPT_MEM; mp_clear_multi(&key->x, &key->y, NULL); done2: @@ -304,10 +281,10 @@ void dh_free(dh_key *key) #define OUTPUT_BIGNUM(num, buf2, y, z) \ { \ - z = mp_raw_size(num); \ + z = mp_unsigned_bin_size(num); \ STORE32L(z, buf2+y); \ y += 4; \ - mp_toraw(num, buf2+y); \ + mp_to_unsigned_bin(num, buf2+y); \ y += z; \ } @@ -329,11 +306,15 @@ void dh_free(dh_key *key) } \ \ /* load it */ \ - if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\ - errno = CRYPT_MEM; \ + if (mp_read_unsigned_bin(num, (unsigned char *)in+y, x) != MP_OKAY) {\ + errno = CRYPT_MEM; \ goto error; \ } \ y += x; \ + if (mp_shrink(num) != MP_OKAY) { \ + errno = CRYPT_MEM; \ + goto error; \ + } \ } @@ -374,14 +355,16 @@ int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key) } /* store header */ - packet_store_header(buf2, PACKET_SECT_DH, PACKET_SUB_KEY, y); + packet_store_header(buf2, PACKET_SECT_DH, PACKET_SUB_KEY); /* output it */ *outlen = y; memcpy(out, buf2, y); /* clear mem */ +#ifdef CLEAN_STACK zeromem(buf2, sizeof(buf2)); +#endif return CRYPT_OK; } @@ -436,6 +419,12 @@ int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key) if (key->type == PK_PRIVATE) { INPUT_BIGNUM(&key->x, in, x, y); } + + /* eliminate private key if public */ + if (key->type == PK_PUBLIC) { + mp_clear(&key->x); + } + return CRYPT_OK; error: mp_clear_multi(&key->y, &key->x, NULL); @@ -469,7 +458,7 @@ int dh_shared_secret(dh_key *private_key, dh_key *public_key, return CRYPT_MEM; } - if (mp_read_radix(&p, sets[private_key->idx].prime, 10) != MP_OKAY) { goto error; } + if (mp_read_radix(&p, sets[private_key->idx].prime, 64) != MP_OKAY) { goto error; } if (mp_exptmod(&public_key->y, &private_key->x, &p, &tmp) != MP_OKAY) { goto error; } /* enough space for output? */ diff --git a/dh_sys.c b/dh_sys.c index ad94896..ff73f45 100644 --- a/dh_sys.c +++ b/dh_sys.c @@ -80,7 +80,7 @@ int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen, } /* store header */ - packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_ENC_KEY, y); + packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_ENC_KEY); #ifdef CLEAN_STACK /* clean up */ @@ -93,8 +93,9 @@ int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen, return CRYPT_OK; } -int dh_decrypt_key(const unsigned char *in, unsigned char *outkey, - unsigned long *keylen, dh_key *key) +int dh_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *outkey, unsigned long *keylen, + dh_key *key) { unsigned char shared_secret[1536], skey[MAXBLOCKSIZE]; unsigned long x, y, z, res, hashsize, keysize; @@ -111,6 +112,13 @@ int dh_decrypt_key(const unsigned char *in, unsigned char *outkey, return CRYPT_PK_NOT_PRIVATE; } + /* check if initial header should fit */ + if (inlen < PACKET_SIZE+1+4+4) { + return CRYPT_INVALID_PACKET; + } else { + inlen -= PACKET_SIZE+1+4+4; + } + /* is header correct? */ if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_ENC_KEY)) != CRYPT_OK) { return errno; @@ -128,6 +136,14 @@ int dh_decrypt_key(const unsigned char *in, unsigned char *outkey, /* get public key */ LOAD32L(x, in+y); + + /* now check if the imported key will fit */ + if (inlen < x) { + return CRYPT_INVALID_PACKET; + } else { + inlen -= x; + } + y += 4; if ((errno = dh_import(in+y, x, &pubkey)) != CRYPT_OK) { return errno; @@ -149,6 +165,14 @@ int dh_decrypt_key(const unsigned char *in, unsigned char *outkey, /* load in the encrypted key */ LOAD32L(keysize, in+y); + + /* will the outkey fit as part of the input */ + if (inlen < keysize) { + return CRYPT_INVALID_PACKET; + } else { + inlen -= keysize; + } + if (keysize > *keylen) { res = CRYPT_BUFFER_OVERFLOW; goto done; @@ -223,8 +247,8 @@ int dh_sign_hash(const unsigned char *in, unsigned long inlen, if (mp_read_raw(&k, buf, sets[key->idx].size) != MP_OKAY) { goto error; } /* load g, p and p1 */ - if (mp_read_radix(&g, sets[key->idx].base, 10) != MP_OKAY) { goto error; } - if (mp_read_radix(&p, sets[key->idx].prime, 10) != MP_OKAY) { goto error; } + if (mp_read_radix(&g, sets[key->idx].base, 64) != MP_OKAY) { goto error; } + if (mp_read_radix(&p, sets[key->idx].prime, 64) != MP_OKAY) { goto error; } if (mp_sub_d(&p, 1, &p1) != MP_OKAY) { goto error; } if (mp_div_2(&p1, &p1) != MP_OKAY) { goto error; } /* p1 = (p-1)/2 */ @@ -256,7 +280,7 @@ int dh_sign_hash(const unsigned char *in, unsigned long inlen, } /* store header */ - packet_store_header(buf, PACKET_SECT_DH, PACKET_SUB_SIGNED, y); + packet_store_header(buf, PACKET_SECT_DH, PACKET_SUB_SIGNED); /* store it */ memcpy(out, buf, y); @@ -275,9 +299,9 @@ done: return res; } -int dh_verify_hash(const unsigned char *sig, const unsigned char *hash, - unsigned long inlen, int *stat, - dh_key *key) +int dh_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, dh_key *key) { mp_int a, b, p, g, m, tmp; unsigned char md[MAXBLOCKSIZE]; @@ -292,17 +316,24 @@ int dh_verify_hash(const unsigned char *sig, const unsigned char *hash, /* default to invalid */ *stat = 0; + /* check initial input length */ + if (siglen < PACKET_SIZE+4+4) { + return CRYPT_INVALID_PACKET; + } else { + siglen -= PACKET_SIZE + 4 + 4; + } + /* header ok? */ if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_DH, PACKET_SUB_SIGNED)) != CRYPT_OK) { return errno; } - + /* get hash out of packet */ y = PACKET_SIZE; /* hash the message */ md[0] = 0; - memcpy(md+1, hash, MIN(sizeof(md) - 1, inlen)); + memcpy(md+1, hash, MIN(sizeof(md) - 1, hashlen)); /* init all bignums */ if (mp_init_multi(&a, &p, &b, &g, &m, &tmp, NULL) != MP_OKAY) { @@ -311,21 +342,32 @@ int dh_verify_hash(const unsigned char *sig, const unsigned char *hash, /* load a and b */ LOAD32L(x, sig+y); + if (siglen < x) { + return CRYPT_INVALID_PACKET; + } else { + siglen -= x; + } + y += 4; if (mp_read_raw(&a, (unsigned char *)sig+y, x) != MP_OKAY) { goto error; } y += x; LOAD32L(x, sig+y); + if (siglen < x) { + return CRYPT_INVALID_PACKET; + } else { + siglen -= x; + } y += 4; if (mp_read_raw(&b, (unsigned char *)sig+y, x) != MP_OKAY) { goto error; } y += x; /* load p and g */ - if (mp_read_radix(&p, sets[key->idx].prime, 10) != MP_OKAY) { goto error; } - if (mp_read_radix(&g, sets[key->idx].base, 10) != MP_OKAY) { goto error; } + if (mp_read_radix(&p, sets[key->idx].prime, 64) != MP_OKAY) { goto error; } + if (mp_read_radix(&g, sets[key->idx].base, 64) != MP_OKAY) { goto error; } /* load m */ - if (mp_read_raw(&m, md, 1+MIN(sizeof(md)-1, inlen)) != MP_OKAY) { goto error; } + if (mp_read_raw(&m, md, 1+MIN(sizeof(md)-1, hashlen)) != MP_OKAY) { goto error; } /* find g^m mod p */ if (mp_exptmod(&g, &m, &p, &m) != MP_OKAY) { goto error; } /* m = g^m mod p */ diff --git a/dsa.c b/dsa.c new file mode 100644 index 0000000..fce0b8b --- /dev/null +++ b/dsa.c @@ -0,0 +1,398 @@ +/* Implementation of the Digital Signature Algorithm (DSA) by Tom St Denis */ +#ifdef MDSA + +#include + +static const struct { + int size, osize; + char *order, + *prime, + *base; +} sets[] = { +#ifdef DSA1024 +{ + 1024, 160, + + "PE6GbKzFwpeAAMtC3PUsqsRQMWl", + + "PyhJv87GTec3fBvC8BQT4yQ8gSYB8rk6DfLRfeirnZsQaQBVwh8PZ7V1hKfD" + "SGGUgr1cAb3YrnZw97HvyaKmypY2dM19OxeNWNI4f6IyYwj/mcAiJpkjxMmZ" + "mYVrTbGxBG8OaKBD9vFd9/Jif8djJ18GnaRsdRoCBDec+W++x6D", + + "3uYLnHhrVRR6hATv30lj/XX5AecEE2tJVgtWcHkbwKuR3WEqqvP8xBUG70Ve" + "p6kUchz/E/kZaGIJ0mrqme6bNDIxoNqtshyDfska/Zfm/QHuDZWljVGbPx68" + "eSBw1vzkRKFCmR8QgpT+R887JufEgQRRIQOuLK8c1ND61efJH2t" +}, +#endif +#ifdef DSA2048 +{ + 2048, 256, + + "TZLgPgD7D46uoATLyNSgKsgh6LglcVDwlPFvT6dcOdN", + + "EUlAFvO8lXjhXn/6BobNq4bo0st12+zwgpshNJgoUap/LFCQcGeVGt/s/ocD" + "M+4v+bU3dNKjFJEYzb+sxmy5dbzQsa15+Ud4v1UJ/7D4p0IyA+h9aeU9i/C9" + "tJQC824mQhmL5cxx7SbQPMD/2+P04hLyeDOir1L1vmvE1tWZg43Jbza2LTQJ" + "52wi/Sguai3vFZVMObEPBfbXzg9b8pH1i75Q1os9w0LtfJ4pYQJD3Xn66jYF" + "mpLVqK4yuMXOOq07bkM5Nx+jQvFpGuRiD5e4a2FB1NjXbCGMtRxu6eurPAIY" + "F5dw3QWXkZm74SFmLTi0GW+3pipDWiBSUu9pUpp6rr", + + "79PG50FKgZgffOnFiUuuZLhWicqFZ6EwvWXQi7uBmvMQUoXNEBschAhRtLQE" + "ev5iHrR2g41rEEundwwFTbRdyq2txBS2bClkFjGlojPwayWvXLAaDltfkhws" + "TjS/gNKch4qD1nPu+Kd1RmjWp1B1JzBXnlcj/z5qMaF8oL4bk9qGGEmaeOLs" + "90vW0Z/7QWBC8h+65SohFBmydUWwXhs4rAa7NwHbPltnXdF6kZHpQOtT5h+4" + "hYA83eYzdeOl5rYrFDiyJ+nfOptgLiLIHB9L0wkOhFrb52+S7qKpgYe1+oof" + "K1/Rd4D8fL5qvGyXWz1dB8W2iqAXeXKlkWZrvHQdMM" +}, +#endif +#ifdef DSA4096 +{ + 4096, 512, + + "4GO4hUY+2MqiwNBYFx/JqRejRKXXJfcaY7mIBYksn2Dwn6JQZp9Qpg3bbnOJ" + "kt5ZqH2dtEjbV9B/AXF51jOkW/", + + "Jddrq1iN+f03IKVqcDSOz7IquBVxzb34Cwzmc7rHpIOW3DqW7IjMz47ETtWu" + "KvG3JxFdYaiv69lAE+X38DEqQSTE8Ba9jfNYs9PYeH4RfsT5op/u3r41anRW" + "jJTHMhnvwwQ0eQrZ+9d7LQePnQSUs3eXb8ZdNsh8/h30b3gIMk+08bZoJejF" + "6Y2vMtMQUHmmoM/+IlrMz7TZ4tu0jkYWBp1y74WLGemXkYvU6pqH8dTQX1MM" + "oG93eBKQ87jHbtBJ+L6EbcqO/jVa6lwUivEbBs9UtKf4lC0pe3SZqfFhrJde" + "2b5LfbPBLk2pNdC5MJCsIVz7TUL28SWYwx7Nx7ybxtKd76L8kgbLfoOYiJRx" + "WIFGRE40Q9/0zuqzz6D1WHKQE4wg5oy6WQeO3Q5BN1UC6O4EUSkD7mC3KmWA" + "MgxNDZYMA+BSCTirVL2eS90WCA4LkTsHhoLgafwZT5xanUKGY/cZix29sy21" + "J1Ut4cbPFjxg76OVu9obONitMLg+63dz3Ho8LMhXaKN43yl5Kc4PxeUCQWVU" + "gHXg8RSldQMOvhwohHFibiMUrRkkCs2//Ts6hVdS3cEFgfYhpnzeEiGBCuat" + "ZZYpaWKZlmrlcUYH7Rg9SyHH1h4DLrki5ySIjGxozT6JhIrMme8uQcN9YOiq" + "GwRhjR3AM1QiOUfolENTYCn", + + "3VIJLic34uyamh2TbNHEjECeH289m938S2wvHYe/3xPNiCjVhBxl6RAgom+Q" + "3X7+r8EII4QQKXXdqR3Ad/nXzJkgMUJVvt5d5lIwwKM7+ffbLmhJWldO0Jkc" + "7oZQr7t81khBUG4wgPVZO8OwjB66v9npPCcBLNLO6DAWE82CM8YfPJzQt0tr" + "JSHwcgixvkFft25SdI0V9zg2H6sj2Q/yAYUEAPzyDfQVvLzqEN2tmIhturnR" + "wUW4WLy8PSls/tt5eWjdI++ofdGHNJmKaZjHgym52GhNQmWZYWzK/hcllWtC" + "U8vCw7GY3nE4uF74YuTYC6LGx7wXS5ivj531KTPe4EarZ4j+aVw9ZJhfy/h+" + "K0esj9ALQP9jSz3OMDKeYaJKjj/scC5NrPdSjeJf7EvlVf41ufZHNGrFVmVW" + "kqaEuNZr+SmC6/2buPEmL4UO94H1z4QItK+rHqNWEQP6ptST0lcFwHO4uESR" + "qp8scA2/Fh+G0TfJ/rg8wImqbWsgrUwGnmDmKtFLRiX4aMPIsyFIsJvPQECT" + "EIR6yd6QIRVGZbCRiVsCqMrHsn0KZWSeKdtW9TRt/yNu+VKcgRZFfU991Nab" + "OBxkAS1kw9kyj/HZYxPG4NrqL0j5bnb1VjqQZKEEQMSBAyMMfDuMyWhrmsxV" + "ffmF/sYGxFHCbacGeu06C3U" +}, +#endif +{ + 0, 0, + NULL, + NULL, + NULL +} +}; + +int dsa_test(void) +{ + mp_int q, p, g, t; + int errno, i, res, primality; + + /* init memory */ + if (mp_init_multi(&q, &p, &g, &t, NULL) != MP_OKAY) { + return CRYPT_MEM; + } + + res = CRYPT_MEM; + for (i = 0; i < sets[i].size; i++) { + #if 0 + printf("Testing size: %d\n", sets[i].size); + #endif + /* read in order, prime, generator */ + if (mp_read_radix(&q, sets[i].order, 64) != MP_OKAY) { goto error; } + if (mp_read_radix(&p, sets[i].prime, 64) != MP_OKAY) { goto error; } + if (mp_read_radix(&g, sets[i].base, 64) != MP_OKAY) { goto error; } + + /* now see if the order and modulus are prime */ + if ((errno = is_prime(&q, &primality)) != CRYPT_OK) { + res = errno; + goto error; + } + if (primality == 0) { + res = CRYPT_FAIL_TESTVECTOR; + goto error; + } + + if ((errno = is_prime(&p, &primality)) != CRYPT_OK) { + res = errno; + goto error; + } + if (primality == 0) { + res = CRYPT_FAIL_TESTVECTOR; + goto error; + } + + /* now see what g^q mod p is (should be 1) */ + if (mp_exptmod(&g, &q, &p, &t) != MP_OKAY) { goto error; } + if (mp_cmp_d(&t, 1)) { + res = CRYPT_FAIL_TESTVECTOR; + goto error; + } + } + res = CRYPT_OK; +error: + mp_clear_multi(&t, &g, &p, &q, NULL); + return res; +} + +int dsa_make_key(prng_state *prng, int wprng, int keysize, dsa_key *key) +{ + mp_int g, p, q; + unsigned char buf[64]; + int errno, idx, x; + + _ARGCHK(prng != NULL); + _ARGCHK(key != NULL); + + /* good prng? */ + if ((errno = prng_is_valid(wprng)) != CRYPT_OK) { + return errno; + } + + /* find key size */ + for (x = 0; (keysize > sets[x].size) && (sets[x].size); x++); + if (sets[x].size == 0) { + return CRYPT_INVALID_KEYSIZE; + } + key->idx = x; + keysize = sets[x].osize; + + /* read prng */ + if (prng_descriptor[wprng].read(buf, keysize, prng) != (unsigned long)keysize) { + return CRYPT_ERROR_READPRNG; + } + + /* init parameters */ + if (mp_init_multi(&g, &p, &q, &key->x, &key->y, NULL) != MP_OKAY) { + return CRYPT_MEM; + } + if (mp_read_radix(&q, sets[x].order, 64) != MP_OKAY) { goto error; } + if (mp_read_radix(&g, sets[x].base, 64) != MP_OKAY) { goto error; } + if (mp_read_radix(&p, sets[x].prime, 64) != MP_OKAY) { goto error; } + + /* load exponent */ + if (mp_read_unsigned_bin(&key->x, buf, keysize) != MP_OKAY) { goto error; } + if (mp_mod(&key->x, &q, &key->x) != MP_OKAY) { goto error; } + + /* calc public key */ + if (mp_exptmod(&g, &key->x, &p, &key->y) != MP_OKAY) { goto error; } + key->type = PK_PRIVATE; + + /* shrink values */ + if (mp_shrink(&key->x) != MP_OKAY) { goto error; } + if (mp_shrink(&key->y) != MP_OKAY) { goto error; } + + /* free temps */ + mp_clear_multi(&g, &q, &p, NULL); +#ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + + return CRYPT_OK; +error: + mp_clear_multi(&g, &q, &p, &key->x, &key->y, NULL); + return CRYPT_MEM; +} + +void dsa_free(dsa_key *key) +{ + _ARGCHK(key != NULL); + mp_clear_multi(&key->x, &key->y, NULL); +} + +static int is_valid_idx(int n) +{ + int x; + + for (x = 0; sets[x].size; x++); + if ((n < 0) || (n >= x)) { + return 0; + } + return 1; +} + +int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key) +{ + unsigned char buf[4096]; + unsigned long x, y; + + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + _ARGCHK(key != NULL); + + if (is_valid_idx(key->idx) == 0) { + return CRYPT_PK_INVALID_TYPE; + } + + if (type == PK_PRIVATE && key->type != PK_PRIVATE) { + return CRYPT_PK_NOT_PRIVATE; + } + + y = PACKET_SIZE; + + buf[y++] = type; + buf[y++] = sets[key->idx].osize/8; + + x = mp_unsigned_bin_size(&key->y); + STORE32L(x, &buf[y]); + y += 4; + mp_to_unsigned_bin(&key->y, &buf[y]); + y += x; + + if (type == PK_PRIVATE) { + x = mp_unsigned_bin_size(&key->x); + STORE32L(x, &buf[y]); + y += 4; + mp_to_unsigned_bin(&key->x, &buf[y]); + y += x; + } + + /* check for overflow */ + if (*outlen < y) { + #ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); + #endif + return CRYPT_BUFFER_OVERFLOW; + } + + /* store header */ + packet_store_header(buf, PACKET_SECT_DSA, PACKET_SUB_KEY); + + /* output it */ + *outlen = y; + memcpy(out, buf, y); + + /* clear mem */ +#ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + return CRYPT_OK; +} + +#define INPUT_BIGNUM(num, in, x, y) \ +{ \ + /* load value */ \ + if (y + 4 > inlen) { \ + errno = CRYPT_INVALID_PACKET; \ + goto error; \ + } \ + LOAD32L(x, in+y); \ + y += 4; \ + \ + /* sanity check... */ \ + if (x+y > inlen) { \ + errno = CRYPT_INVALID_PACKET; \ + goto error; \ + } \ + \ + /* load it */ \ + if (mp_read_unsigned_bin(num, (unsigned char *)in+y, x) != MP_OKAY) {\ + errno = CRYPT_MEM; \ + goto error; \ + } \ + y += x; \ + if (mp_shrink(num) != MP_OKAY) { \ + errno = CRYPT_MEM; \ + goto error; \ + } \ +} + +int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) +{ + unsigned long x, y, s; + int errno; + + _ARGCHK(in != NULL); + _ARGCHK(key != NULL); + + /* check type byte */ + if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_DSA, PACKET_SUB_KEY)) != CRYPT_OK) { + return errno; + } + + if (2+PACKET_SIZE > inlen) { + return CRYPT_INVALID_PACKET; + } + + + /* init */ + if (mp_init_multi(&key->x, &key->y, NULL) != MP_OKAY) { + return CRYPT_MEM; + } + + y = PACKET_SIZE; + key->type = in[y++]; + s = (long)in[y++] * 8; + + for (x = 0; (s > (unsigned long)sets[x].osize) && (sets[x].osize); x++); + if (sets[x].osize == 0) { + errno = CRYPT_INVALID_KEYSIZE; + goto error; + } + key->idx = x; + + /* type check both values */ + if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE)) { + errno = CRYPT_PK_TYPE_MISMATCH; + goto error; + } + + /* is the key idx valid? */ + if (!is_valid_idx(key->idx)) { + errno = CRYPT_PK_TYPE_MISMATCH; + goto error; + } + + /* load public value g^x mod p*/ + INPUT_BIGNUM(&key->y, in, x, y); + + if (key->type == PK_PRIVATE) { + INPUT_BIGNUM(&key->x, in, x, y); + } + + /* eliminate private key if public */ + if (key->type == PK_PUBLIC) { + mp_clear(&key->x); + } + + return CRYPT_OK; +error: + mp_clear_multi(&key->y, &key->x, NULL); + return errno; +} + + + +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 g, q, p, k, tmp; + unsigned char buf[4096]; + int x, y, errno; + + _ARGCHK(in != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + _ARGCHK(prng != NULL); + _ARGCHK(key != NULL); + + if ((errno = prng_is_valid(wprng)) != CRYPT_OK) { + return errno; + } + + if (is_valid_idx(key->idx) == 0) { + return CRYPT_PK_INVALID_TYPE; + } + +return 0; +} + + + +#endif /* MDSA */ + diff --git a/ecc.c b/ecc.c index 2cde908..8b50504 100644 --- a/ecc.c +++ b/ecc.c @@ -18,15 +18,15 @@ static const struct { 20, "ECC-160", /* prime */ - "1461501637330902918203684832716283019655932542983", + "G00000000000000000000000007", /* B */ - "1C9E7C2E5891CBE097BD46", + "1oUV2vOaSlWbxr6", /* order */ - "1461501637330902918203686297565868358251373258181", + "G0000000000004sCQUtDxaqDUN5", /* Gx */ - "2DCF462904B478D868A7FF3F2BF1FCD9", + "jpqOf1BHus6Yd/pyhyVpP", /* Gy */ - "DFFAF2EE3848FA75FB967CEC7B9A399E085ACED8", + "D/wykuuIFfr+vPyx7kQEPu8MixO", }, #endif #ifdef ECC192 @@ -34,19 +34,19 @@ static const struct { 24, "ECC-192", /* prime */ - "6277101735386680763835789423207666416083908700390324961279", + "/////////////////////l//////////", /* B */ - "64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", + "P2456UMSWESFf+chSYGmIVwutkp1Hhcn", /* order */ - "6277101735386680763835789423176059013767194773182842284081", + "////////////////cTxuDXHhoR6qqYWn", /* Gx */ - "188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", + "68se3h0maFPylo3hGw680FJ/2ls2/n0I", /* Gy */ - "07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + "1nahbV/8sdXZ417jQoJDrNFvTw4UUKWH" }, #endif #ifdef ECC224 @@ -55,19 +55,19 @@ static const struct { "ECC-224", /* prime */ - "26959946667150639794667015087019630673637144422540572481103610249951", + "400000000000000000000000000000000000BV", /* B */ - "2051BA041508CED34B3", + "21HkWGL2CxJIp", /* order */ - "26959946667150639794667015087019637467111563745054605861463538557247", + "4000000000000000000Kxnixk9t8MLzMiV264/", /* Gx */ - "2DCF462904B478D868A7FF3F2BF1FCD9", + "jpqOf1BHus6Yd/pyhyVpP", /* Gy */ - "CF337F320BC44A15C3EDB8C4258BB958E57A0CAFA73EB46E9C4BA9AE", + "3FCtyo2yHA5SFjkCGbYxbOvNeChwS+j6wSIwck", }, #endif #ifdef ECC256 @@ -75,19 +75,19 @@ static const struct { 32, "ECC-256", /* Prime */ - "115792089210356248762697446949407573530086143415290314195533631308867097853951", + "F////y000010000000000000000////////////////", /* B */ - "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", + "5h6DTYgEfFdi+kzLNQOXhnb7GQmp5EmzZlEF3udqc1B", /* Order */ - "115792089210356248762697446949407573529996955224135760342422259061068512044369", + "F////y00000//////////+yvlgjfnUUXFEvoiByOoLH", /* Gx */ - "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", + "6iNqVBXB497+BpcvMEaGF9t0ts1BUipeFIXEKNOcCAM", /* Gy */ - "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5" + "4/ZGkB+6d+RZkVhIdmFdXOhpZDNQp5UpiksG6Wtlr7r" }, #endif #ifdef ECC384 @@ -95,22 +95,23 @@ static const struct { 48, "ECC-384", /* prime */ - "394020061963944792122790401001436138050797392704654466679482934042457217714968" - "70329047266088258938001861606973112319", - + "//////////////////////////////////////////x/////00000000003/" + "////", + /* B */ - "b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed1" - "9d2a85c8edd3ec2aef", - + "ip4lf+8+v+IOZWLhu/Wj6HWTd6x+WK4I0nG8Zr0JXrh6LZcDYYxHdIg5oEtJ" + "x2hl", + /* Order */ - "394020061963944792122790401001436138050797392704654466679469052796276593991132" - "63569398956308152294913554433653942643", + "////////////////////////////////nsDDWVGtBTzO6WsoIB2dUkpi6MhC" + "nIbp", /* Gx and Gy */ - "aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf5529" - "6c3a545e3872760ab7", - "3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e81" - "9d7a431d7c90ea0e5f" + "geVA8hwB1JUEiSSUyo2jT6uTEsABfvkOMVT1u89KAZXL0l9TlrKfR3fKNZXo" + "TWgt", + + "DXVUIfOcB6zTdfY/afBSAVZq7RqecXHywTen4xNmkC0AOB7E7Nw1dNf37NoG" + "wWvV" }, #endif #ifdef ECC521 @@ -118,22 +119,23 @@ static const struct { 65, "ECC-521", /* prime */ - "686479766013060971498190079908139321726943530014330540939446345918554318339765" - "6052122559640661454554977296311391480858037121987999716643812574028291115057151", + "V///////////////////////////////////////////////////////////" + "///////////////////////////", /* B */ - "051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7" - "e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", + "56LFhbXZXoQ7vAQ8Q2sXK3kejfoMvcp5VEuj8cHZl49uLOPEL7iVfDx5bB0l" + "JknlmSrSz+8FImqyUz57zHhK3y0", /* Order */ - "686479766013060971498190079908139321726943530014330540939446345918554318339765" - "5394245057746333217197532963996371363321113864768612440380340372808892707005449", + "V//////////////////////////////////////////+b66XuE/BvPhVym1I" + "FS9fT0xjScuYPn7hhjljnwHE6G9", /* Gx and Gy */ - "c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe7" - "5928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", - "11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef" - "42640c550b9013fad0761353c7086a272c24088be94769fd16650", + "CQ5ZWQt10JfpPu+osOZbRH2d6I1EGK/jI7uAAzWQqqzkg5BNdVlvrae/Xt19" + "wB/gDupIBF1XMf2c/b+VZ72vRrc", + + "HWvAMfucZl015oANxGiVHlPcFL4ILURH6WNhxqN9pvcB9VkSfbUz2P0nL2v0" + "J+j1s4rF726edB2G8Y+b7QVqMPG", }, #endif { @@ -251,7 +253,7 @@ static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus) /* s = (3Xp^2 + a) / (2Yp) */ if (mp_mul_2(&P->y, &tmp) != MP_OKAY) { goto error; } /* tmp = 2*y */ if (mp_invmod(&tmp, modulus, &tmp) != MP_OKAY) { goto error; } /* tmp = 1/tmp mod modulus */ - if (mp_sqr(&P->x, &s) != MP_OKAY) { goto error; } /* s = x^2 */ + if (mp_sqr(&P->x, &s) != MP_OKAY) { goto error; } /* s = x^2 */ if (mp_mul_d(&s,(mp_digit)3, &s) != MP_OKAY) { goto error; } /* s = 3*(x^2) */ if (mp_sub_d(&s,(mp_digit)3, &s) != MP_OKAY) { goto error; } /* s = 3*(x^2) - 3 */ if (mp_mulmod(&s, &tmp, modulus, &s) != MP_OKAY) { goto error; } /* s = tmp * s mod modulus */ @@ -329,59 +331,103 @@ done: /* 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, int idx) { - ecc_point *tG; - int i, j, z, first, res; + ecc_point *tG, *M[14]; + int i, j, m, z, first, res; mp_digit d; unsigned char bits[768]; + /* init M tab */ + for (i = 0; i < 14; i++) { + M[i] = new_point(); + if (M[i] == NULL) { + for (j = 0; j < i; j++) { + del_point(M[j]); + } + return CRYPT_MEM; + } + } + /* get bits of k */ + first = m = 0; for (z = i = 0; z < (int)USED(k); z++) { d = DIGIT(k, z); - -#define DO1 bits[i++] = d&1; d >>= 1; -#define DO2 DO1 DO1 -#define DO4 DO2 DO2 - - DO4; DO4; DO4; DO4 - -#undef DO4 -#undef DO2 -#undef DO1 + for (j = 0; j < (int)MP_DIGIT_BIT; j++) { + first |= (d&1)<<(m++); + if (m == 4) { + bits[i++] = first; + first = m = 0; + } + d >>= 1; + } + } + + /* residue of multiplicand [if any] */ + if (m) { + bits[i++] = first; } /* make a copy of G incase R==G */ tG = new_point(); - if (tG == NULL) { - return CRYPT_MEM; - } + if (tG == NULL) { goto error; } + /* skip leading digits which are zero */ + --i; while (i && bits[i] == 0) { --i; } + + if (i == 0) { + res = CRYPT_INVALID_ARG; + goto done; + } + + /* now calc the M tab, note that there are only 14 spots, the normal M[0] is a no-op, and M[1] is the input + point (saves ram) + */ + + /* M[0] now is 2*G */ + if (dbl_point(G, M[0], modulus) != CRYPT_OK) { goto error; } + for (j = 1; j < 14; j++) { + if (add_point(M[j-1], G, M[j], modulus) != CRYPT_OK) { goto error; } + } + /* tG = G */ - if (mp_copy(&G->x, &tG->x) != MP_OKAY) { goto error; } - if (mp_copy(&G->y, &tG->y) != MP_OKAY) { goto error; } + if (mp_copy(&G->x, &tG->x) != MP_OKAY) { goto error; } + if (mp_copy(&G->y, &tG->y) != MP_OKAY) { goto error; } - /* set result to G, R = G */ - if (mp_copy(&G->x, &R->x) != MP_OKAY) { goto error; } - if (mp_copy(&G->y, &R->y) != MP_OKAY) { goto error; } - first = 0; - - /* now do dbl+add through all the bits */ - for (j = i-1; j >= 0; j--) { - if (first) { - if (dbl_point(R, R, modulus) != CRYPT_OK) { goto error; } + /* set result M[bits[i]] */ + if (bits[i] == 1) { + if (mp_copy(&G->x, &R->x) != MP_OKAY) { goto error; } + if (mp_copy(&G->y, &R->y) != MP_OKAY) { goto error; } + } else if (bits[i]>=2) { + if (mp_copy(&M[bits[i]-2]->x, &R->x) != MP_OKAY) { goto error; } + if (mp_copy(&M[bits[i]-2]->y, &R->y) != MP_OKAY) { goto error; } + } + + while (--i >= 0) { + /* double */ + for (j = 0; j < 4; j++) { + if (dbl_point(R, R, modulus) != CRYPT_OK) { goto error; } } - if (bits[j] == 1) { - if (first) { - if (add_point(R, tG, R, modulus) != CRYPT_OK) { goto error; } - } - first = 1; + + /* now based on the value of bits[i] we do ops */ + if (bits[i] == 0) { + /* nop */ + } else if (bits[i] == 1) { + /* add base point */ + if (add_point(R, tG, R, modulus) != CRYPT_OK) { goto error; } + } else { + /* other case */ + if (add_point(R, M[bits[i]-2], R, modulus) != CRYPT_OK) { goto error; } } } + res = CRYPT_OK; goto done; error: res = CRYPT_MEM; done: del_point(tG); + for (i = 0; i < 14; i++) { + del_point(M[i]); + } #ifdef CLEAN_STACK zeromem(bits, sizeof(bits)); #endif @@ -412,8 +458,11 @@ int ecc_test(void) } for (i = 0; sets[i].size; i++) { - if (mp_read_radix(&modulus, (unsigned char *)sets[i].prime, 10) != MP_OKAY) { goto error; } - if (mp_read_radix(&order, (unsigned char *)sets[i].order, 10) != MP_OKAY) { goto error; } + #if 0 + printf("Testing %d\n", sets[i].size); + #endif + if (mp_read_radix(&modulus, (unsigned char *)sets[i].prime, 64) != MP_OKAY) { goto error; } + if (mp_read_radix(&order, (unsigned char *)sets[i].order, 64) != MP_OKAY) { goto error; } /* is prime actually prime? */ if (is_prime(&modulus, &primality) != CRYPT_OK) { goto error; } @@ -429,8 +478,8 @@ int ecc_test(void) goto done1; } - if (mp_read_radix(&G->x, (unsigned char *)sets[i].Gx, 16) != MP_OKAY) { goto error; } - if (mp_read_radix(&G->y, (unsigned char *)sets[i].Gy, 16) != MP_OKAY) { goto error; } + if (mp_read_radix(&G->x, (unsigned char *)sets[i].Gx, 64) != MP_OKAY) { goto error; } + if (mp_read_radix(&G->y, (unsigned char *)sets[i].Gy, 64) != MP_OKAY) { goto error; } /* then we should have G == (order + 1)G */ if (mp_add_d(&order, 1, &order) != MP_OKAY) { goto error; } @@ -509,14 +558,19 @@ int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key) } /* read in the specs for this key */ - if (mp_read_radix(&prime, (unsigned char *)sets[x].prime, 10) != MP_OKAY) { goto error; } - if (mp_read_radix(&base->x, (unsigned char *)sets[x].Gx, 16) != MP_OKAY) { goto error; } - if (mp_read_radix(&base->y, (unsigned char *)sets[x].Gy, 16) != MP_OKAY) { goto error; } + if (mp_read_radix(&prime, (unsigned char *)sets[key->idx].prime, 64) != MP_OKAY) { goto error; } + if (mp_read_radix(&base->x, (unsigned char *)sets[key->idx].Gx, 64) != MP_OKAY) { goto error; } + if (mp_read_radix(&base->y, (unsigned char *)sets[key->idx].Gy, 64) != MP_OKAY) { goto error; } if (mp_read_raw(&key->k, (unsigned char *)buf, keysize+1) != MP_OKAY) { goto error; } /* make the public key */ if (ecc_mulmod(&key->k, base, &key->pubkey, &prime, x) != CRYPT_OK) { goto error; } key->type = PK_PRIVATE; + + /* shrink key */ + if (mp_shrink(&key->k) != MP_OKAY) { goto error; } + if (mp_shrink(&key->pubkey.x) != MP_OKAY) { goto error; } + if (mp_shrink(&key->pubkey.y) != MP_OKAY) { goto error; } /* free up ram */ res = CRYPT_OK; @@ -551,12 +605,12 @@ static int compress_y_point(ecc_point *pt, int idx, int *result) } /* get x^3 - 3x + b */ - if (mp_read_radix(&p, (unsigned char *)sets[idx].B, 16) != MP_OKAY) { goto error; } /* p = B */ + if (mp_read_radix(&p, (unsigned char *)sets[idx].B, 64) != MP_OKAY) { goto error; } /* p = B */ if (mp_expt_d(&pt->x, 3, &tmp) != MP_OKAY) { goto error; } /* tmp = pX^3 */ if (mp_mul_d(&pt->x, 3, &tmp2) != MP_OKAY) { goto error; } /* tmp2 = 3*pX^3 */ if (mp_sub(&tmp, &tmp2, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp - tmp2 */ if (mp_add(&tmp, &p, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp + p */ - if (mp_read_radix(&p, (unsigned char *)sets[idx].prime, 10) != MP_OKAY) { goto error; } /* p = prime */ + if (mp_read_radix(&p, (unsigned char *)sets[idx].prime, 64) != MP_OKAY) { goto error; } /* p = prime */ if (mp_mod(&tmp, &p, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp mod p */ /* now find square root */ @@ -593,12 +647,12 @@ static int expand_y_point(ecc_point *pt, int idx, int result) } /* get x^3 - 3x + b */ - if (mp_read_radix(&p, (unsigned char *)sets[idx].B, 16) != MP_OKAY) { goto error; } /* p = B */ + if (mp_read_radix(&p, (unsigned char *)sets[idx].B, 64) != MP_OKAY) { goto error; } /* p = B */ if (mp_expt_d(&pt->x, 3, &tmp) != MP_OKAY) { goto error; } /* tmp = pX^3 */ if (mp_mul_d(&pt->x, 3, &tmp2) != MP_OKAY) { goto error; } /* tmp2 = 3*pX^3 */ if (mp_sub(&tmp, &tmp2, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp - tmp2 */ if (mp_add(&tmp, &p, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp + p */ - if (mp_read_radix(&p, (unsigned char *)sets[idx].prime, 10) != MP_OKAY) { goto error; } /* p = prime */ + if (mp_read_radix(&p, (unsigned char *)sets[idx].prime, 64) != MP_OKAY) { goto error; } /* p = prime */ if (mp_mod(&tmp, &p, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp mod p */ /* now find square root */ @@ -625,10 +679,10 @@ done: #define OUTPUT_BIGNUM(num, buf2, y, z) \ { \ - z = mp_raw_size(num); \ + z = mp_unsigned_bin_size(num); \ STORE32L(z, buf2+y); \ y += 4; \ - mp_toraw(num, buf2+y); \ + mp_to_unsigned_bin(num, buf2+y); \ y += z; \ } @@ -650,11 +704,15 @@ done: } \ \ /* load it */ \ - if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\ + if (mp_read_unsigned_bin(num, (unsigned char *)in+y, x) != MP_OKAY) {\ errno = CRYPT_MEM; \ goto error; \ } \ y += x; \ + if (mp_shrink(num) != MP_OKAY) { \ + errno = CRYPT_MEM; \ + goto error; \ + } \ } int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key) @@ -696,7 +754,7 @@ int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key } /* store header */ - packet_store_header(buf2, PACKET_SECT_ECC, PACKET_SUB_KEY, y); + packet_store_header(buf2, PACKET_SECT_ECC, PACKET_SUB_KEY); memcpy(out, buf2, y); *outlen = y; @@ -765,10 +823,15 @@ int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key) /* load private key */ INPUT_BIGNUM(&key->k, in, x, y); } + + /* eliminate private key if public */ + if (key->type == PK_PUBLIC) { + mp_clear(&key->k); + } + return CRYPT_OK; error: mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL); -done: return errno; } @@ -805,7 +868,7 @@ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, return CRYPT_MEM; } - if (mp_read_radix(&prime, (unsigned char *)sets[private_key->idx].prime, 10) != MP_OKAY) { goto error; } + if (mp_read_radix(&prime, (unsigned char *)sets[private_key->idx].prime, 64) != MP_OKAY) { goto error; } if ((errno = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime, private_key->idx)) != CRYPT_OK) { res = errno; goto done1; } x = mp_raw_size(&result->x); diff --git a/ecc_sys.c b/ecc_sys.c index adcecdc..e72142d 100644 --- a/ecc_sys.c +++ b/ecc_sys.c @@ -84,7 +84,7 @@ int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen, } /* store header */ - packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY, y); + packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY); #ifdef CLEAN_STACK /* clean up */ @@ -96,8 +96,9 @@ int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen, return CRYPT_OK; } -int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey, - unsigned long *keylen, ecc_key *key) +int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *outkey, unsigned long *keylen, + ecc_key *key) { unsigned char shared_secret[256], skey[MAXBLOCKSIZE]; unsigned long x, y, z, res, hashsize, keysize; @@ -113,6 +114,13 @@ int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey, if (key->type != PK_PRIVATE) { 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 ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY)) != CRYPT_OK) { @@ -131,6 +139,11 @@ int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey, /* get public key */ LOAD32L(x, in+y); + if (inlen < x) { + return CRYPT_INVALID_PACKET; + } else { + inlen -= x; + } y += 4; if ((errno = ecc_import(in+y, x, &pubkey)) != CRYPT_OK) { return errno; @@ -151,6 +164,11 @@ int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey, } LOAD32L(keysize, in+y); + if (inlen < keysize) { + return CRYPT_INVALID_PACKET; + } else { + inlen -= keysize; + } y += 4; if (*keylen < keysize) { @@ -223,7 +241,7 @@ int ecc_sign_hash(const unsigned char *in, unsigned long inlen, ecc_free(&pubkey); return CRYPT_MEM; } - if (mp_read_radix(&p, (unsigned char *)sets[key->idx].order, 10) != MP_OKAY) { goto error; } + if (mp_read_radix(&p, (unsigned char *)sets[key->idx].order, 64) != MP_OKAY) { goto error; } if (mp_read_raw(&b, md, 1+MIN(sizeof(md)-1,inlen)) != MP_OKAY) { goto error; } /* find b = (m - x)/k */ @@ -266,7 +284,7 @@ int ecc_sign_hash(const unsigned char *in, unsigned long inlen, } /* store header */ - packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_SIGNED, y); + packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_SIGNED); /* clear memory */ *outlen = y; @@ -286,9 +304,9 @@ done1: } /* verify that mG = (bA + Y) */ -int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash, - unsigned long inlen, int *stat, - ecc_key *key) +int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long inlen, + int *stat, ecc_key *key) { ecc_point *mG; ecc_key pubkey; @@ -305,6 +323,12 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash, /* default to invalid signature */ *stat = 0; + if (siglen < PACKET_SIZE+4+4) { + return CRYPT_INVALID_PACKET; + } else { + siglen -= PACKET_SIZE+4+4; + } + /* is the message format correct? */ if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_ECC, PACKET_SUB_SIGNED)) != CRYPT_OK) { return errno; @@ -315,6 +339,11 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash, /* 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 */ @@ -325,6 +354,11 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash, /* load size of 'b' */ LOAD32L(x, sig+y); + if (siglen < x) { + return CRYPT_INVALID_PACKET; + } else { + siglen -= x; + } y += 4; /* init values */ @@ -350,7 +384,7 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash, if (mp_read_raw(&m, md, 1+MIN(sizeof(md)-1,inlen)) != MP_OKAY) { goto error; } /* load prime */ - if (mp_read_radix(&p, (unsigned char *)sets[key->idx].prime, 10) != MP_OKAY) { goto error; } + if (mp_read_radix(&p, (unsigned char *)sets[key->idx].prime, 64) != MP_OKAY) { goto error; } /* get bA */ if (ecc_mulmod(&b, &pubkey.pubkey, &pubkey.pubkey, &p, key->idx) != CRYPT_OK) { goto error; } @@ -359,8 +393,8 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash, if (add_point(&pubkey.pubkey, &key->pubkey, &pubkey.pubkey, &p) != CRYPT_OK) { goto error; } /* get mG */ - if (mp_read_radix(&mG->x, (unsigned char *)sets[key->idx].Gx, 16) != MP_OKAY) { goto error; } - if (mp_read_radix(&mG->y, (unsigned char *)sets[key->idx].Gy, 16) != MP_OKAY) { goto error; } + if (mp_read_radix(&mG->x, (unsigned char *)sets[key->idx].Gx, 64) != MP_OKAY) { goto error; } + if (mp_read_radix(&mG->y, (unsigned char *)sets[key->idx].Gy, 64) != MP_OKAY) { goto error; } if (ecc_mulmod(&m, mG, mG, &p, key->idx) != CRYPT_OK) { goto error; } /* compare mG to bA + Y */ diff --git a/examples/ch1-01.c b/examples/ch1-01.c new file mode 100644 index 0000000..010ccd7 --- /dev/null +++ b/examples/ch1-01.c @@ -0,0 +1,18 @@ +/* + * Name : ch1-01.c + * Purpose : Demonstration of a basic libtomcrypt program + * Author : Tom St Denis + * + * History : v0.79 Initial release + */ + +/* ch1-01-1 */ +/* Include the default headers and libtomcrypt headers */ +#include + +int main(void) +{ + return 0; +} +/* ch1-01-1 */ + diff --git a/examples/ch1-02.c b/examples/ch1-02.c new file mode 100644 index 0000000..9d41f21 --- /dev/null +++ b/examples/ch1-02.c @@ -0,0 +1,25 @@ +/* + * Name : ch1-02.c + * Purpose : Demonstration of error handling + * Author : Tom St Denis + * + * History : v0.79 Initial release + */ + +/* ch1-01-1 */ +#include + +int main(void) +{ + int errno; + + if ((errno = some_func(...)) != CRYPT_OK) { + printf("Error: %s\n", error_to_string(errno)); + return EXIT_FAILURE; + } + + return 0; +} +/*ch1-01-1 */ + + diff --git a/examples/ch1-03.c b/examples/ch1-03.c new file mode 100644 index 0000000..c749aa1 --- /dev/null +++ b/examples/ch1-03.c @@ -0,0 +1,29 @@ +/* + * Name : ch1-03.c + * Purpose : Demonstration of variable length outputs + * Author : Tom St Denis + * + * History : v0.79 Initial release + */ + + /* ch1-01-1 */ + #include + + int main(void) + { + unsigned long length; + unsigned char buffer[512]; + int errno; + + length = sizeof(buffer); + if ((errno = some_func(..., buffer, &length)) != CRYPT_OK) { + printf("Error: %s\n", error_to_string(errno)); + return EXIT_FAILURE; + } + printf("Size of output is %lu bytes\n", length); + return 0; +} +/* ch1-01-1 */ + + + \ No newline at end of file diff --git a/keyring.c b/keyring.c index d50c27f..e8e6080 100644 --- a/keyring.c +++ b/keyring.c @@ -70,6 +70,7 @@ static const unsigned long crc_table[256] = { static unsigned long crc32 (unsigned long crc, const unsigned char *buf, unsigned long len) { + //_ARGCHK(buf != NULL && len == 0); crc = crc ^ 0xffffffffL; while (len >= 8) { DO8 (buf); @@ -587,25 +588,26 @@ int kr_encrypt_key(pk_key *pk, unsigned long ID, STORE32L(kr->ID,buf+4); /* now encrypt it */ - len = sizeof(buf)-8; + len = sizeof(buf)-12; switch (kr->system) { case RSA_KEY: - if ((errno = rsa_encrypt_key(in, inlen, buf+8, &len, prng, wprng, &(kr->key.rsa))) != CRYPT_OK) { + if ((errno = rsa_encrypt_key(in, inlen, buf+12, &len, prng, wprng, &(kr->key.rsa))) != CRYPT_OK) { return errno; } break; case DH_KEY: - if ((errno = dh_encrypt_key(in, inlen, buf+8, &len, prng, wprng, hash, &(kr->key.dh))) != CRYPT_OK) { + if ((errno = dh_encrypt_key(in, inlen, buf+12, &len, prng, wprng, hash, &(kr->key.dh))) != CRYPT_OK) { return errno; } break; case ECC_KEY: - if ((errno = ecc_encrypt_key(in, inlen, buf+8, &len, prng, wprng, hash, &(kr->key.ecc))) != CRYPT_OK) { + if ((errno = ecc_encrypt_key(in, inlen, buf+12, &len, prng, wprng, hash, &(kr->key.ecc))) != CRYPT_OK) { return errno; } break; } - len += 8; + STORE32L(len,buf+8); + len += 12; if (len > *outlen) { #ifdef CLEAN_STACK @@ -626,7 +628,7 @@ int kr_decrypt_key(pk_key *pk, const unsigned char *in, unsigned char *out, unsigned long *outlen) { unsigned char buf[8192]; - unsigned long len, ID; + unsigned long pklen, len, ID; pk_key *kr; int errno; @@ -653,20 +655,21 @@ int kr_decrypt_key(pk_key *pk, const unsigned char *in, } /* now try and decrypt it */ + LOAD32L(pklen,in+8); len = sizeof(buf); switch (kr->system) { case RSA_KEY: - if ((errno = rsa_decrypt_key(in+8, buf, &len, &(kr->key.rsa))) != CRYPT_OK) { + if ((errno = rsa_decrypt_key(in+12, pklen, buf, &len, &(kr->key.rsa))) != CRYPT_OK) { return errno; } break; case DH_KEY: - if ((errno = dh_decrypt_key(in+8, buf, &len, &(kr->key.dh))) != CRYPT_OK) { + if ((errno = dh_decrypt_key(in+12, pklen, buf, &len, &(kr->key.dh))) != CRYPT_OK) { return errno; } break; case ECC_KEY: - if ((errno = ecc_decrypt_key(in+8, buf, &len, &(kr->key.ecc))) != CRYPT_OK) { + if ((errno = ecc_decrypt_key(in+12, pklen, buf, &len, &(kr->key.ecc))) != CRYPT_OK) { return errno; } break; @@ -720,26 +723,27 @@ int kr_sign_hash(pk_key *pk, unsigned long ID, STORE32L(kr->ID,buf+4); /* now sign it */ - len = sizeof(buf)-12; + len = sizeof(buf)-16; switch (kr->system) { case RSA_KEY: - if ((errno = rsa_sign_hash(in, inlen, buf+12, &len, &(kr->key.rsa))) != CRYPT_OK) { + if ((errno = rsa_sign_hash(in, inlen, buf+16, &len, &(kr->key.rsa))) != CRYPT_OK) { return errno; } break; case DH_KEY: - if ((errno = dh_sign_hash(in, inlen, buf+12, &len, prng, wprng, &(kr->key.dh))) != CRYPT_OK) { + if ((errno = dh_sign_hash(in, inlen, buf+16, &len, prng, wprng, &(kr->key.dh))) != CRYPT_OK) { return errno; } break; case ECC_KEY: - if ((errno = ecc_sign_hash(in, inlen, buf+12, &len, prng, wprng, &(kr->key.ecc))) != CRYPT_OK) { + if ((errno = ecc_sign_hash(in, inlen, buf+16, &len, prng, wprng, &(kr->key.ecc))) != CRYPT_OK) { return errno; } break; } STORE32L(inlen,buf+8); - len += 12; + STORE32L(len,buf+12); + len += 16; if (len > *outlen) { #ifdef CLEAN_STACK @@ -759,7 +763,7 @@ int kr_sign_hash(pk_key *pk, unsigned long ID, int kr_verify_hash(pk_key *pk, const unsigned char *in, const unsigned char *hash, unsigned long hashlen, int *stat) { - unsigned long inlen, ID; + unsigned long inlen, pklen, ID; pk_key *kr; int errno; @@ -785,23 +789,24 @@ int kr_verify_hash(pk_key *pk, const unsigned char *in, const unsigned char *has /* now try and verify it */ LOAD32L(inlen,in+8); /* this is the length of the original inlen */ + LOAD32L(pklen,in+12); /* size of the PK packet */ if (inlen != hashlen) { /* size doesn't match means the signature is invalid */ return CRYPT_OK; } switch (kr->system) { case RSA_KEY: - if ((errno = rsa_verify_hash(in+12, hash, stat, &(kr->key.rsa))) != CRYPT_OK) { + if ((errno = rsa_verify_hash(in+16, pklen, hash, stat, &(kr->key.rsa))) != CRYPT_OK) { return errno; } break; case DH_KEY: - if ((errno = dh_verify_hash(in+12, hash, inlen, stat, &(kr->key.dh))) != CRYPT_OK) { + if ((errno = dh_verify_hash(in+16, pklen, hash, inlen, stat, &(kr->key.dh))) != CRYPT_OK) { return errno; } break; case ECC_KEY: - if ((errno = ecc_verify_hash(in+12, hash, inlen, stat, &(kr->key.ecc))) != CRYPT_OK) { + if ((errno = ecc_verify_hash(in+16, pklen, hash, inlen, stat, &(kr->key.ecc))) != CRYPT_OK) { return errno; } break; diff --git a/makefile b/makefile index ec3a503..0191ef8 100644 --- a/makefile +++ b/makefile @@ -9,62 +9,77 @@ # a build. This is easy to remedy though, for those that have problems. # The version -VERSION=0.78 +VERSION=0.79 -#Compiler and Linker Names +#ch1-01-1 +# Compiler and Linker Names CC=gcc LD=ld -#Archiver [makes .a files] +# Archiver [makes .a files] AR=ar -ARFLAGS=rs +ARFLAGS=r +#ch1-01-1 -#here you can set the malloc/calloc/free functions you want +#ch1-01-2 +# here you can set the malloc/calloc/free functions you want XMALLOC=malloc XCALLOC=calloc +XREALLOC=realloc XFREE=free -#you can redefine the clock +# you can redefine the clock XCLOCK=clock XCLOCKS_PER_SEC=CLOCKS_PER_SEC +#ch1-01-2 -#Compilation flags. Note the += does not write over the user's CFLAGS! +#ch1-01-3 +# Compilation flags. Note the += does not write over the user's CFLAGS! CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wno-unused -Werror \ - -DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) -DXCLOCK=$(XCLOCK) \ + -DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) \ + -DXREALLOC=$(XREALLOC) -DXCLOCK=$(XCLOCK) \ -DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC) -#optimize for SPEED (comment out SIZE/DEBUG line as well) +# optimize for SPEED #CFLAGS += -O3 -funroll-loops -#optimize for SIZE (comment out SPEED/DEBUG line as well) +# optimize for SIZE CFLAGS += -Os -#Use small code variants of functions when possible? (Slows it down!) -CFLAGS += -DSMALL_CODE - -#compile for DEBUGGING +# compile for DEBUGGING #CFLAGS += -g3 +#ch1-01-3 #These flags control how the library gets built. -#no file support, when defined the library will not have any functions that can read/write files -#(comment out to have file support) +#ch1-01-4 +# Use small code variants of functions when possible? +CFLAGS += -DSMALL_CODE + +# no file support, when defined the library will not +# have any functions that can read/write files +# (comment out to have file support) #CFLAGS += -DNO_FILE -#Support the UNIX /dev/random or /dev/urandom +# Support the UNIX /dev/random or /dev/urandom CFLAGS += -DDEVRANDOM -# Use /dev/urandom first on devices where /dev/random is too slow */ +# Use /dev/urandom first on devices where +# /dev/random is too slow #CFLAGS += -DTRY_URANDOM_FIRST -# Clean the stack after sensitive functions. Not always required... -# With this defined most of the ciphers and hashes will clean their stack area -# after usage with a (sometimes) huge penalty in speed. Normally this is not -# required if you simply lock your stack and wipe it when your program is done. +# Clean the stack after sensitive functions. Not +# always required... With this defined most of +# the ciphers and hashes will clean their stack area +# after usage with a (sometimes) huge penalty in speed. +# Normally this is not required if you simply lock your +# stack and wipe it when your program is done. # #CFLAGS += -DCLEAN_STACK +#ch1-01-4 -# What algorithms to include? comment out and rebuild to remove em +#ch1-01-5 +# What algorithms to include? comment out and rebuild to remove them CFLAGS += -DBLOWFISH CFLAGS += -DRC2 CFLAGS += -DRC5 @@ -78,6 +93,7 @@ CFLAGS += -DTWOFISH CFLAGS += -DDES CFLAGS += -DCAST5 CFLAGS += -DNOEKEON +#ch1-01-5 #You can also customize the Twofish code. All four combinations #of the flags are possible but only three of them make sense. @@ -90,17 +106,23 @@ CFLAGS += -DNOEKEON #_TABLES defined: Very fast, not faster than if both were undefined. Code is ~1KB bigger # faster keysetup though... -# Small Ram Variant of Twofish. For this you must have TWOFISH defined. This -# variant requires about 4kb less memory but is considerably slower. It is ideal -# when high throughput is less important than conserving memory. By default it is -# not defined which means the larger ram (about 4.2Kb used) variant is built. +#ch1-01-6 +# Small Ram Variant of Twofish. For this you must have TWOFISH +# defined. This variant requires about 4kb less memory but +# is considerably slower. It is ideal when high throughput is +# less important than conserving memory. By default it is not +# defined which means the larger ram (about 4.2Kb used) variant +# is built. #CFLAGS += -DTWOFISH_SMALL -# Tell Twofish to use precomputed tables. If you want to use the small table -# variant of Twofish you may want to turn this on. Essentially it tells Twofish to use -# precomputed S-boxes (Q0 and Q1) as well as precomputed GF multiplications [in the MDS]. -# This speeds up the cipher somewhat. +# Tell Twofish to use precomputed tables. If you want to use +# the small table variant of Twofish you may want to turn +# this on. Essentially it tells Twofish to use precomputed +# S-boxes (Q0 and Q1) as well as precomputed GF +# multiplications [in the MDS]. This speeds up the cipher +# somewhat. #CFLAGS += -DTWOFISH_TABLES +#ch1-01-6 #Use fast PK routines. Basically this limits the size of the private key in the #DH system to 256 bits. The group order remains unchanged so the best @@ -110,13 +132,16 @@ CFLAGS += -DNOEKEON #security so its by default not turned on. USE AT YOUR RISK! #CFLAGS += -DFAST_PK +#ch1-01-7 # Chaining modes CFLAGS += -DCFB CFLAGS += -DOFB CFLAGS += -DECB CFLAGS += -DCBC CFLAGS += -DCTR +#ch1-01-7 +#ch1-01-8 #One-way hashes CFLAGS += -DSHA512 CFLAGS += -DSHA384 @@ -126,29 +151,73 @@ CFLAGS += -DSHA1 CFLAGS += -DMD5 CFLAGS += -DMD4 CFLAGS += -DMD2 +#ch1-01-8 -# base64 -CFLAGS += -DBASE64 - +#ch1-01-9 # prngs CFLAGS += -DYARROW CFLAGS += -DSPRNG CFLAGS += -DRC4 +#ch1-01-9 +#ch1-01-10 # PK code CFLAGS += -DMRSA CFLAGS += -DMDH CFLAGS += -DMECC +#CFLAGS += -DMDSA CFLAGS += -DKR +#ch1-01-10 -# include GF math routines? (not currently used by anything internally) +#ch1-01-12 +# Control which built in DH or ECC key paramaters +# are to be allowed +CFLAGS += -DDH768 +CFLAGS += -DDH1024 +CFLAGS += -DDH1280 +CFLAGS += -DDH1536 +CFLAGS += -DDH1792 +CFLAGS += -DDH2048 +CFLAGS += -DDH2560 +CFLAGS += -DDH3072 +CFLAGS += -DDH4096 + +CFLAGS += -DECC160 +CFLAGS += -DECC192 +CFLAGS += -DECC224 +CFLAGS += -DECC256 +CFLAGS += -DECC384 +CFLAGS += -DECC521 + +CFLAGS += -DDSA1024 +CFLAGS += -DDSA2048 +CFLAGS += -DDSA4096 +#ch1-01-12 + +#ch1-01-11 +# base64 +CFLAGS += -DBASE64 + +# include GF math routines? +# (not currently used by anything internally) #CFLAGS += -DGF # include large integer math routines? (required by the PK code) CFLAGS += -DMPI +# use the fast exptmod operation (used in dsa/rsa/dh and is_prime) +# This uses slightly more heap than the old code [only during the function call] +# this is also fairly faster than the previous code +CFLAGS += -DMPI_FASTEXPT + +# use a "low" mem variant of the fast exptmod. It is still always +# faster then the old exptmod but its savings drops off after +# 1024 to 2048-bits +#CFLAGS += -DMPI_FASTEXPT_LOWMEM + # include HMAC support CFLAGS += -DHMAC +#ch1-01-11 #Output filenames for various targets. LIBNAME=libtomcrypt.a @@ -163,7 +232,7 @@ LIBPATH=/usr/lib INCPATH=/usr/include #List of objects to compile. -OBJECTS=keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o \ +OBJECTS=keyring.o gf.o mem.o sprng.o dsa.o ecc.o base64.o dh.o rsa.o \ bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o \ md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o \ safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o \ @@ -199,6 +268,7 @@ sha512.o: sha512.c sha384.c #This rule makes the libtomcrypt library. library: $(OBJECTS) $(AR) $(ARFLAGS) $(LIBNAME) $(OBJECTS) + ranlib $(LIBNAME) #This rule makes the test program included with libtomcrypt test: library $(TESTOBJECTS) @@ -219,9 +289,11 @@ small: library $(SMALLOBJECTS) #This rule installs the library and the header files. This must be run #as root in order to have a high enough permission to write to the correct #directories and to set the owner and group to root. -install: library +install: library docs install -g root -o root $(LIBNAME) $(LIBPATH) install -g root -o root $(HEADERS) $(INCPATH) + mkdir -p /usr/doc/libtomcrypt/pdf + cp crypt.pdf /usr/doc/libtomcrypt/pdf/ #This rule cleans the source tree of all compiled code, not including the pdf #documentation. @@ -241,7 +313,7 @@ docs: crypt.tex makeindex crypt > /dev/null pdflatex crypt > /dev/null rm -f $(LEFTOVERS) - + #zipup the project (take that!) zipup: clean docs chdir .. ; rm -rf crypt* libtomcrypt-$(VERSION) ; mkdir libtomcrypt-$(VERSION) ; \ diff --git a/makefile.out b/makefile.out new file mode 100644 index 0000000..1c66b3b --- /dev/null +++ b/makefile.out @@ -0,0 +1,23 @@ +#makefile generated with config.pl +# +#Tom St Denis (tomstdenis@yahoo.com, http://tom.iahu.ca) + +CC = gcc +AR = ar +LD = ld +CFLAGS += -Os -Wall -Wsign-compare -W -Wno-unused -Werror -I./ -DXMALLOC=malloc -DXCALLOC=calloc -DXFREE=free -DXCLOCK=clock -DXCLOCKS_PER_SEC=CLOCKS_PER_SEC -DSMALL_CODE -DBLOWFISH -DRC2 -DRC5 -DRC6 -DSERPENT -DSAFERP -DSAFER -DRIJNDAEL -DXTEA -DTWOFISH -DDES -DCAST5 -DNOEKEON -DCFB -DOFB -DECB -DCBC -DCTR -DSHA512 -DSHA384 -DSHA256 -DTIGER -DSHA1 -DMD5 -DMD4 -DMD2 -DHMAC -DBASE64 -DYARROW -DSPRNG -DRC4 -DDEVRANDOM -DMRSA -DMDH -DMECC -DMDSA -DKR -DDH768 -DDH1024 -DDH1280 -DDH1536 -DDH1792 -DDH2048 -DDH2560 -DDH3072 -DDH4096 -DECC160 -DECC192 -DECC224 -DECC256 -DECC384 -DECC521 -DDSA1024 -DDSA2048 -DDSA4096 -DMPI -DMPI_FASTEXPT + +default: library + +OBJECTS = keyring.o gf.o mem.o sprng.o dsa.o ecc.o base64.o dh.o rsa.o bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o ampi.o mpi.o prime.o twofish.o packet.o hmac.o strings.o + +rsa.o: rsa_sys.c +dh.o: dh_sys.c +ecc.o: ecc_sys.c + +library: $(OBJECTS) + $(AR) rs libtomcrypt.a $(OBJECTS) + +clean: + rm -f $(OBJECTS) libtomcrypt.a + diff --git a/makefile.ps2 b/makefile.ps2 index f09da3e..be78b6e 100644 --- a/makefile.ps2 +++ b/makefile.ps2 @@ -32,6 +32,7 @@ ARFLAGS=rs #here you can set the malloc/calloc/free functions you want XMALLOC=malloc XCALLOC=calloc +XREALLOC=realloc XFREE=free #you can redefine the clock @@ -40,7 +41,8 @@ XCLOCKS_PER_SEC=576000 #Compilation flags. Note the += does not write over the user's CFLAGS! CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wno-unused -Werror \ - -DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) -DXCLOCK=$(XCLOCK) \ + -DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) \ + -DXREALLOC=$(XREALLOC) -DXCLOCK=$(XCLOCK) \ -DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC) #optimize for SPEED (comment out SIZE line as well) @@ -103,14 +105,6 @@ CFLAGS += -DNOEKEON # This speeds up the cipher somewhat. # CFLAGS += -DTWOFISH_TABLES -#Small code variant of the SAFER+ cipher, uses same RAM but less code space -#With this defined the cipher is slower. On my x86 with GCC 3.2 it required 50KB less space -CFLAGS += -DSAFERP_SMALL - -#Small Rijndael [saves 13KB on an x86] -#With this defined the cipher is slower (by 50Mbit/sec on an Athon XP) -CFLAGS += -DRIJNDAEL_SMALL - #Use fast PK routines. Basically this limits the size of the private key in the #DH system to 256 bits. The group order remains unchanged so the best #attacks are still GNFS (for DH upto 2560-bits) @@ -148,14 +142,48 @@ CFLAGS += -DRC4 CFLAGS += -DMRSA CFLAGS += -DMDH CFLAGS += -DMECC +#CFLAGS += -DDSA CFLAGS += -DKR +# Control which built in DH or ECC key paramaters +# are to be allowed +CFLAGS += -DDH768 +CFLAGS += -DDH1024 +CFLAGS += -DDH1280 +CFLAGS += -DDH1536 +CFLAGS += -DDH1792 +CFLAGS += -DDH2048 +CFLAGS += -DDH2560 +CFLAGS += -DDH3072 +CFLAGS += -DDH4096 + +CFLAGS += -DECC160 +CFLAGS += -DECC192 +CFLAGS += -DECC224 +CFLAGS += -DECC256 +CFLAGS += -DECC384 +CFLAGS += -DECC521 + +CFLAGS += -DDSA1024 +CFLAGS += -DDSA2048 +CFLAGS += -DDSA4096 + # include GF math routines? (not currently used by anything internally) #CFLAGS += -DGF # include large integer math routines? (required by the PK code) CFLAGS += -DMPI +# use the fast exptmod operation (used in dsa/rsa/dh and is_prime) +# This uses slightly more heap than the old code [only during the function call] +# this is also fairly faster than the previous code +CFLAGS += -DMPI_FASTEXPT + +# use a "low" mem variant of the fast exptmod. It is still always +# faster then the old exptmod but its savings drops off after +# 1024-bits +CFLAGS += -DMPI_FASTEXPT_LOWMEM + # include HMAC support CFLAGS += -DHMAC @@ -175,7 +203,7 @@ LIBPATH=/usr/lib INCPATH=/usr/include #List of objects to compile. -OBJECTS=keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o \ +OBJECTS=keyring.o gf.o mem.o sprng.o dsa.o ecc.o base64.o dh.o rsa.o \ bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o \ md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o \ safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o \ diff --git a/makefile.vc b/makefile.vc index e8deeb5..d3536ee 100644 --- a/makefile.vc +++ b/makefile.vc @@ -8,13 +8,14 @@ AR=lib #here you can set the malloc/calloc/free functions you want XMALLOC=malloc XCALLOC=calloc +XREALLOC=realloc XFREE=free #you can redefine the clock XCLOCK=clock XCLOCKS_PER_SEC=CLOCKS_PER_SEC -CFLAGS = /c /Ogisy1 /Gs /I. /W3 /DWIN32 /DXMALLOC=$(XMALLOC) /DXCALLOC=$(XCALLOC) /DXFREE=$(XFREE) /DXCLOCK=$(XCLOCK) /DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC) +CFLAGS = /c /Ogisy1 /Gs /I. /W3 /DWIN32 /DXREALLOC=$(XREALLOC) /DXMALLOC=$(XMALLOC) /DXCALLOC=$(XCALLOC) /DXFREE=$(XFREE) /DXCLOCK=$(XCLOCK) /DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC) #Small code (smaller variants of some block ciphers) CFLAGS += /DSMALL_CODE @@ -113,14 +114,49 @@ CFLAGS += /DRC4 CFLAGS += /DMRSA CFLAGS += /DMDH CFLAGS += /DMECC +#CFLAGS += /DDSA CFLAGS += /DKR +# Control which built in DH or ECC key paramaters +# are to be allowed +CFLAGS += /DDH768 +CFLAGS += /DDH1024 +CFLAGS += /DDH1280 +CFLAGS += /DDH1536 +CFLAGS += /DDH1792 +CFLAGS += /DDH2048 +CFLAGS += /DDH2560 +CFLAGS += /DDH3072 +CFLAGS += /DDH4096 + +CFLAGS += /DECC160 +CFLAGS += /DECC192 +CFLAGS += /DECC224 +CFLAGS += /DECC256 +CFLAGS += /DECC384 +CFLAGS += /DECC521 + +CFLAGS += /DDSA1024 +CFLAGS += /DDSA2048 +CFLAGS += /DDSA4096 + # include GF math routines? (not currently used by anything internally) #CFLAGS += /DGF # include large integer math routines? (required by the PK code) CFLAGS += /DMPI +# use the fast exptmod operation (used in dsa/rsa/dh and is_prime) +# This uses slightly more heap than the old code [only during the function call] +# this is also fairly faster than the previous code +CFLAGS += /DMPI_FASTEXPT + +# use a "low" mem variant of the fast exptmod. It is still always +# faster then the old exptmod but its savings drops off after +# 1024-bits +#CFLAGS += /DMPI_FASTEXPT_LOWMEM + + # include HMAC support CFLAGS += /DHMAC @@ -216,6 +252,8 @@ cast5.obj: cast5.c $(CC) $(CFLAGS) cast5.c noekeon.obj: noekeon.c $(CC) $(CFLAGS) noekeon.c +dsa.obj: dsa.c + $(CC) $(CFLAGS) dsa.c demos/test.obj: demos/test.c $(CC) $(CFLAGS) demos/test.c @@ -223,11 +261,11 @@ demos/test.obj: demos/test.c demos/hashsum.obj: demos/hashsum.c $(CC) $(CFLAGS) demos/hashsum.c -tomcrypt.lib: keyring.obj gf.obj mem.obj sprng.obj ecc.obj base64.obj dh.obj rsa.obj bits.obj hmac.obj \ +tomcrypt.lib: keyring.obj gf.obj mem.obj sprng.obj dsa.obj ecc.obj base64.obj dh.obj rsa.obj bits.obj hmac.obj \ yarrow.obj cfb.obj ofb.obj ecb.obj ctr.obj cbc.obj hash.obj tiger.obj sha1.obj md2.obj md5.obj md4.obj sha256.obj sha512.obj xtea.obj \ aes.obj serpent.obj safer_tab.obj safer.obj safer+.obj cast5.obj noekeon.obj rc2.obj rc6.obj rc5.obj des.obj blowfish.obj crypt.obj ampi.obj \ strings.obj mpi.obj prime.obj twofish.obj packet.obj - $(AR) /out:tomcrypt.lib keyring.obj gf.obj mem.obj sprng.obj ecc.obj base64.obj dh.obj rsa.obj hmac.obj \ + $(AR) /out:tomcrypt.lib keyring.obj gf.obj mem.obj sprng.obj dsa.obj ecc.obj base64.obj dh.obj rsa.obj hmac.obj \ bits.obj yarrow.obj cfb.obj ofb.obj ecb.obj ctr.obj cbc.obj hash.obj tiger.obj sha1.obj md2.obj md5.obj md4.obj sha256.obj \ strings.obj sha512.obj xtea.obj aes.obj serpent.obj safer_tab.obj safer.obj safer+.obj cast5.obj noekeon.obj rc2.obj rc6.obj rc5.obj des.obj \ blowfish.obj crypt.obj ampi.obj mpi.obj prime.obj twofish.obj packet.obj diff --git a/mpi.c b/mpi.c index fa8a777..4293f6b 100644 --- a/mpi.c +++ b/mpi.c @@ -1635,8 +1635,159 @@ mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c) /* }}} */ +/* shrinks the memory required to store a mp_int if possible */ +mp_err mp_shrink(mp_int *a) +{ + if (a->used != a->alloc) { + if ((a->dp = XREALLOC(a->dp, a->used * sizeof(mp_digit))) == NULL) { + return MP_MEM; + } else { + a->alloc = a->used; + return MP_OKAY; + } + } else { + return MP_OKAY; + } +} + /* {{{ mp_exptmod(a, b, m, c) */ +#ifdef MPI_FASTEXPT + +/* computes y == g^x mod p */ +mp_err mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y) +{ + mp_int *M, tx, mu, res; + int QQQ, QQ, Q, x, *vals, err; + + /* determine the value of Q */ + x = (USED(X) - 1) * DIGIT_BIT; + Q = DIGIT(X, USED(X)-1); + while (Q) { + ++x; + Q >>= 1; + } + if (x <= 8) { Q = 2; } + else if (x <= 64) { Q = 3; } + else if (x <= 256) { Q = 4; } + else if (x <= 950) { Q = 5; } + else if (x <= 2755) { Q = 6; } + else { Q = 7; } + +#ifdef MPI_FASTEXPT_LOWMEM + if (Q > 5) { + Q = 5; + } +#endif + + /* alloc room for table */ + vals = XCALLOC(sizeof(int), USED(X)*((DIGIT_BIT/Q)+((DIGIT_BIT%Q)?1:0))); + if (vals == NULL) { err = MP_MEM; goto _ERR; } + + M = XCALLOC(sizeof(mp_int), 1<= 0) { + for (QQ = 0; QQ < Q; QQ++) { + if ((err = s_mp_sqr(&res)) != MP_OKAY) { goto _TX; } + if ((err = s_mp_reduce(&res, P, &mu)) != MP_OKAY) { goto _TX; } + } + if (vals[x] != 0) { + if ((err = s_mp_mul(&res, &M[vals[x]])) != MP_OKAY) { goto _TX; } + if ((err = s_mp_reduce(&res, P, &mu)) != MP_OKAY) { goto _TX; } + } + } + s_mp_exch(&res, Y); + + /* free ram */ +_TX: + mp_clear(&tx); +_RES: + mp_clear(&res); +_MU: + mp_clear(&mu); +_M: + for (x = 0; x < (1< digs) { break; } + pt = pbt + ix + jx; + w = *pb * *pa + k + *pt; + *pt = ACCUM(w); + k = CARRYOUT(w); + } + if ((int)(ix + jx) < digs) { + pbt[ix + jx] = k; + } + k = 0; + } + + USED(&tmp) = digs; + s_mp_clamp(&tmp); + s_mp_exch(&tmp, a); + + mp_clear(&tmp); + + return MP_OKAY; + +} /* end s_mp_mul() */ + /* }}} */ /* {{{ s_mp_kmul(a, b, out, len) */ @@ -3763,8 +3972,8 @@ mp_err s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu) s_mp_mod_2d(x, (mp_digit)(DIGIT_BIT * (um + 1))); /* q = q * m mod b^(k+1), quick (no division) */ - s_mp_mul(&q, m); - s_mp_mod_2d(&q, (mp_digit)(DIGIT_BIT * (um + 1))); + s_mp_mul_dig(&q, m, um + 1); +// s_mp_mod_2d(&q, (mp_digit)(DIGIT_BIT * (um + 1))); /* x = x - q */ if((res = mp_sub(x, &q, x)) != MP_OKAY) diff --git a/mpi.h b/mpi.h index cbcdc4d..afe2486 100644 --- a/mpi.h +++ b/mpi.h @@ -98,6 +98,8 @@ void mp_clear_array(mp_int mp[], int count); void mp_zero(mp_int *mp); void mp_set(mp_int *mp, mp_digit d); mp_err mp_set_int(mp_int *mp, long z); +mp_err mp_shrink(mp_int *a); + /*------------------------------------------------------------------------*/ /* Single digit arithmetic */ @@ -149,6 +151,9 @@ mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c); #define mp_sqrmod(a, m, c) mp_mulmod(a, a, m, c) #endif mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c); +mp_err s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu); +mp_err s_mp_lshd(mp_int *mp, mp_size p); +mp_err s_mp_mul_dig(mp_int *a, mp_int *b, int digs); mp_err mp_exptmod_d(mp_int *a, mp_digit d, mp_int *m, mp_int *c); #endif /* MP_MODARITH */ diff --git a/mycrypt.h b/mycrypt.h index 02d6ee0..dc6a107 100644 --- a/mycrypt.h +++ b/mycrypt.h @@ -13,46 +13,48 @@ extern "C" { #endif /* version */ -#define CRYPT 0x0078 -#define SCRYPT "0.78" +#define CRYPT 0x0079 +#define SCRYPT "0.79" /* max size of either a cipher/hash block or symmetric key [largest of the two] */ #define MAXBLOCKSIZE 128 +/* ch1-01-1 */ /* error codes [will be expanded in future releases] */ enum { - CRYPT_OK=0, - CRYPT_ERROR, + CRYPT_OK=0, /* Result OK */ + CRYPT_ERROR, /* Generic Error */ - CRYPT_INVALID_KEYSIZE, - CRYPT_INVALID_ROUNDS, - CRYPT_FAIL_TESTVECTOR, + CRYPT_INVALID_KEYSIZE, /* Invalid key size given */ + CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */ + CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */ - CRYPT_BUFFER_OVERFLOW, - CRYPT_INVALID_PACKET, + CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */ + CRYPT_INVALID_PACKET, /* Invalid input packet given */ - CRYPT_INVALID_PRNGSIZE, - CRYPT_ERROR_READPRNG, + CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */ + CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */ - CRYPT_INVALID_CIPHER, - CRYPT_INVALID_HASH, - CRYPT_INVALID_PRNG, + CRYPT_INVALID_CIPHER, /* Invalid cipher specified */ + CRYPT_INVALID_HASH, /* Invalid hash specified */ + CRYPT_INVALID_PRNG, /* Invalid PRNG specified */ - CRYPT_MEM, + CRYPT_MEM, /* Out of memory */ - CRYPT_PK_TYPE_MISMATCH, - CRYPT_PK_NOT_PRIVATE, + CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */ + CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */ - CRYPT_INVALID_ARG, + CRYPT_INVALID_ARG, /* Generic invalid argument */ - CRYPT_PK_INVALID_TYPE, - CRYPT_PK_INVALID_SYSTEM, - CRYPT_PK_DUP, - CRYPT_PK_NOT_FOUND, - CRYPT_PK_INVALID_SIZE, + CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */ + CRYPT_PK_INVALID_SYSTEM,/* Invalid PK system specified */ + CRYPT_PK_DUP, /* Duplicate key already in key ring */ + CRYPT_PK_NOT_FOUND, /* Key not found in keyring */ + CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */ - CRYPT_INVALID_PRIME_SIZE + CRYPT_INVALID_PRIME_SIZE/* Invalid size of prime requested */ }; +/* ch1-01-1 */ #include #include @@ -63,10 +65,8 @@ enum { #include #include #include - #include - #ifdef __cplusplus } #endif diff --git a/mycrypt_argchk.h b/mycrypt_argchk.h index 9369a8e..8f38e54 100644 --- a/mycrypt_argchk.h +++ b/mycrypt_argchk.h @@ -1,26 +1,14 @@ /* Defines the _ARGCHK macro used within the library */ +/* ch1-01-1 */ /* ARGTYPE is defined in mycrypt_cfg.h */ #if ARGTYPE == 0 #include -/* this is the default LibTomCrypt macro - * - * On embedded platforms you can change the fprintf() to be a routine that would display a message - * somehow - */ - -#ifdef SMALL_CODE - extern void crypt_argchk(char *v, char *s, int d); - #define _ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } -#else - #ifdef SONY_PS2 - #define _ARGCHK(x) if (!(x)) { printf("_ARGCHK '%s' failure on line %d of file %s\n", #x, __LINE__, __FILE__); raise(SIGABRT); } - #else - #define _ARGCHK(x) if (!(x)) { fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n", #x, __LINE__, __FILE__); raise(SIGABRT); } - #endif -#endif +/* this is the default LibTomCrypt macro */ +extern void crypt_argchk(char *v, char *s, int d); +#define _ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } #elif ARGTYPE == 1 @@ -32,4 +20,5 @@ #define _ARGCHK(x) #endif +/* ch1-01-1 */ diff --git a/mycrypt_cfg.h b/mycrypt_cfg.h index a70d619..daf4f63 100644 --- a/mycrypt_cfg.h +++ b/mycrypt_cfg.h @@ -9,18 +9,21 @@ /* you can change how memory allocation works ... */ extern void *XMALLOC(size_t n); +extern void *REALLOC(void *p, size_t n); extern void *XCALLOC(size_t n, size_t s); extern void XFREE(void *p); /* change the clock function too */ extern clock_t XCLOCK(void); +/* ch1-01-1 */ /* type of argument checking, 0=default, 1=fatal and 2=none */ #define ARGTYPE 0 +/* ch1-01-1 */ /* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code */ /* detect x86-32 machines somewhat */ -#if (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__))) +#if (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__))) #define ENDIAN_LITTLE #define ENDIAN_32BITWORD #endif @@ -53,7 +56,7 @@ extern clock_t XCLOCK(void); #ifdef YARROW #ifndef CTR - #error YARROW Requires CTR mode + #error YARROW requires CTR chaining mode to be defined! #endif #endif @@ -62,12 +65,13 @@ extern clock_t XCLOCK(void); #define PACKET /* size of a packet header in bytes */ - #define PACKET_SIZE 8 + #define PACKET_SIZE 4 /* Section tags */ #define PACKET_SECT_RSA 0 #define PACKET_SECT_DH 1 #define PACKET_SECT_ECC 2 + #define PACKET_SECT_DSA 4 /* Subsection Tags for the first three sections */ #define PACKET_SUB_KEY 0 @@ -76,33 +80,6 @@ extern clock_t XCLOCK(void); #define PACKET_SUB_ENC_KEY 3 #endif -/* Diffie-Hellman key settings you can omit ones you don't want to save space */ -#ifdef MDH - -#define DH768 -#define DH1024 -#define DH1280 -#define DH1536 -#define DH1792 -#define DH2048 -#define DH2560 -#define DH3072 -#define DH4096 - -#endif /* MDH */ - -/* ECC Key settings */ -#ifdef MECC - -#define ECC160 -#define ECC192 -#define ECC224 -#define ECC256 -#define ECC384 -#define ECC521 - -#endif /* MECC */ - #ifdef MPI #include "mpi.h" #else @@ -115,6 +92,9 @@ extern clock_t XCLOCK(void); #ifdef MDH #error DH requires the big int library #endif + #ifdef MDSA + #error DSA requires the big int library + #endif #endif /* MPI */ #endif /* MYCRYPT_CFG_H */ diff --git a/mycrypt_misc.h b/mycrypt_misc.h index ac4ed07..1c759f6 100644 --- a/mycrypt_misc.h +++ b/mycrypt_misc.h @@ -11,6 +11,8 @@ extern int base64_decode(const unsigned char *in, unsigned long len, extern void zeromem(void *dst, unsigned long len); extern void burn_stack(unsigned long len); +/* ch1-01-1*/ extern const char *error_to_string(int errno); +/* ch1-01-1*/ extern const char *crypt_build_settings; diff --git a/mycrypt_pk.h b/mycrypt_pk.h index b86bb7f..f570741 100644 --- a/mycrypt_pk.h +++ b/mycrypt_pk.h @@ -17,7 +17,7 @@ extern void mp_clear_multi(mp_int* mp, ...); /* ---- PACKET ---- */ #ifdef PACKET -extern void packet_store_header(unsigned char *dst, int section, int subsection, unsigned long length); +extern void packet_store_header(unsigned char *dst, int section, int subsection); extern int packet_valid_header(unsigned char *src, int section, int subsection); #endif @@ -56,15 +56,16 @@ extern int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen, unsigned char *outkey, unsigned long *outlen, prng_state *prng, int wprng, rsa_key *key); -extern int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey, - unsigned long *keylen, rsa_key *key); +extern int rsa_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *outkey, unsigned long *keylen, + rsa_key *key); extern int rsa_sign_hash(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, rsa_key *key); -extern int rsa_verify_hash(const unsigned char *sig, const unsigned char *hash, - int *stat, rsa_key *key); +extern int rsa_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, int *stat, rsa_key *key); extern int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key); extern int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key); @@ -96,16 +97,17 @@ extern int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen, prng_state *prng, int wprng, int hash, dh_key *key); -extern int dh_decrypt_key(const unsigned char *in, unsigned char *outkey, - unsigned long *keylen, dh_key *key); +extern int dh_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *outkey, unsigned long *keylen, + dh_key *key); extern int dh_sign_hash(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, dh_key *key); -extern int dh_verify_hash(const unsigned char *sig, const unsigned char *hash, - unsigned long inlen, int *stat, - dh_key *key); +extern int dh_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, dh_key *key); #endif @@ -140,15 +142,35 @@ extern int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen, prng_state *prng, int wprng, int hash, ecc_key *key); -extern int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey, - unsigned long *keylen, ecc_key *key); +extern int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *outkey, unsigned long *keylen, + ecc_key *key); extern int ecc_sign_hash(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, ecc_key *key); -extern int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash, - unsigned long inlen, int *stat, - ecc_key *key); +extern int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, ecc_key *key); +#endif + +#ifdef MDSA + +typedef struct { + int type, idx; + mp_int x, y; +} dsa_key; + +extern int dsa_test(void); + +extern int dsa_make_key(prng_state *prng, int wprng, int keysize, dsa_key *key); +extern void dsa_free(dsa_key *key); + +extern int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key); +extern int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key); + + + #endif diff --git a/packet.c b/packet.c index 5ff054e..84df77e 100644 --- a/packet.c +++ b/packet.c @@ -2,7 +2,7 @@ #ifdef PACKET -void packet_store_header(unsigned char *dst, int section, int subsection, unsigned long length) +void packet_store_header(unsigned char *dst, int section, int subsection) { _ARGCHK(dst != NULL); @@ -14,8 +14,6 @@ void packet_store_header(unsigned char *dst, int section, int subsection, unsign dst[2] = section & 255; dst[3] = subsection & 255; - /* store length */ - STORE32L(length, &dst[4]); } int packet_valid_header(unsigned char *src, int section, int subsection) diff --git a/prime.c b/prime.c index 59774a3..f8c8a12 100644 --- a/prime.c +++ b/prime.c @@ -230,8 +230,6 @@ done: return res; } - - int rand_prime(mp_int *N, long len, prng_state *prng, int wprng) { unsigned char buf[260]; diff --git a/rsa.c b/rsa.c index ea4f86a..8a6a3e5 100644 --- a/rsa.c +++ b/rsa.c @@ -73,7 +73,19 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) if (mp_copy(&p, &key->p) != MP_OKAY) { goto error2; } if (mp_copy(&q, &key->q) != MP_OKAY) { goto error2; } + + /* shrink ram required */ + if (mp_shrink(&key->e) != MP_OKAY) { goto error2; } + if (mp_shrink(&key->d) != MP_OKAY) { goto error2; } + if (mp_shrink(&key->N) != MP_OKAY) { goto error2; } + if (mp_shrink(&key->dQ) != MP_OKAY) { goto error2; } + if (mp_shrink(&key->dP) != MP_OKAY) { goto error2; } + if (mp_shrink(&key->qP) != MP_OKAY) { goto error2; } + if (mp_shrink(&key->pQ) != MP_OKAY) { goto error2; } + if (mp_shrink(&key->p) != MP_OKAY) { goto error2; } + if (mp_shrink(&key->q) != MP_OKAY) { goto error2; } + res = CRYPT_OK; key->type = PK_PRIVATE_OPTIMIZED; goto done; @@ -293,10 +305,10 @@ int rsa_depad(const unsigned char *in, unsigned long inlen, #define OUTPUT_BIGNUM(num, buf2, y, z) \ { \ - z = mp_raw_size(num); \ + z = mp_unsigned_bin_size(num); \ STORE32L(z, buf2+y); \ y += 4; \ - mp_toraw(num, buf2+y); \ + mp_to_unsigned_bin(num, buf2+y); \ y += z; \ } @@ -318,11 +330,16 @@ int rsa_depad(const unsigned char *in, unsigned long inlen, } \ \ /* load it */ \ - if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\ + if (mp_read_unsigned_bin(num, (unsigned char *)in+y, x) != MP_OKAY) {\ errno = CRYPT_MEM; \ goto error2; \ } \ y += x; \ + \ + if (mp_shrink(num) != MP_OKAY) { \ + errno = CRYPT_MEM; \ + goto error2; \ + } \ } int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key) @@ -371,7 +388,7 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key } /* store packet header */ - packet_store_header(buf2, PACKET_SECT_RSA, PACKET_SUB_KEY, y); + packet_store_header(buf2, PACKET_SECT_RSA, PACKET_SUB_KEY); /* copy to the user buffer */ memcpy(out, buf2, y); @@ -431,6 +448,14 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) INPUT_BIGNUM(&key->p, in, x, y); INPUT_BIGNUM(&key->q, in, x, y); } + + /* free up ram not required */ + if (key->type != PK_PRIVATE_OPTIMIZED) { + mp_clear_multi(&key->dQ, &key->dP, &key->pQ, &key->qP, &key->p, &key->q, NULL); + } + if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) { + mp_clear(&key->d); + } return CRYPT_OK; error2: diff --git a/rsa_sys.c b/rsa_sys.c index 187deb2..479cfca 100644 --- a/rsa_sys.c +++ b/rsa_sys.c @@ -49,7 +49,7 @@ int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen, } /* store header */ - packet_store_header(outkey, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY, y); + packet_store_header(outkey, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY); #ifdef CLEAN_STACK /* clean up */ @@ -60,8 +60,9 @@ int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen, return CRYPT_OK; } -int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey, - unsigned long *keylen, rsa_key *key) +int rsa_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *outkey, unsigned long *keylen, + rsa_key *key) { unsigned char sym_key[MAXBLOCKSIZE], rsa_in[4096], rsa_out[4096]; unsigned long x, y, z, i, rsa_size; @@ -77,6 +78,12 @@ int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey, return CRYPT_PK_NOT_PRIVATE; } + if (inlen < PACKET_SIZE+4) { + return CRYPT_INVALID_PACKET; + } else { + inlen -= PACKET_SIZE+4; + } + /* check the header */ if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY)) != CRYPT_OK) { return errno; @@ -84,7 +91,12 @@ int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey, /* grab length of the rsa key */ y = PACKET_SIZE; - LOAD32L(rsa_size, (in+y)) + LOAD32L(rsa_size, (in+y)); + if (inlen < rsa_size) { + return CRYPT_INVALID_PACKET; + } else { + inlen -= rsa_size; + } y += 4; /* read it in */ @@ -94,8 +106,9 @@ int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey, /* decrypt it */ x = sizeof(rsa_out); - if ((errno = rsa_exptmod(rsa_in, rsa_size, rsa_out, &x, PK_PRIVATE, key)) != CRYPT_OK) + if ((errno = rsa_exptmod(rsa_in, rsa_size, rsa_out, &x, PK_PRIVATE, key)) != CRYPT_OK) { return errno; + } /* depad it */ z = sizeof(sym_key); @@ -170,7 +183,7 @@ int rsa_sign_hash(const unsigned char *in, unsigned long inlen, } /* store header */ - packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_SIGNED, y); + packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_SIGNED); #ifdef CLEAN_STACK /* clean up */ @@ -181,8 +194,8 @@ int rsa_sign_hash(const unsigned char *in, unsigned long inlen, return CRYPT_OK; } -int rsa_verify_hash(const unsigned char *sig, const unsigned char *md, - int *stat, rsa_key *key) +int rsa_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *md, int *stat, rsa_key *key) { unsigned long rsa_size, x, y, z; unsigned char rsa_in[4096], rsa_out[4096]; @@ -195,6 +208,12 @@ int rsa_verify_hash(const unsigned char *sig, const unsigned char *md, /* always be incorrect by default */ *stat = 0; + + if (siglen < PACKET_SIZE+4) { + return CRYPT_INVALID_PACKET; + } else { + siglen -= PACKET_SIZE+4; + } /* verify header */ if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_RSA, PACKET_SUB_SIGNED)) != CRYPT_OK) { @@ -204,6 +223,11 @@ int rsa_verify_hash(const unsigned char *sig, const unsigned char *md, /* get the len */ y = PACKET_SIZE; LOAD32L(rsa_size, (sig+y)); + if (siglen < rsa_size) { + return CRYPT_INVALID_PACKET; + } else { + siglen -= rsa_size; + } y += 4; /* load the signature */ diff --git a/sha1.c b/sha1.c index f27a536..2ad6505 100644 --- a/sha1.c +++ b/sha1.c @@ -25,7 +25,7 @@ static void _sha1_compress(hash_state *md) static void sha1_compress(hash_state *md) #endif { - unsigned long a,b,c,d,e,W[80],i,j; + unsigned long a,b,c,d,e,W[80],i,j,j2,j3; _ARGCHK(md != NULL); @@ -47,6 +47,7 @@ static void sha1_compress(hash_state *md) W[i] = ROL(j, 1); } + /* compress */ /* round one */ for (i = 0; i < 20; i++) { diff --git a/strings.c b/strings.c index 6ca2749..d454e65 100644 --- a/strings.c +++ b/strings.c @@ -38,7 +38,7 @@ static const char *err_2_str[] = const char *error_to_string(int errno) { - if (errno < 0 || errno > (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) { + if (errno < 0 || errno >= (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) { return "Invalid error code."; } else { return err_2_str[errno]; diff --git a/update_libtomcrypt.sh b/update_libtomcrypt.sh new file mode 100644 index 0000000..9940827 --- /dev/null +++ b/update_libtomcrypt.sh @@ -0,0 +1,131 @@ +#!/bin/tcsh +# Get latest copy of libtomcrypt and install it using "tcsh" +# +# Tom St Denis +echo libtomcrypt update script, Tom St Denis +echo "http://libtomcrypt.iahu.ca\n" + +if ($1 == "--help") then + echo "update_libtomcrypt.sh [makefile] [sig]-- Download and optionally build the libtomcrypt project.\n" + echo "\t[makefile] --\tYou can optionally specify which makefile you want to build with. If you specify " + echo "\t\t\t'nobuild' then the library is not built, just downloaded and unzipped. If you " + echo "\t\t\tleave it empty the default 'makefile' is used to build the library.\n" + echo "\t[sig] -- \tOptionally verify [via GPG] the signature of the package." + exit +endif + +if ($1 == "" || $1 == "sig") then + set make = "makefile" +else + set make = $1; +endif + +if ($1 == "sig" || $2 == "sig") then + set sig = "sig" +else + set sig = "" +endif + +rm -f latest +echo Getting latest version number from website. +wget -q http://iahu.ca:8080/download/latest +if (-r latest) then + set a = `cat latest` + echo "Latest release is v$a.\n" + if (-d "libtomcrypt-$a" && (-r "libtomcrypt-$a/libtomcrypt.a" || $make == "nobuild")) then + echo Libtomcrypt v$a is already installed on your system. + else + echo "Downloading libtomcrypt v$a ..." + if (-r "crypt-$a.tar.bz2") then + rm -f crypt-$a.tar.bz2 + endif + wget http://iahu.ca:8080/download/crypt-$a.tar.bz2 + if (-r "crypt-$a.tar.bz2") then + if (-d "libtomcrypt-$a") then + echo "WARNING! Directory libtomcrypt-$a already exists. Cannot continue.\n" + exit + endif + if ($sig == "sig") then + if (!(-r public.asc)) then + echo "Downloading and installing code signing key...\n" + wget -q http://iahu.ca:8080/download/public.asc + if (-r public.asc) then + gpg --import public.asc + if ($? != 0) then + echo Could not import signing key required to verify the package. + exit + else + echo "\n********************************************************************************" + echo "A new key has been imported to your keyring. You should check that it is valid." + echo "********************************************************************************" + endif + else + echo "Could not download the key to import." + exit + endif + endif + echo Verifying signature... + wget -q http://iahu.ca:8080/download/crypt-$a.tar.bz2.asc + if (!(-r "crypt-$a.tar.bz2.asc")) then + echo Could not download signature to test. + exit + endif + gpg -q --verify crypt-$a.tar.bz2.asc + if ($? != 0) then + echo "\n\nSignature for crypt-$a.tar.bz2 is ****not**** valid.\n\n" + exit + else + echo "\n\nSignature for crypt-$a.tar.bz2 is valid.\n\n" + endif + endif + bzip2 -d -c crypt-$a.tar.bz2 | tar -x + if (-d "libtomcrypt-$a") then + if (-r "libtomcrypt-$a/$make") then + cd libtomcrypt-$a + make -f $make + if (-r "libtomcrypt.a") then + echo "\n\n*****************************************************************" + echo The library has been built and you can now install it either with + echo + echo "cd libtomcrypt-$a ; make install" + echo + echo Or by editing the makefile and changing the user you wish to install + echo it with, or simply copy "libtomcrypt.a" to your library directory and + echo copy "*.h" to your include directory + echo "*****************************************************************" + else + echo "\n\n*****************************************************************" + echo The library failed to build. Please note the errors and send them to tomstdenis@yahoo.com + echo "*****************************************************************" + endif + else if ($make == "nobuild") then + echo "\n\n*****************************************************************" + echo "The library was downloaded and unzipped into libtomcrypt-$a/" + echo "*****************************************************************" + else + echo "The makefile '$make' was not found in the archive.\n"; + endif + else + echo "Could not unpack the libtomcrypt archive (corrupt?)." + endif + cd .. + else + echo "Could not download the libtomcrypt archive from server." + endif + endif + if (-r "libtomcrypt-$a/changes") then + perl <; print \$a; \$a = ; + while () { + if (\$_ =~ m/^(v\d\.\d\d)/) { close(IN); exit(0); } + print "\$a"; \$a = \$_; + } +! + else + echo "Change log not found. Is the package really installed?" + endif +else + echo "Could not download latest file from server to check version." +endif