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 | ||||
| }; | ||||
| 
 | ||||
| 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" | ||||
| 
 | ||||
| #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, 3, k) | ||||
|      | ||||
| #ifdef RIJNDAEL_SMALL | ||||
| #ifdef SMALL_CODE | ||||
| 
 | ||||
| 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, 3, k) | ||||
|      | ||||
| #ifdef RIJNDAEL_SMALL | ||||
| #ifdef SMALL_CODE | ||||
| 
 | ||||
| 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 | ||||
| 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. | ||||
|  | ||||
							
								
								
									
										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 } }; | ||||
| 
 | ||||
| #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 x; | ||||
| @ -187,7 +202,7 @@ int register_cipher(const struct _cipher_descriptor *cipher) | ||||
| 
 | ||||
|    /* is it already registered? */ | ||||
|    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; | ||||
|        } | ||||
|    } | ||||
| @ -214,6 +229,7 @@ int unregister_cipher(const struct _cipher_descriptor *cipher) | ||||
|    for (x = 0; x < 32; x++) { | ||||
|        if (!memcmp(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor))) { | ||||
|           cipher_descriptor[x].name = NULL; | ||||
|           cipher_descriptor[x].ID   = 255; | ||||
|           return CRYPT_OK; | ||||
|        } | ||||
|    } | ||||
|  | ||||
							
								
								
									
										220
									
								
								crypt.tex
									
									
									
									
									
								
							
							
						
						
									
										220
									
								
								crypt.tex
									
									
									
									
									
								
							| @ -44,7 +44,7 @@ | ||||
| \def\gap{\vspace{0.5ex}} | ||||
| \makeindex | ||||
| \begin{document} | ||||
| \title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.77} | ||||
| \title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.78} | ||||
| \author{Tom St Denis \\ | ||||
| Algonquin College \\ | ||||
| \\ | ||||
| @ -398,12 +398,6 @@ int main(void) | ||||
|    symmetric_key skey; | ||||
|    int errno; | ||||
| 
 | ||||
|    /* first register Blowfish */ | ||||
|    if (register_cipher(&blowfish_desc) == -1) { | ||||
|       printf("Error registering Blowfish.\n"); | ||||
|       return -1; | ||||
|    } | ||||
| 
 | ||||
|    /* ... key is loaded appropriately in ``key'' ... */ | ||||
|    /* ... 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 SK128 & safer\_sk128\_desc & 8 & 16 & 6 .. 13 \\ | ||||
|      \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 DES & des\_desc & 8 & 7 & 16 \\ | ||||
|      \hline 3DES (EDE mode) & des3\_desc & 8 & 21 & 16 \\ | ||||
|      \hline CAST5 (CAST-128) & cast5\_desc & 8 & 5 .. 16 & 12, 16 \\ | ||||
|      \hline Noekeon & noekeon\_desc & 16 & 16 & 16 \\ | ||||
|      \hline | ||||
| \end{tabular} | ||||
| \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 | ||||
| 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 | ||||
| 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) | ||||
| 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,  | ||||
|                 int which, rsa_key *key); | ||||
| \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''  | ||||
| (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} | ||||
| The remaining RSA functions are non-standard but should (to the best of my knowledge) be secure if used correctly.  To | ||||
| encrypt a buffer of memory in a hybrid fashion call: | ||||
| \index{rsa\_encrypt()} | ||||
| \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: | ||||
| To encrypt or decrypt a symmetric key using RSA the following functions are provided.  The idea is that you make up | ||||
| a random symmetric key and use that to encode your message.  By RSA encrypting the symmetric key you can send it to a | ||||
| recipient who can RSA decrypt it and symmetrically decrypt the message. | ||||
| \begin{verbatim} | ||||
| int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen, | ||||
|                           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 | ||||
| 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: | ||||
| \begin{verbatim} | ||||
| int rsa_export(unsigned char *out, unsigned long *outlen,  | ||||
|                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} | ||||
| 
 | ||||
| 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} | ||||
| 
 | ||||
| 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  | ||||
| are at a minimum 1024 bits in length.  If you want to use any of the large size message digests  | ||||
| (SHA-512 or SHA-384) you will have to use a larger key. | ||||
| required to use all of the symmetric ciphers with the RSA routines. If you want to use any of the large size  | ||||
| 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 | ||||
| keys.  None of the hashes will have problems with such key sizes. | ||||
| 
 | ||||
| \chapter{Diffie-Hellman Key Exchange} | ||||
| 
 | ||||
| @ -1535,7 +1493,7 @@ over communication mediums. | ||||
| int dh_export(unsigned char *out, unsigned long *outlen,  | ||||
|               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} | ||||
| 
 | ||||
| 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 long x, len; | ||||
|    int res, errno; | ||||
|    int res, errno, inlen; | ||||
|    dh_key mykey, theirkey; | ||||
| 
 | ||||
|    /* make up our private key */ | ||||
| @ -1597,13 +1555,13 @@ int establish_secure_socket(int sock, int mode, unsigned char *key, | ||||
|       }           | ||||
| 
 | ||||
|       /* get their key */ | ||||
|       if (recv(sock, buf2, sizeof(buf2), 0) <= 0) { | ||||
|       if ((inlen = recv(sock, buf2, sizeof(buf2), 0)) <= 0) { | ||||
|          res = CRYPT_ERROR; | ||||
|          goto done2; | ||||
|       } | ||||
|    } else { | ||||
|       /* 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; | ||||
|          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; | ||||
|       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. | ||||
| 
 | ||||
| \section{DH Packet} | ||||
| There are routines to perform the work similar to that of ``rsa\_encrypt()'' and ``rsa\_decrypt()'' for DH keys as well. | ||||
| The encrypt routine will make up a random key, attach the public key to the message and used the shared secret to encrypt | ||||
| 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: | ||||
| Similar to the RSA related functions there are functions to encrypt or decrypt symmetric keys using the DH public key | ||||
| algorithms.   | ||||
| \begin{verbatim} | ||||
| int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen, | ||||
|                          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 | ||||
| as the symmetric key you are trying to share. | ||||
| 
 | ||||
| To sign with a Diffie-Hellman key call: | ||||
| \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: | ||||
| Similar to the RSA system you can sign and verify a hash of a message. | ||||
| \begin{verbatim} | ||||
| int dh_sign_hash(const unsigned char *in,  unsigned long inlen, | ||||
|                        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); | ||||
| \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} | ||||
| 
 | ||||
| \section{Background} | ||||
| @ -1784,7 +1705,7 @@ To import and export a key there are: | ||||
| int ecc_export(unsigned char *out, unsigned long *outlen,  | ||||
|                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} | ||||
| These two work exactly like there DH counterparts.  Finally when you share your public key you can make a shared secret | ||||
| with: | ||||
| @ -1813,28 +1734,8 @@ void ecc_sizes(int *low, int *high); | ||||
| Which both work like their DH counterparts. | ||||
| 
 | ||||
| \section{ECC Packet} | ||||
| There are routines to perform the work similar to that of ``rsa\_encrypt()'' and ``rsa\_decrypt()'' for ECC keys as well. | ||||
| The encrypt routine will make up a random key, attach the public key to the message and used the shared secret to encrypt | ||||
| 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: | ||||
| Similar to the RSA API there are two functions which encrypt and decrypt symmetric keys using the ECC public key | ||||
| algorithms. | ||||
| \begin{verbatim} | ||||
| int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen, | ||||
|                           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,  | ||||
|                           unsigned long *keylen, ecc_key *key); | ||||
| \end{verbatim} | ||||
| You can sign messages with the ECC routines as well, to sign a message call: | ||||
| \index{ecc\_sign()} | ||||
| \begin{verbatim} | ||||
| 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); | ||||
| \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 | ||||
| 
 | ||||
| Where ``inkey'' is an input symmetric key of no more than 32 bytes.  Essentially these routines created a random public key | ||||
| and find the hash of the shared secret.  The message digest is than XOR'ed against the symmetric key.  All of the required | ||||
| data is placed in ``out'' by ``ecc\_encrypt\_key()''.   The hash chosen must produce a message digest at least as large | ||||
| as the symmetric key you are trying to share. | ||||
| 
 | ||||
| There are also functions to sign and verify the hash of a message. | ||||
| \begin{verbatim} | ||||
| int ecc_sign_hash(const unsigned char *in,  unsigned long inlen, | ||||
|                         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); | ||||
| \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} | ||||
| 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 | ||||
| @ -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 | ||||
| it will not speed up the encryption or decryption functions. | ||||
| 
 | ||||
| \subsubsection{SAFERP\_SMALL and RIJNDAEL\_SMALL} | ||||
| These two build options let you use slower versions of the ciphers which are also much smaller.  In the case of the SAFER+ | ||||
| implementation it ends up being 1/6th the size.  As for Rijndael its roughly half the size. | ||||
| 
 | ||||
| \subsubsection{SMALL\_CODE} | ||||
| When this is defined some of the code such as the Rijndael and SAFER+ ciphers are replaced with smaller code variants. | ||||
| These variants are slower but can save quite a bit of code space. | ||||
| 
 | ||||
| \end{document} | ||||
|  | ||||
| @ -6,6 +6,6 @@ int main(void) | ||||
| { | ||||
|    register_cipher(&rijndael_desc); | ||||
|    register_prng(&yarrow_desc); | ||||
|    register_hash(&sha1_desc); | ||||
|    register_hash(&sha256_desc); | ||||
|    return 0; | ||||
| } | ||||
|  | ||||
							
								
								
									
										35
									
								
								demos/test.c
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								demos/test.c
									
									
									
									
									
								
							| @ -259,7 +259,7 @@ void ctr_tests(void) | ||||
|  for (x = 0; x < 32; x++) blk[x] = count[x] = x; | ||||
| 
 | ||||
|  /* now lets start a ctr session */ | ||||
|  if ((errno = ctr_start(find_cipher("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 */ | ||||
|  for (x = 0; x < 4; x++) | ||||
| @ -272,7 +272,7 @@ void ctr_tests(void) | ||||
|  for (x = 0; x < 32; x++) count[x] = x; | ||||
| 
 | ||||
|  /* now lets start a cbc session */ | ||||
|  if ((errno = ctr_start(find_cipher("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 */ | ||||
|  for (x = 0; x < 4; x++) | ||||
| @ -369,7 +369,7 @@ void rsa_test(void) | ||||
|  /* now lets test rsa_encrypt() */ | ||||
|  for (x = 0; x < 8; x++) in[x] = (unsigned char)x; | ||||
|  x = sizeof(out); | ||||
|  if ((errno = rsa_encrypt(in, 8, out, &x, &prng, find_prng("yarrow"), find_cipher("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)); | ||||
|     return; | ||||
|  } | ||||
| @ -410,7 +410,7 @@ void rsa_test(void) | ||||
|  } | ||||
|  printf("RSA Export takes %lu bytes\n", x); | ||||
|  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)); | ||||
|     return; | ||||
|  } | ||||
| @ -596,7 +596,7 @@ void time_ecb(void) | ||||
|         func = cipher_descriptor[x].ecb_encrypt; | ||||
|         y1 = 0; | ||||
|         t1 = XCLOCK(); | ||||
|         while (XCLOCK() - t1 < 2*XCLOCKS_PER_SEC) { | ||||
|         while (XCLOCK() - t1 < 3*XCLOCKS_PER_SEC) { | ||||
|             DO256; y1 += 256; | ||||
|         } | ||||
|         t1 = XCLOCK() - t1; | ||||
| @ -604,7 +604,7 @@ void time_ecb(void) | ||||
|         func = cipher_descriptor[x].ecb_decrypt; | ||||
|         y2 = 0; | ||||
|         t2 = XCLOCK(); | ||||
|         while (XCLOCK() - t2 < 2*XCLOCKS_PER_SEC) { | ||||
|         while (XCLOCK() - t2 < 3*XCLOCKS_PER_SEC) { | ||||
|             DO256; y2 += 256; | ||||
|         } | ||||
|         t2 = XCLOCK() - t2; | ||||
| @ -673,7 +673,7 @@ void dh_tests(void) | ||||
|    dh_free(&userb); | ||||
| 
 | ||||
|    /* 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)); | ||||
|       return; | ||||
|    } | ||||
| @ -741,7 +741,7 @@ void dh_tests(void) | ||||
|    dh_make_key(&prng, find_prng("yarrow"), 24, &usera); | ||||
| 
 | ||||
|    x = 4096; | ||||
|    if (dh_encrypt(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), find_cipher("rijndael"), | ||||
|    if (dh_encrypt(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), find_cipher("aes"), | ||||
|                    find_hash("sha1"), &usera) != CRYPT_OK) { | ||||
|       printf("dh_encrypt says %s\n", error_to_string(errno)); | ||||
|       return; | ||||
| @ -910,7 +910,7 @@ void ecc_tests(void) | ||||
|    printf("ECC-192 export took %ld bytes\n", y); | ||||
| 
 | ||||
|    /* 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)); | ||||
|       return; | ||||
|    } | ||||
| @ -973,7 +973,7 @@ void ecc_tests(void) | ||||
|    ecc_make_key(&prng, find_prng("yarrow"), 20, &usera); | ||||
| 
 | ||||
|    x = 4096; | ||||
|    if (ecc_encrypt(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), find_cipher("rijndael"), | ||||
|    if (ecc_encrypt(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), find_cipher("aes"), | ||||
|                    find_hash("tiger"), &usera) != CRYPT_OK) { | ||||
|       printf("ecc_encrypt says %s\n", error_to_string(errno)); | ||||
|       return; | ||||
| @ -1158,7 +1158,7 @@ void register_all_algs(void) | ||||
|    register_cipher(&serpent_desc); | ||||
| #endif | ||||
| #ifdef RIJNDAEL | ||||
|    register_cipher(&rijndael_desc); | ||||
|    register_cipher(&aes_desc); | ||||
| #endif | ||||
| #ifdef TWOFISH | ||||
|    register_cipher(&twofish_desc); | ||||
| @ -1179,6 +1179,9 @@ void register_all_algs(void) | ||||
| #ifdef CAST5 | ||||
|    register_cipher(&cast5_desc); | ||||
| #endif | ||||
| #ifdef NOEKEON | ||||
|    register_cipher(&noekeon_desc); | ||||
| #endif | ||||
| 
 | ||||
|    register_cipher(&null_desc); | ||||
| 
 | ||||
| @ -1284,7 +1287,7 @@ void kr_test(void) | ||||
|           exit(-1); | ||||
|        } | ||||
|        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)); | ||||
|           exit(-1); | ||||
|        } | ||||
| @ -1303,7 +1306,7 @@ void kr_test(void) | ||||
|           exit(-1); | ||||
|        } | ||||
|        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)); | ||||
|           exit(-1); | ||||
|        } | ||||
| @ -1441,7 +1444,7 @@ void kr_test(void) | ||||
|    kr_clear(&kr); | ||||
|    kr_init(&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)); | ||||
|       exit(-1); | ||||
|    } | ||||
| @ -1459,7 +1462,7 @@ void kr_test(void) | ||||
|    kr_clear(&kr); | ||||
|    kr_init(&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)); | ||||
|       exit(-1); | ||||
|    } | ||||
| @ -1529,7 +1532,7 @@ int main(void) | ||||
| #endif | ||||
| 
 | ||||
|  register_all_algs(); | ||||
|   | ||||
| 
 | ||||
|  if ((errno = yarrow_start(&prng)) != CRYPT_OK) { | ||||
|     printf("yarrow_start: %s\n", error_to_string(errno)); | ||||
|  } | ||||
|  | ||||
							
								
								
									
										20
									
								
								dh.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								dh.c
									
									
									
									
									
								
							| @ -315,18 +315,22 @@ void dh_free(dh_key *key) | ||||
| #define INPUT_BIGNUM(num, in, x, y)                              \ | ||||
| {                                                                \ | ||||
|      /* load value */                                            \ | ||||
|      if (y + 4 > inlen) {                                        \ | ||||
|         errno = CRYPT_INVALID_PACKET;                            \ | ||||
|         goto error;                                              \ | ||||
|      }                                                           \ | ||||
|      LOAD32L(x, in+y);                                           \ | ||||
|      y += 4;                                                     \ | ||||
|                                                                  \ | ||||
|      /* sanity check... */                                       \ | ||||
|      if (x > 1024) {                                             \ | ||||
|         errno = CRYPT_ERROR;                                     \ | ||||
|      if (x+y > inlen) {                                          \ | ||||
|         errno = CRYPT_INVALID_PACKET;                            \ | ||||
|         goto error;                                              \ | ||||
|      }                                                           \ | ||||
|                                                                  \ | ||||
|      /* load it */                                               \ | ||||
|      if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\ | ||||
|         return CRYPT_MEM;                                        \ | ||||
|         errno =  CRYPT_MEM;                                        \ | ||||
|         goto error;                                              \ | ||||
|      }                                                           \ | ||||
|      y += x;                                                     \ | ||||
| @ -381,9 +385,9 @@ int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key) | ||||
|    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; | ||||
| 
 | ||||
|    _ARGCHK(in != NULL); | ||||
| @ -393,6 +397,10 @@ int dh_import(const unsigned char *in, dh_key *key) | ||||
|    if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_KEY)) != CRYPT_OK) { | ||||
|       return errno; | ||||
|    } | ||||
|     | ||||
|    if (2+PACKET_SIZE > inlen) { | ||||
|       return CRYPT_INVALID_PACKET; | ||||
|    } | ||||
| 
 | ||||
|    /* init */ | ||||
|    if (mp_init_multi(&key->x, &key->y, NULL) != MP_OKAY) {  | ||||
| @ -403,7 +411,7 @@ int dh_import(const unsigned char *in, dh_key *key) | ||||
|    key->type = in[y++]; | ||||
|    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) { | ||||
|       errno = CRYPT_INVALID_KEYSIZE; | ||||
|       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, | ||||
|                          unsigned char *out,  unsigned long *len, | ||||
|                          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 */ | ||||
|    LOAD32L(x, in+y); | ||||
|    y += 4; | ||||
|    if ((errno = dh_import(in+y, &pubkey)) != CRYPT_OK) { | ||||
|    if ((errno = dh_import(in+y, x, &pubkey)) != CRYPT_OK) { | ||||
|       return errno; | ||||
|    } | ||||
|    y += x; | ||||
|  | ||||
							
								
								
									
										39
									
								
								ecc.c
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								ecc.c
									
									
									
									
									
								
							| @ -636,16 +636,22 @@ done: | ||||
| #define INPUT_BIGNUM(num, in, x, y)                              \ | ||||
| {                                                                \ | ||||
|      /* load value */                                            \ | ||||
|      if (y+4 > inlen) {                                          \ | ||||
|         errno = CRYPT_INVALID_PACKET;                            \ | ||||
|         goto error;                                              \ | ||||
|      }                                                           \ | ||||
|      LOAD32L(x, in+y);                                           \ | ||||
|      y += 4;                                                     \ | ||||
|                                                                  \ | ||||
|      /* sanity check... */                                       \ | ||||
|      if (x > 1024) {                                             \ | ||||
|      if (y+x > inlen) {                                          \ | ||||
|         errno = CRYPT_INVALID_PACKET;                            \ | ||||
|         goto error;                                              \ | ||||
|      }                                                           \ | ||||
|                                                                  \ | ||||
|      /* load it */                                               \ | ||||
|      if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\ | ||||
|         errno = CRYPT_MEM;                                       \ | ||||
|         goto error;                                              \ | ||||
|      }                                                           \ | ||||
|      y += x;                                                     \ | ||||
| @ -701,10 +707,10 @@ int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key | ||||
|    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; | ||||
|    int res, errno; | ||||
|    int errno; | ||||
| 
 | ||||
|    _ARGCHK(in != NULL); | ||||
|    _ARGCHK(key != NULL); | ||||
| @ -713,6 +719,10 @@ int ecc_import(const unsigned char *in, ecc_key *key) | ||||
|    if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_KEY)) != CRYPT_OK) {  | ||||
|       return errno; | ||||
|    } | ||||
|     | ||||
|    if (2+PACKET_SIZE > inlen) { | ||||
|       return CRYPT_INVALID_PACKET; | ||||
|    } | ||||
| 
 | ||||
|    /* init key */ | ||||
|    if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL) != MP_OKAY) { | ||||
| @ -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++); | ||||
|    if (sets[x].size == 0) {  | ||||
|       res = CRYPT_INVALID_KEYSIZE; | ||||
|       goto error2; | ||||
|       errno = CRYPT_INVALID_KEYSIZE; | ||||
|       goto error; | ||||
|    } | ||||
|    key->idx = x; | ||||
| 
 | ||||
|    /* type check both values */ | ||||
|    if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE))  { | ||||
|       res = CRYPT_INVALID_PACKET; | ||||
|       goto error2; | ||||
|       errno = CRYPT_INVALID_PACKET; | ||||
|       goto error; | ||||
|    } | ||||
| 
 | ||||
|    /* is the key idx valid? */ | ||||
|    if (!is_valid_idx(key->idx)) { | ||||
|       res = CRYPT_INVALID_PACKET; | ||||
|       goto error2; | ||||
|       errno = CRYPT_INVALID_PACKET; | ||||
|       goto error; | ||||
|    } | ||||
| 
 | ||||
|    /* load x coordinate */ | ||||
| @ -747,20 +757,19 @@ int ecc_import(const unsigned char *in, ecc_key *key) | ||||
|    | ||||
|    /* load 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) { | ||||
|       /* load private key */ | ||||
|       INPUT_BIGNUM(&key->k, in, x, y); | ||||
|    } | ||||
|    res = CRYPT_OK; | ||||
|    goto done; | ||||
|    return CRYPT_OK; | ||||
| error: | ||||
|    res = CRYPT_MEM; | ||||
| error2: | ||||
|    mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL); | ||||
| done: | ||||
|    return res; | ||||
|    return errno; | ||||
| } | ||||
| 
 | ||||
| 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, | ||||
|                           unsigned char *out,  unsigned long *len,  | ||||
|                           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 */ | ||||
|    LOAD32L(x, in+y); | ||||
|    y += 4; | ||||
|    if ((errno = ecc_import(in+y, &pubkey)) != CRYPT_OK) { | ||||
|    if ((errno = ecc_import(in+y, x, &pubkey)) != CRYPT_OK) { | ||||
|       return errno; | ||||
|    } | ||||
|    y += x; | ||||
| @ -805,7 +318,7 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash, | ||||
|    y += 4; | ||||
| 
 | ||||
|    /* 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; | ||||
|    } | ||||
|    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; | ||||
|    int system, key_type, errno; | ||||
| @ -370,6 +370,10 @@ int kr_import(pk_key *pk, const unsigned char *in) | ||||
|    _ARGCHK(pk != NULL); | ||||
|    _ARGCHK(in != NULL); | ||||
| 
 | ||||
|    if (inlen < 10) { | ||||
|       return CRYPT_INVALID_PACKET; | ||||
|    } | ||||
| 
 | ||||
|    if (memcmp(in, key_magic, 4)) { | ||||
|       return CRYPT_INVALID_PACKET; | ||||
|    } | ||||
| @ -382,19 +386,23 @@ int kr_import(pk_key *pk, const unsigned char *in) | ||||
|    } | ||||
| 
 | ||||
|    zeromem(&key, sizeof(key)); | ||||
|     | ||||
|    /* size of remaining packet */ | ||||
|    inlen -= 10 + 3*MAXLEN; | ||||
|     | ||||
|    switch (system) { | ||||
|         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; | ||||
|             } | ||||
|             break; | ||||
|         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; | ||||
|             } | ||||
|             break; | ||||
|         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; | ||||
|             } | ||||
|             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 ((errno = kr_import(*pk, buf)) != CRYPT_OK) {  | ||||
|       if ((errno = kr_import(*pk, buf, len)) != CRYPT_OK) {  | ||||
|          return errno;  | ||||
|       } | ||||
|    } | ||||
|  | ||||
							
								
								
									
										20
									
								
								makefile
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								makefile
									
									
									
									
									
								
							| @ -9,7 +9,7 @@ | ||||
| # a build. This is easy to remedy though, for those that have problems.
 | ||||
| 
 | ||||
| # The version
 | ||||
| VERSION=0.77 | ||||
| VERSION=0.78 | ||||
| 
 | ||||
| #Compiler and Linker Names
 | ||||
| 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)
 | ||||
| CFLAGS += -Os  | ||||
| 
 | ||||
| #Use small code variants of functions when possible?  (Slows it down!)
 | ||||
| CFLAGS += -DSMALL_CODE | ||||
| 
 | ||||
| #compile for DEBUGGING 
 | ||||
| #CFLAGS += -g3
 | ||||
| 
 | ||||
| @ -74,6 +77,7 @@ CFLAGS += -DXTEA | ||||
| CFLAGS += -DTWOFISH | ||||
| CFLAGS += -DDES | ||||
| CFLAGS += -DCAST5 | ||||
| CFLAGS += -DNOEKEON | ||||
| 
 | ||||
| #You can also customize the Twofish code.  All four combinations 
 | ||||
| #of the flags are possible but only three of them make sense.
 | ||||
| @ -98,14 +102,6 @@ CFLAGS += -DCAST5 | ||||
| # This speeds up the cipher somewhat.
 | ||||
| #CFLAGS += -DTWOFISH_TABLES 
 | ||||
| 
 | ||||
| #Small code variant of the SAFER+ cipher, uses same RAM but less code space
 | ||||
| #With this defined the cipher is slower.  On my x86 with GCC 3.2 it required 50KB less space
 | ||||
| CFLAGS += -DSAFERP_SMALL | ||||
| 
 | ||||
| #Small Rijndael [saves 13KB on an x86]
 | ||||
| #With this defined the cipher is slower (by 50Mbit/sec on an Athon XP)
 | ||||
| CFLAGS += -DRIJNDAEL_SMALL | ||||
| 
 | ||||
| #Use fast PK routines.  Basically this limits the size of the private key in the
 | ||||
| #DH system to 256 bits.  The group order remains unchanged so the best
 | ||||
| #attacks are still GNFS (for DH upto 2560-bits)
 | ||||
| @ -114,10 +110,6 @@ CFLAGS += -DRIJNDAEL_SMALL | ||||
| #security so its by default not turned on.  USE AT YOUR RISK!
 | ||||
| #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
 | ||||
| CFLAGS += -DCFB | ||||
| 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 \
 | ||||
| bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o \ | ||||
| md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o \ | ||||
| safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o 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 | ||||
| 
 | ||||
| TESTOBJECTS=demos/test.o | ||||
|  | ||||
							
								
								
									
										25
									
								
								makefile.ps2
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								makefile.ps2
									
									
									
									
									
								
							| @ -43,15 +43,18 @@ CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wno-unused -Werror  \ | ||||
|    -DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) -DXCLOCK=$(XCLOCK) \ | ||||
|    -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) | ||||
| #CFLAGS += -O3 -fomit-frame-pointer -funroll-loops | ||||
| 
 | ||||
| #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. | ||||
| 
 | ||||
| @ -75,6 +78,7 @@ CFLAGS += -DXTEA | ||||
| CFLAGS += -DTWOFISH | ||||
| CFLAGS += -DDES | ||||
| CFLAGS += -DCAST5 | ||||
| CFLAGS += -DNOEKEON | ||||
| 
 | ||||
| #You can also customize the Twofish code.  All four combinations  | ||||
| #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! | ||||
| #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 | ||||
| CFLAGS += -DCFB | ||||
| CFLAGS += -DOFB | ||||
| @ -156,11 +156,6 @@ CFLAGS += -DKR | ||||
| # include large integer math routines? (required by the PK code) | ||||
| 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 | ||||
| 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 \ | ||||
| bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o \ | ||||
| md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o \ | ||||
| safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o 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 | ||||
| 
 | ||||
| # 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) | ||||
| 
 | ||||
| #Small code (smaller variants of some block ciphers) | ||||
| CFLAGS += /DSMALL_CODE | ||||
| 
 | ||||
| #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  | ||||
| @ -48,6 +51,7 @@ CFLAGS += /DXTEA | ||||
| CFLAGS += /DTWOFISH | ||||
| CFLAGS += /DDES | ||||
| CFLAGS += /DCAST5 | ||||
| CFLAGS += /DNOEKEON | ||||
| 
 | ||||
| #You can also customize the Twofish code.  All four combinations  | ||||
| #of the flags are possible but only three of them make sense. | ||||
| @ -72,14 +76,6 @@ CFLAGS += /DCAST5 | ||||
| # This speeds up the cipher somewhat. | ||||
| # CFLAGS += /DTWOFISH_TABLES  | ||||
| 
 | ||||
| #Small code variant of the SAFER+ cipher, uses same RAM but less code space | ||||
| #With this defined the cipher is slower.  On my x86 with GCC 3.2 it required 50KB less space | ||||
| CFLAGS += /DSAFERP_SMALL | ||||
| 
 | ||||
| #Small Rijndael [saves 13KB on an x86] | ||||
| #With this defined the cipher is slower (by 50Mbit/sec on an Athon XP) | ||||
| CFLAGS += /DRIJNDAEL_SMALL | ||||
| 
 | ||||
| #Use fast PK routines.  Basically this limits the size of the private key in the | ||||
| #DH system to 256 bits.  The group order remains unchanged so the best | ||||
| #attacks are still GNFS (for DH upto 2560-bits) | ||||
| @ -88,10 +84,6 @@ CFLAGS += /DRIJNDAEL_SMALL | ||||
| #security so its by default not turned on.  USE AT YOUR RISK! | ||||
| #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 | ||||
| CFLAGS += /DCFB | ||||
| CFLAGS += /DOFB | ||||
| @ -129,11 +121,6 @@ CFLAGS += /DKR | ||||
| # include large integer math routines? (required by the PK code) | ||||
| 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 | ||||
| CFLAGS += /DHMAC | ||||
| 
 | ||||
| @ -227,6 +214,8 @@ md2.obj: md2.c | ||||
| 	$(CC) $(CFLAGS) md2.c | ||||
| cast5.obj: cast5.c | ||||
| 	$(CC) $(CFLAGS) cast5.c | ||||
| noekeon.obj: noekeon.c | ||||
| 	$(CC) $(CFLAGS) noekeon.c | ||||
| 
 | ||||
| demos/test.obj: 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  \ | ||||
| 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 | ||||
| 	$(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 \ | ||||
| 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 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -13,8 +13,8 @@ extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /* version */ | ||||
| #define CRYPT   0x0077 | ||||
| #define SCRYPT  "0.77" | ||||
| #define CRYPT   0x0078 | ||||
| #define SCRYPT  "0.78" | ||||
| 
 | ||||
| /* max size of either a cipher/hash block or symmetric key [largest of the two] */ | ||||
| #define MAXBLOCKSIZE           128 | ||||
|  | ||||
| @ -10,23 +10,17 @@ | ||||
|  * On embedded platforms you can change the fprintf() to be a routine that would display a message | ||||
|  * 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 | ||||
| 
 | ||||
| #define _ARGCHK(x) \ | ||||
|     if (!(x)) { \ | ||||
|         printf("_ARGCHK '%s' failure on line %d of file %s\n", #x, __LINE__, __FILE__); \ | ||||
|         raise(SIGABRT); \ | ||||
|     } | ||||
| 
 | ||||
| #endif  /* SONY_PS2 */ | ||||
|    #ifdef SONY_PS2 | ||||
|       #define _ARGCHK(x) if (!(x)) { printf("_ARGCHK '%s' failure on line %d of file %s\n", #x, __LINE__, __FILE__); raise(SIGABRT); } | ||||
|    #else | ||||
|       #define _ARGCHK(x) if (!(x)) { fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n", #x, __LINE__, __FILE__); raise(SIGABRT); } | ||||
|    #endif | ||||
| #endif    | ||||
| 
 | ||||
| #elif ARGTYPE == 1 | ||||
| 
 | ||||
|  | ||||
| @ -94,6 +94,12 @@ struct cast5_key { | ||||
| }; | ||||
| #endif | ||||
| 
 | ||||
| #ifdef NOEKEON | ||||
| struct noekeon_key { | ||||
| 	unsigned long K[4], dK[4]; | ||||
| }; | ||||
| #endif | ||||
| 
 | ||||
| typedef union Symmetric_key { | ||||
| #ifdef DES | ||||
|    struct des_key des; | ||||
| @ -132,6 +138,9 @@ typedef union Symmetric_key { | ||||
| #ifdef CAST5 | ||||
|    struct cast5_key    cast5; | ||||
| #endif | ||||
| #ifdef NOEKEON | ||||
|    struct noekeon_key  noekeon; | ||||
| #endif    | ||||
| } symmetric_key; | ||||
| 
 | ||||
| /* A block cipher ECB structure */ | ||||
| @ -252,12 +261,20 @@ extern const struct _cipher_descriptor serpent_desc; | ||||
| #endif | ||||
| 
 | ||||
| #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 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 int rijndael_test(void); | ||||
| extern int rijndael_keysize(int *desired_keysize); | ||||
| extern const struct _cipher_descriptor rijndael_desc; | ||||
| extern const struct _cipher_descriptor rijndael_desc, aes_desc; | ||||
| #endif | ||||
| 
 | ||||
| #ifdef XTEA | ||||
| @ -303,6 +320,15 @@ extern int cast5_keysize(int *desired_keysize); | ||||
| extern const struct _cipher_descriptor cast5_desc; | ||||
| #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 | ||||
| extern int ecb_start(int cipher, const unsigned char *key,  | ||||
|                      int keylen, int num_rounds, symmetric_ECB *ecb); | ||||
|  | ||||
| @ -1,5 +1,9 @@ | ||||
| #ifdef KR | ||||
| 
 | ||||
| #if !defined(MRSA) || !defined(MDH) || !defined(MECC) | ||||
|     #error "Keyring code requires all three public key algorithms." | ||||
| #endif | ||||
| 
 | ||||
| #define MAXLEN    256 | ||||
| 
 | ||||
| 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); | ||||
| 
 | ||||
| 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_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); | ||||
| 
 | ||||
| #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, | ||||
|                                  unsigned char *outkey, unsigned long *outlen, | ||||
|                                  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); | ||||
| 
 | ||||
| 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 | ||||
| 
 | ||||
| /* ---- 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 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, | ||||
|                             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, | ||||
|                                 unsigned char *out,  unsigned long *len,  | ||||
|                                 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 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,  | ||||
|                              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, | ||||
|                                  unsigned char *out,  unsigned long *len,  | ||||
|                                  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                           | | ||||
| 3DES        | 768                           | | ||||
| CAST5       | 132                           | | ||||
| Noekeon     | 32                            | | ||||
| ------------+-------------------------------/ | ||||
| Memory used per cipher on a 32-bit platform. | ||||
| 
 | ||||
| [*] For Twofish with TWOFISH_SMALL defined | ||||
| [#] 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 | ||||
| left.  CAST5 is a fairly fast cipher on all platforms which makes it ideally suited.  It should be noted that the | ||||
| SAFER and SAFER+ keys are formed of arrays of unsigned char.  So in effect on platforms where "unsigned long" is  | ||||
| 8 bytes SAFER would have the smallest key (CAST5 would come out to 264 bytes).  In this case I would recommend  | ||||
| SAFER-SK128. | ||||
| Noekeon is a fairly fast cipher and uses very little memory.  Ideally in low-ram platforms all other ciphers should be | ||||
| left undefined and Noekeon should remain.  While Noekeon is generally considered a secure block cipher (it is insecure | ||||
| as a hash) CAST5 is perhaps a "runner-up" choice.  CAST5 has been around longer (it is also known as CAST-128) and is  | ||||
| fairly fast as well.   | ||||
							
								
								
									
										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)                              \ | ||||
| {                                                                \ | ||||
|      /* load value */                                            \ | ||||
|      if (y + 4 > inlen) {                                        \ | ||||
|          errno = CRYPT_INVALID_PACKET;                           \ | ||||
|          goto error2;                                            \ | ||||
|      }                                                           \ | ||||
|      LOAD32L(x, in+y);                                           \ | ||||
|      y += 4;                                                     \ | ||||
|                                                                  \ | ||||
|      /* sanity check... */                                       \ | ||||
|      if (x > 1024) {                                             \ | ||||
|      if (y+x > inlen) {                                          \ | ||||
|         errno = CRYPT_INVALID_PACKET;                            \ | ||||
|         goto error2;                                             \ | ||||
|      }                                                           \ | ||||
|                                                                  \ | ||||
|      /* load it */                                               \ | ||||
|      if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\ | ||||
|         errno = CRYPT_MEM;                                       \ | ||||
|         goto error2;                                             \ | ||||
|      }                                                           \ | ||||
|      y += x;                                                     \ | ||||
| @ -378,7 +384,7 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key | ||||
|    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; | ||||
|    int errno; | ||||
| @ -390,6 +396,10 @@ int rsa_import(const unsigned char *in, rsa_key *key) | ||||
|    if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_KEY)) != CRYPT_OK) {  | ||||
|       return errno; | ||||
|    } | ||||
|     | ||||
|    if (inlen < 1+PACKET_SIZE) { | ||||
|       return CRYPT_INVALID_PACKET; | ||||
|    } | ||||
| 
 | ||||
|    /* init key */ | ||||
|    if (mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP,  | ||||
| @ -426,7 +436,7 @@ int rsa_import(const unsigned char *in, rsa_key *key) | ||||
| error2: | ||||
|    mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,  | ||||
|                   &key->pQ, &key->qP, &key->p, &key->q, NULL); | ||||
|    return CRYPT_MEM; | ||||
|    return errno; | ||||
| } | ||||
| 
 | ||||
| #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 
 | ||||
|  * 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(b, b2); iPHT(b2); | ||||
|      | ||||
| #ifdef SAFERP_SMALL     | ||||
| #ifdef SMALL_CODE     | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
|    _ARGCHK(desired_keysize); | ||||
|    _ARGCHK(desired_keysize != NULL); | ||||
|    if (*desired_keysize < 16) { | ||||
|       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 */ | ||||
| #ifdef RIJNDAEL | ||||
|    prng->yarrow.cipher = register_cipher(&rijndael_desc); | ||||
| #elif defined(NOEKEON)    | ||||
|    prng->yarrow.cipher = register_cipher(&noekeon_desc); | ||||
| #elif defined(BLOWFISH) | ||||
|    prng->yarrow.cipher = register_cipher(&blowfish_desc); | ||||
| #elif defined(TWOFISH) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user