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

  1. /****************************************************************************
  2. *                                                                            *
  3. *                        cryptlib RSA Encryption Routines                    *
  4. *                        Copyright Peter Gutmann 1993-1996                    *
  5. *                                                                            *
  6. ****************************************************************************/
  7.  
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include "crypt.h"
  11.  
  12. /****************************************************************************
  13. *                                                                            *
  14. *                            RSA Self-test Routines                            *
  15. *                                                                            *
  16. ****************************************************************************/
  17.  
  18. /* Test the RSA implementation using a sample key.  Because a lot of the
  19.    high-level encryption routines don't exist yet, we cheat a bit and set
  20.    up a dummy encryption context with just enough information for the
  21.    following code to work */
  22.  
  23. typedef struct {
  24.     int nLen; BYTE n[ 64 ];
  25.     int eLen; BYTE e[ 1 ];
  26.     int dLen; BYTE d[ 64 ];
  27.     int pLen; BYTE p[ 32 ];
  28.     int qLen; BYTE q[ 32 ];
  29.     int uLen; BYTE u[ 32 ];
  30.     int e1Len; BYTE e1[ 32 ];
  31.     int e2Len; BYTE e2[ 32 ];
  32.     } RSA_PRIVKEY;
  33.  
  34. static RSA_PRIVKEY rsaTestKey = {
  35.     /* n */
  36.     512,
  37.     { 0xE1, 0x95, 0x41, 0x17, 0xB4, 0xCB, 0xDC, 0xD0,
  38.       0xCB, 0x9B, 0x11, 0x19, 0x9C, 0xED, 0x04, 0x6F,
  39.       0xBD, 0x70, 0x2D, 0x5C, 0x8A, 0x32, 0xFF, 0x16,
  40.       0x22, 0x57, 0x30, 0x3B, 0xD4, 0x59, 0x9C, 0x01,
  41.       0xF0, 0xA3, 0x70, 0xA1, 0x6C, 0x16, 0xAC, 0xCC,
  42.       0x8C, 0xAD, 0xB0, 0xA0, 0xAF, 0xC7, 0xCC, 0x49,
  43.       0x4F, 0xD9, 0x5D, 0x32, 0x1C, 0x2A, 0xE8, 0x4E,
  44.       0x15, 0xE1, 0x26, 0x6C, 0xC4, 0xB8, 0x94, 0xE1 },
  45.     /* e */
  46.     5,
  47.     { 0x11 },
  48.     /* d */
  49.     509,
  50.     { 0x13, 0xE7, 0x85, 0xBE, 0x53, 0xB7, 0xA2, 0x8A, 
  51.       0xE4, 0xC9, 0xEA, 0xEB, 0xAB, 0xF6, 0xCB, 0xAF,
  52.       0x81, 0xA8, 0x04, 0x00, 0xA2, 0xC8, 0x43, 0xAF,
  53.       0x21, 0x25, 0xCF, 0x8C, 0xCE, 0xF8, 0xD9, 0x0F, 
  54.       0x10, 0x78, 0x4C, 0x1A, 0x26, 0x5D, 0x90, 0x18,
  55.       0x79, 0x90, 0x42, 0x83, 0x6E, 0xAE, 0x3E, 0x20, 
  56.       0x0B, 0x0C, 0x5B, 0x6B, 0x8E, 0x31, 0xE5, 0xCF,
  57.       0xD6, 0xE0, 0xBB, 0x41, 0xC1, 0xB8, 0x2E, 0x17 },
  58.     /* p */
  59.     256,
  60.     { 0xED, 0xE4, 0x02, 0x90, 0xA4, 0xA4, 0x98, 0x0D,
  61.       0x45, 0xA2, 0xF3, 0x96, 0x09, 0xED, 0x7B, 0x40,
  62.       0xCD, 0xF6, 0x21, 0xCC, 0xC0, 0x1F, 0x83, 0x09,
  63.       0x56, 0x37, 0x97, 0xFB, 0x05, 0x5B, 0x87, 0xB7 },
  64.     /* q */
  65.     256,
  66.     { 0xF2, 0xC1, 0x64, 0xE8, 0x69, 0xF8, 0x5E, 0x54, 
  67.       0x8F, 0xFD, 0x20, 0x8E, 0x6A, 0x23, 0x90, 0xF2, 
  68.       0xAF, 0x57, 0x2F, 0x4D, 0x10, 0x80, 0x8E, 0x11,
  69.       0x3C, 0x61, 0x44, 0x33, 0x2B, 0xE0, 0x58, 0x27 },
  70.     /* u */
  71.     255,
  72.     { 0x68, 0x45, 0x00, 0x64, 0x32, 0x9D, 0x09, 0x6E, 
  73.       0x0A, 0xD3, 0xF3, 0x8A, 0xFE, 0x15, 0x8C, 0x79,
  74.       0xAD, 0x84, 0x35, 0x05, 0x19, 0x2C, 0x19, 0x51,
  75.       0xAB, 0x83, 0xC7, 0xE8, 0x5C, 0xAC, 0xAD, 0x7A },
  76.     /* exponent1 */
  77.     256,
  78.     { 0x99, 0xED, 0xE3, 0x8A, 0xC4, 0xE2, 0xF8, 0xF9,
  79.       0x87, 0x69, 0x70, 0x70, 0x24, 0x8A, 0x9B, 0x0B, 
  80.       0xD0, 0x90, 0x33, 0xFC, 0xF4, 0xC9, 0x18, 0x8D,
  81.       0x92, 0x23, 0xF8, 0xED, 0xB8, 0x2C, 0x2A, 0xA3 },
  82.     /* exponent2 */
  83.     256,
  84.     { 0xB9, 0xA2, 0xF2, 0xCF, 0xD8, 0x90, 0xC0, 0x9B, 
  85.       0x04, 0xB2, 0x82, 0x4E, 0xC9, 0xA2, 0xBA, 0x22,
  86.       0xFE, 0x8D, 0xF6, 0xFE, 0xB2, 0x44, 0x30, 0x67,
  87.       0x88, 0x86, 0x9D, 0x90, 0x8A, 0xF6, 0xD9, 0xFF }
  88.     };
  89.  
  90. int rsaInitKey( CRYPT_INFO *cryptInfo );
  91. int rsaEncrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes );
  92. int rsaDecrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes );
  93.  
  94. int rsaSelfTest( void )
  95.     {
  96.     CRYPT_INFO cryptInfo;
  97.     CRYPT_PKCINFO_RSA *rsaKey;
  98.     CAPABILITY_INFO capabilityInfo = { CRYPT_ALGO_RSA, CRYPT_MODE_PKC, 0,
  99.                                        NULL, NULL, CRYPT_ERROR, 64, 128, 512,
  100.                                        0, 0, 0, NULL, NULL, NULL, NULL, NULL,
  101.                                        NULL, NULL, NULL, NULL, NULL,
  102.                                        CRYPT_ERROR, NULL };
  103.     BYTE buffer[ 64 ];
  104.     int status;
  105.  
  106.     /* Allocate room for the public-key components */
  107.     if( ( rsaKey = ( CRYPT_PKCINFO_RSA * ) malloc( sizeof( CRYPT_PKCINFO_RSA ) ) ) == NULL )
  108.         return( CRYPT_NOMEM );
  109.  
  110.     /* Initialise the BigNum information and components */
  111.     memset( &cryptInfo, 0, sizeof( CRYPT_INFO ) );
  112.     bnBegin( &cryptInfo.pkcParam1 );
  113.     bnBegin( &cryptInfo.pkcParam2 );
  114.     bnBegin( &cryptInfo.pkcParam3 );
  115.     bnBegin( &cryptInfo.pkcParam4 );
  116.     bnBegin( &cryptInfo.pkcParam5 );
  117.     bnBegin( &cryptInfo.pkcParam6 );
  118.     bnBegin( &cryptInfo.pkcParam7 );
  119.     bnBegin( &cryptInfo.pkcParam8 );
  120.     cryptInfo.keyComponentsLittleEndian = FALSE;
  121.     cryptInitComponents( rsaKey, CRYPT_COMPONENTS_BIGENDIAN,
  122.                          CRYPT_KEYTYPE_PRIVATE );
  123.     cryptSetComponent( rsaKey->n, rsaTestKey.n, rsaTestKey.nLen );
  124.     cryptSetComponent( rsaKey->e, rsaTestKey.e, rsaTestKey.eLen );
  125.     cryptSetComponent( rsaKey->d, rsaTestKey.d, rsaTestKey.dLen );
  126.     cryptSetComponent( rsaKey->p, rsaTestKey.p, rsaTestKey.pLen );
  127.     cryptSetComponent( rsaKey->q, rsaTestKey.q, rsaTestKey.qLen );
  128.     cryptSetComponent( rsaKey->u, rsaTestKey.u, rsaTestKey.uLen );
  129.     cryptSetComponent( rsaKey->e1, rsaTestKey.e1, rsaTestKey.e1Len );
  130.     cryptSetComponent( rsaKey->e2, rsaTestKey.e2, rsaTestKey.e2Len );
  131.     cryptInfo.keyComponentPtr = rsaKey;
  132.     cryptInfo.capabilityInfo = &capabilityInfo;
  133.  
  134.     /* Perform the test en/decryption of a block of data */
  135.     memset( buffer, 0, 64 );
  136.     memcpy( buffer, "abcde", 5 );
  137.     rsaInitKey( &cryptInfo );
  138.     if( ( status = rsaEncrypt( &cryptInfo, buffer, CRYPT_USE_DEFAULT ) ) == CRYPT_OK )
  139.         status = rsaDecrypt( &cryptInfo, buffer, CRYPT_USE_DEFAULT );
  140.     if( status != CRYPT_OK || memcmp( buffer, "abcde", 5 ) )
  141.         status = CRYPT_SELFTEST;
  142.  
  143.     /* Clean up */
  144.     cryptDestroyComponents( rsaKey );
  145.     bnEnd( &cryptInfo.pkcParam1 );
  146.     bnEnd( &cryptInfo.pkcParam2 );
  147.     bnEnd( &cryptInfo.pkcParam3 );
  148.     bnEnd( &cryptInfo.pkcParam4 );
  149.     bnEnd( &cryptInfo.pkcParam5 );
  150.     bnEnd( &cryptInfo.pkcParam6 );
  151.     bnEnd( &cryptInfo.pkcParam7 );
  152.     bnEnd( &cryptInfo.pkcParam8 );
  153.     zeroise( &cryptInfo, sizeof( CRYPT_INFO ) );
  154.     free( rsaKey );
  155.  
  156.     return( status );
  157.     }
  158.  
  159. /****************************************************************************
  160. *                                                                            *
  161. *                            Init/Shutdown Routines                            *
  162. *                                                                            *
  163. ****************************************************************************/
  164.  
  165. /* Not needed for the RSA routines */
  166.  
  167. /****************************************************************************
  168. *                                                                            *
  169. *                            RSA En/Decryption Routines                        *
  170. *                                                                            *
  171. ****************************************************************************/
  172.  
  173. /* Encrypt a single block of data  */
  174.  
  175. int rsaEncrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  176.     {
  177.     BIGNUM n;
  178.     int length = bitsToBytes( cryptInfo->keySizeBits ), status = CRYPT_OK;
  179.  
  180.     /* The length of the encrypted data is determined by the PKC key size */
  181.     UNUSED( noBytes );
  182.  
  183.     /* Move the data from the buffer into a bignum, perform the modexp,
  184.        and move the result back into the buffer */
  185.     bnBegin( &n );
  186.     bnInsertBigBytes( &n, buffer, 0, length );
  187.     zeroise( buffer, length );    /* Clear buffer while data is in bignum */
  188.     if( bnExpMod( &n, &n, &cryptInfo->rsaParam_e, &cryptInfo->rsaParam_n ) != 0 )
  189.         status = CRYPT_PKCCRYPT;
  190.     bnExtractBigBytes( &n, buffer, 0, length );
  191.     bnEnd( &n );
  192.  
  193.     return( status );
  194.     }
  195.  
  196. /* Use the Chinese Remainder Theorem shortcut for RSA decryption.
  197.    M is the output plaintext message, C is the input ciphertext message,
  198.    d is the secret decryption exponent, p and q are the prime factors of n,
  199.    u is the multiplicative inverse of q, mod p.  n, the common modulus, is not
  200.    used because of the Chinese Remainder Theorem shortcut */
  201.  
  202. int rsaDecrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  203.     {
  204.     BIGNUM *p = &cryptInfo->rsaParam_p, *q = &cryptInfo->rsaParam_q;
  205.     BIGNUM *u = &cryptInfo->rsaParam_u, *e1 = &cryptInfo->rsaParam_exponent1;
  206.     BIGNUM *e2 = &cryptInfo->rsaParam_exponent2;
  207.     BIGNUM data, p2, q2, temp1, temp2;
  208.     int length = bitsToBytes( cryptInfo->keySizeBits ), status = 0;
  209.  
  210.     /* The length of the encrypted data is determined by the PKC key size */
  211.     UNUSED( noBytes );
  212.  
  213.     /* Initialise the bignums */
  214.     bnBegin( &p2 );
  215.     bnBegin( &q2 );
  216.     bnBegin( &temp1 );
  217.     bnBegin( &temp2 );
  218.     bnBegin( &data );
  219.     bnInsertBigBytes( &data, buffer, 0, length );
  220.     zeroise( buffer, length );    /* Clear buffer while data is in bignum */
  221.  
  222.     /* Make sure that p < q */
  223.     if( bnCmp( p, q ) >= 0 )
  224.         bnSwap( p, q );
  225.  
  226.     /* Rather than decrypting by computing modexp with full mod n precision,
  227.        compute a shorter modexp with mod p precision:
  228.  
  229.        p2 = ( ( C mod p ) ** exponent1 ) mod p */
  230.     CK( bnCopy( &temp1, p ) );
  231.     CK( bnMod( &temp1, &data, p ) );    /* temp1 = C mod p  */
  232.     CK( bnExpMod( &p2, &temp1, e1, p ) );
  233.  
  234.     /* Then compute a short modexp with mod q precision:
  235.  
  236.        q2 = ( ( C mod q ) ** exponent2 ) mod q */
  237.     CK( bnCopy( &temp1, q ) );
  238.     CK( bnMod( &temp1, &data, q ) );    /* temp1 = C mod q  */
  239.     CK( bnExpMod( &q2, &temp1, e2, q ) );
  240.  
  241.     /* Now use the multiplicative inverse u to combine the two halves, saving
  242.        a lot of time by avoiding a full mod n exponentiation.  At key
  243.        generation time, u was computed with the secret key as the
  244.        multiplicative inverse of p, mod q such that ( p * u ) mod q = 1,
  245.        assuming p < q */
  246.     if( !bnCmp( &p2, &q2 ) )
  247.         /* Only happens if C < p */
  248.         CK( bnCopy( &data, &p2 ) );
  249.     else
  250.         {
  251.         /* q2 = q2 - p2; if q2 < 0 then q2 = q2 + q */
  252.         if( bnSub( &q2, &p2 ) == 1 )
  253.             {
  254.             /* Since bnlib doesn't work with negative numbers, we need to
  255.                perform a reverse subtract on q to obtain the intended result.
  256.                This rarely happens, so we perform a few extra steps here
  257.                rather than checking if q2 would go negative before the
  258.                subtract */
  259.             CK( bnCopy( &temp1, q ) );
  260.             CK( bnSub( &temp1, &q2 ) );
  261.             CK( bnCopy( &q2, &temp1 ) );
  262.             }
  263.  
  264.         /* M = ( ( ( q2 * u ) mod q ) * p ) + p2 */
  265.         CK( bnMul( &temp1, &q2, u ) );        /* temp1 = q2 * u  */
  266.         CK( bnMod( &temp2, &temp1, q ) );    /* temp2 = temp1 mod q */
  267.         CK( bnMul( &temp1, p, &temp2 ) );    /* temp1 = p * temp2 */
  268.         CK( bnAdd( &temp1, &p2 ) );            /* temp1 = temp1 + p2 */
  269.         CK( bnCopy( &data, &temp1 ) );        /* M = temp1 */
  270.         }
  271.  
  272.     /* Copy the result to the output buffer and destroy sensitive data */
  273.     bnExtractBigBytes( &data, buffer, 0, length );
  274.     bnEnd( &p2 );
  275.     bnEnd( &q2 );
  276.     bnEnd( &temp1 );
  277.     bnEnd( &temp2 );
  278.     bnEnd( &data );
  279.  
  280.     return( ( status == -1 ) ? CRYPT_PKCCRYPT : CRYPT_OK );
  281.     }
  282.  
  283. /****************************************************************************
  284. *                                                                            *
  285. *                            RSA Key Management Routines                        *
  286. *                                                                            *
  287. ****************************************************************************/
  288.  
  289. /* Load RSA public/private key components into an encryption context */
  290.  
  291. int rsaInitKey( CRYPT_INFO *cryptInfo )
  292.     {
  293.     CRYPT_PKCINFO_RSA *rsaKey = ( CRYPT_PKCINFO_RSA * ) cryptInfo->keyComponentPtr;
  294.     int status = CRYPT_OK;
  295.  
  296.     /* Allocate storage for the external-format key components */
  297.     if( ( status = secureMalloc( &cryptInfo->pkcInfo,
  298.                                  sizeof( CRYPT_PKCINFO_RSA ) ) ) != CRYPT_OK )
  299.         return( status );
  300.  
  301.     /* Load the key component from the external representation into the
  302.        internal BigNums */
  303.     cryptInfo->keyComponentsLittleEndian = rsaKey->endianness;
  304.     cryptInfo->isPublicKey = rsaKey->isPublicKey;
  305.     if( cryptInfo->keyComponentsLittleEndian )
  306.         {
  307.         bnInsertLittleBytes( &cryptInfo->rsaParam_n, rsaKey->n, 0,
  308.                              bitsToBytes( rsaKey->nLen ) );
  309.         bnInsertLittleBytes( &cryptInfo->rsaParam_e, rsaKey->e, 0,
  310.                              bitsToBytes( rsaKey->eLen ) );
  311.         if( !rsaKey->isPublicKey )
  312.             {
  313.             bnInsertLittleBytes( &cryptInfo->rsaParam_d, rsaKey->d, 0,
  314.                                  bitsToBytes( rsaKey->dLen ) );
  315.             bnInsertLittleBytes( &cryptInfo->rsaParam_p, rsaKey->p, 0,
  316.                                  bitsToBytes( rsaKey->pLen ) );
  317.             bnInsertLittleBytes( &cryptInfo->rsaParam_q, rsaKey->q, 0,
  318.                                  bitsToBytes( rsaKey->qLen ) );
  319.             bnInsertLittleBytes( &cryptInfo->rsaParam_u, rsaKey->u, 0,
  320.                                  bitsToBytes( rsaKey->uLen ) );
  321.             bnInsertLittleBytes( &cryptInfo->rsaParam_exponent1,
  322.                                  rsaKey->e1, 0, bitsToBytes( rsaKey->e1Len ) );
  323.             bnInsertLittleBytes( &cryptInfo->rsaParam_exponent2,
  324.                                  rsaKey->e2, 0, bitsToBytes( rsaKey->e2Len ) );
  325.             }
  326.         }
  327.     else
  328.         {
  329.         bnInsertBigBytes( &cryptInfo->rsaParam_n, rsaKey->n, 0,
  330.                           bitsToBytes( rsaKey->nLen ) );
  331.         bnInsertBigBytes( &cryptInfo->rsaParam_e, rsaKey->e, 0,
  332.                           bitsToBytes( rsaKey->eLen ) );
  333.         if( !rsaKey->isPublicKey )
  334.             {
  335.             bnInsertBigBytes( &cryptInfo->rsaParam_d, rsaKey->d, 0,
  336.                               bitsToBytes( rsaKey->dLen ) );
  337.             bnInsertBigBytes( &cryptInfo->rsaParam_p, rsaKey->p, 0,
  338.                               bitsToBytes( rsaKey->pLen ) );
  339.             bnInsertBigBytes( &cryptInfo->rsaParam_q, rsaKey->q, 0,
  340.                               bitsToBytes( rsaKey->qLen ) );
  341.             bnInsertBigBytes( &cryptInfo->rsaParam_u, rsaKey->u, 0,
  342.                               bitsToBytes( rsaKey->uLen ) );
  343.             bnInsertBigBytes( &cryptInfo->rsaParam_exponent1,
  344.                               rsaKey->e1, 0, bitsToBytes( rsaKey->e1Len ) );
  345.             bnInsertBigBytes( &cryptInfo->rsaParam_exponent2,
  346.                               rsaKey->e2, 0, bitsToBytes( rsaKey->e2Len ) );
  347.             }
  348.         }
  349.  
  350.     /* Load the key components into the external-format component storage */
  351.     memcpy( cryptInfo->pkcInfo, rsaKey, sizeof( CRYPT_PKCINFO_RSA ) );
  352.  
  353.     /* Make sure the necessary key parameters have been initialised */
  354.     if( !bnCmpQ( &cryptInfo->rsaParam_n, 0 ) || \
  355.         !bnCmpQ( &cryptInfo->rsaParam_e, 0 ) )
  356.         status = CRYPT_BADPARM2;
  357.     if( !rsaKey->isPublicKey )
  358.         if( !bnCmpQ( &cryptInfo->rsaParam_d, 0 ) || \
  359.             !bnCmpQ( &cryptInfo->rsaParam_p, 0 ) || \
  360.             !bnCmpQ( &cryptInfo->rsaParam_q, 0 ) || \
  361.             !bnCmpQ( &cryptInfo->rsaParam_u, 0 ) )
  362.         status = CRYPT_BADPARM2;
  363.  
  364.     /* If we're not using PKCS keys which have exponent1 = d mod ( p - 1 )
  365.        and exponent2 = d mod ( q - 1 ) precalculated, evaluate them now */
  366.     if( !rsaKey->isPublicKey && !bnCmpQ( &cryptInfo->rsaParam_exponent1, 0 ) )
  367.         {
  368.         BIGNUM *d = &cryptInfo->rsaParam_d, tmp;
  369.         CRYPT_PKCINFO_RSA *externalRSAkey = cryptInfo->pkcInfo;
  370.  
  371.         bnBegin( &tmp );
  372.         CK( bnCopy( &tmp, &cryptInfo->rsaParam_p ) );
  373.         CK( bnSubQ( &tmp, 1 ) );            /* tmp = p - 1 */
  374.         CK( bnMod( &cryptInfo->rsaParam_exponent1, d, &tmp ) );
  375.                                             /* exponent1 = d mod ( p - 1 ) ) */
  376.         CK( bnCopy( &tmp, &cryptInfo->rsaParam_q ) );
  377.         CK( bnSubQ( &tmp, 1 ) );            /* tmp = q - 1 */
  378.         CK( bnMod( &cryptInfo->rsaParam_exponent2, d, &tmp ) );
  379.                                             /* exponent1 = d mod ( q - 1 ) ) */
  380.         bnEnd( &tmp );
  381.  
  382.         /* Check that everything went OK */
  383.         status = ( status == -1 ) ? CRYPT_BADPARM2 : CRYPT_OK;
  384.  
  385.         /* Since these two fields weren't present in the external-format
  386.            form from which the key components were loaded, we need to insert
  387.            them back into the the local copy of the external-format data */
  388.         if( cryptInfo->keyComponentsLittleEndian )
  389.             {
  390.             bnExtractLittleBytes( &cryptInfo->rsaParam_exponent1,
  391.                                   externalRSAkey->e1, 0,
  392.                                   bnBits( &cryptInfo->rsaParam_exponent1 ) );
  393.             bnExtractLittleBytes( &cryptInfo->rsaParam_exponent2,
  394.                                   externalRSAkey->e2, 0,
  395.                                   bnBits( &cryptInfo->rsaParam_exponent2 ) );
  396.             }
  397.         else
  398.             {
  399.             bnExtractBigBytes( &cryptInfo->rsaParam_exponent1,
  400.                                externalRSAkey->e1, 0,
  401.                                bnBits( &cryptInfo->rsaParam_exponent1 ) );
  402.             bnExtractBigBytes( &cryptInfo->rsaParam_exponent2,
  403.                                externalRSAkey->e2, 0,
  404.                                bnBits( &cryptInfo->rsaParam_exponent2 ) );
  405.             }
  406.         }
  407.  
  408.     /* Set the nominal keysize in bits */
  409.     cryptInfo->keySizeBits = rsaKey->nLen;
  410.  
  411.     /* Finally, generate a key ID for this key */
  412.     if( cryptStatusOK( status ) )
  413.         status = generateKeyID( CRYPT_ALGO_RSA, cryptInfo->keyID, \
  414.                                 &cryptInfo->keyIDlength, rsaKey );
  415.  
  416.     return( status );
  417.     }
  418.