home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / crypl200.zip / LIB_DH.C < prev    next >
Text File  |  1996-10-01  |  10KB  |  273 lines

  1. /****************************************************************************
  2. *                                                                            *
  3. *                    cryptlib Diffie-Hellman Key Exchange Routines            *
  4. *                        Copyright Peter Gutmann 1995-1996                    *
  5. *                                                                            *
  6. ****************************************************************************/
  7.  
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include "crypt.h"
  11.  
  12. /****************************************************************************
  13. *                                                                            *
  14. *                        Predefined DH p and g Parameters                    *
  15. *                                                                            *
  16. ****************************************************************************/
  17.  
  18. #include "testdh.h"
  19.  
  20. /* The structure for storing the primes */
  21.  
  22. typedef struct {
  23.     int baseLen; BYTE base[ 1 ];
  24.     int primeLen; BYTE *prime;
  25.     } DH_PUBLIC_VALUES;
  26.  
  27. static DH_PUBLIC_VALUES dhPublicValues[] = {
  28.     { 1, { 0x02 }, 512, prime512 },
  29.     { 1, { 0x02 }, 768, prime768 },
  30.     { 1, { 0x02 }, 1024, prime1024 },
  31.     { 1, { 0x02 }, 1280, prime1280 },
  32.     { 1, { 0x02 }, 1536, prime1536 },
  33.     { 1, { 0x02 }, 2048, prime2048 },
  34.     { 1, { 0x02 }, 3072, prime3072 },
  35.     { 1, { 0x02 }, 4096, prime4096 },
  36.     { 0, { 0 }, 0, NULL }
  37.     };
  38.  
  39. /****************************************************************************
  40. *                                                                            *
  41. *                        Diffie-Hellman Self-test Routines                    *
  42. *                                                                            *
  43. ****************************************************************************/
  44.  
  45. /* Test the Diffie-Hellman implementation using a sample key exchange.
  46.    Because a lot of the high-level encryption routines don't exist yet, we
  47.    cheat a bit and set up a dummy encryption context with just enough
  48.    information for the following code to work */
  49.  
  50. int dhInitKey( CRYPT_INFO *cryptInfo );
  51. int dhEncrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes );
  52. int dhDecrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes );
  53.  
  54. int dhSelfTest( void )
  55.     {
  56.     CRYPT_INFO cryptInfo1, cryptInfo2;
  57.     CRYPT_PKCINFO_DH *dhKey;
  58.     CAPABILITY_INFO capabilityInfo = { CRYPT_ALGO_DH, CRYPT_MODE_PKC, 0,
  59.                                        NULL, NULL, CRYPT_ERROR, 64, 128, 512,
  60.                                        0, 0, 0, NULL, NULL, NULL, NULL, NULL,
  61.                                        NULL, NULL, NULL, NULL, NULL,
  62.                                        CRYPT_ERROR, NULL };
  63.     BYTE buffer1[ 64 ], buffer2[ 64 ];
  64.     int status = CRYPT_OK;
  65.  
  66.     /* Allocate room for the public-key components */
  67.     if( ( dhKey = ( CRYPT_PKCINFO_DH * ) malloc( sizeof( CRYPT_PKCINFO_DH ) ) ) == NULL )
  68.         return( CRYPT_NOMEM );
  69.  
  70.     /* Initialise the BigNum information and components */
  71.     cryptInitComponents( dhKey, 512, CRYPT_UNUSED );
  72.     memset( &cryptInfo1, 0, sizeof( CRYPT_INFO ) );
  73.     bnBegin( &cryptInfo1.pkcParam1 );
  74.     bnBegin( &cryptInfo1.pkcParam2 );
  75.     bnBegin( &cryptInfo1.pkcParam3 );
  76.     cryptInfo1.keyComponentPtr = dhKey;
  77.     cryptInfo1.capabilityInfo = &capabilityInfo;
  78.     memset( &cryptInfo2, 0, sizeof( CRYPT_INFO ) );
  79.     bnBegin( &cryptInfo2.pkcParam1 );
  80.     bnBegin( &cryptInfo2.pkcParam2 );
  81.     bnBegin( &cryptInfo2.pkcParam3 );
  82.     cryptInfo2.keyComponentPtr = dhKey;
  83.     cryptInfo2.capabilityInfo = &capabilityInfo;
  84.  
  85.     /* Perform the test key exchange on a block of data */
  86.     memset( buffer1, 0, 64 );
  87.     memcpy( buffer1, "abcde", 5 );
  88.     memset( buffer2, 0, 64 );
  89.     memcpy( buffer2, "efghi", 5 );
  90.     if( dhInitKey( &cryptInfo1 ) != CRYPT_OK ||
  91.         dhInitKey( &cryptInfo2 ) != CRYPT_OK ||
  92.         dhEncrypt( &cryptInfo1, buffer1, CRYPT_USE_DEFAULT ) != CRYPT_OK ||
  93.         dhEncrypt( &cryptInfo2, buffer2, CRYPT_USE_DEFAULT ) != CRYPT_OK ||
  94.         dhDecrypt( &cryptInfo1, buffer2, CRYPT_USE_DEFAULT ) != CRYPT_OK ||
  95.         dhDecrypt( &cryptInfo2, buffer1, CRYPT_USE_DEFAULT ) != CRYPT_OK ||
  96.         memcmp( buffer1, buffer2, 64 ) )
  97.         status = CRYPT_SELFTEST;
  98.  
  99.     /* Clean up */
  100.     cryptDestroyComponents( dhKey );
  101.     bnEnd( &cryptInfo1.pkcParam1 );
  102.     bnEnd( &cryptInfo1.pkcParam2 );
  103.     bnEnd( &cryptInfo1.pkcParam3 );
  104.     zeroise( &cryptInfo1, sizeof( CRYPT_INFO ) );
  105.     bnEnd( &cryptInfo2.pkcParam1 );
  106.     bnEnd( &cryptInfo2.pkcParam2 );
  107.     bnEnd( &cryptInfo2.pkcParam3 );
  108.     zeroise( &cryptInfo2, sizeof( CRYPT_INFO ) );
  109.     free( dhKey );
  110.  
  111.     return( status );
  112.     }
  113.  
  114. /****************************************************************************
  115. *                                                                            *
  116. *                            Init/Shutdown Routines                            *
  117. *                                                                            *
  118. ****************************************************************************/
  119.  
  120. /* Not needed for the DH routines */
  121.  
  122. /****************************************************************************
  123. *                                                                            *
  124. *                        Diffie-Hellman Key Exchange Routines                *
  125. *                                                                            *
  126. ****************************************************************************/
  127.  
  128. /* Perform phase 1 of Diffie-Hellman */
  129.  
  130. int dhEncrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  131.     {
  132.     BIGNUM y;
  133.     int length = bitsToBytes( cryptInfo->keySizeBits ), status = 0;
  134.  
  135.     /* The length of the encrypted data is determined by the PKC key size */
  136.     UNUSED( noBytes );
  137.  
  138.     /* Move the public data from the buffer into a bignum making sure it
  139.        obeys the constraint 0 < x < p-1, perform phase 1 of DH, and move the
  140.        resulting public value back into the buffer.  Note that it would be
  141.        slightly more efficient to call bnTwoExpMod() in place of bnExpMod(),
  142.        but there's a chance the caller may want to use a base other than two,
  143.        and bnExpMod() calls bnTwoExpMod() anyway if the base == 2 */
  144.     bnBegin( &y );
  145.     bnInsertBigBytes( &cryptInfo->dhParam_x, buffer, 0, length );
  146.     zeroise( buffer, length );    /* Clear buffer while data is in bignum */
  147.     CK( bnMod( &cryptInfo->dhParam_x, &cryptInfo->dhParam_x,
  148.                &cryptInfo->dhParam_p ) );
  149.     CK( bnSubQ( &cryptInfo->dhParam_x, 1 ) );
  150.     CK( bnExpMod( &y, &cryptInfo->dhParam_g, &cryptInfo->dhParam_x,
  151.                   &cryptInfo->dhParam_p ) );
  152.     bnExtractBigBytes( &y, buffer, 0, length );
  153.     bnEnd( &y );
  154.  
  155.     return( ( status == -1 ) ? CRYPT_PKCCRYPT : CRYPT_OK );
  156.     }
  157.  
  158. /* Perform phase 2 of Diffie-Hellman */
  159.  
  160. int dhDecrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  161.     {
  162.     BIGNUM y, z;
  163.     int length = bitsToBytes( cryptInfo->keySizeBits ), status = CRYPT_OK;
  164.  
  165.     /* The length of the data is determined by the DH key size */
  166.     UNUSED( noBytes );
  167.  
  168.     /* Move the public data from the buffer into a bignum, perform phase 2
  169.        of DH, and move the resulting secret value back into the buffer */
  170.     bnBegin( &y );
  171.     bnBegin( &z );
  172.     bnInsertBigBytes( &y, buffer, 0, length );
  173.     zeroise( buffer, length );    /* Clear buffer while data is in bignum */
  174.     if( bnExpMod( &z, &y, &cryptInfo->dhParam_x, &cryptInfo->dhParam_p ) != 0 )
  175.         status = CRYPT_PKCCRYPT;
  176.     bnExtractBigBytes( &z, buffer, 0, length );
  177.     bnEnd( &z );
  178.     bnEnd( &y );
  179.  
  180.     return( status );
  181.     }
  182.  
  183. /****************************************************************************
  184. *                                                                            *
  185. *                        Diffie-Hellman Key Management Routines                *
  186. *                                                                            *
  187. ****************************************************************************/
  188.  
  189. /* Load DH public key components into an encryption context */
  190.  
  191. int dhInitKey( CRYPT_INFO *cryptInfo )
  192.     {
  193.     CRYPT_PKCINFO_DH *dhKey = ( CRYPT_PKCINFO_DH * ) cryptInfo->keyComponentPtr;
  194.     int status = CRYPT_OK;
  195.  
  196.     /* Make sure the last parameter is correct.  Sinc the DH parameters are
  197.        somewhat different from those used for normal PKC's, this is a useful
  198.        test to make sure the caller hasn't confused things */
  199.     if( dhKey->isPublicKey != CRYPT_UNUSED )
  200.         return( CRYPT_BADPARM3 );
  201.  
  202.     /* Allocate storage for the external-format key components */
  203.     if( ( status = secureMalloc( &cryptInfo->pkcInfo,
  204.                                  sizeof( CRYPT_PKCINFO_DH ) ) ) != CRYPT_OK )
  205.         return( status );
  206.  
  207.     /* If a key size is given, use the default public values */
  208.     if( dhKey->endianness > CRYPT_COMPONENTS_LITTLENDIAN )
  209.         {
  210.         CRYPT_PKCINFO_DH *externalDHkey = cryptInfo->pkcInfo;
  211.         int index, size = dhKey->endianness;
  212.  
  213.         /* Determine which parameters to use */
  214.         for( index = 0; dhPublicValues[ index ].primeLen && \
  215.              dhPublicValues[ index ].primeLen != size; index++ );
  216.         if( !dhPublicValues[ index ].primeLen )
  217.             return( CRYPT_BADPARM2 );
  218.  
  219.         /* Load them into the external-format component storage */
  220.         cryptInitComponents( externalDHkey, CRYPT_COMPONENTS_BIGENDIAN,
  221.                              CRYPT_UNUSED );
  222.         cryptSetComponent( externalDHkey->p, dhPublicValues[ index ].prime, size );
  223.         cryptSetComponent( externalDHkey->g, dhPublicValues[ index ].base, 1 );
  224.  
  225.         /* Load them into the internal-format component storage and generate
  226.            a key ID for them */
  227.         bnInsertBigBytes( &cryptInfo->dhParam_p, dhPublicValues[ index ].prime,
  228.                           0, bitsToBytes( size ) );
  229.         bnInsertBigBytes( &cryptInfo->dhParam_g, dhPublicValues[ index ].base,
  230.                           0, 1 );
  231.         cryptInfo->keySizeBits = size;
  232.  
  233.         return( generateKeyID( CRYPT_ALGO_DH, cryptInfo->keyID, \
  234.                                &cryptInfo->keyIDlength, dhKey ) );
  235.         }
  236.  
  237.     /* Load the key components into the external-format component storage */
  238.     memcpy( cryptInfo->pkcInfo, dhKey, sizeof( CRYPT_PKCINFO_DH ) );
  239.  
  240.     /* Load the key component from the external representation into the
  241.        internal BigNums */
  242.     cryptInfo->keyComponentsLittleEndian = dhKey->endianness;
  243.     if( cryptInfo->keyComponentsLittleEndian )
  244.         {
  245.         bnInsertLittleBytes( &cryptInfo->dhParam_p, dhKey->p, 0,
  246.                              bitsToBytes( dhKey->pLen ) );
  247.         bnInsertLittleBytes( &cryptInfo->dhParam_g, dhKey->g, 0,
  248.                              bitsToBytes( dhKey->gLen ) );
  249.         }
  250.     else
  251.         {
  252.         bnInsertBigBytes( &cryptInfo->dhParam_p, dhKey->p, 0,
  253.                           bitsToBytes( dhKey->pLen ) );
  254.         bnInsertBigBytes( &cryptInfo->dhParam_g, dhKey->g, 0,
  255.                           bitsToBytes( dhKey->gLen ) );
  256.         }
  257.  
  258.     /* Make sure the necessary key parameters have been initialised */
  259.     if( !bnCmpQ( &cryptInfo->dhParam_p, 0 ) || \
  260.         !bnCmpQ( &cryptInfo->dhParam_g, 0 ) )
  261.         status = CRYPT_BADPARM2;
  262.  
  263.     /* Set the nominal keysize in bits */
  264.     cryptInfo->keySizeBits = dhKey->pLen;
  265.  
  266.     /* Finally, generate a key ID for this key */
  267.     if( cryptStatusOK( status ) )
  268.         status = generateKeyID( CRYPT_ALGO_DH, cryptInfo->keyID, \
  269.                                 &cryptInfo->keyIDlength, dhKey );
  270.  
  271.     return( status );
  272.     }
  273.