added libtomcrypt-0.78
This commit is contained in:
		
							parent
							
								
									5581d44fd4
								
							
						
					
					
						commit
						2ef59575df
					
				
							
								
								
									
										16
									
								
								aes.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								aes.c
									
									
									
									
									
								
							| @ -31,6 +31,18 @@ const struct _cipher_descriptor rijndael_desc = | |||||||
|     &rijndael_keysize |     &rijndael_keysize | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | const struct _cipher_descriptor aes_desc = | ||||||
|  | { | ||||||
|  |     "aes", | ||||||
|  |     6, | ||||||
|  |     16, 32, 16, 10, | ||||||
|  |     &rijndael_setup, | ||||||
|  |     &rijndael_ecb_encrypt, | ||||||
|  |     &rijndael_ecb_decrypt, | ||||||
|  |     &rijndael_test, | ||||||
|  |     &rijndael_keysize | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| #include "aes_tab.c" | #include "aes_tab.c" | ||||||
| 
 | 
 | ||||||
| #define byte(x, y) (((x)>>(8*(y)))&255) | #define byte(x, y) (((x)>>(8*(y)))&255) | ||||||
| @ -186,7 +198,7 @@ int rijndael_setup(const unsigned char *key, int keylen, int numrounds, symmetri | |||||||
|     f_rl(bo, bi, 2, k);     \ |     f_rl(bo, bi, 2, k);     \ | ||||||
|     f_rl(bo, bi, 3, k) |     f_rl(bo, bi, 3, k) | ||||||
|      |      | ||||||
| #ifdef RIJNDAEL_SMALL | #ifdef SMALL_CODE | ||||||
| 
 | 
 | ||||||
| static void _fnround(unsigned long *bo, unsigned long *bi, unsigned long *k) | static void _fnround(unsigned long *bo, unsigned long *bi, unsigned long *k) | ||||||
| { | { | ||||||
| @ -255,7 +267,7 @@ void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_ | |||||||
|     i_rl(bo, bi, 2, k);     \ |     i_rl(bo, bi, 2, k);     \ | ||||||
|     i_rl(bo, bi, 3, k) |     i_rl(bo, bi, 3, k) | ||||||
|      |      | ||||||
| #ifdef RIJNDAEL_SMALL | #ifdef SMALL_CODE | ||||||
| 
 | 
 | ||||||
| static void _inround(unsigned long *bo, unsigned long *bi, unsigned long *k) | static void _inround(unsigned long *bo, unsigned long *bi, unsigned long *k) | ||||||
| { | { | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								changes
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								changes
									
									
									
									
									
								
							| @ -1,3 +1,17 @@ | |||||||
|  | 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. | ||||||
|  |        -- Added Noekeon block cipher at 2,800 bytes of object code and 345Mbit/sec it is a welcome addition. | ||||||
|  |        -- Made the KR code check if the other PK systems are included [provides error when building otherwise]. | ||||||
|  |        -- Made "aes" an alias for Rijndael via a pre-processor macro.  Now you can use "aes_ecb_encrypt", etc... :-) | ||||||
|  |           Thanks to Jean-Luc Cooke for the "buzzword conformance" suggestion. | ||||||
|  |        -- Removed the old PK code entirely (e.g. rsa_sign, dh_encrypt).  The *_sign_hash and *_encrypt_key functions | ||||||
|  |           are all that is to remain. | ||||||
|  |        -- **NOTE** Changed the PK *_import (including the keyring) routine to accept a "inlen" parameter.  This fixes a | ||||||
|  |           bug where improperly made key packets could result in reading passed the end of the buffer.  This means | ||||||
|  |           the code is no longer source compatible but still binary compatible. | ||||||
|  |        -- Fixed a few other minor bugs in the PK import code while I was at it. | ||||||
|  |         | ||||||
| Nov 26th, 2002 | Nov 26th, 2002 | ||||||
| v0.77  -- Updated the XTEA code to use pre-computed keys.  With optimizations for speed it achieves 222Mbit/sec | v0.77  -- Updated the XTEA code to use pre-computed keys.  With optimizations for speed it achieves 222Mbit/sec | ||||||
|           compared to the 121Mbit/sec before.  It is 288 bytes bigger than before. |           compared to the 121Mbit/sec before.  It is 288 bytes bigger than before. | ||||||
|  | |||||||
							
								
								
									
										18
									
								
								crypt.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								crypt.c
									
									
									
									
									
								
							| @ -103,6 +103,21 @@ struct _prng_descriptor prng_descriptor[32] = { | |||||||
| { NULL, NULL, NULL, NULL, NULL }, | { NULL, NULL, NULL, NULL, NULL }, | ||||||
| { NULL, NULL, NULL, NULL, NULL } }; | { NULL, NULL, NULL, NULL, NULL } }; | ||||||
| 
 | 
 | ||||||
|  | #if (ARGTYPE == 0) && defined(SMALL_CODE) | ||||||
|  | 
 | ||||||
|  | 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); | ||||||
|  | #else  | ||||||
|  |    fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n", v, d, s); | ||||||
|  | #endif | ||||||
|  |    raise(SIGABRT); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  |     | ||||||
|  | 
 | ||||||
| int find_cipher(const char *name) | int find_cipher(const char *name) | ||||||
| { | { | ||||||
|    int x; |    int x; | ||||||
| @ -187,7 +202,7 @@ int register_cipher(const struct _cipher_descriptor *cipher) | |||||||
| 
 | 
 | ||||||
|    /* is it already registered? */ |    /* is it already registered? */ | ||||||
|    for (x = 0; x < 32; x++) { |    for (x = 0; x < 32; x++) { | ||||||
|        if (!memcmp(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor))) { |        if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) { | ||||||
|           return x; |           return x; | ||||||
|        } |        } | ||||||
|    } |    } | ||||||
| @ -214,6 +229,7 @@ int unregister_cipher(const struct _cipher_descriptor *cipher) | |||||||
|    for (x = 0; x < 32; x++) { |    for (x = 0; x < 32; x++) { | ||||||
|        if (!memcmp(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor))) { |        if (!memcmp(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor))) { | ||||||
|           cipher_descriptor[x].name = NULL; |           cipher_descriptor[x].name = NULL; | ||||||
|  |           cipher_descriptor[x].ID   = 255; | ||||||
|           return CRYPT_OK; |           return CRYPT_OK; | ||||||
|        } |        } | ||||||
|    } |    } | ||||||
|  | |||||||
							
								
								
									
										220
									
								
								crypt.tex
									
									
									
									
									
								
							
							
						
						
									
										220
									
								
								crypt.tex
									
									
									
									
									
								
							| @ -44,7 +44,7 @@ | |||||||
| \def\gap{\vspace{0.5ex}} | \def\gap{\vspace{0.5ex}} | ||||||
| \makeindex | \makeindex | ||||||
| \begin{document} | \begin{document} | ||||||
| \title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.77} | \title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.78} | ||||||
| \author{Tom St Denis \\ | \author{Tom St Denis \\ | ||||||
| Algonquin College \\ | Algonquin College \\ | ||||||
| \\ | \\ | ||||||
| @ -398,12 +398,6 @@ int main(void) | |||||||
|    symmetric_key skey; |    symmetric_key skey; | ||||||
|    int errno; |    int errno; | ||||||
| 
 | 
 | ||||||
|    /* first register Blowfish */ |  | ||||||
|    if (register_cipher(&blowfish_desc) == -1) { |  | ||||||
|       printf("Error registering Blowfish.\n"); |  | ||||||
|       return -1; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* ... key is loaded appropriately in ``key'' ... */ |    /* ... key is loaded appropriately in ``key'' ... */ | ||||||
|    /* ... load a block of plaintext in ``pt'' ... */ |    /* ... load a block of plaintext in ``pt'' ... */ | ||||||
| 
 | 
 | ||||||
| @ -484,11 +478,12 @@ As of this release the current cipher\_descriptors elements are | |||||||
|      \hline Safer K128  & safer\_k128\_desc & 8 & 16 & 6 .. 13 \\ |      \hline Safer K128  & safer\_k128\_desc & 8 & 16 & 6 .. 13 \\ | ||||||
|      \hline Safer SK128 & safer\_sk128\_desc & 8 & 16 & 6 .. 13 \\ |      \hline Safer SK128 & safer\_sk128\_desc & 8 & 16 & 6 .. 13 \\ | ||||||
|      \hline Serpent & serpent\_desc & 16 & 16 .. 32 & 32 \\ |      \hline Serpent & serpent\_desc & 16 & 16 .. 32 & 32 \\ | ||||||
|      \hline Rijndael (AES) & rijndael\_desc & 16 & 16, 24, 32 & 10, 12, 14 \\ |      \hline AES & aes\_desc & 16 & 16, 24, 32 & 10, 12, 14 \\ | ||||||
|      \hline Twofish & twofish\_desc & 16 & 16, 24, 32 & 16 \\ |      \hline Twofish & twofish\_desc & 16 & 16, 24, 32 & 16 \\ | ||||||
|      \hline DES & des\_desc & 8 & 7 & 16 \\ |      \hline DES & des\_desc & 8 & 7 & 16 \\ | ||||||
|      \hline 3DES (EDE mode) & des3\_desc & 8 & 21 & 16 \\ |      \hline 3DES (EDE mode) & des3\_desc & 8 & 21 & 16 \\ | ||||||
|      \hline CAST5 (CAST-128) & cast5\_desc & 8 & 5 .. 16 & 12, 16 \\ |      \hline CAST5 (CAST-128) & cast5\_desc & 8 & 5 .. 16 & 12, 16 \\ | ||||||
|  |      \hline Noekeon & noekeon\_desc & 16 & 16 & 16 \\ | ||||||
|      \hline |      \hline | ||||||
| \end{tabular} | \end{tabular} | ||||||
| \end{center} | \end{center} | ||||||
| @ -704,7 +699,7 @@ Where ``XXX'' is one of (ecb, cbc) and ``YYY'' is one of (ctr, ofb, cfb).  In th | |||||||
| size of the buffer (as number of chars) to encrypt or decrypt.  The CTR, OFB and CFB modes are order sensitive but not | size of the buffer (as number of chars) to encrypt or decrypt.  The CTR, OFB and CFB modes are order sensitive but not | ||||||
| chunk sensitive.  That is you can encrypt ``ABCDEF'' in three calls like ``AB'', ``CD'', ``EF'' or two like ``ABCDE'' and ``F'' | chunk sensitive.  That is you can encrypt ``ABCDEF'' in three calls like ``AB'', ``CD'', ``EF'' or two like ``ABCDE'' and ``F'' | ||||||
| and end up with the same ciphertext.  However, encrypting ``ABC'' and ``DABC'' will result in different ciphertexts.  All | and end up with the same ciphertext.  However, encrypting ``ABC'' and ``DABC'' will result in different ciphertexts.  All | ||||||
| four of the functions return {\bf CRYPT\_OK} on success. | five of the modes will return {\bf CRYPT\_OK} on success from the encrypt or decrypt functions. | ||||||
| 
 | 
 | ||||||
| To decrypt in either mode you simply perform the setup like before (recall you have to fetch the IV value you used) | To decrypt in either mode you simply perform the setup like before (recall you have to fetch the IV value you used) | ||||||
| and use the decrypt routine on all of the blocks.  When you are done working with either mode you should wipe the  | and use the decrypt routine on all of the blocks.  When you are done working with either mode you should wipe the  | ||||||
| @ -1359,66 +1354,14 @@ int rsa_exptmod(const unsigned char *in, unsigned long inlen, | |||||||
|                 unsigned char *out, unsigned long *outlen,  |                 unsigned char *out, unsigned long *outlen,  | ||||||
|                 int which, rsa_key *key); |                 int which, rsa_key *key); | ||||||
| \end{verbatim} | \end{verbatim} | ||||||
| This loads the bignum from ``in'' as a big endian word, raises it to either ``e'' or ``d'' and stores the result | This loads the bignum from ``in'' as a big endian word in the format PKCS specifies, raises it to either ``e'' or ``d'' and stores the result | ||||||
| in ``out'' and the size of the result in ``outlen''. ``which'' is set to {\bf PK\_PUBLIC} to use ``e''  | in ``out'' and the size of the result in ``outlen''. ``which'' is set to {\bf PK\_PUBLIC} to use ``e''  | ||||||
| (i.e. for encryption/verifying) and set to {\bf PK\_PRIVATE} to use ``d'' as the exponent (i.e. for decrypting/signing). | (i.e. for encryption/verifying) and set to {\bf PK\_PRIVATE} to use ``d'' as the exponent (i.e. for decrypting/signing). | ||||||
| 
 | 
 | ||||||
| \section{Packet Routines} | \section{Packet Routines} | ||||||
| The remaining RSA functions are non-standard but should (to the best of my knowledge) be secure if used correctly.  To | To encrypt or decrypt a symmetric key using RSA the following functions are provided.  The idea is that you make up | ||||||
| encrypt a buffer of memory in a hybrid fashion call: | a random symmetric key and use that to encode your message.  By RSA encrypting the symmetric key you can send it to a | ||||||
| \index{rsa\_encrypt()} | recipient who can RSA decrypt it and symmetrically decrypt the message. | ||||||
| \begin{verbatim} |  | ||||||
| int rsa_encrypt(const unsigned char *in, unsigned long len,  |  | ||||||
|                 unsigned char *out, unsigned long *outlen, |  | ||||||
|                 prng_state *prng, int wprng, int cipher,  |  | ||||||
|                 rsa_key *key); |  | ||||||
| \end{verbatim} |  | ||||||
| This will encrypt the message with the cipher specified by ``cipher'' under a random key made by a PRNG specified by |  | ||||||
| ``wprng'' and RSA encrypt the symmetric key with ``key''.  This stores all the relevant information in ``out'' and sets |  | ||||||
| the length in ``outlen''.  You must ensure that ``outlen'' is set to the buffer size before calling this.   |  | ||||||
| 
 |  | ||||||
| The rsa\_encrypt() function will use up to a 256-bit symmetric key (limited by the max key length of the cipher being |  | ||||||
| used).  To decrypt packets made by this routine call: |  | ||||||
| \index{rsa\_decrypt()} |  | ||||||
| \begin{verbatim} |  | ||||||
| int rsa_decrypt(const unsigned char *in, unsigned long len,  |  | ||||||
|                 unsigned char *out, unsigned long *outlen,  |  | ||||||
|                 rsa_key *key); |  | ||||||
| \end{verbatim} |  | ||||||
| Which works akin to rsa\_encrypt().  ``in'' is the ciphertext and ``out'' is where the plaintext will be stored.  Similarly |  | ||||||
| to sign/verify there are: |  | ||||||
| \index{rsa\_sign()} \index{rsa\_verify()} |  | ||||||
| \begin{verbatim} |  | ||||||
| int rsa_sign(const unsigned char *in, unsigned long inlen,  |  | ||||||
|                    unsigned char *out, unsigned long *outlen,  |  | ||||||
|                    int hash, rsa_key *key); |  | ||||||
| 
 |  | ||||||
| int rsa_verify(const unsigned char *sig, |  | ||||||
|                const unsigned char *msg,  |  | ||||||
|                unsigned long inlen, int *stat,  |  | ||||||
|                rsa_key *key); |  | ||||||
| \end{verbatim} |  | ||||||
| 
 |  | ||||||
| The verify function sets ``stat'' to 1 if it passes or to 0 if it fails.  The ``sig'' parameter is the output of the |  | ||||||
| rsa\_sign() function and ``msg'' is the original msg that was signed.  An important fact to note is that with |  | ||||||
| the padding scheme used in ``rsa\_sign()'' you cannot use the SHA-384 or SHA-512 hash function with 1024 bit |  | ||||||
| RSA keys.  This is because the padding makes the values too large to fit in the space allowed.  You can use SHA-384 |  | ||||||
| with 1160 and above bit RSA keys.  You can use SHA-512 with 1544 and above bit RSA keys. |  | ||||||
| 
 |  | ||||||
| There are related functions to sign and verify hashes. |  | ||||||
| \begin{verbatim} |  | ||||||
| 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); |  | ||||||
| \end{verbatim} |  | ||||||
| Which works just like the two previous functions except the data is not hashed before being signed. |  | ||||||
| 
 |  | ||||||
| There are times where you may want to encrypt a message to multiple recipients via RSA public keys.  The simplest way to |  | ||||||
| accomplish this is to make up your own symmetric key and then RSA encrypt the symmetric key using all of the recipients |  | ||||||
| public keys.  To facilitate this task two functions\footnote{Donated by Clay Culver.} are available: |  | ||||||
| \begin{verbatim} | \begin{verbatim} | ||||||
| int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen, | int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen, | ||||||
|                           unsigned char *outkey, unsigned long *outlen, |                           unsigned char *outkey, unsigned long *outlen, | ||||||
| @ -1434,12 +1377,27 @@ algorithm.  It will store the result in ``outkey'' along with the length in ``ou | |||||||
| performs the opposite.  The ``in'' variable is where the RSA packet goes and it will store the original symmetric key in | 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''. | 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.   | ||||||
|  | \begin{verbatim} | ||||||
|  | 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); | ||||||
|  | \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 | ||||||
|  | and ``hash'' is the hash of the message.  The integer ``stat'' is set to non-zero if the signature is valid or zero  | ||||||
|  | otherwise. | ||||||
|  | 
 | ||||||
| To import/export RSA keys as a memory buffer (e.g. to store them to disk) call: | To import/export RSA keys as a memory buffer (e.g. to store them to disk) call: | ||||||
| \begin{verbatim} | \begin{verbatim} | ||||||
| int rsa_export(unsigned char *out, unsigned long *outlen,  | int rsa_export(unsigned char *out, unsigned long *outlen,  | ||||||
|                int type, rsa_key *key); |                int type, rsa_key *key); | ||||||
| 
 | 
 | ||||||
| int rsa_import(const unsigned char *in, rsa_key *key); | int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key); | ||||||
| \end{verbatim} | \end{verbatim} | ||||||
| 
 | 
 | ||||||
| The ``type'' parameter is {\bf PK\_PUBLIC}, {\bf PK\_PRIVATE} or {\bf PK\_PRIVATE\_OPTIMIZED} to export either a public or  | The ``type'' parameter is {\bf PK\_PUBLIC}, {\bf PK\_PRIVATE} or {\bf PK\_PRIVATE\_OPTIMIZED} to export either a public or  | ||||||
| @ -1474,9 +1432,9 @@ The following table gives the size requirements for various hashes. | |||||||
| \end{center} | \end{center} | ||||||
| 
 | 
 | ||||||
| The symmetric ciphers will use at a maximum a 256-bit key which means at the least a 776-bit RSA key is  | The symmetric ciphers will use at a maximum a 256-bit key which means at the least a 776-bit RSA key is  | ||||||
| required to use all of the symmetric ciphers with the RSA routines.  It is suggested that you make keys that  | required to use all of the symmetric ciphers with the RSA routines. If you want to use any of the large size  | ||||||
| are at a minimum 1024 bits in length.  If you want to use any of the large size message digests  | message digests (SHA-512 or SHA-384) you will have to use a larger key.  Or to be simple just make 2048-bit or larger | ||||||
| (SHA-512 or SHA-384) you will have to use a larger key. | keys.  None of the hashes will have problems with such key sizes. | ||||||
| 
 | 
 | ||||||
| \chapter{Diffie-Hellman Key Exchange} | \chapter{Diffie-Hellman Key Exchange} | ||||||
| 
 | 
 | ||||||
| @ -1535,7 +1493,7 @@ over communication mediums. | |||||||
| int dh_export(unsigned char *out, unsigned long *outlen,  | int dh_export(unsigned char *out, unsigned long *outlen,  | ||||||
|               int type, dh_key *key); |               int type, dh_key *key); | ||||||
| 
 | 
 | ||||||
| int dh_import(const unsigned char *in, dh_key *key); | int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key); | ||||||
| \end{verbatim} | \end{verbatim} | ||||||
| 
 | 
 | ||||||
| These two functions work just like the ``rsa\_export()'' and ``rsa\_import()'' functions except these work with  | These two functions work just like the ``rsa\_export()'' and ``rsa\_import()'' functions except these work with  | ||||||
| @ -1574,7 +1532,7 @@ int establish_secure_socket(int sock, int mode, unsigned char *key, | |||||||
| { | { | ||||||
|    unsigned char buf[4096], buf2[4096]; |    unsigned char buf[4096], buf2[4096]; | ||||||
|    unsigned long x, len; |    unsigned long x, len; | ||||||
|    int res, errno; |    int res, errno, inlen; | ||||||
|    dh_key mykey, theirkey; |    dh_key mykey, theirkey; | ||||||
| 
 | 
 | ||||||
|    /* make up our private key */ |    /* make up our private key */ | ||||||
| @ -1597,13 +1555,13 @@ int establish_secure_socket(int sock, int mode, unsigned char *key, | |||||||
|       }           |       }           | ||||||
| 
 | 
 | ||||||
|       /* get their key */ |       /* get their key */ | ||||||
|       if (recv(sock, buf2, sizeof(buf2), 0) <= 0) { |       if ((inlen = recv(sock, buf2, sizeof(buf2), 0)) <= 0) { | ||||||
|          res = CRYPT_ERROR; |          res = CRYPT_ERROR; | ||||||
|          goto done2; |          goto done2; | ||||||
|       } |       } | ||||||
|    } else { |    } else { | ||||||
|       /* mode >0 so we send second */ |       /* mode >0 so we send second */ | ||||||
|       if (recv(sock, buf2, sizeof(buf2), 0) <= 0) { |       if ((inlen = recv(sock, buf2, sizeof(buf2), 0)) <= 0) { | ||||||
|          res = CRYPT_ERROR; |          res = CRYPT_ERROR; | ||||||
|          goto done2; |          goto done2; | ||||||
|       } |       } | ||||||
| @ -1614,7 +1572,7 @@ int establish_secure_socket(int sock, int mode, unsigned char *key, | |||||||
|       } |       } | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    if ((errno = dh_import(buf2, &theirkey)) != CRYPT_OK) {  |    if ((errno = dh_import(buf2, inlen, &theirkey)) != CRYPT_OK) {  | ||||||
|       res = errno; |       res = errno; | ||||||
|       goto done2; |       goto done2; | ||||||
|    } |    } | ||||||
| @ -1667,31 +1625,8 @@ void dh_sizes(int *low, int *high); | |||||||
| Which stores the smallest and largest key sizes support into the two variables. | Which stores the smallest and largest key sizes support into the two variables. | ||||||
| 
 | 
 | ||||||
| \section{DH Packet} | \section{DH Packet} | ||||||
| There are routines to perform the work similar to that of ``rsa\_encrypt()'' and ``rsa\_decrypt()'' for DH keys as well. | Similar to the RSA related functions there are functions to encrypt or decrypt symmetric keys using the DH public key | ||||||
| The encrypt routine will make up a random key, attach the public key to the message and used the shared secret to encrypt | algorithms.   | ||||||
| the message with a cipher you choose (and hash the shared secret into a symmetric key with a hash you choose).  The encrypt |  | ||||||
| function is a bit long to call but its worth it. |  | ||||||
| \index{dh\_encrypt()} |  | ||||||
| \begin{verbatim} |  | ||||||
| int dh_encrypt(const unsigned char *in, unsigned long len,  |  | ||||||
|                unsigned char *out, unsigned long *outlen, |  | ||||||
|                prng_state *prng, int wprng, int cipher, int hash,  |  | ||||||
|                dh_key *key); |  | ||||||
| \end{verbatim} |  | ||||||
| Where ``in'' is the plaintext and ``out'' is where the ciphertext will go.  Make sure you set the ``outlen'' value before |  | ||||||
| calling.  The ``key'' is the public DH key of the user you want to encrypt to not your private key.  It will randomly make up |  | ||||||
| a Diffie-Hellman key, export the public copy, hash the shared key with the hash you specify and use the message digest in a |  | ||||||
| cipher you specify to encrypt the message. To decrypt one of these packets call: |  | ||||||
| \index{dh\_decrypt()} |  | ||||||
| \begin{verbatim} |  | ||||||
| int dh_decrypt(const unsigned char *in, unsigned long len,  |  | ||||||
|                unsigned char *out, unsigned long *outlen,  |  | ||||||
|                dh_key *key); |  | ||||||
| \end{verbatim} |  | ||||||
| Where ``in'' is the ciphertext and len is the length of the ciphertext.  ``out'' is where the plaintext should be stored |  | ||||||
| and ``outlen'' is the length of the output (you must first set it to the size of your buffer).   |  | ||||||
| 
 |  | ||||||
| To facilate encrypting to multiple parties the follow two functions are provided: |  | ||||||
| \begin{verbatim} | \begin{verbatim} | ||||||
| int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen, | int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen, | ||||||
|                          unsigned char *out,  unsigned long *len,  |                          unsigned char *out,  unsigned long *len,  | ||||||
| @ -1706,25 +1641,7 @@ and find the hash of the shared secret.  The message digest is than XOR'ed again | |||||||
| data is placed in ``out'' by ``dh\_encrypt\_key()''.   The hash must produce a message digest at least as large | 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. | as the symmetric key you are trying to share. | ||||||
| 
 | 
 | ||||||
| To sign with a Diffie-Hellman key call: | Similar to the RSA system you can sign and verify a hash of a message. | ||||||
| \index{dh\_sign()} |  | ||||||
| \begin{verbatim} |  | ||||||
| int dh_sign(const unsigned char *in, unsigned long inlen,  |  | ||||||
|             unsigned char *out, unsigned long *outlen, int hash,  |  | ||||||
|             prng_state *prng, int wprng, dh_key *key); |  | ||||||
| \end{verbatim} |  | ||||||
| Where ``in'' is the message to size of length ``inlen'' bytes.  ``out'' is where the signature is placed and ``outlen'' |  | ||||||
| is the length of the signature (you must first set it to the size of your buffer).  To verify call: |  | ||||||
| \index{dh\_verify()} |  | ||||||
| \begin{verbatim} |  | ||||||
| int dh_verify(const unsigned char *sig,  |  | ||||||
|               const unsigned char *msg,  |  | ||||||
|               unsigned long inlen, int *stat, dh_key *key); |  | ||||||
| \end{verbatim} |  | ||||||
| Where ``sig'' is the output of ''dh\_sign()`` and ``msg'' is the message of length ``inlen''.  It stores a zero in ``stat'' |  | ||||||
| if the signature is invalid otherwise it puts a one in there. |  | ||||||
| 
 |  | ||||||
| Similar to the RSA system you can sign and verify a pre-hashed block as well using: |  | ||||||
| \begin{verbatim} | \begin{verbatim} | ||||||
| int dh_sign_hash(const unsigned char *in,  unsigned long inlen, | int dh_sign_hash(const unsigned char *in,  unsigned long inlen, | ||||||
|                        unsigned char *out, unsigned long *outlen, |                        unsigned char *out, unsigned long *outlen, | ||||||
| @ -1735,6 +1652,10 @@ int dh_verify_hash(const unsigned char *sig, const unsigned char *hash, | |||||||
|                          dh_key *key); |                          dh_key *key); | ||||||
| \end{verbatim} | \end{verbatim} | ||||||
| 
 | 
 | ||||||
|  | The ``dh\_sign\_hash'' function signs the message hash in ``in'' of length ``inlen'' and forms a DH packet in ``out''.   | ||||||
|  | The ``dh\_verify\_hash'' function verifies the DH signature in ``sig'' against the hash in ``hash''.  It sets ``stat'' | ||||||
|  | to non-zero if the signature passes or zero if it fails. | ||||||
|  | 
 | ||||||
| \chapter{Elliptic Curve Cryptography} | \chapter{Elliptic Curve Cryptography} | ||||||
| 
 | 
 | ||||||
| \section{Background} | \section{Background} | ||||||
| @ -1784,7 +1705,7 @@ To import and export a key there are: | |||||||
| int ecc_export(unsigned char *out, unsigned long *outlen,  | int ecc_export(unsigned char *out, unsigned long *outlen,  | ||||||
|                int type, ecc_key *key); |                int type, ecc_key *key); | ||||||
| 
 | 
 | ||||||
| int ecc_import(const unsigned char *in, ecc_key *key); | int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key); | ||||||
| \end{verbatim} | \end{verbatim} | ||||||
| These two work exactly like there DH counterparts.  Finally when you share your public key you can make a shared secret | These two work exactly like there DH counterparts.  Finally when you share your public key you can make a shared secret | ||||||
| with: | with: | ||||||
| @ -1813,28 +1734,8 @@ void ecc_sizes(int *low, int *high); | |||||||
| Which both work like their DH counterparts. | Which both work like their DH counterparts. | ||||||
| 
 | 
 | ||||||
| \section{ECC Packet} | \section{ECC Packet} | ||||||
| There are routines to perform the work similar to that of ``rsa\_encrypt()'' and ``rsa\_decrypt()'' for ECC keys as well. | Similar to the RSA API there are two functions which encrypt and decrypt symmetric keys using the ECC public key | ||||||
| The encrypt routine will make up a random key, attach the public key to the message and used the shared secret to encrypt | algorithms. | ||||||
| the message with a cipher you choose (and hash the shared secret into a symmetric key with a hash you choose).  The encrypt |  | ||||||
| function is a bit long to call but its worth it. |  | ||||||
| \index{ecc\_encrypt()} |  | ||||||
| \begin{verbatim} |  | ||||||
| int ecc_encrypt(const unsigned char *in, unsigned long len,  |  | ||||||
|                 unsigned char *out, unsigned long *outlen, |  | ||||||
|                 prng_state *prng,  |  | ||||||
|                 int wprng, int cipher, int hash,  |  | ||||||
|                 ecc_key *key); |  | ||||||
| \end{verbatim} |  | ||||||
| Where ``in'' is the plaintext and ``out'' is where the ciphertext will go.  Make sure you set the ``outlen'' value before |  | ||||||
| calling.  The ``key'' is the public ECC key of the user you want to encrypt too.  To decrypt one of these packets call: |  | ||||||
| \index{ecc\_decrypt()} |  | ||||||
| \begin{verbatim} |  | ||||||
| int ecc_decrypt(const unsigned char *in, unsigned long len,  |  | ||||||
|                 unsigned char *out, unsigned long *outlen,  |  | ||||||
|                 ecc_key *key); |  | ||||||
| \end{verbatim} |  | ||||||
| Similar to the DH code there are two functions to facilate multi-party code.  They work exactly like the DH code and are  |  | ||||||
| given as: |  | ||||||
| \begin{verbatim} | \begin{verbatim} | ||||||
| int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen, | int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen, | ||||||
|                           unsigned char *out,  unsigned long *len,  |                           unsigned char *out,  unsigned long *len,  | ||||||
| @ -1844,24 +1745,13 @@ int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen, | |||||||
| int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey,  | int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey,  | ||||||
|                           unsigned long *keylen, ecc_key *key); |                           unsigned long *keylen, ecc_key *key); | ||||||
| \end{verbatim} | \end{verbatim} | ||||||
| You can sign messages with the ECC routines as well, to sign a message call: | 
 | ||||||
| \index{ecc\_sign()} | Where ``inkey'' is an input symmetric key of no more than 32 bytes.  Essentially these routines created a random public key | ||||||
| \begin{verbatim} | and find the hash of the shared secret.  The message digest is than XOR'ed against the symmetric key.  All of the required | ||||||
| int ecc_sign(const unsigned char *in, unsigned long inlen,  | data is placed in ``out'' by ``ecc\_encrypt\_key()''.   The hash chosen must produce a message digest at least as large | ||||||
|              unsigned char *out, unsigned long *outlen,  | as the symmetric key you are trying to share. | ||||||
|              int hash, prng_state *prng, int wprng,  | 
 | ||||||
|              ecc_key *key); | There are also functions to sign and verify the hash of a message. | ||||||
| \end{verbatim} |  | ||||||
| Where ``in'' is the message to sign and ``out'' is where the signature will go.  ``hash'' is the index into the descriptor |  | ||||||
| table of which hash function you want to use (e.g. use ``find\_hash()'').  You must set ``outlen'' to the size of the  |  | ||||||
| output buffer before calling.  To verify a signature call: |  | ||||||
| \index{ecc\_verify()} |  | ||||||
| \begin{verbatim} |  | ||||||
| int ecc_verify(const unsigned char *sig, const unsigned char *msg,  |  | ||||||
|                unsigned long inlen, int *stat, ecc_key *key); |  | ||||||
| \end{verbatim} |  | ||||||
| Where ``sig'' is the signature from ``ecc\_sign()'' and ``msg'' is the input message.  It sets ``stat'' to 0 if the signature |  | ||||||
| is invalid and it sets ``stat'' to 1 if its valid.  To sign or verify pre-hashed blocks use |  | ||||||
| \begin{verbatim} | \begin{verbatim} | ||||||
| int ecc_sign_hash(const unsigned char *in,  unsigned long inlen, | int ecc_sign_hash(const unsigned char *in,  unsigned long inlen, | ||||||
|                         unsigned char *out, unsigned long *outlen, |                         unsigned char *out, unsigned long *outlen, | ||||||
| @ -1872,6 +1762,11 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash, | |||||||
|                           ecc_key *key); |                           ecc_key *key); | ||||||
| \end{verbatim} | \end{verbatim} | ||||||
| 
 | 
 | ||||||
|  | The ``ecc\_sign\_hash'' function signs the message hash in ``in'' of length ``inlen'' and forms a ECC packet in ``out''.   | ||||||
|  | The ``ecc\_verify\_hash'' function verifies the ECC signature in ``sig'' against the hash in ``hash''.  It sets ``stat'' | ||||||
|  | to non-zero if the signature passes or zero if it fails. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| \section{ECC Keysizes} | \section{ECC Keysizes} | ||||||
| With ECC if you try and sign a hash that is bigger than your ECC key you can run into problems.  The math will still work | With ECC if you try and sign a hash that is bigger than your ECC key you can run into problems.  The math will still work | ||||||
| and in effect the signature will still work.  With ECC keys the strength of the signature is limited by the size of | and in effect the signature will still work.  With ECC keys the strength of the signature is limited by the size of | ||||||
| @ -2417,9 +2312,8 @@ useful when TWOFISH\_SMALL is defined as the table values are computed on the fl | |||||||
| will increase by approximately 500 bytes.  If this is defined but TWOFISH\_SMALL is not the cipher will still work but | will increase by approximately 500 bytes.  If this is defined but TWOFISH\_SMALL is not the cipher will still work but | ||||||
| it will not speed up the encryption or decryption functions. | it will not speed up the encryption or decryption functions. | ||||||
| 
 | 
 | ||||||
| \subsubsection{SAFERP\_SMALL and RIJNDAEL\_SMALL} | \subsubsection{SMALL\_CODE} | ||||||
| These two build options let you use slower versions of the ciphers which are also much smaller.  In the case of the SAFER+ | When this is defined some of the code such as the Rijndael and SAFER+ ciphers are replaced with smaller code variants. | ||||||
| implementation it ends up being 1/6th the size.  As for Rijndael its roughly half the size. | These variants are slower but can save quite a bit of code space. | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| \end{document} | \end{document} | ||||||
|  | |||||||
| @ -6,6 +6,6 @@ int main(void) | |||||||
| { | { | ||||||
|    register_cipher(&rijndael_desc); |    register_cipher(&rijndael_desc); | ||||||
|    register_prng(&yarrow_desc); |    register_prng(&yarrow_desc); | ||||||
|    register_hash(&sha1_desc); |    register_hash(&sha256_desc); | ||||||
|    return 0; |    return 0; | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										33
									
								
								demos/test.c
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								demos/test.c
									
									
									
									
									
								
							| @ -259,7 +259,7 @@ void ctr_tests(void) | |||||||
|  for (x = 0; x < 32; x++) blk[x] = count[x] = x; |  for (x = 0; x < 32; x++) blk[x] = count[x] = x; | ||||||
| 
 | 
 | ||||||
|  /* now lets start a ctr session */ |  /* now lets start a ctr session */ | ||||||
|  if ((errno = ctr_start(find_cipher("rijndael"), count, key, 16, 0, &ctr)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } |  if ((errno = ctr_start(find_cipher("aes"), count, key, 16, 0, &ctr)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } | ||||||
| 
 | 
 | ||||||
|  /* now lets encode 32 bytes */ |  /* now lets encode 32 bytes */ | ||||||
|  for (x = 0; x < 4; x++) |  for (x = 0; x < 4; x++) | ||||||
| @ -272,7 +272,7 @@ void ctr_tests(void) | |||||||
|  for (x = 0; x < 32; x++) count[x] = x; |  for (x = 0; x < 32; x++) count[x] = x; | ||||||
| 
 | 
 | ||||||
|  /* now lets start a cbc session */ |  /* now lets start a cbc session */ | ||||||
|  if ((errno = ctr_start(find_cipher("rijndael"), count, key, 16, 0, &ctr)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } |  if ((errno = ctr_start(find_cipher("aes"), count, key, 16, 0, &ctr)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; } | ||||||
| 
 | 
 | ||||||
|  /* now lets decode 32 bytes */ |  /* now lets decode 32 bytes */ | ||||||
|  for (x = 0; x < 4; x++) |  for (x = 0; x < 4; x++) | ||||||
| @ -369,7 +369,7 @@ void rsa_test(void) | |||||||
|  /* now lets test rsa_encrypt() */ |  /* now lets test rsa_encrypt() */ | ||||||
|  for (x = 0; x < 8; x++) in[x] = (unsigned char)x; |  for (x = 0; x < 8; x++) in[x] = (unsigned char)x; | ||||||
|  x = sizeof(out); |  x = sizeof(out); | ||||||
|  if ((errno = rsa_encrypt(in, 8, out, &x, &prng, find_prng("yarrow"), find_cipher("rijndael"), &key)) != CRYPT_OK) { |  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)); |     printf("Error: %s\n", error_to_string(errno)); | ||||||
|     return; |     return; | ||||||
|  } |  } | ||||||
| @ -410,7 +410,7 @@ void rsa_test(void) | |||||||
|  } |  } | ||||||
|  printf("RSA Export takes %lu bytes\n", x); |  printf("RSA Export takes %lu bytes\n", x); | ||||||
|  rsa_free(&key); |  rsa_free(&key); | ||||||
|  if ((errno = rsa_import(out, &key)) != CRYPT_OK) { |  if ((errno = rsa_import(out, &key, x)) != CRYPT_OK) { | ||||||
|     printf("Error: %s\n", error_to_string(errno)); |     printf("Error: %s\n", error_to_string(errno)); | ||||||
|     return; |     return; | ||||||
|  } |  } | ||||||
| @ -596,7 +596,7 @@ void time_ecb(void) | |||||||
|         func = cipher_descriptor[x].ecb_encrypt; |         func = cipher_descriptor[x].ecb_encrypt; | ||||||
|         y1 = 0; |         y1 = 0; | ||||||
|         t1 = XCLOCK(); |         t1 = XCLOCK(); | ||||||
|         while (XCLOCK() - t1 < 2*XCLOCKS_PER_SEC) { |         while (XCLOCK() - t1 < 3*XCLOCKS_PER_SEC) { | ||||||
|             DO256; y1 += 256; |             DO256; y1 += 256; | ||||||
|         } |         } | ||||||
|         t1 = XCLOCK() - t1; |         t1 = XCLOCK() - t1; | ||||||
| @ -604,7 +604,7 @@ void time_ecb(void) | |||||||
|         func = cipher_descriptor[x].ecb_decrypt; |         func = cipher_descriptor[x].ecb_decrypt; | ||||||
|         y2 = 0; |         y2 = 0; | ||||||
|         t2 = XCLOCK(); |         t2 = XCLOCK(); | ||||||
|         while (XCLOCK() - t2 < 2*XCLOCKS_PER_SEC) { |         while (XCLOCK() - t2 < 3*XCLOCKS_PER_SEC) { | ||||||
|             DO256; y2 += 256; |             DO256; y2 += 256; | ||||||
|         } |         } | ||||||
|         t2 = XCLOCK() - t2; |         t2 = XCLOCK() - t2; | ||||||
| @ -673,7 +673,7 @@ void dh_tests(void) | |||||||
|    dh_free(&userb); |    dh_free(&userb); | ||||||
| 
 | 
 | ||||||
|    /* import and make the shared secret again */ |    /* import and make the shared secret again */ | ||||||
|    if ((errno = dh_import(buf[1], &userb)) != CRYPT_OK) { |    if ((errno = dh_import(buf[1], y, &userb)) != CRYPT_OK) { | ||||||
|       printf("Error: %s\n", error_to_string(errno)); |       printf("Error: %s\n", error_to_string(errno)); | ||||||
|       return; |       return; | ||||||
|    } |    } | ||||||
| @ -741,7 +741,7 @@ void dh_tests(void) | |||||||
|    dh_make_key(&prng, find_prng("yarrow"), 24, &usera); |    dh_make_key(&prng, find_prng("yarrow"), 24, &usera); | ||||||
| 
 | 
 | ||||||
|    x = 4096; |    x = 4096; | ||||||
|    if (dh_encrypt(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), find_cipher("rijndael"), |    if (dh_encrypt(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), find_cipher("aes"), | ||||||
|                    find_hash("sha1"), &usera) != CRYPT_OK) { |                    find_hash("sha1"), &usera) != CRYPT_OK) { | ||||||
|       printf("dh_encrypt says %s\n", error_to_string(errno)); |       printf("dh_encrypt says %s\n", error_to_string(errno)); | ||||||
|       return; |       return; | ||||||
| @ -910,7 +910,7 @@ void ecc_tests(void) | |||||||
|    printf("ECC-192 export took %ld bytes\n", y); |    printf("ECC-192 export took %ld bytes\n", y); | ||||||
| 
 | 
 | ||||||
|    /* import and make the shared secret again */ |    /* import and make the shared secret again */ | ||||||
|    if ((errno = ecc_import(buf[1], &userb)) != CRYPT_OK) { |    if ((errno = ecc_import(buf[1], y, &userb)) != CRYPT_OK) { | ||||||
|       printf("Error: %s\n", error_to_string(errno)); |       printf("Error: %s\n", error_to_string(errno)); | ||||||
|       return; |       return; | ||||||
|    } |    } | ||||||
| @ -973,7 +973,7 @@ void ecc_tests(void) | |||||||
|    ecc_make_key(&prng, find_prng("yarrow"), 20, &usera); |    ecc_make_key(&prng, find_prng("yarrow"), 20, &usera); | ||||||
| 
 | 
 | ||||||
|    x = 4096; |    x = 4096; | ||||||
|    if (ecc_encrypt(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), find_cipher("rijndael"), |    if (ecc_encrypt(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), find_cipher("aes"), | ||||||
|                    find_hash("tiger"), &usera) != CRYPT_OK) { |                    find_hash("tiger"), &usera) != CRYPT_OK) { | ||||||
|       printf("ecc_encrypt says %s\n", error_to_string(errno)); |       printf("ecc_encrypt says %s\n", error_to_string(errno)); | ||||||
|       return; |       return; | ||||||
| @ -1158,7 +1158,7 @@ void register_all_algs(void) | |||||||
|    register_cipher(&serpent_desc); |    register_cipher(&serpent_desc); | ||||||
| #endif | #endif | ||||||
| #ifdef RIJNDAEL | #ifdef RIJNDAEL | ||||||
|    register_cipher(&rijndael_desc); |    register_cipher(&aes_desc); | ||||||
| #endif | #endif | ||||||
| #ifdef TWOFISH | #ifdef TWOFISH | ||||||
|    register_cipher(&twofish_desc); |    register_cipher(&twofish_desc); | ||||||
| @ -1179,6 +1179,9 @@ void register_all_algs(void) | |||||||
| #ifdef CAST5 | #ifdef CAST5 | ||||||
|    register_cipher(&cast5_desc); |    register_cipher(&cast5_desc); | ||||||
| #endif | #endif | ||||||
|  | #ifdef NOEKEON | ||||||
|  |    register_cipher(&noekeon_desc); | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
|    register_cipher(&null_desc); |    register_cipher(&null_desc); | ||||||
| 
 | 
 | ||||||
| @ -1284,7 +1287,7 @@ void kr_test(void) | |||||||
|           exit(-1); |           exit(-1); | ||||||
|        } |        } | ||||||
|        kr_display(kr); |        kr_display(kr); | ||||||
|        if ((errno = kr_import(kr, buf)) != CRYPT_OK) { |        if ((errno = kr_import(kr, buf, len)) != CRYPT_OK) { | ||||||
|           printf("Error importing key %d, %s\n", i, error_to_string(errno)); |           printf("Error importing key %d, %s\n", i, error_to_string(errno)); | ||||||
|           exit(-1); |           exit(-1); | ||||||
|        } |        } | ||||||
| @ -1303,7 +1306,7 @@ void kr_test(void) | |||||||
|           exit(-1); |           exit(-1); | ||||||
|        } |        } | ||||||
|        kr_display(kr); |        kr_display(kr); | ||||||
|        if ((errno = kr_import(kr, buf)) != CRYPT_OK) { |        if ((errno = kr_import(kr, buf, len)) != CRYPT_OK) { | ||||||
|           printf("Error importing key %d, %s\n", i, error_to_string(errno)); |           printf("Error importing key %d, %s\n", i, error_to_string(errno)); | ||||||
|           exit(-1); |           exit(-1); | ||||||
|        } |        } | ||||||
| @ -1441,7 +1444,7 @@ void kr_test(void) | |||||||
|    kr_clear(&kr); |    kr_clear(&kr); | ||||||
|    kr_init(&kr); |    kr_init(&kr); | ||||||
|    kr_display(kr); |    kr_display(kr); | ||||||
|    if ((errno = kr_import(kr, buf)) != CRYPT_OK) { |    if ((errno = kr_import(kr, buf, len)) != CRYPT_OK) { | ||||||
|       printf("Error importing key %s\n", error_to_string(errno)); |       printf("Error importing key %s\n", error_to_string(errno)); | ||||||
|       exit(-1); |       exit(-1); | ||||||
|    } |    } | ||||||
| @ -1459,7 +1462,7 @@ void kr_test(void) | |||||||
|    kr_clear(&kr); |    kr_clear(&kr); | ||||||
|    kr_init(&kr); |    kr_init(&kr); | ||||||
|    kr_display(kr); |    kr_display(kr); | ||||||
|    if ((errno = kr_import(kr, buf2)) != CRYPT_OK) { |    if ((errno = kr_import(kr, buf2, len)) != CRYPT_OK) { | ||||||
|       printf("Error importing key %s\n", error_to_string(errno)); |       printf("Error importing key %s\n", error_to_string(errno)); | ||||||
|       exit(-1); |       exit(-1); | ||||||
|    } |    } | ||||||
|  | |||||||
							
								
								
									
										20
									
								
								dh.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								dh.c
									
									
									
									
									
								
							| @ -315,18 +315,22 @@ void dh_free(dh_key *key) | |||||||
| #define INPUT_BIGNUM(num, in, x, y)                              \ | #define INPUT_BIGNUM(num, in, x, y)                              \ | ||||||
| {                                                                \ | {                                                                \ | ||||||
|      /* load value */                                            \ |      /* load value */                                            \ | ||||||
|  |      if (y + 4 > inlen) {                                        \ | ||||||
|  |         errno = CRYPT_INVALID_PACKET;                            \ | ||||||
|  |         goto error;                                              \ | ||||||
|  |      }                                                           \ | ||||||
|      LOAD32L(x, in+y);                                           \ |      LOAD32L(x, in+y);                                           \ | ||||||
|      y += 4;                                                     \ |      y += 4;                                                     \ | ||||||
|                                                                  \ |                                                                  \ | ||||||
|      /* sanity check... */                                       \ |      /* sanity check... */                                       \ | ||||||
|      if (x > 1024) {                                             \ |      if (x+y > inlen) {                                          \ | ||||||
|         errno = CRYPT_ERROR;                                     \ |         errno = CRYPT_INVALID_PACKET;                            \ | ||||||
|         goto error;                                              \ |         goto error;                                              \ | ||||||
|      }                                                           \ |      }                                                           \ | ||||||
|                                                                  \ |                                                                  \ | ||||||
|      /* load it */                                               \ |      /* load it */                                               \ | ||||||
|      if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\ |      if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\ | ||||||
|         return CRYPT_MEM;                                        \ |         errno =  CRYPT_MEM;                                        \ | ||||||
|         goto error;                                              \ |         goto error;                                              \ | ||||||
|      }                                                           \ |      }                                                           \ | ||||||
|      y += x;                                                     \ |      y += x;                                                     \ | ||||||
| @ -381,9 +385,9 @@ int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key) | |||||||
|    return CRYPT_OK; |    return CRYPT_OK; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int dh_import(const unsigned char *in, dh_key *key) | int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key) | ||||||
| { | { | ||||||
|    long x, y, s; |    unsigned long x, y, s; | ||||||
|    int errno; |    int errno; | ||||||
| 
 | 
 | ||||||
|    _ARGCHK(in != NULL); |    _ARGCHK(in != NULL); | ||||||
| @ -394,6 +398,10 @@ int dh_import(const unsigned char *in, dh_key *key) | |||||||
|       return errno; |       return errno; | ||||||
|    } |    } | ||||||
|     |     | ||||||
|  |    if (2+PACKET_SIZE > inlen) { | ||||||
|  |       return CRYPT_INVALID_PACKET; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|    /* init */ |    /* init */ | ||||||
|    if (mp_init_multi(&key->x, &key->y, NULL) != MP_OKAY) {  |    if (mp_init_multi(&key->x, &key->y, NULL) != MP_OKAY) {  | ||||||
|       return CRYPT_MEM; |       return CRYPT_MEM; | ||||||
| @ -403,7 +411,7 @@ int dh_import(const unsigned char *in, dh_key *key) | |||||||
|    key->type = in[y++]; |    key->type = in[y++]; | ||||||
|    s  = (long)in[y++] * 8; |    s  = (long)in[y++] * 8; | ||||||
|     |     | ||||||
|    for (x = 0; (s > sets[x].size) && (sets[x].size); x++); |    for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size); x++); | ||||||
|    if (sets[x].size == 0) { |    if (sets[x].size == 0) { | ||||||
|       errno = CRYPT_INVALID_KEYSIZE; |       errno = CRYPT_INVALID_KEYSIZE; | ||||||
|       goto error; |       goto error; | ||||||
|  | |||||||
							
								
								
									
										431
									
								
								dh_sys.c
									
									
									
									
									
								
							
							
						
						
									
										431
									
								
								dh_sys.c
									
									
									
									
									
								
							| @ -1,432 +1,3 @@ | |||||||
| #ifdef PK_PACKET |  | ||||||
| 
 |  | ||||||
| int dh_encrypt(const unsigned char *in,  unsigned long len,  |  | ||||||
|                      unsigned char *out, unsigned long *outlen, |  | ||||||
|                      prng_state *prng, int wprng, int cipher, int hash,  |  | ||||||
|                      dh_key *key) |  | ||||||
| { |  | ||||||
|     unsigned char pub_expt[1536], dh_shared[1536], IV[MAXBLOCKSIZE], skey[MAXBLOCKSIZE]; |  | ||||||
|     dh_key pubkey; |  | ||||||
|     unsigned long x, y, z, hashsize, blocksize, pubkeysize; |  | ||||||
|     int keysize, errno; |  | ||||||
|     symmetric_CTR ctr; |  | ||||||
| 
 |  | ||||||
|     _ARGCHK(in != NULL); |  | ||||||
|     _ARGCHK(out != NULL); |  | ||||||
|     _ARGCHK(outlen != NULL); |  | ||||||
|     _ARGCHK(key != NULL); |  | ||||||
| 
 |  | ||||||
|     /* check that wprng/cipher/hash are not invalid */ |  | ||||||
|     if ((errno = prng_is_valid(wprng)) != CRYPT_OK) { |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if ((errno = hash_is_valid(hash)) != CRYPT_OK) { |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if ((errno = cipher_is_valid(cipher)) != CRYPT_OK) { |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* make a random key and export the public copy */ |  | ||||||
|     if ((errno = dh_make_key(prng, wprng, dh_get_size(key), &pubkey)) != CRYPT_OK) { |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pubkeysize = sizeof(pub_expt); |  | ||||||
|     if ((errno = dh_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) { |  | ||||||
|        dh_free(&pubkey); |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     /* now check if the out buffer is big enough */ |  | ||||||
|     if (*outlen < (10 + PACKET_SIZE + pubkeysize + cipher_descriptor[cipher].block_length + len)) { |  | ||||||
|        dh_free(&pubkey); |  | ||||||
|        return CRYPT_BUFFER_OVERFLOW; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* make random key */ |  | ||||||
|     blocksize = cipher_descriptor[cipher].block_length; |  | ||||||
|     hashsize  = hash_descriptor[hash].hashsize; |  | ||||||
|     keysize = hashsize; |  | ||||||
|     if ((errno = cipher_descriptor[cipher].keysize(&keysize)) != CRYPT_OK) { |  | ||||||
|        dh_free(&pubkey); |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     x = sizeof(dh_shared); |  | ||||||
|     if ((errno = dh_shared_secret(&pubkey, key, dh_shared, &x)) != CRYPT_OK) { |  | ||||||
|        dh_free(&pubkey); |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
|     dh_free(&pubkey); |  | ||||||
| 
 |  | ||||||
|     z = sizeof(skey); |  | ||||||
|     if ((errno = hash_memory(hash, dh_shared, x, skey, &z)) != CRYPT_OK) { |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* make up IV */ |  | ||||||
|     if (prng_descriptor[wprng].read(IV, cipher_descriptor[cipher].block_length, prng) !=  |  | ||||||
|         cipher_descriptor[cipher].block_length) { |  | ||||||
|        return CRYPT_ERROR_READPRNG; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* setup CTR mode */ |  | ||||||
|     if ((errno = ctr_start(cipher, IV, skey, keysize, 0, &ctr)) != CRYPT_OK) { |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* output header */ |  | ||||||
|     y = PACKET_SIZE; |  | ||||||
|   |  | ||||||
|     /* size of cipher name and the name itself */ |  | ||||||
|     out[y++] = cipher_descriptor[cipher].ID; |  | ||||||
| 
 |  | ||||||
|     /* size of hash name and the name itself */ |  | ||||||
|     out[y++] = hash_descriptor[hash].ID; |  | ||||||
| 
 |  | ||||||
|     /* length of DH pubkey and the key itself */ |  | ||||||
|     STORE32L(pubkeysize, out+y); |  | ||||||
|     y += 4; |  | ||||||
|     for (x = 0; x < pubkeysize; x++, y++) { |  | ||||||
|         out[y] = pub_expt[x]; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* cipher IV */ |  | ||||||
|     for (x = 0; x < blocksize; x++, y++) { |  | ||||||
|         out[y] = IV[x]; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* length of ciphertext */ |  | ||||||
|     STORE32L(len, out+y); |  | ||||||
|     y += 4; |  | ||||||
| 
 |  | ||||||
|     /* encrypt the message */ |  | ||||||
|     if ((errno = ctr_encrypt(in, out+y, len, &ctr)) != CRYPT_OK) { |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
|     y += len; |  | ||||||
| 
 |  | ||||||
|     /* store header */ |  | ||||||
|     packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_ENCRYPTED, y); |  | ||||||
| 
 |  | ||||||
| #ifdef CLEAN_STACK |  | ||||||
|     /* clean up */ |  | ||||||
|     zeromem(pub_expt, sizeof(pub_expt)); |  | ||||||
|     zeromem(dh_shared, sizeof(dh_shared)); |  | ||||||
|     zeromem(skey, sizeof(skey)); |  | ||||||
|     zeromem(IV, sizeof(IV)); |  | ||||||
|     zeromem(&ctr, sizeof(ctr)); |  | ||||||
| #endif |  | ||||||
|     *outlen = y; |  | ||||||
|     return CRYPT_OK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int dh_decrypt(const unsigned char *in,  unsigned long len,  |  | ||||||
|                      unsigned char *out, unsigned long *outlen,  |  | ||||||
|                      dh_key *key) |  | ||||||
| { |  | ||||||
|    unsigned char shared_secret[1536], skey[MAXBLOCKSIZE]; |  | ||||||
|    unsigned long x, y, z, res, hashsize, blocksize; |  | ||||||
|    int hash, cipher, keysize, errno; |  | ||||||
|    dh_key pubkey; |  | ||||||
|    symmetric_CTR ctr; |  | ||||||
| 
 |  | ||||||
|    _ARGCHK(in != NULL); |  | ||||||
|    _ARGCHK(out != NULL); |  | ||||||
|    _ARGCHK(outlen != NULL); |  | ||||||
|    _ARGCHK(key != NULL); |  | ||||||
| 
 |  | ||||||
|    /* right key type? */ |  | ||||||
|    if (key->type != PK_PRIVATE) { |  | ||||||
|       return CRYPT_PK_NOT_PRIVATE; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* is header correct? */ |  | ||||||
|    if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_ENCRYPTED)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* now lets get the cipher name */ |  | ||||||
|    y = PACKET_SIZE; |  | ||||||
|    cipher = find_cipher_id(in[y++]); |  | ||||||
|    if (cipher == -1) { |  | ||||||
|       return CRYPT_INVALID_CIPHER; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* now lets get the hash name */ |  | ||||||
|    hash = find_hash_id(in[y++]); |  | ||||||
|    if (hash == -1) { |  | ||||||
|       return CRYPT_INVALID_HASH; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* common values */ |  | ||||||
|    blocksize = cipher_descriptor[cipher].block_length; |  | ||||||
|    hashsize  = hash_descriptor[hash].hashsize; |  | ||||||
|    keysize = hashsize; |  | ||||||
|    if ((errno = cipher_descriptor[cipher].keysize(&keysize)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* get public key */ |  | ||||||
|    LOAD32L(x, in+y); |  | ||||||
|    y += 4; |  | ||||||
|    if ((errno = dh_import(in+y, &pubkey)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
|    y += x; |  | ||||||
| 
 |  | ||||||
|    /* make shared key */ |  | ||||||
|    x = sizeof(shared_secret); |  | ||||||
|    if ((errno = dh_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) { |  | ||||||
|       dh_free(&pubkey); |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
|    dh_free(&pubkey); |  | ||||||
| 
 |  | ||||||
|    z = sizeof(skey); |  | ||||||
|    if ((errno = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* setup CTR mode */ |  | ||||||
|    if ((errno = ctr_start(cipher, in+y, skey, keysize, 0, &ctr)) != CRYPT_OK) { |  | ||||||
|       res = errno; |  | ||||||
|       goto done; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* skip over the IV */ |  | ||||||
|    y += blocksize; |  | ||||||
| 
 |  | ||||||
|    /* get length */ |  | ||||||
|    LOAD32L(len,in+y); |  | ||||||
|    y += 4; |  | ||||||
| 
 |  | ||||||
|    /* buffer overflow? */ |  | ||||||
|    if (len > *outlen) { |  | ||||||
|       res = CRYPT_BUFFER_OVERFLOW; |  | ||||||
|       goto done; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* decrypt message */ |  | ||||||
|    if ((errno = ctr_decrypt(in+y, out, len, &ctr)) != CRYPT_OK) { |  | ||||||
|       res = errno; |  | ||||||
|       goto done; |  | ||||||
|    } |  | ||||||
|    *outlen = len; |  | ||||||
|     |  | ||||||
|    res = CRYPT_OK; |  | ||||||
| done: |  | ||||||
| #ifdef CLEAN_STACK |  | ||||||
|    zeromem(shared_secret, sizeof(shared_secret)); |  | ||||||
|    zeromem(skey, sizeof(skey)); |  | ||||||
|    zeromem(&ctr, sizeof(ctr)); |  | ||||||
| #endif |  | ||||||
|    return res; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int dh_sign(const unsigned char *in,  unsigned long inlen, |  | ||||||
|                   unsigned char *out, unsigned long *outlen, |  | ||||||
|                   int hash, prng_state *prng, int wprng, |  | ||||||
|                   dh_key *key) |  | ||||||
| { |  | ||||||
|    mp_int a, b, k, m, g, p, p1, tmp; |  | ||||||
|    unsigned char buf[1536], md[MAXBLOCKSIZE]; |  | ||||||
|    unsigned long x, y, z; |  | ||||||
|    int res, errno; |  | ||||||
| 
 |  | ||||||
|     _ARGCHK(in != NULL); |  | ||||||
|     _ARGCHK(out != NULL); |  | ||||||
|     _ARGCHK(outlen != NULL); |  | ||||||
|     _ARGCHK(key != NULL); |  | ||||||
| 
 |  | ||||||
|    /* check parameters */ |  | ||||||
|    if (key->type != PK_PRIVATE) { |  | ||||||
|       return CRYPT_PK_NOT_PRIVATE; |  | ||||||
|    } |  | ||||||
|     |  | ||||||
|    /* is the IDX valid ?  */ |  | ||||||
|    if (!is_valid_idx(key->idx)) { |  | ||||||
|       return CRYPT_PK_INVALID_TYPE; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    if ((errno = prng_is_valid(wprng)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    if ((errno = hash_is_valid(hash)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* hash the message */ |  | ||||||
|    z = sizeof(md) - 1; |  | ||||||
|    md[0] = 0; |  | ||||||
|    if ((errno = hash_memory(hash, in, inlen, md+1, &z)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* make up a random value k,
 |  | ||||||
|     * since the order of the group is prime |  | ||||||
|     * we need not check if gcd(k, r) is 1  |  | ||||||
|     */ |  | ||||||
|    buf[0] = 0; |  | ||||||
|    if (prng_descriptor[wprng].read(buf+1, sets[key->idx].size-1, prng) != (unsigned long)(sets[key->idx].size-1)) { |  | ||||||
|       return CRYPT_ERROR_READPRNG; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* init bignums */ |  | ||||||
|    if (mp_init_multi(&a, &b, &k, &m, &p, &g, &p1, &tmp, NULL) != MP_OKAY) {  |  | ||||||
|       return CRYPT_MEM; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* load k and m */ |  | ||||||
|    if (mp_read_raw(&m, md,  1+hash_descriptor[hash].hashsize) != MP_OKAY)     { goto error; } |  | ||||||
|    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_sub_d(&p, 1, &p1) != MP_OKAY)                         { goto error; } /* p1 = p-1 */ |  | ||||||
|    if (mp_div_2(&p1, &p1) != MP_OKAY)                           { goto error; } /* p1 = (p-1)/2 */ |  | ||||||
| 
 |  | ||||||
|    /* now get a = g^k mod p */ |  | ||||||
|    if (mp_exptmod(&g, &k, &p, &a) != MP_OKAY)                   { goto error; } /* a = g^k mod p */ |  | ||||||
| 
 |  | ||||||
|    /* now find M = xa + kb mod p1 or just b = (M - xa)/k mod p1 */ |  | ||||||
|    if (mp_invmod(&k, &p1, &k) != MP_OKAY)                       { goto error; } /* k = 1/k mod p1 */ |  | ||||||
|    if (mp_mulmod(&a, &key->x, &p1, &tmp) != MP_OKAY)            { goto error; } /* tmp = xa */ |  | ||||||
|    if (mp_submod(&m, &tmp, &p1, &tmp) != MP_OKAY)               { goto error; } /* tmp = M - xa */ |  | ||||||
|    if (mp_mulmod(&k, &tmp, &p1, &b) != MP_OKAY)                 { goto error; } /* b = (M - xa)/k */ |  | ||||||
| 
 |  | ||||||
|    /* store header  */ |  | ||||||
|    y = PACKET_SIZE; |  | ||||||
| 
 |  | ||||||
|    /* store length and name of hash */ |  | ||||||
|    buf[y++] = hash_descriptor[hash].ID;                         /* store hash ID */ |  | ||||||
|   |  | ||||||
|    /* now store them both (a,b) */ |  | ||||||
|    x = mp_raw_size(&a);                                         /* get raw size of a */ |  | ||||||
|    STORE32L(x, buf+y);  y += 4;                                 /* store size of a */ |  | ||||||
|    mp_toraw(&a, buf+y); y += x;                                 /* store a itself */ |  | ||||||
| 
 |  | ||||||
|    x = mp_raw_size(&b);                                         /* get raw size of b */ |  | ||||||
|    STORE32L(x, buf+y);  y += 4;                                 /* store size of b */ |  | ||||||
|    mp_toraw(&b, buf+y); y += x;                                 /* store b itself */ |  | ||||||
| 
 |  | ||||||
|    /* check if size too big */ |  | ||||||
|    if (*outlen < y) { goto error; } |  | ||||||
| 
 |  | ||||||
|    /* store header */ |  | ||||||
|    packet_store_header(buf, PACKET_SECT_DH, PACKET_SUB_SIGNED, y); |  | ||||||
| 
 |  | ||||||
|    /* store it */ |  | ||||||
|    memcpy(out, buf, y); |  | ||||||
|    *outlen = y; |  | ||||||
| 
 |  | ||||||
| #ifdef CLEAN_STACK |  | ||||||
|    zeromem(md, sizeof(md)); |  | ||||||
|    zeromem(buf, sizeof(buf)); |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|    res = CRYPT_OK; |  | ||||||
|    goto done; |  | ||||||
| error: |  | ||||||
|    res = CRYPT_MEM; |  | ||||||
| done: |  | ||||||
|    mp_clear_multi(&tmp, &p1, &g, &p, &m, &k, &b, &a, NULL); |  | ||||||
|    return res; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int dh_verify(const unsigned char *sig, const unsigned char *msg,  |  | ||||||
|                     unsigned long inlen, int *stat,  |  | ||||||
|                     dh_key *key) |  | ||||||
| { |  | ||||||
|    mp_int a, b, p, g, m, tmp; |  | ||||||
|    unsigned char md[MAXBLOCKSIZE]; |  | ||||||
|    unsigned long x, y, z; |  | ||||||
|    int hash, res, errno; |  | ||||||
| 
 |  | ||||||
|    _ARGCHK(sig != NULL); |  | ||||||
|    _ARGCHK(msg != NULL); |  | ||||||
|    _ARGCHK(stat != NULL); |  | ||||||
|    _ARGCHK(key != NULL); |  | ||||||
| 
 |  | ||||||
|    /* default to invalid */ |  | ||||||
|    *stat = 0; |  | ||||||
| 
 |  | ||||||
|    /* 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 = find_hash_id(sig[y++]); |  | ||||||
| 
 |  | ||||||
|    if (hash == -1) { |  | ||||||
|       return CRYPT_INVALID_HASH; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* hash the message */ |  | ||||||
|    md[0] = 0; |  | ||||||
|    z = sizeof(md) - 1; |  | ||||||
|    if ((errno = hash_memory(hash, msg, inlen, md+1, &z)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* init all bignums */ |  | ||||||
|    if (mp_init_multi(&a, &p, &b, &g, &m, &tmp, NULL) != MP_OKAY) {  |  | ||||||
|       return CRYPT_MEM; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* load a and b */ |  | ||||||
|    LOAD32L(x, sig+y); |  | ||||||
|    y += 4; |  | ||||||
|    if (mp_read_raw(&a, (unsigned char *)sig+y, x) != MP_OKAY)        { goto error; } |  | ||||||
|    y += x; |  | ||||||
| 
 |  | ||||||
|    LOAD32L(x, sig+y); |  | ||||||
|    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; } |  | ||||||
| 
 |  | ||||||
|    /* load m */ |  | ||||||
|    if (mp_read_raw(&m, md, hash_descriptor[hash].hashsize + 1) != 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 */ |  | ||||||
| 
 |  | ||||||
|    /* find y^a * a^b */ |  | ||||||
|    if (mp_exptmod(&key->y, &a, &p, &tmp) != MP_OKAY)                 { goto error; } /* tmp = y^a mod p */ |  | ||||||
|    if (mp_exptmod(&a, &b, &p, &a) != MP_OKAY)                        { goto error; } /* a = a^b mod p */ |  | ||||||
|    if (mp_mulmod(&a, &tmp, &p, &a) != MP_OKAY)                       { goto error; } /* a = y^a * a^b mod p */ |  | ||||||
| 
 |  | ||||||
|    /* y^a * a^b == g^m ??? */ |  | ||||||
|    if (mp_cmp(&a, &m) == 0) { |  | ||||||
|       *stat = 1; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* clean up */ |  | ||||||
|    res = CRYPT_OK; |  | ||||||
|    goto done; |  | ||||||
| error: |  | ||||||
|    res = CRYPT_MEM; |  | ||||||
| done: |  | ||||||
|    mp_clear_multi(&tmp, &m, &g, &p, &b, &a, NULL); |  | ||||||
| #ifdef CLEAN_STACK |  | ||||||
|    zeromem(md, sizeof(md)); |  | ||||||
| #endif |  | ||||||
|    return res; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen, | int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen, | ||||||
|                          unsigned char *out,  unsigned long *len, |                          unsigned char *out,  unsigned long *len, | ||||||
|                          prng_state *prng, int wprng, int hash, |                          prng_state *prng, int wprng, int hash, | ||||||
| @ -558,7 +129,7 @@ int dh_decrypt_key(const unsigned char *in, unsigned char *outkey, | |||||||
|    /* get public key */ |    /* get public key */ | ||||||
|    LOAD32L(x, in+y); |    LOAD32L(x, in+y); | ||||||
|    y += 4; |    y += 4; | ||||||
|    if ((errno = dh_import(in+y, &pubkey)) != CRYPT_OK) { |    if ((errno = dh_import(in+y, x, &pubkey)) != CRYPT_OK) { | ||||||
|       return errno; |       return errno; | ||||||
|    } |    } | ||||||
|    y += x; |    y += x; | ||||||
|  | |||||||
							
								
								
									
										39
									
								
								ecc.c
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								ecc.c
									
									
									
									
									
								
							| @ -636,16 +636,22 @@ done: | |||||||
| #define INPUT_BIGNUM(num, in, x, y)                              \ | #define INPUT_BIGNUM(num, in, x, y)                              \ | ||||||
| {                                                                \ | {                                                                \ | ||||||
|      /* load value */                                            \ |      /* load value */                                            \ | ||||||
|  |      if (y+4 > inlen) {                                          \ | ||||||
|  |         errno = CRYPT_INVALID_PACKET;                            \ | ||||||
|  |         goto error;                                              \ | ||||||
|  |      }                                                           \ | ||||||
|      LOAD32L(x, in+y);                                           \ |      LOAD32L(x, in+y);                                           \ | ||||||
|      y += 4;                                                     \ |      y += 4;                                                     \ | ||||||
|                                                                  \ |                                                                  \ | ||||||
|      /* sanity check... */                                       \ |      /* sanity check... */                                       \ | ||||||
|      if (x > 1024) {                                             \ |      if (y+x > inlen) {                                          \ | ||||||
|  |         errno = CRYPT_INVALID_PACKET;                            \ | ||||||
|         goto error;                                              \ |         goto error;                                              \ | ||||||
|      }                                                           \ |      }                                                           \ | ||||||
|                                                                  \ |                                                                  \ | ||||||
|      /* load it */                                               \ |      /* load it */                                               \ | ||||||
|      if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\ |      if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\ | ||||||
|  |         errno = CRYPT_MEM;                                       \ | ||||||
|         goto error;                                              \ |         goto error;                                              \ | ||||||
|      }                                                           \ |      }                                                           \ | ||||||
|      y += x;                                                     \ |      y += x;                                                     \ | ||||||
| @ -701,10 +707,10 @@ int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key | |||||||
|    return CRYPT_OK; |    return CRYPT_OK; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int ecc_import(const unsigned char *in, ecc_key *key) | int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key) | ||||||
| { | { | ||||||
|    unsigned long x, y, s; |    unsigned long x, y, s; | ||||||
|    int res, errno; |    int errno; | ||||||
| 
 | 
 | ||||||
|    _ARGCHK(in != NULL); |    _ARGCHK(in != NULL); | ||||||
|    _ARGCHK(key != NULL); |    _ARGCHK(key != NULL); | ||||||
| @ -714,6 +720,10 @@ int ecc_import(const unsigned char *in, ecc_key *key) | |||||||
|       return errno; |       return errno; | ||||||
|    } |    } | ||||||
|     |     | ||||||
|  |    if (2+PACKET_SIZE > inlen) { | ||||||
|  |       return CRYPT_INVALID_PACKET; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|    /* init key */ |    /* init key */ | ||||||
|    if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL) != MP_OKAY) { |    if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL) != MP_OKAY) { | ||||||
|       return CRYPT_MEM; |       return CRYPT_MEM; | ||||||
| @ -725,21 +735,21 @@ int ecc_import(const unsigned char *in, ecc_key *key) | |||||||
|     |     | ||||||
|    for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size); x++); |    for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size); x++); | ||||||
|    if (sets[x].size == 0) {  |    if (sets[x].size == 0) {  | ||||||
|       res = CRYPT_INVALID_KEYSIZE; |       errno = CRYPT_INVALID_KEYSIZE; | ||||||
|       goto error2; |       goto error; | ||||||
|    } |    } | ||||||
|    key->idx = x; |    key->idx = x; | ||||||
| 
 | 
 | ||||||
|    /* type check both values */ |    /* type check both values */ | ||||||
|    if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE))  { |    if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE))  { | ||||||
|       res = CRYPT_INVALID_PACKET; |       errno = CRYPT_INVALID_PACKET; | ||||||
|       goto error2; |       goto error; | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    /* is the key idx valid? */ |    /* is the key idx valid? */ | ||||||
|    if (!is_valid_idx(key->idx)) { |    if (!is_valid_idx(key->idx)) { | ||||||
|       res = CRYPT_INVALID_PACKET; |       errno = CRYPT_INVALID_PACKET; | ||||||
|       goto error2; |       goto error; | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    /* load x coordinate */ |    /* load x coordinate */ | ||||||
| @ -747,20 +757,19 @@ int ecc_import(const unsigned char *in, ecc_key *key) | |||||||
|    |    | ||||||
|    /* load y */ |    /* load y */ | ||||||
|    x = in[y++]; |    x = in[y++]; | ||||||
|    if ((errno = expand_y_point(&key->pubkey, key->idx, x)) != CRYPT_OK) { res = errno; goto error2; } |    if ((errno = expand_y_point(&key->pubkey, key->idx, x)) != CRYPT_OK) {  | ||||||
|  |        goto error;  | ||||||
|  |    } | ||||||
| 
 | 
 | ||||||
|    if (key->type == PK_PRIVATE) { |    if (key->type == PK_PRIVATE) { | ||||||
|       /* load private key */ |       /* load private key */ | ||||||
|       INPUT_BIGNUM(&key->k, in, x, y); |       INPUT_BIGNUM(&key->k, in, x, y); | ||||||
|    } |    } | ||||||
|    res = CRYPT_OK; |    return CRYPT_OK; | ||||||
|    goto done; |  | ||||||
| error: | error: | ||||||
|    res = CRYPT_MEM; |  | ||||||
| error2: |  | ||||||
|    mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL); |    mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL); | ||||||
| done: | done: | ||||||
|    return res; |    return errno; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,  | int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,  | ||||||
|  | |||||||
							
								
								
									
										491
									
								
								ecc_sys.c
									
									
									
									
									
								
							
							
						
						
									
										491
									
								
								ecc_sys.c
									
									
									
									
									
								
							| @ -1,490 +1,3 @@ | |||||||
| #ifdef PK_PACKET |  | ||||||
| 
 |  | ||||||
| int ecc_encrypt(const unsigned char *in,  unsigned long len,  |  | ||||||
|                       unsigned char *out, unsigned long *outlen, |  | ||||||
|                       prng_state *prng, int wprng, int cipher, int hash,  |  | ||||||
|                       ecc_key *key) |  | ||||||
| { |  | ||||||
|     unsigned char pub_expt[512], ecc_shared[256], IV[MAXBLOCKSIZE], skey[MAXBLOCKSIZE]; |  | ||||||
|     ecc_key pubkey; |  | ||||||
|     unsigned long x, y, z, pubkeysize; |  | ||||||
|     int keysize, blocksize, hashsize, errno; |  | ||||||
|     symmetric_CTR ctr; |  | ||||||
| 
 |  | ||||||
|     _ARGCHK(in != NULL); |  | ||||||
|     _ARGCHK(out != NULL); |  | ||||||
|     _ARGCHK(outlen != NULL); |  | ||||||
|     _ARGCHK(key != NULL); |  | ||||||
| 
 |  | ||||||
|     /* check that wprng/cipher/hash are not invalid */ |  | ||||||
|     if ((errno = prng_is_valid(wprng)) != CRYPT_OK) { |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if ((errno = cipher_is_valid(cipher)) != CRYPT_OK) { |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if ((errno = hash_is_valid(hash)) != CRYPT_OK) { |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* make a random key and export the public copy */ |  | ||||||
|     if ((errno = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) { |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pubkeysize = sizeof(pub_expt); |  | ||||||
|     if ((errno = ecc_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) { |  | ||||||
|        ecc_free(&pubkey); |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     /* now check if the out buffer is big enough */ |  | ||||||
|     if (*outlen < (10 + PACKET_SIZE + pubkeysize +  |  | ||||||
|                    cipher_descriptor[cipher].block_length + len)) { |  | ||||||
|        ecc_free(&pubkey); |  | ||||||
|        return CRYPT_BUFFER_OVERFLOW; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* make random key */ |  | ||||||
|     blocksize = cipher_descriptor[cipher].block_length; |  | ||||||
|     hashsize  = hash_descriptor[hash].hashsize; |  | ||||||
|     keysize = hashsize; |  | ||||||
|     if ((errno = cipher_descriptor[cipher].keysize(&keysize)) != CRYPT_OK) { |  | ||||||
|        ecc_free(&pubkey); |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
|     x = sizeof(ecc_shared); |  | ||||||
|     if ((errno = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) { |  | ||||||
|        ecc_free(&pubkey); |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
|     ecc_free(&pubkey); |  | ||||||
| 
 |  | ||||||
|     z = sizeof(skey); |  | ||||||
|     if ((errno = hash_memory(hash, ecc_shared, x, skey, &z)) != CRYPT_OK) { |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* make up IV */ |  | ||||||
|     if (prng_descriptor[wprng].read(IV, cipher_descriptor[cipher].block_length, prng) !=  |  | ||||||
|         (unsigned long)cipher_descriptor[cipher].block_length) { |  | ||||||
|        return CRYPT_ERROR_READPRNG; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* setup CTR mode */ |  | ||||||
|     if ((errno = ctr_start(cipher, IV, skey, keysize, 0, &ctr)) != CRYPT_OK) { |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* output header */ |  | ||||||
|     y = PACKET_SIZE; |  | ||||||
| 
 |  | ||||||
|     /* size of cipher name and the name itself */ |  | ||||||
|     out[y++] = cipher_descriptor[cipher].ID; |  | ||||||
| 
 |  | ||||||
|     /* size of hash name and the name itself */ |  | ||||||
|     out[y++] = hash_descriptor[hash].ID; |  | ||||||
| 
 |  | ||||||
|     /* length of ECC pubkey and the key itself */ |  | ||||||
|     STORE32L(pubkeysize, out+y); |  | ||||||
|     y += 4; |  | ||||||
|     for (x = 0; x < (unsigned)pubkeysize; x++, y++) { |  | ||||||
|         out[y] = pub_expt[x]; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* cipher IV */ |  | ||||||
|     for (x = 0; x < (unsigned)blocksize; x++, y++) { |  | ||||||
|         out[y] = IV[x]; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* length of ciphertext */ |  | ||||||
|     STORE32L(len, out+y); |  | ||||||
|     y += 4; |  | ||||||
| 
 |  | ||||||
|     /* encrypt the message */ |  | ||||||
|     if ((errno = ctr_encrypt(in, out+y, len, &ctr)) != CRYPT_OK) { |  | ||||||
|        return errno; |  | ||||||
|     } |  | ||||||
|     y += len; |  | ||||||
|      |  | ||||||
|     /* store header */ |  | ||||||
|     packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_ENCRYPTED, y); |  | ||||||
| 
 |  | ||||||
| #ifdef CLEAN_STACK |  | ||||||
|     /* clean up */ |  | ||||||
|     zeromem(pub_expt, sizeof(pub_expt)); |  | ||||||
|     zeromem(ecc_shared, sizeof(ecc_shared)); |  | ||||||
|     zeromem(skey, sizeof(skey)); |  | ||||||
|     zeromem(IV, sizeof(IV)); |  | ||||||
|     zeromem(&ctr, sizeof(ctr)); |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|     *outlen = y; |  | ||||||
|     return CRYPT_OK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int ecc_decrypt(const unsigned char *in,  unsigned long len,  |  | ||||||
|                       unsigned char *out, unsigned long *outlen,  |  | ||||||
|                       ecc_key *key) |  | ||||||
| { |  | ||||||
|    unsigned char shared_secret[256], skey[MAXBLOCKSIZE]; |  | ||||||
|    unsigned long x, y, z, res, hashsize, blocksize; |  | ||||||
|    int cipher, hash, keysize, errno; |  | ||||||
|    ecc_key pubkey; |  | ||||||
|    symmetric_CTR ctr; |  | ||||||
| 
 |  | ||||||
|    _ARGCHK(in != NULL); |  | ||||||
|    _ARGCHK(out != NULL); |  | ||||||
|    _ARGCHK(outlen != NULL); |  | ||||||
|    _ARGCHK(key != NULL); |  | ||||||
| 
 |  | ||||||
|    /* right key type? */ |  | ||||||
|    if (key->type != PK_PRIVATE) { |  | ||||||
|       return CRYPT_PK_NOT_PRIVATE; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* is header correct? */ |  | ||||||
|    if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_ENCRYPTED)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* now lets get the cipher name */ |  | ||||||
|    y = PACKET_SIZE; |  | ||||||
|    cipher = find_cipher_id(in[y++]); |  | ||||||
|    if (cipher == -1) { |  | ||||||
|       return CRYPT_INVALID_CIPHER; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* now lets get the hash name */ |  | ||||||
|    hash = find_hash_id(in[y++]); |  | ||||||
|    if (hash == -1) { |  | ||||||
|       return CRYPT_INVALID_HASH; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* common values */ |  | ||||||
|    blocksize = cipher_descriptor[cipher].block_length; |  | ||||||
|    hashsize  = hash_descriptor[hash].hashsize; |  | ||||||
|    keysize = hashsize; |  | ||||||
|    if ((errno = cipher_descriptor[cipher].keysize(&keysize)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* get public key */ |  | ||||||
|    LOAD32L(x, in+y); |  | ||||||
|    y += 4; |  | ||||||
|    if ((errno = ecc_import(in+y, &pubkey)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
|    y += x; |  | ||||||
| 
 |  | ||||||
|    /* make shared key */ |  | ||||||
|    x = sizeof(shared_secret); |  | ||||||
|    if ((errno = ecc_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) { |  | ||||||
|       ecc_free(&pubkey); |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
|    ecc_free(&pubkey); |  | ||||||
| 
 |  | ||||||
|    z = sizeof(skey); |  | ||||||
|    if ((errno = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) { |  | ||||||
|       res = errno; |  | ||||||
|       goto done; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* setup CTR mode */ |  | ||||||
|    if ((errno = ctr_start(cipher, in+y, skey, keysize, 0, &ctr)) != CRYPT_OK) { |  | ||||||
|       res = errno; |  | ||||||
|       goto done; |  | ||||||
|    } |  | ||||||
|    y += blocksize; |  | ||||||
| 
 |  | ||||||
|    /* get length */ |  | ||||||
|    LOAD32L(len,in+y); |  | ||||||
|    y += 4; |  | ||||||
|     |  | ||||||
|    /* buffer overflow? */ |  | ||||||
|    if (len > *outlen) { |  | ||||||
|       res = CRYPT_BUFFER_OVERFLOW; |  | ||||||
|       goto done; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* decrypt message */ |  | ||||||
|    if ((errno = ctr_decrypt(in+y, out, len, &ctr)) != CRYPT_OK) { |  | ||||||
|       res = errno; |  | ||||||
|       goto done; |  | ||||||
|    } |  | ||||||
|    *outlen = len; |  | ||||||
| 
 |  | ||||||
|    res = CRYPT_OK; |  | ||||||
| done: |  | ||||||
| #ifdef CLEAN_STACK |  | ||||||
|    zeromem(shared_secret, sizeof(shared_secret)); |  | ||||||
|    zeromem(skey, sizeof(skey)); |  | ||||||
|    zeromem(&ctr, sizeof(ctr)); |  | ||||||
| #endif |  | ||||||
|    return res; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Signatures 
 |  | ||||||
|  * |  | ||||||
|  * Signatures are performed using a slightly modified ElGamal protocol.   |  | ||||||
|  * In these notes uppercase letters are points and lowercase letters are  |  | ||||||
|  * scalars.  The users private key is 'x' and public key is Y = xG.   |  | ||||||
|  * The order of the curve is 'r'. |  | ||||||
|  * |  | ||||||
|  * |  | ||||||
|  * To sign a message 'm' the user does this |  | ||||||
| 
 |  | ||||||
| 1.  Makes up a random 'k' and finds kG [basically makes up a ecc_key], we will let A = kG |  | ||||||
| 2.  Finds b such that b = (m - x)/k mod r |  | ||||||
| 3.  Outputs (A, b) as the signature |  | ||||||
| 
 |  | ||||||
| To verify a user computes mG and compares that to (bA + Y).  Note that (bA + Y) is equal to |  | ||||||
| 
 |  | ||||||
| = ((m - x)/k)(kG) + xG |  | ||||||
| = (m - x)G + xG |  | ||||||
| = mG |  | ||||||
| 
 |  | ||||||
| In theory, assuming the ECC Discrete Log is a hard problem an attacker  |  | ||||||
| cannot find 'x' from (A, b).  'b' is perfectly decorrelated and reveals no  |  | ||||||
| information.  A reveals what kG is but not 'k' directly.  Therefore,  |  | ||||||
| assuming finding 'k' given kG is hard, finding 'x' from b is hard too. |  | ||||||
| 
 |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| int ecc_sign(const unsigned char *in,  unsigned long inlen,  |  | ||||||
|                    unsigned char *out, unsigned long *outlen,  |  | ||||||
|                    int hash, prng_state *prng, int wprng,  |  | ||||||
|                    ecc_key *key) |  | ||||||
| { |  | ||||||
|    ecc_key pubkey; |  | ||||||
|    mp_int b, p; |  | ||||||
|    unsigned char epubkey[256], er[256], md[MAXBLOCKSIZE]; |  | ||||||
|    unsigned long x, y, z, pubkeysize, rsize; |  | ||||||
|    int res, errno; |  | ||||||
| 
 |  | ||||||
|    _ARGCHK(in != NULL); |  | ||||||
|    _ARGCHK(out != NULL); |  | ||||||
|    _ARGCHK(outlen != NULL); |  | ||||||
|    _ARGCHK(key != NULL); |  | ||||||
| 
 |  | ||||||
|    /* is this a private key? */ |  | ||||||
|    if (key->type != PK_PRIVATE) { |  | ||||||
|       return CRYPT_PK_NOT_PRIVATE; |  | ||||||
|    } |  | ||||||
|     |  | ||||||
|    /* is the IDX valid ?  */ |  | ||||||
|    if (!is_valid_idx(key->idx)) { |  | ||||||
|       return CRYPT_PK_INVALID_TYPE; |  | ||||||
|    } |  | ||||||
|        |  | ||||||
|    if ((errno = prng_is_valid(wprng)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    if ((errno = hash_is_valid(hash)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* make up a key and export the public copy */ |  | ||||||
|    if ((errno = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK)  { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    pubkeysize = sizeof(epubkey); |  | ||||||
|    if ((errno = ecc_export(epubkey, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) { |  | ||||||
|       ecc_free(&pubkey); |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* get the hash and load it as a bignum into 'b' */ |  | ||||||
|    md[0] = 0; |  | ||||||
|    z = sizeof(md)-1; |  | ||||||
|    if ((errno = hash_memory(hash, in, inlen, md+1, &z)) != CRYPT_OK) { |  | ||||||
|       ecc_free(&pubkey); |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* init the bignums */ |  | ||||||
|    if (mp_init_multi(&b, &p, NULL) != MP_OKAY) {  |  | ||||||
|       ecc_free(&pubkey); |  | ||||||
|       return CRYPT_MEM; |  | ||||||
|    } |  | ||||||
|    if (mp_read_radix(&p, sets[key->idx].order, 10) != MP_OKAY)            { goto error; } |  | ||||||
|    if (mp_read_raw(&b, md, 1+hash_descriptor[hash].hashsize) != MP_OKAY)  { goto error; } |  | ||||||
| 
 |  | ||||||
|    /* find b = (m - x)/k */ |  | ||||||
|    if (mp_invmod(&pubkey.k, &p, &pubkey.k) != MP_OKAY)                    { goto error; } /* k = 1/k */ |  | ||||||
|    if (mp_submod(&b, &key->k, &p, &b) != MP_OKAY)                         { goto error; } /* b = m - x */ |  | ||||||
|    if (mp_mulmod(&b, &pubkey.k, &p, &b) != MP_OKAY)                       { goto error; } /* b = (m - x)/k */ |  | ||||||
| 
 |  | ||||||
|    /* export it */ |  | ||||||
|    rsize = mp_raw_size(&b); |  | ||||||
|    if (rsize > sizeof(er)) {  |  | ||||||
|       goto error;  |  | ||||||
|    } |  | ||||||
|    mp_toraw(&b, er); |  | ||||||
| 
 |  | ||||||
|    /* now lets check the outlen before we write */ |  | ||||||
|    if (*outlen < (9 + PACKET_SIZE + rsize + pubkeysize)) { |  | ||||||
|       res = CRYPT_BUFFER_OVERFLOW; |  | ||||||
|       goto done1; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* lets output */ |  | ||||||
|    y = PACKET_SIZE; |  | ||||||
|     |  | ||||||
|    /* length of hash name plus NULL */ |  | ||||||
|    out[y++] = hash_descriptor[hash].ID; |  | ||||||
| 
 |  | ||||||
|    /* size of public key */ |  | ||||||
|    STORE32L(pubkeysize, out+y); |  | ||||||
|    y += 4; |  | ||||||
| 
 |  | ||||||
|    /* copy the public key */ |  | ||||||
|    for (x = 0; x < pubkeysize; x++, y++) { |  | ||||||
|        out[y] = epubkey[x]; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* size of 'r' */ |  | ||||||
|    STORE32L(rsize, out+y); |  | ||||||
|    y += 4; |  | ||||||
| 
 |  | ||||||
|    /* copy r */ |  | ||||||
|    for (x = 0; x < rsize; x++, y++) { |  | ||||||
|        out[y] = er[x]; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* store header */ |  | ||||||
|    packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_SIGNED, y); |  | ||||||
| 
 |  | ||||||
|    /* clear memory */ |  | ||||||
|    *outlen = y; |  | ||||||
|    res = CRYPT_OK; |  | ||||||
|    goto done1; |  | ||||||
| error: |  | ||||||
|    res = CRYPT_MEM; |  | ||||||
| done1: |  | ||||||
|    mp_clear_multi(&b, &p, NULL); |  | ||||||
|    ecc_free(&pubkey); |  | ||||||
| #ifdef CLEAN_STACK |  | ||||||
|    zeromem(er, sizeof(er)); |  | ||||||
|    zeromem(epubkey, sizeof(epubkey)); |  | ||||||
|    zeromem(md, sizeof(md)); |  | ||||||
| #endif |  | ||||||
|    return res;    |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* verify that mG = (bA + Y) */ |  | ||||||
| int ecc_verify(const unsigned char *sig, const unsigned char *msg,  |  | ||||||
|                      unsigned long inlen, int *stat,  |  | ||||||
|                      ecc_key *key) |  | ||||||
| { |  | ||||||
|    ecc_point *mG; |  | ||||||
|    ecc_key   pubkey; |  | ||||||
|    mp_int b, p, m; |  | ||||||
|    unsigned long x, y, z; |  | ||||||
|    int hash, res, errno; |  | ||||||
|    unsigned char md[MAXBLOCKSIZE]; |  | ||||||
| 
 |  | ||||||
|    _ARGCHK(sig != NULL); |  | ||||||
|    _ARGCHK(msg != NULL); |  | ||||||
|    _ARGCHK(stat != NULL); |  | ||||||
|    _ARGCHK(key != NULL); |  | ||||||
| 
 |  | ||||||
|    /* default to invalid signature */ |  | ||||||
|    *stat = 0; |  | ||||||
| 
 |  | ||||||
|    /* is the message format correct? */ |  | ||||||
|    if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_ECC, PACKET_SUB_SIGNED)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    }      |  | ||||||
| 
 |  | ||||||
|    /* get hash name */ |  | ||||||
|    y = PACKET_SIZE; |  | ||||||
|    hash = find_hash_id(sig[y++]); |  | ||||||
|    if (hash == -1) { |  | ||||||
|       return CRYPT_INVALID_HASH; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* get size of public key */ |  | ||||||
|    LOAD32L(x, sig+y); |  | ||||||
|    y += 4; |  | ||||||
| 
 |  | ||||||
|    /* load the public key */ |  | ||||||
|    if ((errno = ecc_import((unsigned char*)sig+y, &pubkey)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
|    y += x; |  | ||||||
| 
 |  | ||||||
|    /* load size of 'b' */ |  | ||||||
|    LOAD32L(x, sig+y); |  | ||||||
|    y += 4; |  | ||||||
| 
 |  | ||||||
|    /* init values */ |  | ||||||
|    if (mp_init_multi(&b, &m, &p, NULL) != MP_OKAY) {  |  | ||||||
|       ecc_free(&pubkey); |  | ||||||
|       return CRYPT_MEM; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    mG = new_point(); |  | ||||||
|    if (mG == NULL) {  |  | ||||||
|       mp_clear_multi(&b, &m, &p, NULL); |  | ||||||
|       ecc_free(&pubkey); |  | ||||||
|       return CRYPT_MEM; |  | ||||||
|    }  |  | ||||||
| 
 |  | ||||||
|    /* load b */ |  | ||||||
|    if (mp_read_raw(&b, (unsigned char *)sig+y, x) != MP_OKAY)                      { goto error; } |  | ||||||
|    y += x; |  | ||||||
| 
 |  | ||||||
|    /* get m in binary a bignum */ |  | ||||||
|    md[0] = 0; |  | ||||||
|    z = sizeof(md)-1; |  | ||||||
|    if ((errno = hash_memory(hash, msg, inlen, md+1, &z)) != CRYPT_OK) { |  | ||||||
|       res = errno; |  | ||||||
|       goto done1; |  | ||||||
|    } |  | ||||||
|    if (mp_read_raw(&m, md, hash_descriptor[hash].hashsize + 1) != MP_OKAY)         { goto error; } |  | ||||||
|     |  | ||||||
|    /* load prime */ |  | ||||||
|    if (mp_read_radix(&p, sets[key->idx].prime, 10) != MP_OKAY)                     { goto error; } |  | ||||||
| 
 |  | ||||||
|    /* get bA */ |  | ||||||
|    if (ecc_mulmod(&b, &pubkey.pubkey, &pubkey.pubkey, &p, key->idx) != CRYPT_OK)             { goto error; } |  | ||||||
|     |  | ||||||
|    /* get bA + Y */ |  | ||||||
|    if (add_point(&pubkey.pubkey, &key->pubkey, &pubkey.pubkey, &p) != CRYPT_OK)    { goto error; } |  | ||||||
| 
 |  | ||||||
|    /* get mG */ |  | ||||||
|    if (mp_read_radix(&mG->x, sets[key->idx].Gx, 16) != MP_OKAY)                    { goto error; } |  | ||||||
|    if (mp_read_radix(&mG->y, sets[key->idx].Gy, 16) != MP_OKAY)                    { goto error; } |  | ||||||
|    if (ecc_mulmod(&m, mG, mG, &p, key->idx) != CRYPT_OK)                                     { goto error; } |  | ||||||
| 
 |  | ||||||
|    /* compare mG to bA + Y */ |  | ||||||
|    if (!mp_cmp(&mG->x, &pubkey.pubkey.x) && !mp_cmp(&mG->y, &pubkey.pubkey.y)) { |  | ||||||
|       *stat = 1; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* clear up and return */ |  | ||||||
|    res = CRYPT_OK; |  | ||||||
|    goto done1; |  | ||||||
| error: |  | ||||||
|    res = CRYPT_MEM; |  | ||||||
| done1: |  | ||||||
|    del_point(mG); |  | ||||||
|    ecc_free(&pubkey); |  | ||||||
|    mp_clear_multi(&p, &m, &b, NULL); |  | ||||||
| #ifdef CLEAN_STACK |  | ||||||
|    zeromem(md, sizeof(md)); |  | ||||||
| #endif |  | ||||||
|    return CRYPT_OK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen, | int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen, | ||||||
|                           unsigned char *out,  unsigned long *len,  |                           unsigned char *out,  unsigned long *len,  | ||||||
|                           prng_state *prng, int wprng, int hash,  |                           prng_state *prng, int wprng, int hash,  | ||||||
| @ -619,7 +132,7 @@ int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey, | |||||||
|    /* get public key */ |    /* get public key */ | ||||||
|    LOAD32L(x, in+y); |    LOAD32L(x, in+y); | ||||||
|    y += 4; |    y += 4; | ||||||
|    if ((errno = ecc_import(in+y, &pubkey)) != CRYPT_OK) { |    if ((errno = ecc_import(in+y, x, &pubkey)) != CRYPT_OK) { | ||||||
|       return errno; |       return errno; | ||||||
|    } |    } | ||||||
|    y += x; |    y += x; | ||||||
| @ -805,7 +318,7 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash, | |||||||
|    y += 4; |    y += 4; | ||||||
| 
 | 
 | ||||||
|    /* load the public key */ |    /* load the public key */ | ||||||
|    if ((errno = ecc_import((unsigned char*)sig+y, &pubkey)) != CRYPT_OK) { |    if ((errno = ecc_import((unsigned char*)sig+y, x, &pubkey)) != CRYPT_OK) { | ||||||
|       return errno; |       return errno; | ||||||
|    } |    } | ||||||
|    y += x; |    y += x; | ||||||
|  | |||||||
							
								
								
									
										18
									
								
								keyring.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								keyring.c
									
									
									
									
									
								
							| @ -361,7 +361,7 @@ int kr_export(pk_key *pk, unsigned long ID, int key_type, unsigned char *out, un | |||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int kr_import(pk_key *pk, const unsigned char *in) | int kr_import(pk_key *pk, const unsigned char *in, unsigned long inlen) | ||||||
| { | { | ||||||
|    _pk_key key; |    _pk_key key; | ||||||
|    int system, key_type, errno; |    int system, key_type, errno; | ||||||
| @ -370,6 +370,10 @@ int kr_import(pk_key *pk, const unsigned char *in) | |||||||
|    _ARGCHK(pk != NULL); |    _ARGCHK(pk != NULL); | ||||||
|    _ARGCHK(in != NULL); |    _ARGCHK(in != NULL); | ||||||
| 
 | 
 | ||||||
|  |    if (inlen < 10) { | ||||||
|  |       return CRYPT_INVALID_PACKET; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|    if (memcmp(in, key_magic, 4)) { |    if (memcmp(in, key_magic, 4)) { | ||||||
|       return CRYPT_INVALID_PACKET; |       return CRYPT_INVALID_PACKET; | ||||||
|    } |    } | ||||||
| @ -382,19 +386,23 @@ int kr_import(pk_key *pk, const unsigned char *in) | |||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    zeromem(&key, sizeof(key)); |    zeromem(&key, sizeof(key)); | ||||||
|  |     | ||||||
|  |    /* size of remaining packet */ | ||||||
|  |    inlen -= 10 + 3*MAXLEN; | ||||||
|  |     | ||||||
|    switch (system) { |    switch (system) { | ||||||
|         case RSA_KEY: |         case RSA_KEY: | ||||||
|             if ((errno = rsa_import(in+10+3*MAXLEN, &(key.rsa))) != CRYPT_OK) { |             if ((errno = rsa_import(in+10+3*MAXLEN, inlen, &(key.rsa))) != CRYPT_OK) { | ||||||
|                return errno; |                return errno; | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case DH_KEY: |         case DH_KEY: | ||||||
|             if ((errno = dh_import(in+10+3*MAXLEN, &(key.dh))) != CRYPT_OK) { |             if ((errno = dh_import(in+10+3*MAXLEN, inlen, &(key.dh))) != CRYPT_OK) { | ||||||
|                return errno; |                return errno; | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case ECC_KEY: |         case ECC_KEY: | ||||||
|             if ((errno = ecc_import(in+10+3*MAXLEN, &(key.ecc))) != CRYPT_OK) { |             if ((errno = ecc_import(in+10+3*MAXLEN, inlen, &(key.ecc))) != CRYPT_OK) { | ||||||
|                return errno; |                return errno; | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
| @ -443,7 +451,7 @@ int kr_load(pk_key **pk, FILE *in, symmetric_CTR *ctr) | |||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       if (_read(buf, len, in, ctr) != len)           { goto done2; } |       if (_read(buf, len, in, ctr) != len)           { goto done2; } | ||||||
|       if ((errno = kr_import(*pk, buf)) != CRYPT_OK) {  |       if ((errno = kr_import(*pk, buf, len)) != CRYPT_OK) {  | ||||||
|          return errno;  |          return errno;  | ||||||
|       } |       } | ||||||
|    } |    } | ||||||
|  | |||||||
							
								
								
									
										20
									
								
								makefile
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								makefile
									
									
									
									
									
								
							| @ -9,7 +9,7 @@ | |||||||
| # a build. This is easy to remedy though, for those that have problems.
 | # a build. This is easy to remedy though, for those that have problems.
 | ||||||
| 
 | 
 | ||||||
| # The version
 | # The version
 | ||||||
| VERSION=0.77 | VERSION=0.78 | ||||||
| 
 | 
 | ||||||
| #Compiler and Linker Names
 | #Compiler and Linker Names
 | ||||||
| CC=gcc | CC=gcc | ||||||
| @ -39,6 +39,9 @@ CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wno-unused -Werror  \ | |||||||
| #optimize for SIZE (comment out SPEED/DEBUG line as well)
 | #optimize for SIZE (comment out SPEED/DEBUG line as well)
 | ||||||
| CFLAGS += -Os  | CFLAGS += -Os  | ||||||
| 
 | 
 | ||||||
|  | #Use small code variants of functions when possible?  (Slows it down!)
 | ||||||
|  | CFLAGS += -DSMALL_CODE | ||||||
|  | 
 | ||||||
| #compile for DEBUGGING 
 | #compile for DEBUGGING 
 | ||||||
| #CFLAGS += -g3
 | #CFLAGS += -g3
 | ||||||
| 
 | 
 | ||||||
| @ -74,6 +77,7 @@ CFLAGS += -DXTEA | |||||||
| CFLAGS += -DTWOFISH | CFLAGS += -DTWOFISH | ||||||
| CFLAGS += -DDES | CFLAGS += -DDES | ||||||
| CFLAGS += -DCAST5 | CFLAGS += -DCAST5 | ||||||
|  | CFLAGS += -DNOEKEON | ||||||
| 
 | 
 | ||||||
| #You can also customize the Twofish code.  All four combinations 
 | #You can also customize the Twofish code.  All four combinations 
 | ||||||
| #of the flags are possible but only three of them make sense.
 | #of the flags are possible but only three of them make sense.
 | ||||||
| @ -98,14 +102,6 @@ CFLAGS += -DCAST5 | |||||||
| # This speeds up the cipher somewhat.
 | # This speeds up the cipher somewhat.
 | ||||||
| #CFLAGS += -DTWOFISH_TABLES 
 | #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
 | #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
 | #DH system to 256 bits.  The group order remains unchanged so the best
 | ||||||
| #attacks are still GNFS (for DH upto 2560-bits)
 | #attacks are still GNFS (for DH upto 2560-bits)
 | ||||||
| @ -114,10 +110,6 @@ CFLAGS += -DRIJNDAEL_SMALL | |||||||
| #security so its by default not turned on.  USE AT YOUR RISK!
 | #security so its by default not turned on.  USE AT YOUR RISK!
 | ||||||
| #CFLAGS += -DFAST_PK
 | #CFLAGS += -DFAST_PK
 | ||||||
| 
 | 
 | ||||||
| #Include the PK Packet functions (e.g. dh_encrypt)
 |  | ||||||
| #Does not affect the key/hash routines (e.g. ecc_sign_hash)
 |  | ||||||
| #CFLAGS += -DPK_PACKET
 |  | ||||||
| 
 |  | ||||||
| # Chaining modes
 | # Chaining modes
 | ||||||
| CFLAGS += -DCFB | CFLAGS += -DCFB | ||||||
| CFLAGS += -DOFB | CFLAGS += -DOFB | ||||||
| @ -174,7 +166,7 @@ INCPATH=/usr/include | |||||||
| 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 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 \ | 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 \ | 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 blowfish.o crypt.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 | ampi.o mpi.o prime.o twofish.o packet.o hmac.o strings.o | ||||||
| 
 | 
 | ||||||
| TESTOBJECTS=demos/test.o | TESTOBJECTS=demos/test.o | ||||||
|  | |||||||
							
								
								
									
										23
									
								
								makefile.ps2
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								makefile.ps2
									
									
									
									
									
								
							| @ -43,16 +43,19 @@ CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wno-unused -Werror  \ | |||||||
|    -DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) -DXCLOCK=$(XCLOCK) \ |    -DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) -DXCLOCK=$(XCLOCK) \ | ||||||
|    -DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC) |    -DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC) | ||||||
| 
 | 
 | ||||||
| #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 |  | ||||||
| 
 |  | ||||||
| #optimize for SPEED (comment out SIZE line as well) | #optimize for SPEED (comment out SIZE line as well) | ||||||
| #CFLAGS += -O3 -fomit-frame-pointer -funroll-loops | #CFLAGS += -O3 -fomit-frame-pointer -funroll-loops | ||||||
| 
 | 
 | ||||||
| #optimize for SIZE (comment out SPEED line as well) | #optimize for SIZE (comment out SPEED line as well) | ||||||
| CFLAGS += -Os  | CFLAGS += -Os  | ||||||
| 
 | 
 | ||||||
|  | #Use small code variants of functions when possible?  (Slows it down!) | ||||||
|  | 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 | ||||||
|  | 
 | ||||||
| #These flags control how the library gets built. | #These flags control how the library gets built. | ||||||
| 
 | 
 | ||||||
| # Clean the stack after sensitive functions.  Not always required...  | # Clean the stack after sensitive functions.  Not always required...  | ||||||
| @ -75,6 +78,7 @@ CFLAGS += -DXTEA | |||||||
| CFLAGS += -DTWOFISH | CFLAGS += -DTWOFISH | ||||||
| CFLAGS += -DDES | CFLAGS += -DDES | ||||||
| CFLAGS += -DCAST5 | CFLAGS += -DCAST5 | ||||||
|  | CFLAGS += -DNOEKEON | ||||||
| 
 | 
 | ||||||
| #You can also customize the Twofish code.  All four combinations  | #You can also customize the Twofish code.  All four combinations  | ||||||
| #of the flags are possible but only three of them make sense. | #of the flags are possible but only three of them make sense. | ||||||
| @ -115,10 +119,6 @@ CFLAGS += -DRIJNDAEL_SMALL | |||||||
| #security so its by default not turned on.  USE AT YOUR RISK! | #security so its by default not turned on.  USE AT YOUR RISK! | ||||||
| #CFLAGS += -DFAST_PK | #CFLAGS += -DFAST_PK | ||||||
| 
 | 
 | ||||||
| #Include the PK Packet functions (e.g. dh_encrypt) |  | ||||||
| #Does not affect the key/hash routines (e.g. ecc_sign_hash) |  | ||||||
| #CFLAGS += -DPK_PACKET |  | ||||||
| 
 |  | ||||||
| # Chaining modes | # Chaining modes | ||||||
| CFLAGS += -DCFB | CFLAGS += -DCFB | ||||||
| CFLAGS += -DOFB | CFLAGS += -DOFB | ||||||
| @ -156,11 +156,6 @@ CFLAGS += -DKR | |||||||
| # include large integer math routines? (required by the PK code) | # include large integer math routines? (required by the PK code) | ||||||
| CFLAGS += -DMPI | CFLAGS += -DMPI | ||||||
| 
 | 
 | ||||||
| # Use a small prime table?  It greatly reduces the size of prime.c at a little impact |  | ||||||
| # in speed. |  | ||||||
| # |  | ||||||
| CFLAGS += -DSMALL_PRIME_TAB |  | ||||||
| 
 |  | ||||||
| # include HMAC support | # include HMAC support | ||||||
| CFLAGS += -DHMAC | CFLAGS += -DHMAC | ||||||
| 
 | 
 | ||||||
| @ -183,7 +178,7 @@ INCPATH=/usr/include | |||||||
| 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 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 \ | 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 \ | 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 blowfish.o crypt.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 | ampi.o mpi.o prime.o twofish.o packet.o hmac.o strings.o | ||||||
| 
 | 
 | ||||||
| # PlayStation(tm) 2 C run-time startup module | # PlayStation(tm) 2 C run-time startup module | ||||||
|  | |||||||
							
								
								
									
										27
									
								
								makefile.vc
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								makefile.vc
									
									
									
									
									
								
							| @ -16,6 +16,9 @@ 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 /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 | ||||||
|  | 
 | ||||||
| #These flags control how the library gets built. | #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  | #no file support, when defined the library will not have any functions that can read/write files  | ||||||
| @ -48,6 +51,7 @@ CFLAGS += /DXTEA | |||||||
| CFLAGS += /DTWOFISH | CFLAGS += /DTWOFISH | ||||||
| CFLAGS += /DDES | CFLAGS += /DDES | ||||||
| CFLAGS += /DCAST5 | CFLAGS += /DCAST5 | ||||||
|  | CFLAGS += /DNOEKEON | ||||||
| 
 | 
 | ||||||
| #You can also customize the Twofish code.  All four combinations  | #You can also customize the Twofish code.  All four combinations  | ||||||
| #of the flags are possible but only three of them make sense. | #of the flags are possible but only three of them make sense. | ||||||
| @ -72,14 +76,6 @@ CFLAGS += /DCAST5 | |||||||
| # This speeds up the cipher somewhat. | # This speeds up the cipher somewhat. | ||||||
| # CFLAGS += /DTWOFISH_TABLES  | # 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 | #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 | #DH system to 256 bits.  The group order remains unchanged so the best | ||||||
| #attacks are still GNFS (for DH upto 2560-bits) | #attacks are still GNFS (for DH upto 2560-bits) | ||||||
| @ -88,10 +84,6 @@ CFLAGS += /DRIJNDAEL_SMALL | |||||||
| #security so its by default not turned on.  USE AT YOUR RISK! | #security so its by default not turned on.  USE AT YOUR RISK! | ||||||
| #CFLAGS += /DFAST_PK | #CFLAGS += /DFAST_PK | ||||||
| 
 | 
 | ||||||
| #Include the PK Packet functions (e.g. dh_encrypt) |  | ||||||
| #Does not affect the key/hash routines (e.g. ecc_sign_hash) |  | ||||||
| #CFLAGS += /DPK_PACKET |  | ||||||
| 
 |  | ||||||
| # Chaining modes | # Chaining modes | ||||||
| CFLAGS += /DCFB | CFLAGS += /DCFB | ||||||
| CFLAGS += /DOFB | CFLAGS += /DOFB | ||||||
| @ -129,11 +121,6 @@ CFLAGS += /DKR | |||||||
| # include large integer math routines? (required by the PK code) | # include large integer math routines? (required by the PK code) | ||||||
| CFLAGS += /DMPI | CFLAGS += /DMPI | ||||||
| 
 | 
 | ||||||
| # Use a small prime table?  It greatly reduces the size of prime.c at a little impact |  | ||||||
| # in speed. |  | ||||||
| # |  | ||||||
| CFLAGS += /DSMALL_PRIME_TAB |  | ||||||
| 
 |  | ||||||
| # include HMAC support | # include HMAC support | ||||||
| CFLAGS += /DHMAC | CFLAGS += /DHMAC | ||||||
| 
 | 
 | ||||||
| @ -227,6 +214,8 @@ md2.obj: md2.c | |||||||
| 	$(CC) $(CFLAGS) md2.c | 	$(CC) $(CFLAGS) md2.c | ||||||
| cast5.obj: cast5.c | cast5.obj: cast5.c | ||||||
| 	$(CC) $(CFLAGS) cast5.c | 	$(CC) $(CFLAGS) cast5.c | ||||||
|  | noekeon.obj: noekeon.c | ||||||
|  | 	$(CC) $(CFLAGS) noekeon.c | ||||||
| 
 | 
 | ||||||
| demos/test.obj: demos/test.c | demos/test.obj: demos/test.c | ||||||
| 	$(CC) $(CFLAGS) demos/test.c | 	$(CC) $(CFLAGS) demos/test.c | ||||||
| @ -236,11 +225,11 @@ demos/hashsum.obj: 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 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 \ | 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 rc2.obj rc6.obj rc5.obj des.obj blowfish.obj crypt.obj ampi.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 | 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 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 \ | 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 rc2.obj rc6.obj rc5.obj des.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 | blowfish.obj crypt.obj ampi.obj mpi.obj prime.obj twofish.obj packet.obj | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -13,8 +13,8 @@ extern "C" { | |||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| /* version */ | /* version */ | ||||||
| #define CRYPT   0x0077 | #define CRYPT   0x0078 | ||||||
| #define SCRYPT  "0.77" | #define SCRYPT  "0.78" | ||||||
| 
 | 
 | ||||||
| /* max size of either a cipher/hash block or symmetric key [largest of the two] */ | /* max size of either a cipher/hash block or symmetric key [largest of the two] */ | ||||||
| #define MAXBLOCKSIZE           128 | #define MAXBLOCKSIZE           128 | ||||||
|  | |||||||
| @ -10,23 +10,17 @@ | |||||||
|  * On embedded platforms you can change the fprintf() to be a routine that would display a message |  * On embedded platforms you can change the fprintf() to be a routine that would display a message | ||||||
|  * somehow  |  * somehow  | ||||||
|  */ |  */ | ||||||
| #ifndef SONY_PS2 |  | ||||||
| 
 |  | ||||||
| #define _ARGCHK(x) \ |  | ||||||
|     if (!(x)) { \ |  | ||||||
|         fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n", #x, __LINE__, __FILE__); \ |  | ||||||
|         raise(SIGABRT); \ |  | ||||||
|     } |  | ||||||
|   |   | ||||||
|  | #ifdef SMALL_CODE  | ||||||
|  |    extern void crypt_argchk(char *v, char *s, int d); | ||||||
|  |    #define _ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } | ||||||
| #else | #else | ||||||
| 
 |    #ifdef SONY_PS2 | ||||||
| #define _ARGCHK(x) \ |       #define _ARGCHK(x) if (!(x)) { printf("_ARGCHK '%s' failure on line %d of file %s\n", #x, __LINE__, __FILE__); raise(SIGABRT); } | ||||||
|     if (!(x)) { \ |    #else | ||||||
|         printf("_ARGCHK '%s' failure on line %d of file %s\n", #x, __LINE__, __FILE__); \ |       #define _ARGCHK(x) if (!(x)) { fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n", #x, __LINE__, __FILE__); raise(SIGABRT); } | ||||||
|         raise(SIGABRT); \ |    #endif | ||||||
|     } | #endif    | ||||||
| 
 |  | ||||||
| #endif  /* SONY_PS2 */ |  | ||||||
| 
 | 
 | ||||||
| #elif ARGTYPE == 1 | #elif ARGTYPE == 1 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -94,6 +94,12 @@ struct cast5_key { | |||||||
| }; | }; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifdef NOEKEON | ||||||
|  | struct noekeon_key { | ||||||
|  | 	unsigned long K[4], dK[4]; | ||||||
|  | }; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| typedef union Symmetric_key { | typedef union Symmetric_key { | ||||||
| #ifdef DES | #ifdef DES | ||||||
|    struct des_key des; |    struct des_key des; | ||||||
| @ -132,6 +138,9 @@ typedef union Symmetric_key { | |||||||
| #ifdef CAST5 | #ifdef CAST5 | ||||||
|    struct cast5_key    cast5; |    struct cast5_key    cast5; | ||||||
| #endif | #endif | ||||||
|  | #ifdef NOEKEON | ||||||
|  |    struct noekeon_key  noekeon; | ||||||
|  | #endif    | ||||||
| } symmetric_key; | } symmetric_key; | ||||||
| 
 | 
 | ||||||
| /* A block cipher ECB structure */ | /* A block cipher ECB structure */ | ||||||
| @ -252,12 +261,20 @@ extern const struct _cipher_descriptor serpent_desc; | |||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef RIJNDAEL | #ifdef RIJNDAEL | ||||||
|  | 
 | ||||||
|  | /* make aes an alias */ | ||||||
|  | #define aes_setup			rijndael_setup | ||||||
|  | #define aes_ecb_encrypt		rijndael_ecb_encrypt | ||||||
|  | #define aes_ecb_decrypt		rijndael_ecb_decrypt | ||||||
|  | #define aes_test			rijndael_test | ||||||
|  | #define aes_keysize			rijndael_keysize | ||||||
|  | 
 | ||||||
| extern int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); | extern int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); | ||||||
| extern void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key); | extern void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key); | ||||||
| extern void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key); | extern void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key); | ||||||
| extern int rijndael_test(void); | extern int rijndael_test(void); | ||||||
| extern int rijndael_keysize(int *desired_keysize); | extern int rijndael_keysize(int *desired_keysize); | ||||||
| extern const struct _cipher_descriptor rijndael_desc; | extern const struct _cipher_descriptor rijndael_desc, aes_desc; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef XTEA | #ifdef XTEA | ||||||
| @ -303,6 +320,15 @@ extern int cast5_keysize(int *desired_keysize); | |||||||
| extern const struct _cipher_descriptor cast5_desc; | extern const struct _cipher_descriptor cast5_desc; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifdef NOEKEON | ||||||
|  | extern int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); | ||||||
|  | extern void noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key); | ||||||
|  | extern void noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key); | ||||||
|  | extern int noekeon_test(void); | ||||||
|  | extern int noekeon_keysize(int *desired_keysize); | ||||||
|  | extern const struct _cipher_descriptor noekeon_desc; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #ifdef ECB | #ifdef ECB | ||||||
| extern int ecb_start(int cipher, const unsigned char *key,  | extern int ecb_start(int cipher, const unsigned char *key,  | ||||||
|                      int keylen, int num_rounds, symmetric_ECB *ecb); |                      int keylen, int num_rounds, symmetric_ECB *ecb); | ||||||
|  | |||||||
| @ -1,5 +1,9 @@ | |||||||
| #ifdef KR | #ifdef KR | ||||||
| 
 | 
 | ||||||
|  | #if !defined(MRSA) || !defined(MDH) || !defined(MECC) | ||||||
|  |     #error "Keyring code requires all three public key algorithms." | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #define MAXLEN    256 | #define MAXLEN    256 | ||||||
| 
 | 
 | ||||||
| enum { | enum { | ||||||
| @ -48,7 +52,7 @@ extern int kr_make_key(pk_key *pk, prng_state *prng, int wprng, | |||||||
|                        const unsigned char *email, const unsigned char *description); |                        const unsigned char *email, const unsigned char *description); | ||||||
| 
 | 
 | ||||||
| extern int kr_export(pk_key *pk, unsigned long ID, int key_type, unsigned char *out, unsigned long *outlen); | extern int kr_export(pk_key *pk, unsigned long ID, int key_type, unsigned char *out, unsigned long *outlen); | ||||||
| extern int kr_import(pk_key *pk, const unsigned char *in); | extern int kr_import(pk_key *pk, const unsigned char *in, unsigned long inlen); | ||||||
| 
 | 
 | ||||||
| extern int kr_load(pk_key **pk, FILE *in, symmetric_CTR *ctr); | extern int kr_load(pk_key **pk, FILE *in, symmetric_CTR *ctr); | ||||||
| extern int kr_save(pk_key *pk, FILE *out, symmetric_CTR *ctr); | extern int kr_save(pk_key *pk, FILE *out, symmetric_CTR *ctr); | ||||||
|  | |||||||
							
								
								
									
										71
									
								
								mycrypt_pk.h
									
									
									
									
									
								
							
							
						
						
									
										71
									
								
								mycrypt_pk.h
									
									
									
									
									
								
							| @ -52,27 +52,6 @@ extern int rsa_signdepad(const unsigned char *in,  unsigned long inlen, | |||||||
| 
 | 
 | ||||||
| extern void rsa_free(rsa_key *key); | extern void rsa_free(rsa_key *key); | ||||||
| 
 | 
 | ||||||
| #ifdef PK_PACKET |  | ||||||
| 
 |  | ||||||
| extern int rsa_encrypt(const unsigned char *in,  unsigned long len,  |  | ||||||
|                              unsigned char *out, unsigned long *outlen, |  | ||||||
|                              prng_state *prng, int wprng, int cipher,  |  | ||||||
|                              rsa_key *key); |  | ||||||
| 
 |  | ||||||
| extern int rsa_decrypt(const unsigned char *in,  unsigned long len,  |  | ||||||
|                              unsigned char *out, unsigned long *outlen,  |  | ||||||
|                              rsa_key *key); |  | ||||||
| 
 |  | ||||||
| extern int rsa_sign(const unsigned char *in, unsigned long inlen,  |  | ||||||
|                           unsigned char *out, unsigned long *outlen,  |  | ||||||
|                           int hash, rsa_key *key); |  | ||||||
| 
 |  | ||||||
| extern int rsa_verify(const unsigned char *sig, const unsigned char *msg,  |  | ||||||
|                             unsigned long inlen, int *stat,  |  | ||||||
|                             rsa_key *key); |  | ||||||
|                              |  | ||||||
| #endif                             |  | ||||||
| 
 |  | ||||||
| extern int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen, | extern int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen, | ||||||
|                                  unsigned char *outkey, unsigned long *outlen, |                                  unsigned char *outkey, unsigned long *outlen, | ||||||
|                                  prng_state *prng, int wprng, rsa_key *key); |                                  prng_state *prng, int wprng, rsa_key *key); | ||||||
| @ -88,7 +67,7 @@ extern int rsa_verify_hash(const unsigned char *sig, const unsigned char *hash, | |||||||
|                                  int *stat, rsa_key *key); |                                  int *stat, rsa_key *key); | ||||||
| 
 | 
 | ||||||
| extern int rsa_export(unsigned char *out, unsigned long *outlen, int type, 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, rsa_key *key); | extern int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| /* ---- DH Routines ---- */ | /* ---- DH Routines ---- */ | ||||||
| @ -107,33 +86,11 @@ extern int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key); | |||||||
| extern void dh_free(dh_key *key); | extern void dh_free(dh_key *key); | ||||||
| 
 | 
 | ||||||
| extern int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key); | extern int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key); | ||||||
| extern int dh_import(const unsigned char *in, dh_key *key); | extern int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key); | ||||||
| 
 | 
 | ||||||
| extern int dh_shared_secret(dh_key *private_key, dh_key *public_key, | extern int dh_shared_secret(dh_key *private_key, dh_key *public_key, | ||||||
|                             unsigned char *out, unsigned long *outlen); |                             unsigned char *out, unsigned long *outlen); | ||||||
| 
 | 
 | ||||||
| #ifdef PK_PACKET |  | ||||||
| 
 |  | ||||||
| extern int dh_encrypt(const unsigned char *in,  unsigned long len,  |  | ||||||
|                             unsigned char *out, unsigned long *outlen, |  | ||||||
|                             prng_state *prng, int wprng, int cipher, int hash,  |  | ||||||
|                             dh_key *key); |  | ||||||
| 
 |  | ||||||
| extern int dh_decrypt(const unsigned char *in,  unsigned long len,  |  | ||||||
|                             unsigned char *out, unsigned long *outlen,  |  | ||||||
|                             dh_key *key); |  | ||||||
| 
 |  | ||||||
| extern int dh_sign(const unsigned char *in,  unsigned long inlen,  |  | ||||||
|                          unsigned char *out, unsigned long *outlen, int hash,  |  | ||||||
|                          prng_state *prng, int wprng,  |  | ||||||
|                          dh_key *key); |  | ||||||
| 
 |  | ||||||
| extern int dh_verify(const unsigned char *sig, const unsigned char *msg,  |  | ||||||
|                            unsigned long inlen, int *stat,  |  | ||||||
|                            dh_key *key); |  | ||||||
|                             |  | ||||||
| #endif                            |  | ||||||
| 
 |  | ||||||
| extern int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen, | extern int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen, | ||||||
|                                 unsigned char *out,  unsigned long *len,  |                                 unsigned char *out,  unsigned long *len,  | ||||||
|                                 prng_state *prng, int wprng, int hash,  |                                 prng_state *prng, int wprng, int hash,  | ||||||
| @ -173,33 +130,11 @@ extern int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key); | |||||||
| extern void ecc_free(ecc_key *key); | extern void ecc_free(ecc_key *key); | ||||||
| 
 | 
 | ||||||
| extern int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key); | extern int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key); | ||||||
| extern int ecc_import(const unsigned char *in, ecc_key *key); | extern int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key); | ||||||
| 
 | 
 | ||||||
| extern int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,  | extern int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,  | ||||||
|                              unsigned char *out, unsigned long *outlen); |                              unsigned char *out, unsigned long *outlen); | ||||||
| 
 | 
 | ||||||
| #ifdef PK_PACKET |  | ||||||
| 
 |  | ||||||
| extern int ecc_encrypt(const unsigned char *in,  unsigned long len,  |  | ||||||
|                              unsigned char *out, unsigned long *outlen, |  | ||||||
|                              prng_state *prng, int wprng, int cipher, int hash,  |  | ||||||
|                              ecc_key *key); |  | ||||||
| 
 |  | ||||||
| extern int ecc_decrypt(const unsigned char *in,  unsigned long len, |  | ||||||
|                              unsigned char *out, unsigned long *outlen,  |  | ||||||
|                              ecc_key *key); |  | ||||||
| 
 |  | ||||||
| extern int ecc_sign(const unsigned char *in, unsigned long inlen,  |  | ||||||
|                           unsigned char *out, unsigned long *outlen, int hash,  |  | ||||||
|                           prng_state *prng, int wprng,  |  | ||||||
|                           ecc_key *key); |  | ||||||
| 
 |  | ||||||
| extern int ecc_verify(const unsigned char *sig, const unsigned char *msg,  |  | ||||||
|                             unsigned long inlen, int *stat,  |  | ||||||
|                             ecc_key *key); |  | ||||||
|                              |  | ||||||
| #endif                             |  | ||||||
| 
 |  | ||||||
| extern int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen, | extern int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen, | ||||||
|                                  unsigned char *out,  unsigned long *len,  |                                  unsigned char *out,  unsigned long *len,  | ||||||
|                                  prng_state *prng, int wprng, int hash,  |                                  prng_state *prng, int wprng, int hash,  | ||||||
|  | |||||||
							
								
								
									
										210
									
								
								noekeon.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								noekeon.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,210 @@ | |||||||
|  | /* Implementation of the Noekeon block cipher by Tom St Denis */ | ||||||
|  | #include "mycrypt.h" | ||||||
|  | 
 | ||||||
|  | #ifdef NOEKEON | ||||||
|  | 
 | ||||||
|  | const struct _cipher_descriptor noekeon_desc = | ||||||
|  | { | ||||||
|  |     "noekeon", | ||||||
|  |     16, | ||||||
|  |     16, 16, 16, 16, | ||||||
|  |     &noekeon_setup, | ||||||
|  |     &noekeon_ecb_encrypt, | ||||||
|  |     &noekeon_ecb_decrypt, | ||||||
|  |     &noekeon_test, | ||||||
|  |     &noekeon_keysize | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const unsigned long RC[] = { | ||||||
|  |    0x00000080, 0x0000001b, 0x00000036, 0x0000006c, | ||||||
|  |    0x000000d8, 0x000000ab, 0x0000004d, 0x0000009a, | ||||||
|  |    0x0000002f, 0x0000005e, 0x000000bc, 0x00000063, | ||||||
|  |    0x000000c6, 0x00000097, 0x00000035, 0x0000006a, | ||||||
|  |    0x000000d4  | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const unsigned long zero[] = { 0, 0, 0, 0 }; | ||||||
|  | 
 | ||||||
|  | #define THETA(k, a, b, c, d)                               \ | ||||||
|  |     temp = a^c; temp = temp ^ ROL(temp, 8) ^ ROR(temp, 8); \ | ||||||
|  |     b ^= temp; d ^= temp;                                  \ | ||||||
|  |     a ^= k[0]; b ^= k[1];                                  \ | ||||||
|  |     c ^= k[2]; d ^= k[3];                                  \ | ||||||
|  |     temp = b^d; temp = temp ^ ROL(temp, 8) ^ ROR(temp, 8); \ | ||||||
|  |     a ^= temp; c ^= temp; | ||||||
|  |      | ||||||
|  | #define GAMMA(a, b, c, d)     \ | ||||||
|  |     b ^= ~(d|c);              \ | ||||||
|  |     a ^= c&b;                 \ | ||||||
|  |     temp = d; d = a; a = temp;\ | ||||||
|  |     c ^= a ^ b ^ d;           \ | ||||||
|  |     b ^= ~(d|c);              \ | ||||||
|  |     a ^= c&b; | ||||||
|  |      | ||||||
|  | #define PI1(a, b, c, d) \ | ||||||
|  |     a = ROL(a, 1); c = ROL(c, 5); d = ROL(d, 2); | ||||||
|  |      | ||||||
|  | #define PI2(a, b, c, d) \ | ||||||
|  |     a = ROR(a, 1); c = ROR(c, 5); d = ROR(d, 2); | ||||||
|  |      | ||||||
|  | int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) | ||||||
|  | { | ||||||
|  |    unsigned long temp; | ||||||
|  |     | ||||||
|  |    _ARGCHK(key != NULL); | ||||||
|  |    _ARGCHK(skey != NULL); | ||||||
|  |     | ||||||
|  |    if (keylen != 16) { | ||||||
|  |       return CRYPT_INVALID_KEYSIZE; | ||||||
|  |    } | ||||||
|  |     | ||||||
|  |    if (num_rounds != 16 && num_rounds != 0) { | ||||||
|  |       return CRYPT_INVALID_ROUNDS; | ||||||
|  |    } | ||||||
|  |     | ||||||
|  |    LOAD32L(skey->noekeon.K[0],&key[0]); | ||||||
|  |    LOAD32L(skey->noekeon.K[1],&key[4]); | ||||||
|  |    LOAD32L(skey->noekeon.K[2],&key[8]); | ||||||
|  |    LOAD32L(skey->noekeon.K[3],&key[12]); | ||||||
|  |     | ||||||
|  |    LOAD32L(skey->noekeon.dK[0],&key[0]); | ||||||
|  |    LOAD32L(skey->noekeon.dK[1],&key[4]); | ||||||
|  |    LOAD32L(skey->noekeon.dK[2],&key[8]); | ||||||
|  |    LOAD32L(skey->noekeon.dK[3],&key[12]); | ||||||
|  | 
 | ||||||
|  |    THETA(zero, skey->noekeon.dK[0], skey->noekeon.dK[1], skey->noekeon.dK[2], skey->noekeon.dK[3]); | ||||||
|  | 
 | ||||||
|  |    return CRYPT_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #ifdef CLEAN_STACK | ||||||
|  | static void _noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key) | ||||||
|  | #else | ||||||
|  | void noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key) | ||||||
|  | #endif | ||||||
|  | { | ||||||
|  |    unsigned long a,b,c,d,temp; | ||||||
|  |    int r; | ||||||
|  | 
 | ||||||
|  |    _ARGCHK(key != NULL); | ||||||
|  |    _ARGCHK(pt != NULL); | ||||||
|  |    _ARGCHK(ct != NULL); | ||||||
|  |     | ||||||
|  |    LOAD32L(a,&pt[0]); LOAD32L(b,&pt[4]); | ||||||
|  |    LOAD32L(c,&pt[8]); LOAD32L(d,&pt[12]); | ||||||
|  |     | ||||||
|  | #define ROUND(i) \ | ||||||
|  |        a ^= RC[r+i]; \ | ||||||
|  |        THETA(key->noekeon.K, a,b,c,d); \ | ||||||
|  |        PI1(a,b,c,d); \ | ||||||
|  |        GAMMA(a,b,c,d); \ | ||||||
|  |        PI2(a,b,c,d); | ||||||
|  | 
 | ||||||
|  |    for (r = 0; r < 16; r += 2) { | ||||||
|  |        ROUND(0); | ||||||
|  |        ROUND(1); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  | #undef ROUND | ||||||
|  | 
 | ||||||
|  |    a ^= RC[16]; | ||||||
|  |    THETA(key->noekeon.K, a, b, c, d); | ||||||
|  |     | ||||||
|  |    STORE32L(a,&ct[0]); STORE32L(b,&ct[4]); | ||||||
|  |    STORE32L(c,&ct[8]); STORE32L(d,&ct[12]); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #ifdef CLEAN_STACK | ||||||
|  | void noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key) | ||||||
|  | { | ||||||
|  |    _noekeon_ecb_encrypt(pt, ct, key); | ||||||
|  |    burn_stack(sizeof(unsigned long) * 5 + sizeof(int)); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #ifdef CLEAN_STACK | ||||||
|  | static void _noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key) | ||||||
|  | #else | ||||||
|  | void noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key) | ||||||
|  | #endif | ||||||
|  | { | ||||||
|  |    unsigned long a,b,c,d, temp; | ||||||
|  |    int r; | ||||||
|  | 
 | ||||||
|  |    _ARGCHK(key != NULL); | ||||||
|  |    _ARGCHK(pt != NULL); | ||||||
|  |    _ARGCHK(ct != NULL); | ||||||
|  |     | ||||||
|  |    LOAD32L(a,&ct[0]); LOAD32L(b,&ct[4]); | ||||||
|  |    LOAD32L(c,&ct[8]); LOAD32L(d,&ct[12]); | ||||||
|  |     | ||||||
|  | #define ROUND(i) \ | ||||||
|  |        THETA(key->noekeon.dK, a,b,c,d); \ | ||||||
|  |        a ^= RC[r-i]; \ | ||||||
|  |        PI1(a,b,c,d); \ | ||||||
|  |        GAMMA(a,b,c,d); \ | ||||||
|  |        PI2(a,b,c,d);  | ||||||
|  |         | ||||||
|  | 
 | ||||||
|  |    for (r = 16; r > 0; r -= 2) { | ||||||
|  |        ROUND(0); | ||||||
|  |        ROUND(1); | ||||||
|  |    } | ||||||
|  |     | ||||||
|  | #undef ROUND | ||||||
|  | 
 | ||||||
|  |    THETA(key->noekeon.dK, a,b,c,d); | ||||||
|  |    a ^= RC[0]; | ||||||
|  |    STORE32L(a,&pt[0]); STORE32L(b, &pt[4]); | ||||||
|  |    STORE32L(c,&pt[8]); STORE32L(d, &pt[12]); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #ifdef CLEAN_STACK | ||||||
|  | void noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key) | ||||||
|  | { | ||||||
|  |    _noekeon_ecb_decrypt(ct, pt, key); | ||||||
|  |    burn_stack(sizeof(unsigned long) * 5 + sizeof(int)); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | int noekeon_test(void) | ||||||
|  | { | ||||||
|  |    static const unsigned char | ||||||
|  |           key[] =  | ||||||
|  |              { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, | ||||||
|  |           pt[] =  | ||||||
|  |              { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, | ||||||
|  |           ct[] =  | ||||||
|  |              { 0x57, 0x9a, 0x6c, 0xe8, 0x91, 0x16, 0x52, 0x53, | ||||||
|  |                0x32, 0x00, 0xca, 0x0a, 0x17, 0x5d, 0x28, 0x0e }; | ||||||
|  |    unsigned char tmp[2][16]; | ||||||
|  |    int x, errno; | ||||||
|  |    symmetric_key skey; | ||||||
|  |     | ||||||
|  |    if ((errno = noekeon_setup(key, 16, 0, &skey)) != CRYPT_OK) { | ||||||
|  |       return errno; | ||||||
|  |    } | ||||||
|  |     | ||||||
|  |    noekeon_ecb_encrypt(pt, tmp[0], &skey); | ||||||
|  |    noekeon_ecb_decrypt(tmp[0], tmp[1], &skey); | ||||||
|  |     | ||||||
|  |    if (memcmp(tmp[0], ct, 16) || memcmp(tmp[1], pt, 16)) { | ||||||
|  |       return CRYPT_FAIL_TESTVECTOR; | ||||||
|  |    } | ||||||
|  |     | ||||||
|  |    return CRYPT_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int noekeon_keysize(int *desired_keysize) | ||||||
|  | { | ||||||
|  |    _ARGCHK(desired_keysize != NULL); | ||||||
|  |    if (*desired_keysize < 16) { | ||||||
|  |    	  return CRYPT_INVALID_KEYSIZE; | ||||||
|  |    } else { | ||||||
|  |       *desired_keysize = 16; | ||||||
|  |       return CRYPT_OK; | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| @ -33,14 +33,14 @@ RC2         | 256                           | | |||||||
| DES         | 256                           | | DES         | 256                           | | ||||||
| 3DES        | 768                           | | 3DES        | 768                           | | ||||||
| CAST5       | 132                           | | CAST5       | 132                           | | ||||||
|  | Noekeon     | 32                            | | ||||||
| ------------+-------------------------------/ | ------------+-------------------------------/ | ||||||
| Memory used per cipher on a 32-bit platform. | Memory used per cipher on a 32-bit platform. | ||||||
| 
 | 
 | ||||||
| [*] For Twofish with TWOFISH_SMALL defined | [*] For Twofish with TWOFISH_SMALL defined | ||||||
| [#] For all 64-bit SAFER ciphers. | [#] For all 64-bit SAFER ciphers. | ||||||
| 
 | 
 | ||||||
| Following this chart its ideal that in extremely low memory platforms that all of the ciphers are disabled and CAST5 is | Noekeon is a fairly fast cipher and uses very little memory.  Ideally in low-ram platforms all other ciphers should be | ||||||
| left.  CAST5 is a fairly fast cipher on all platforms which makes it ideally suited.  It should be noted that the | left undefined and Noekeon should remain.  While Noekeon is generally considered a secure block cipher (it is insecure | ||||||
| SAFER and SAFER+ keys are formed of arrays of unsigned char.  So in effect on platforms where "unsigned long" is  | as a hash) CAST5 is perhaps a "runner-up" choice.  CAST5 has been around longer (it is also known as CAST-128) and is  | ||||||
| 8 bytes SAFER would have the smallest key (CAST5 would come out to 264 bytes).  In this case I would recommend  | fairly fast as well.   | ||||||
| SAFER-SK128. |  | ||||||
							
								
								
									
										16
									
								
								rsa.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								rsa.c
									
									
									
									
									
								
							| @ -304,16 +304,22 @@ int rsa_depad(const unsigned char *in,  unsigned long inlen, | |||||||
| #define INPUT_BIGNUM(num, in, x, y)                              \ | #define INPUT_BIGNUM(num, in, x, y)                              \ | ||||||
| {                                                                \ | {                                                                \ | ||||||
|      /* load value */                                            \ |      /* load value */                                            \ | ||||||
|  |      if (y + 4 > inlen) {                                        \ | ||||||
|  |          errno = CRYPT_INVALID_PACKET;                           \ | ||||||
|  |          goto error2;                                            \ | ||||||
|  |      }                                                           \ | ||||||
|      LOAD32L(x, in+y);                                           \ |      LOAD32L(x, in+y);                                           \ | ||||||
|      y += 4;                                                     \ |      y += 4;                                                     \ | ||||||
|                                                                  \ |                                                                  \ | ||||||
|      /* sanity check... */                                       \ |      /* sanity check... */                                       \ | ||||||
|      if (x > 1024) {                                             \ |      if (y+x > inlen) {                                          \ | ||||||
|  |         errno = CRYPT_INVALID_PACKET;                            \ | ||||||
|         goto error2;                                             \ |         goto error2;                                             \ | ||||||
|      }                                                           \ |      }                                                           \ | ||||||
|                                                                  \ |                                                                  \ | ||||||
|      /* load it */                                               \ |      /* load it */                                               \ | ||||||
|      if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\ |      if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\ | ||||||
|  |         errno = CRYPT_MEM;                                       \ | ||||||
|         goto error2;                                             \ |         goto error2;                                             \ | ||||||
|      }                                                           \ |      }                                                           \ | ||||||
|      y += x;                                                     \ |      y += x;                                                     \ | ||||||
| @ -378,7 +384,7 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key | |||||||
|    return CRYPT_OK; |    return CRYPT_OK; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int rsa_import(const unsigned char *in, rsa_key *key) | int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) | ||||||
| { | { | ||||||
|    unsigned long x, y; |    unsigned long x, y; | ||||||
|    int errno; |    int errno; | ||||||
| @ -391,6 +397,10 @@ int rsa_import(const unsigned char *in, rsa_key *key) | |||||||
|       return errno; |       return errno; | ||||||
|    } |    } | ||||||
|     |     | ||||||
|  |    if (inlen < 1+PACKET_SIZE) { | ||||||
|  |       return CRYPT_INVALID_PACKET; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|    /* init key */ |    /* init key */ | ||||||
|    if (mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP,  |    if (mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP,  | ||||||
|                      &key->pQ, &key->p, &key->q, NULL) != MP_OKAY) { |                      &key->pQ, &key->p, &key->q, NULL) != MP_OKAY) { | ||||||
| @ -426,7 +436,7 @@ int rsa_import(const unsigned char *in, rsa_key *key) | |||||||
| error2: | error2: | ||||||
|    mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,  |    mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,  | ||||||
|                   &key->pQ, &key->qP, &key->p, &key->q, NULL); |                   &key->pQ, &key->qP, &key->p, &key->q, NULL); | ||||||
|    return CRYPT_MEM; |    return errno; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #include "rsa_sys.c" | #include "rsa_sys.c" | ||||||
|  | |||||||
							
								
								
									
										347
									
								
								rsa_sys.c
									
									
									
									
									
								
							
							
						
						
									
										347
									
								
								rsa_sys.c
									
									
									
									
									
								
							| @ -1,350 +1,3 @@ | |||||||
| #ifdef PK_PACKET |  | ||||||
| 
 |  | ||||||
| int rsa_encrypt(const unsigned char *in,  unsigned long len,  |  | ||||||
|                       unsigned char *out, unsigned long *outlen, |  | ||||||
|                       prng_state *prng, int wprng, int cipher,  |  | ||||||
|                       rsa_key *key) |  | ||||||
| { |  | ||||||
|    unsigned char sym_IV[MAXBLOCKSIZE], sym_key[MAXBLOCKSIZE], rsa_in[4096], rsa_out[4096]; |  | ||||||
|    symmetric_CTR ctr; |  | ||||||
|    unsigned long x, y, blklen, rsa_size; |  | ||||||
|    int keylen, errno;; |  | ||||||
| 
 |  | ||||||
|    _ARGCHK(in != NULL); |  | ||||||
|    _ARGCHK(out != NULL); |  | ||||||
|    _ARGCHK(outlen != NULL); |  | ||||||
|    _ARGCHK(key != NULL); |  | ||||||
| 
 |  | ||||||
|    /* are the parameters valid? */ |  | ||||||
|    if ((errno = prng_is_valid(wprng)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    if ((errno = cipher_is_valid(cipher)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* setup the CTR key */ |  | ||||||
|    keylen = 32;                                                             /* default to 256-bit keys */ |  | ||||||
|    if ((errno = cipher_descriptor[cipher].keysize(&keylen)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    blklen = cipher_descriptor[cipher].block_length; |  | ||||||
|    if (prng_descriptor[wprng].read(sym_key, keylen, prng) != (unsigned long)keylen) { |  | ||||||
|       return CRYPT_ERROR_READPRNG; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    if (prng_descriptor[wprng].read(sym_IV, blklen, prng) != blklen) { |  | ||||||
|       return CRYPT_ERROR_READPRNG; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* setup CTR mode */ |  | ||||||
|    if ((errno = ctr_start(cipher, sym_IV, sym_key, keylen, 0, &ctr)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* rsa_pad the symmetric key */ |  | ||||||
|    y = sizeof(rsa_in);  |  | ||||||
|    if ((errno = rsa_pad(sym_key, keylen, rsa_in, &y, wprng, prng)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
|     |  | ||||||
|    /* rsa encrypt it */ |  | ||||||
|    rsa_size = sizeof(rsa_out); |  | ||||||
|    if ((errno = rsa_exptmod(rsa_in, y, rsa_out, &rsa_size, PK_PUBLIC, key)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* check size */ |  | ||||||
|    if (*outlen < (PACKET_SIZE+9+rsa_size+blklen+len)) {  |  | ||||||
|       return CRYPT_BUFFER_OVERFLOW; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* now lets make the header */ |  | ||||||
|    y = PACKET_SIZE; |  | ||||||
|    out[y++] = cipher_descriptor[cipher].ID; |  | ||||||
| 
 |  | ||||||
|    /* store the size of the RSA value */ |  | ||||||
|    STORE32L(rsa_size, (out+y)); |  | ||||||
|    y += 4; |  | ||||||
| 
 |  | ||||||
|    /* store the rsa value */ |  | ||||||
|    for (x = 0; x < rsa_size; x++, y++) { |  | ||||||
|        out[y] = rsa_out[x]; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* store the IV used */ |  | ||||||
|    for (x = 0; x < blklen; x++, y++) { |  | ||||||
|        out[y] = sym_IV[x]; |  | ||||||
|    } |  | ||||||
|         |  | ||||||
|    /* store the length */ |  | ||||||
|    STORE32L(len, (out+y)); |  | ||||||
|    y += 4; |  | ||||||
| 
 |  | ||||||
|    /* encrypt the message */ |  | ||||||
|    if ((errno = ctr_encrypt(in, out+y, len, &ctr)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    y += len; |  | ||||||
| 
 |  | ||||||
|    /* store the header */ |  | ||||||
|    packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_ENCRYPTED, y); |  | ||||||
|     |  | ||||||
| #ifdef CLEAN_STACK |  | ||||||
|    /* clean up */ |  | ||||||
|    zeromem(sym_key, sizeof(sym_key)); |  | ||||||
|    zeromem(sym_IV, sizeof(sym_IV)); |  | ||||||
|    zeromem(&ctr, sizeof(ctr)); |  | ||||||
|    zeromem(rsa_in, sizeof(rsa_in)); |  | ||||||
|    zeromem(rsa_out, sizeof(rsa_out)); |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|    *outlen = y; |  | ||||||
|    return CRYPT_OK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int rsa_decrypt(const unsigned char *in,  unsigned long len,  |  | ||||||
|                       unsigned char *out, unsigned long *outlen,  |  | ||||||
|                       rsa_key *key) |  | ||||||
| { |  | ||||||
|    unsigned char sym_IV[MAXBLOCKSIZE], sym_key[MAXBLOCKSIZE], rsa_in[4096], rsa_out[4096]; |  | ||||||
|    symmetric_CTR ctr; |  | ||||||
|    unsigned long x, y, z, keylen, blklen, rsa_size; |  | ||||||
|    int cipher, errno; |  | ||||||
| 
 |  | ||||||
|    _ARGCHK(in != NULL); |  | ||||||
|    _ARGCHK(out != NULL); |  | ||||||
|    _ARGCHK(outlen != NULL); |  | ||||||
|    _ARGCHK(key != NULL); |  | ||||||
| 
 |  | ||||||
|    /* right key type? */ |  | ||||||
|    if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) { |  | ||||||
|       return CRYPT_PK_NOT_PRIVATE; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* check the header */ |  | ||||||
|    if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_ENCRYPTED)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* grab cipher name */ |  | ||||||
|    y = PACKET_SIZE; |  | ||||||
|    cipher = find_cipher_id(in[y++]); |  | ||||||
|    if (cipher == -1) { |  | ||||||
|       return CRYPT_INVALID_CIPHER; |  | ||||||
|    } |  | ||||||
|    keylen = MIN(cipher_descriptor[cipher].max_key_length, 32); |  | ||||||
|    blklen = cipher_descriptor[cipher].block_length; |  | ||||||
| 
 |  | ||||||
|    /* grab length of the rsa key */ |  | ||||||
|    LOAD32L(rsa_size, (in+y)) |  | ||||||
|    y += 4; |  | ||||||
| 
 |  | ||||||
|    /* read it in */ |  | ||||||
|    for (x = 0; x < rsa_size; x++, y++) { |  | ||||||
|        rsa_in[x] = in[y]; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* decrypt it */ |  | ||||||
|    x = sizeof(rsa_out); |  | ||||||
|    if ((errno = rsa_exptmod(rsa_in, rsa_size, rsa_out, &x, PK_PRIVATE, key)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* depad it */ |  | ||||||
|    z = sizeof(sym_key); |  | ||||||
|    if ((errno = rsa_depad(rsa_out, x, sym_key, &z)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* read the IV in */ |  | ||||||
|    for (x = 0; x < blklen; x++, y++) { |  | ||||||
|        sym_IV[x] = in[y]; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* setup CTR mode */ |  | ||||||
|    if ((errno = ctr_start(cipher, sym_IV, sym_key, keylen, 0, &ctr)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* get len */ |  | ||||||
|    LOAD32L(len, (in+y)); |  | ||||||
|    y += 4; |  | ||||||
| 
 |  | ||||||
|    /* check size */ |  | ||||||
|    if (*outlen < len) {  |  | ||||||
|       return CRYPT_BUFFER_OVERFLOW; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* decrypt the message */ |  | ||||||
|    if ((errno = ctr_decrypt(in+y, out, len, &ctr)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
|     |  | ||||||
| #ifdef CLEAN_STACK |  | ||||||
|    /* clean up */ |  | ||||||
|    zeromem(sym_key, sizeof(sym_key)); |  | ||||||
|    zeromem(sym_IV, sizeof(sym_IV)); |  | ||||||
|    zeromem(&ctr, sizeof(ctr)); |  | ||||||
|    zeromem(rsa_in, sizeof(rsa_in)); |  | ||||||
|    zeromem(rsa_out, sizeof(rsa_out)); |  | ||||||
| #endif |  | ||||||
|    *outlen = len; |  | ||||||
|    return CRYPT_OK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Signature Message Format 
 |  | ||||||
| offset    |  length   |    Contents |  | ||||||
| ---------------------------------------------------------------------- |  | ||||||
| 0         |    1      | hash ID |  | ||||||
| 1         |    4      | length of rsa_pad'ed signature |  | ||||||
| 5         |    p      | the rsa_pad'ed signature |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| int rsa_sign(const unsigned char *in,  unsigned long inlen,  |  | ||||||
|                    unsigned char *out, unsigned long *outlen,  |  | ||||||
|                    int hash, rsa_key *key) |  | ||||||
| { |  | ||||||
|    unsigned long hashlen, rsa_size, x, y, z; |  | ||||||
|    unsigned char rsa_in[4096], rsa_out[4096]; |  | ||||||
|    int errno; |  | ||||||
| 
 |  | ||||||
|    _ARGCHK(in != NULL); |  | ||||||
|    _ARGCHK(out != NULL); |  | ||||||
|    _ARGCHK(outlen != NULL); |  | ||||||
|    _ARGCHK(key != NULL); |  | ||||||
| 
 |  | ||||||
|    /* type of key? */ |  | ||||||
|    if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) { |  | ||||||
|       return CRYPT_PK_NOT_PRIVATE; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* are the parameters valid? */ |  | ||||||
|    if ((errno = hash_is_valid(hash)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* hash it */ |  | ||||||
|    hashlen = hash_descriptor[hash].hashsize; |  | ||||||
|    z = sizeof(rsa_in); |  | ||||||
|    if ((errno = hash_memory(hash, in, inlen, rsa_in, &z)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* pad it */ |  | ||||||
|    x = sizeof(rsa_in); |  | ||||||
|    if ((errno = rsa_signpad(rsa_in, hashlen, rsa_out, &x)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* sign it */ |  | ||||||
|    rsa_size = sizeof(rsa_in); |  | ||||||
|    if ((errno = rsa_exptmod(rsa_out, x, rsa_in, &rsa_size, PK_PRIVATE, key)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* check size */ |  | ||||||
|    if (*outlen < (PACKET_SIZE+4+rsa_size)) { |  | ||||||
|       return CRYPT_BUFFER_OVERFLOW; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* now lets output the message */ |  | ||||||
|    y = PACKET_SIZE; |  | ||||||
|    out[y++] = hash_descriptor[hash].ID; |  | ||||||
| 
 |  | ||||||
|    /* output the len */ |  | ||||||
|    STORE32L(rsa_size, (out+y)); |  | ||||||
|    y += 4; |  | ||||||
| 
 |  | ||||||
|    /* store the signature */ |  | ||||||
|    for (x = 0; x < rsa_size; x++, y++) { |  | ||||||
|        out[y] = rsa_in[x]; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* store header */ |  | ||||||
|    packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_SIGNED, y); |  | ||||||
| 
 |  | ||||||
| #ifdef CLEAN_STACK |  | ||||||
|    /* clean up */ |  | ||||||
|    zeromem(rsa_in, sizeof(rsa_in)); |  | ||||||
|    zeromem(rsa_out, sizeof(rsa_out)); |  | ||||||
| #endif |  | ||||||
|    *outlen = y; |  | ||||||
|    return CRYPT_OK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int rsa_verify(const unsigned char *sig, const unsigned char *msg, |  | ||||||
|                      unsigned long inlen, int *stat, |  | ||||||
|                      rsa_key *key) |  | ||||||
| { |  | ||||||
|    unsigned long hashlen, rsa_size, x, y, z, w; |  | ||||||
|    int hash, errno; |  | ||||||
|    unsigned char rsa_in[4096], rsa_out[4096]; |  | ||||||
| 
 |  | ||||||
|    _ARGCHK(sig != NULL); |  | ||||||
|    _ARGCHK(msg != NULL); |  | ||||||
|    _ARGCHK(stat != NULL); |  | ||||||
|    _ARGCHK(key != NULL); |  | ||||||
| 
 |  | ||||||
|    /* always be incorrect by default */ |  | ||||||
|    *stat = 0; |  | ||||||
| 
 |  | ||||||
|    /* verify header */ |  | ||||||
|    if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_RSA, PACKET_SUB_SIGNED)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* grab hash name */ |  | ||||||
|    y = PACKET_SIZE; |  | ||||||
|    hash = find_hash_id(sig[y++]); |  | ||||||
|    if (hash == -1) { |  | ||||||
|       return CRYPT_INVALID_HASH; |  | ||||||
|    } |  | ||||||
|    hashlen = hash_descriptor[hash].hashsize; |  | ||||||
| 
 |  | ||||||
|    /* get the len */ |  | ||||||
|    LOAD32L(rsa_size, (sig+y)); |  | ||||||
|    y += 4; |  | ||||||
| 
 |  | ||||||
|    /* load the signature */ |  | ||||||
|    for (x = 0; x < rsa_size; x++, y++) { |  | ||||||
|        rsa_in[x] = sig[y]; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* exptmod it */ |  | ||||||
|    x = sizeof(rsa_in); |  | ||||||
|    if ((errno = rsa_exptmod(rsa_in, rsa_size, rsa_out, &x, PK_PUBLIC, key)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* depad it */ |  | ||||||
|    z = sizeof(rsa_in); |  | ||||||
|    if ((errno = rsa_signdepad(rsa_out, x, rsa_in, &z)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /* check? */ |  | ||||||
|    w = sizeof(rsa_out); |  | ||||||
|    if ((errno = hash_memory(hash, msg, inlen, rsa_out, &w)) != CRYPT_OK) { |  | ||||||
|       return errno; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    if ((z == hashlen) && (!memcmp(rsa_in, rsa_out, hashlen))) { |  | ||||||
|       *stat = 1; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
| #ifdef CLEAN_STACK |  | ||||||
|    zeromem(rsa_in, sizeof(rsa_in)); |  | ||||||
|    zeromem(rsa_out, sizeof(rsa_out)); |  | ||||||
| #endif |  | ||||||
|    return CRYPT_OK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| /* these are smaller routines written by Clay Culver.  They do the same function as the rsa_encrypt/decrypt 
 | /* these are smaller routines written by Clay Culver.  They do the same function as the rsa_encrypt/decrypt 
 | ||||||
|  * except that they are used to RSA encrypt/decrypt a single value and not a packet. |  * except that they are used to RSA encrypt/decrypt a single value and not a packet. | ||||||
|  */ |  */ | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								safer+.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								safer+.c
									
									
									
									
									
								
							| @ -117,7 +117,7 @@ extern const unsigned char safer_ebox[], safer_lbox[]; | |||||||
|     iSHUF(b2, b); iPHT(b);    \ |     iSHUF(b2, b); iPHT(b);    \ | ||||||
|     iSHUF(b, b2); iPHT(b2); |     iSHUF(b, b2); iPHT(b2); | ||||||
|      |      | ||||||
| #ifdef SAFERP_SMALL     | #ifdef SMALL_CODE     | ||||||
| 
 | 
 | ||||||
| static void _round(unsigned char *b, int i, symmetric_key *skey)  | static void _round(unsigned char *b, int i, symmetric_key *skey)  | ||||||
| { | { | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								xtea.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								xtea.c
									
									
									
									
									
								
							| @ -133,7 +133,7 @@ int xtea_test(void) | |||||||
| 
 | 
 | ||||||
| int xtea_keysize(int *desired_keysize) | int xtea_keysize(int *desired_keysize) | ||||||
| { | { | ||||||
|    _ARGCHK(desired_keysize); |    _ARGCHK(desired_keysize != NULL); | ||||||
|    if (*desired_keysize < 16) { |    if (*desired_keysize < 16) { | ||||||
|       return CRYPT_INVALID_KEYSIZE;  |       return CRYPT_INVALID_KEYSIZE;  | ||||||
|    } |    } | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								yarrow.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								yarrow.c
									
									
									
									
									
								
							| @ -20,6 +20,8 @@ int yarrow_start(prng_state *prng) | |||||||
|    /* these are the default hash/cipher combo used */ |    /* these are the default hash/cipher combo used */ | ||||||
| #ifdef RIJNDAEL | #ifdef RIJNDAEL | ||||||
|    prng->yarrow.cipher = register_cipher(&rijndael_desc); |    prng->yarrow.cipher = register_cipher(&rijndael_desc); | ||||||
|  | #elif defined(NOEKEON)    | ||||||
|  |    prng->yarrow.cipher = register_cipher(&noekeon_desc); | ||||||
| #elif defined(BLOWFISH) | #elif defined(BLOWFISH) | ||||||
|    prng->yarrow.cipher = register_cipher(&blowfish_desc); |    prng->yarrow.cipher = register_cipher(&blowfish_desc); | ||||||
| #elif defined(TWOFISH) | #elif defined(TWOFISH) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user