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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										33
									
								
								demos/test.c
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								demos/test.c
									
									
									
									
									
								
							@ -259,7 +259,7 @@ void ctr_tests(void)
 | 
			
		||||
 for (x = 0; x < 32; x++) blk[x] = count[x] = x;
 | 
			
		||||
 | 
			
		||||
 /* 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);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										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);
 | 
			
		||||
@ -394,6 +398,10 @@ int dh_import(const unsigned char *in, dh_key *key)
 | 
			
		||||
      return errno;
 | 
			
		||||
   }
 | 
			
		||||
   
 | 
			
		||||
   if (2+PACKET_SIZE > inlen) {
 | 
			
		||||
      return CRYPT_INVALID_PACKET;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /* init */
 | 
			
		||||
   if (mp_init_multi(&key->x, &key->y, NULL) != MP_OKAY) { 
 | 
			
		||||
      return CRYPT_MEM;
 | 
			
		||||
@ -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);
 | 
			
		||||
@ -714,6 +720,10 @@ int ecc_import(const unsigned char *in, ecc_key *key)
 | 
			
		||||
      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) {
 | 
			
		||||
      return CRYPT_MEM;
 | 
			
		||||
@ -725,21 +735,21 @@ int ecc_import(const unsigned char *in, ecc_key *key)
 | 
			
		||||
   
 | 
			
		||||
   for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size); x++);
 | 
			
		||||
   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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										23
									
								
								makefile.ps2
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								makefile.ps2
									
									
									
									
									
								
							@ -43,16 +43,19 @@ CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wno-unused -Werror  \
 | 
			
		||||
   -DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) -DXCLOCK=$(XCLOCK) \
 | 
			
		||||
   -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 
 | 
			
		||||
 | 
			
		||||
#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.
 | 
			
		||||
 | 
			
		||||
# Clean the stack after sensitive functions.  Not always required... 
 | 
			
		||||
@ -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;
 | 
			
		||||
@ -391,6 +397,10 @@ int rsa_import(const unsigned char *in, rsa_key *key)
 | 
			
		||||
      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, 
 | 
			
		||||
                     &key->pQ, &key->p, &key->q, NULL) != MP_OKAY) {
 | 
			
		||||
@ -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