home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / crypl200.zip / KEYMGMT / PGP_KEY.C < prev    next >
C/C++ Source or Header  |  1996-10-08  |  17KB  |  539 lines

  1. /****************************************************************************
  2. *                                                                            *
  3. *                              PGP Key Read Routines                            *
  4. *                        Copyright Peter Gutmann 1992-1996                    *
  5. *                                                                            *
  6. ****************************************************************************/
  7.  
  8. #include <ctype.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #if defined( INC_ALL )
  13.   #include "crypt.h"
  14.   #include "keymgmt.h"
  15.   #include "pgp_idea.h"
  16. #elif defined( INC_CHILD )
  17.   #include "../crypt.h"
  18.   #include "keymgmt.h"
  19.   #include "pgp_idea.h"
  20. #else
  21.   #include "crypt.h"
  22.   #include "keymgmt/keymgmt.h"
  23.   #include "keymgmt/pgp_idea.h"
  24. #endif /* Compiler-specific includes */
  25.  
  26. /* Magic numbers for PGP 2.x keyrings */
  27.  
  28. #define PGP_CTB_SIGNATURE    0x89    /* Signature CTB */
  29. #define PGP_CTB_SECKEY        0x95    /* Secret key packet CTB */
  30. #define PGP_CTB_PUBKEY        0x99    /* Public key packet CTB */
  31. #define PGP_CTB_TRUST        0xB0    /* Trust packet CTB */
  32. #define PGP_CTB_USERID        0xB4    /* Userid packet CTB */
  33.  
  34. #define PGP2_VERSION_BYTE    2        /* Version number byte for PGP 2.0 */
  35. #define PGP3_VERSION_BYTE    3        /* Version number byte for PGP 3.0 or
  36.                                        legal-kludged 2.0 */
  37.  
  38. #define PKE_ALGORITHM_RSA    1        /* RSA public-key encryption algorithm */
  39.  
  40. #define CKE_ALGORITHM_NONE    0        /* No CKE algorithm */
  41. #define CKE_ALGORITHM_IDEA    1        /* IDEA cipher */
  42.  
  43. /* The size of the IDEA IV and key */
  44.  
  45. #define IDEA_IV_SIZE        8
  46. #define IDEA_KEY_SIZE        16
  47.  
  48. /* The maximum size of an MPI (4096 bits) */
  49.  
  50. #define MAX_MPI_SIZE        512
  51.  
  52. /* The maximum size of a user ID */
  53.  
  54. #define MAX_USERID_SIZE        256
  55.  
  56. /* Since the key components can consume a sizeable amount of memory, we
  57.    allocate storage for them dynamically.  This also keeps them in one place
  58.    for easy sanitization */
  59.  
  60. typedef struct {
  61.     /* Key components (in PGP format) */
  62.     BYTE n[ MAX_MPI_SIZE ], e[ MAX_MPI_SIZE ], d[ MAX_MPI_SIZE ];
  63.     BYTE p[ MAX_MPI_SIZE ], q[ MAX_MPI_SIZE ], u[ MAX_MPI_SIZE ];
  64.     int nLen, eLen, dLen, pLen, qLen, uLen;
  65.  
  66.     /* Key components (in cryptlib format) */
  67.     CRYPT_PKCINFO_RSA rsaKey;
  68.  
  69.     /* userID for this key */
  70.     char userID[ MAX_USERID_SIZE ];
  71.     } PGP_INFO;
  72.  
  73. /* There are a few OS's broken enough not to define the standard seek codes
  74.    (SunOS springs to mind) so we define them here if they're not defined */
  75.  
  76. #ifndef SEEK_SET
  77.   #define SEEK_SET        0
  78.   #define SEEK_CUR        1
  79.   #define SEEK_END        2
  80. #endif /* SEEK_SET */
  81.  
  82. /****************************************************************************
  83. *                                                                            *
  84. *                                Read Byte/Word/Long                         *
  85. *                                                                            *
  86. ****************************************************************************/
  87.  
  88. /* Routines to read BYTE, WORD, LONG */
  89.  
  90. static BYTE fgetByte( FILE *filePtr )
  91.     {
  92.     return( ( BYTE ) getc( filePtr ) );
  93.     }
  94.  
  95. static WORD fgetWord( FILE *filePtr )
  96.     {
  97.     WORD value;
  98.  
  99.     value = ( ( WORD ) getc( filePtr ) ) << 8;
  100.     value |= ( WORD ) getc( filePtr );
  101.     return( value );
  102.     }
  103.  
  104. static LONG fgetLong( FILE *filePtr )
  105.     {
  106.     LONG value;
  107.  
  108.     value = ( ( LONG ) getc( filePtr ) ) << 24;
  109.     value |= ( ( LONG ) getc( filePtr ) ) << 16;
  110.     value |= ( ( LONG ) getc( filePtr ) ) << 8;
  111.     value |= ( LONG ) getc( filePtr );
  112.     return( value );
  113.     }
  114.  
  115. /****************************************************************************
  116. *                                                                            *
  117. *                            PGP Keyring Read Routines                        *
  118. *                                                                            *
  119. ****************************************************************************/
  120.  
  121. /* Read an MPI, setting the global precision if necessary */
  122.  
  123. static int readMPI( FILE *filePtr, BYTE *mpReg, int *mpiLen )
  124.     {
  125.     BYTE *regPtr;
  126.     int length;
  127.  
  128.     *mpiLen = fgetWord( filePtr );
  129.     length = bitsToBytes( *mpiLen );
  130.     if( length > MAX_MPI_SIZE )
  131.         return( CRYPT_ERROR );
  132.     regPtr = mpReg;
  133.     while( length-- )
  134.         *regPtr++ = fgetByte( filePtr );
  135.  
  136.     return( CRYPT_OK );
  137.     }
  138.  
  139.  
  140. /* Checksum a block of data */
  141.  
  142. static WORD checksum( BYTE *data, int length )
  143.     {
  144.     WORD checkSum = ( ( BYTE ) ( length >> 8 ) ) + ( ( BYTE ) length );
  145.  
  146.     length = bitsToBytes( length );
  147.     while( length-- )
  148.         checkSum += *data++;
  149.     return( checkSum );
  150.     }
  151.  
  152. /* Get the length of a packet based on the CTB length field */
  153.  
  154. static int getLength( FILE *filePtr, const int ctb )
  155.     {
  156.     switch( ctb & 3 )
  157.         {
  158.         case 0:
  159.             return( ( int ) fgetByte( filePtr ) );
  160.  
  161.         case 1:
  162.             return( fgetWord( filePtr ) );
  163.  
  164.         case 2:
  165.             return( ( int ) fgetLong( filePtr ) );
  166.         }
  167.  
  168.     /* Packet error, should never happen */
  169.     return( 0 );
  170.     }
  171.  
  172. /* Skip to the start of the next key packet */
  173.  
  174. static void skipToKeyPacket( FILE *filePtr )
  175.     {
  176.     int ctb;
  177.  
  178.     /* Skip any following non-key packets */
  179.     while( ( ctb = fgetByte( filePtr ) ) != PGP_CTB_PUBKEY && \
  180.         ctb != PGP_CTB_SECKEY && !feof( filePtr ) )
  181.         {
  182.         int length = getLength( filePtr, ctb );
  183.  
  184.         /* If we get an impossibly large packet, assume we're in trouble and
  185.            move to the end of the file to ensure we get an EOF if we try any
  186.            further reads */
  187.         if( length > 5000 )
  188.             fseek( filePtr, 0L, SEEK_END );
  189.         else
  190.             /* Skip the current packet */
  191.             fseek( filePtr, ( long ) length, SEEK_CUR );
  192.         }
  193.  
  194.     /* Finally, put back the last CTB we read unless we've reached the end
  195.        of the file */
  196.     if( !feof( filePtr ) )
  197.         ungetc( ctb, filePtr );
  198.     }
  199.  
  200. /* Generate a cryptlib-style key ID for the PGP key and check it against the
  201.    given key ID */
  202.  
  203. static BOOLEAN matchKeyID( PGP_INFO *pgpInfo, const BYTE *requiredID,
  204.                            const int requiredIDsize )
  205.     {
  206.     CRYPT_PKCINFO_RSA *rsaKeyPtr = &pgpInfo->rsaKey;
  207.     BYTE keyID[ CRYPT_MAX_KEYIDSIZE ];
  208.     int keyIDsize, status;
  209.  
  210.     /* Generate the key ID */
  211.     cryptInitComponents( rsaKeyPtr, CRYPT_COMPONENTS_BIGENDIAN,
  212.                          CRYPT_KEYTYPE_PUBLIC );
  213.     cryptSetComponent( rsaKeyPtr->n, pgpInfo->n, pgpInfo->nLen );
  214.     cryptSetComponent( rsaKeyPtr->e, pgpInfo->e, pgpInfo->eLen );
  215.     status = generateKeyID( CRYPT_ALGO_RSA, keyID, &keyIDsize, rsaKeyPtr );
  216.     cryptDestroyComponents( rsaKeyPtr );
  217.  
  218.     /* Check if it's the same as the key ID we're looking for */
  219.     if( status == CRYPT_OK && keyIDsize == requiredIDsize && \
  220.         !memcmp( requiredID, keyID, keyIDsize ) )
  221.         return( TRUE );
  222.  
  223.     return( FALSE );
  224.     }
  225.  
  226. /* Read a key and check whether it matches the required user ID */
  227.  
  228. static int readKey( PGP_INFO *pgpInfo, FILE *filePtr,
  229.                     const GETKEY_INFO *getkeyInfo )
  230.     {
  231.     BOOLEAN isEncrypted, gotUserID = FALSE, foundKey = FALSE;
  232.     WORD checkSum, packetChecksum;
  233.     BYTE keyIV[ IDEA_IV_SIZE ];
  234.     int ctb, length, i, packetLength, status = CRYPT_OK;
  235.  
  236.     /* Skip CTB, packet length, and version byte */
  237.     if( ( ctb = fgetc( filePtr ) ) != PGP_CTB_PUBKEY && \
  238.         ctb != PGP_CTB_SECKEY )
  239.         return( feof( filePtr ) ? CRYPT_KEYSET_NOTFOUND : CRYPT_BADDATA );
  240.     packetLength = getLength( filePtr, ctb );
  241.     if( ( i = fgetByte( filePtr ) ) != PGP2_VERSION_BYTE && \
  242.         i != PGP3_VERSION_BYTE )
  243.         {
  244.         /* Unknown version number, skip this packet */
  245.         ungetc( i, filePtr );
  246.         skipToKeyPacket( filePtr );
  247.         return( -1000 );
  248.         }
  249.     packetLength -= sizeof( BYTE );
  250.  
  251.     /* Read timestamp, validity period */
  252.     fgetLong( filePtr );
  253.     fgetWord( filePtr );
  254.     packetLength -= sizeof( LONG ) + sizeof( WORD );
  255.  
  256.     /* Read the public key components */
  257.     if( ( i = fgetByte( filePtr ) ) != PKE_ALGORITHM_RSA )
  258.         {
  259.         /* Unknown PKE algorithm type, skip this packet */
  260.         ungetc( i, filePtr );
  261.         skipToKeyPacket( filePtr );
  262.         return( -1000 );
  263.         }
  264.     if( readMPI( filePtr, pgpInfo->n, &pgpInfo->nLen ) == CRYPT_ERROR || \
  265.         readMPI( filePtr, pgpInfo->e, &pgpInfo->eLen ) == CRYPT_ERROR )
  266.         return( -1000 );
  267.     packetLength -= sizeof( BYTE ) + sizeof( WORD ) + bitsToBytes( pgpInfo->nLen ) + \
  268.                                      sizeof( WORD ) + bitsToBytes( pgpInfo->eLen );
  269.  
  270.     /* If it's a private keyring, read in the private key components */
  271.     if( !getkeyInfo->isPublicKey )
  272.         {
  273.         /* Handle decryption info for secret components if necessary */
  274.         isEncrypted = ( ctb = fgetByte( filePtr ) ) == CKE_ALGORITHM_IDEA;
  275.         if( isEncrypted )
  276.             for( i = 0; i < IDEA_IV_SIZE; i++ )
  277.                 keyIV[ i ] = fgetc( filePtr );
  278.         packetLength -= sizeof( BYTE ) + ( ( isEncrypted ) ? IDEA_IV_SIZE : 0 );
  279.  
  280.         /* Read in private key components and checksum */
  281.         readMPI( filePtr, pgpInfo->d, &pgpInfo->dLen );
  282.         readMPI( filePtr, pgpInfo->p, &pgpInfo->pLen );
  283.         readMPI( filePtr, pgpInfo->q, &pgpInfo->qLen );
  284.         readMPI( filePtr, pgpInfo->u, &pgpInfo->uLen );
  285.         packetLength -= sizeof( WORD ) + bitsToBytes( pgpInfo->dLen ) + \
  286.                         sizeof( WORD ) + bitsToBytes( pgpInfo->pLen ) + \
  287.                         sizeof( WORD ) + bitsToBytes( pgpInfo->qLen ) + \
  288.                         sizeof( WORD ) + bitsToBytes( pgpInfo->uLen );
  289.         packetChecksum = fgetWord( filePtr );
  290.         packetLength -= sizeof( WORD );
  291.         }
  292.  
  293.     /* If we're searching by key ID, check whether this is the packet we
  294.        want */
  295.     if( getkeyInfo->isKeyID )
  296.         if( matchKeyID( pgpInfo, getkeyInfo->keyID, getkeyInfo->keyIDsize ) )
  297.             foundKey = TRUE;
  298.         else
  299.             {
  300.             /* These aren't the keys you're looking for... you may go about
  301.                your business... move along, move along */
  302.             skipToKeyPacket( filePtr );
  303.             return( -1000 );
  304.             }
  305.  
  306.     /* Read the userID packet(s).  We also make sure we get at least one
  307.        userID if we've already got a match based on a key ID */
  308.     while( !foundKey || !gotUserID )
  309.         {
  310.         /* Skip keyring trust and signature packets */
  311.         ctb = fgetByte( filePtr );
  312.         while( ctb == PGP_CTB_TRUST || ctb == PGP_CTB_SIGNATURE )
  313.             {
  314.             /* Skip the packet */
  315.             length = getLength( filePtr, ctb );
  316.             fseek( filePtr, length, SEEK_CUR );
  317.             ctb = fgetByte( filePtr );
  318.             }
  319.  
  320.         /* Check if we've got a userID packet now */
  321.         if( ctb != PGP_CTB_USERID )
  322.             {
  323.             ungetc( ctb, filePtr );
  324.  
  325.             /* If we saw at least one userID, everything was OK.  Before we
  326.                exit we move to the next key packet so we can continue looking
  327.                for keys if required */
  328.             if( gotUserID )
  329.                 {
  330.                 skipToKeyPacket( filePtr );
  331.                 return( foundKey ? CRYPT_OK : -1000 );
  332.                 }
  333.  
  334.             /* We still don't have a userID CTB, complain */
  335.             skipToKeyPacket( filePtr );
  336.             return( -1000 );
  337.             }
  338.         length = getLength( filePtr, ctb );
  339.         for( i = 0; i < length && i < MAX_USERID_SIZE; i++ )
  340.             pgpInfo->userID[ i ] = fgetByte( filePtr );
  341.         pgpInfo->userID[ i ] = '\0';
  342.         while( i++ < length )
  343.             fgetByte( filePtr );    /* Skip excessively long userID */
  344.         gotUserID = TRUE;
  345.  
  346.         /* Check if it's the one we want */
  347.         if( !getkeyInfo->isKeyID && \
  348.             ( getkeyInfo->keyID == CRYPT_KEYSET_GETFIRST || \
  349.               getkeyInfo->keyID == CRYPT_KEYSET_GETNEXT || \
  350.               matchSubstring( ( char * ) getkeyInfo->keyID, pgpInfo->userID ) ) )
  351.             foundKey = TRUE;
  352.         }
  353.  
  354.     /* Process the secret-key fields if necessary */
  355.     if( !getkeyInfo->isPublicKey )
  356.         {
  357.         /* Decrypt the secret-key fields if necessary */
  358.         if( isEncrypted )
  359.             {
  360.             struct IdeaCfbContext ideaContext;
  361. #ifdef TEST
  362.             MD5_CTX    mdContext;
  363.  
  364.             /* Reduce the passphrase to 128 bits */
  365.             MD5Process( &mdContext, ( BYTE * ) password, strlen( password ) );
  366.  
  367.             /* Set up the IDEA key.  PGP does IV's in a funny way by treating
  368.                them as the first block to en/decrypt */
  369.             ideaCfbInit( &ideaContext, mdContext.digest );
  370.             ideaCfbDecrypt( &ideaContext, keyIV, keyIV, 8 );
  371.             zeroise( &mdContext, 0, sizeof( MD5_CTX ) );
  372.  
  373. #else
  374.             HASHFUNCTION hashFunction;
  375.             BYTE ideaKey[ IDEA_KEY_SIZE ];
  376.             int hashInfoSize, hashInputSize, hashOutputSize;
  377.  
  378.             /* If no password is supplied, let the caller know they need a
  379.                password */
  380.             if( getkeyInfo->password == NULL )
  381.                 {
  382.                 skipToKeyPacket( filePtr );
  383.                 return( CRYPT_WRONGKEY );
  384.                 }
  385.  
  386.             /* Get the hash algorithm information and hash the password */
  387.             if( !getHashParameters( CRYPT_ALGO_MD5, &hashFunction,
  388.                                     &hashInputSize, &hashOutputSize,
  389.                                     &hashInfoSize ) )
  390.                 return( CRYPT_ERROR );    /* API error, should never occur */
  391.             hashFunction( NULL, ideaKey, getkeyInfo->password,
  392.                           getkeyInfo->passwordSize, HASH_ALL );
  393.  
  394.             /* Set up the IDEA key.  PGP does IV's in a funny way by treating
  395.                them as the first block to en/decrypt */
  396.             ideaCfbInit( &ideaContext, ideaKey );
  397.             ideaCfbDecrypt( &ideaContext, keyIV, keyIV, 8 );
  398.             zeroise( ideaKey, IDEA_KEY_SIZE );
  399. #endif /* TEST */
  400.  
  401.             /* Decrypt the secret-key fields */
  402.             ideaCfbDecrypt( &ideaContext, pgpInfo->d, pgpInfo->d,
  403.                             bitsToBytes( pgpInfo->dLen ) );
  404.             ideaCfbDecrypt( &ideaContext, pgpInfo->p, pgpInfo->p,
  405.                             bitsToBytes( pgpInfo->pLen ) );
  406.             ideaCfbDecrypt( &ideaContext, pgpInfo->q, pgpInfo->q,
  407.                             bitsToBytes( pgpInfo->qLen ) );
  408.             ideaCfbDecrypt( &ideaContext, pgpInfo->u, pgpInfo->u,
  409.                             bitsToBytes( pgpInfo->uLen ) );
  410.             ideaCfbDestroy( &ideaContext );
  411.             }
  412.  
  413.         /* Make sure all was OK */
  414.         checkSum = checksum( pgpInfo->d, pgpInfo->dLen );
  415.         checkSum += checksum( pgpInfo->p, pgpInfo->pLen );
  416.         checkSum += checksum( pgpInfo->q, pgpInfo->qLen );
  417.         checkSum += checksum( pgpInfo->u, pgpInfo->uLen );
  418.         if( checkSum != packetChecksum )
  419.             status = isEncrypted ? CRYPT_WRONGKEY : CRYPT_BADDATA;
  420.         }
  421.  
  422.     /* Move on to the next key packet so we can continue looking for keys if
  423.        required */
  424.     skipToKeyPacket( filePtr );
  425.     return( status );
  426.     }
  427.  
  428. /* Get the subtype of the key file */
  429.  
  430. KEYSET_SUBTYPE pgpGetKeysetType( FILE *filePtr )
  431.     {
  432.     int ctb, type = KEYSET_SUBTYPE_ERROR, length;
  433.  
  434.     /* Try and establish the file type based on the initial CTB */
  435.     ctb = fgetc( filePtr );
  436.     if( ctb == PGP_CTB_PUBKEY )
  437.         type = KEYSET_SUBTYPE_PUBLIC;
  438.     if( ctb == PGP_CTB_SECKEY )
  439.         type = KEYSET_SUBTYPE_PRIVATE;
  440.  
  441.     /* Perform a sanity check to make sure the rest looks like a PGP
  442.        keyring */
  443.     length = getLength( filePtr, ctb );
  444.     if( type == KEYSET_SUBTYPE_PUBLIC )
  445.         {
  446.         if( length < 64 || length > 1024  )
  447.             type = KEYSET_SUBTYPE_ERROR;
  448.         }
  449.     else
  450.         if( length < 200 || length > 4096 )
  451.             type = KEYSET_SUBTYPE_ERROR;
  452.     ctb = fgetByte( filePtr );
  453.     if( ctb != PGP2_VERSION_BYTE && ctb != PGP3_VERSION_BYTE )
  454.         type = KEYSET_SUBTYPE_ERROR;
  455.  
  456.     /* Move back to the start of the file */
  457.     fseek( filePtr, 0L, SEEK_SET );
  458.  
  459.     return( type );
  460.     }
  461.  
  462. /* Get a public or private key from a file and return it in an encryption
  463.    context */
  464.  
  465. int pgpGetKey( FILE *filePtr, CRYPT_CONTEXT *cryptContext,
  466.                const GETKEY_INFO *getkeyInfo )
  467.     {
  468.     CRYPT_PKCINFO_RSA *rsaKey;
  469.     CRYPT_INFO *cryptInfoPtr;
  470.     PGP_INFO *pgpInfo;
  471.     int status = CRYPT_OK;
  472.  
  473.     /* Allocate memory for the PGP key info.  This is somewhat messy
  474.        security-wise for private keys because we first read the PGP key
  475.        components into the pgpInfo structure, decrypt and unmangle them, and
  476.        then move them into the rsaInfo structure in preparation for loading
  477.        them into an encryption context, but there's no real way around this.
  478.        The memory is sanitised immediately after the transfer, so the
  479.        critical information is only held in one of the two structures at any
  480.        one time */
  481.     if( ( pgpInfo = malloc( sizeof( PGP_INFO ) ) ) == NULL )
  482.         return( CRYPT_NOMEM );
  483.     memset( pgpInfo, 0, sizeof( PGP_INFO ) );
  484.  
  485.     /* Get the key from the keyring */
  486.     while( ( status = readKey( pgpInfo, filePtr, getkeyInfo ) ) == -1000 );
  487.     if( cryptStatusError( status ) )
  488.         goto endGetKey;
  489.  
  490.     /* Load the key into the encryption context */
  491.     status = cryptCreateContext( cryptContext, CRYPT_ALGO_RSA, CRYPT_MODE_PKC );
  492.     if( cryptStatusError( status ) )
  493.         goto endGetKey;
  494.     rsaKey = &pgpInfo->rsaKey;
  495.     if( getkeyInfo->isPublicKey )
  496.         {
  497.         /* Set up the RSA public-key fields */
  498.         cryptInitComponents( rsaKey, CRYPT_COMPONENTS_BIGENDIAN, \
  499.                              CRYPT_KEYTYPE_PUBLIC );
  500.         cryptSetComponent( rsaKey->n, pgpInfo->n, pgpInfo->nLen );
  501.         cryptSetComponent( rsaKey->e, pgpInfo->e, pgpInfo->eLen );
  502.         }
  503.     else
  504.         {
  505.         /* Set up the RSA private-key fields */
  506.         cryptInitComponents( rsaKey, CRYPT_COMPONENTS_BIGENDIAN, \
  507.                              CRYPT_KEYTYPE_PRIVATE );
  508.         cryptSetComponent( rsaKey->n, pgpInfo->n, pgpInfo->nLen );
  509.         cryptSetComponent( rsaKey->e, pgpInfo->e, pgpInfo->eLen );
  510.         cryptSetComponent( rsaKey->d, pgpInfo->d, pgpInfo->dLen );
  511.         cryptSetComponent( rsaKey->p, pgpInfo->p, pgpInfo->pLen );
  512.         cryptSetComponent( rsaKey->q, pgpInfo->q, pgpInfo->qLen );
  513.         cryptSetComponent( rsaKey->u, pgpInfo->u, pgpInfo->uLen );
  514.         }
  515.     status = cryptLoadContext( *cryptContext, rsaKey, CRYPT_UNUSED );
  516.     cryptDestroyComponents( rsaKey );
  517.  
  518.     /* Store the userID in the encryption context as well in case we want to
  519.        later export the key to another type of keyset */
  520.     if( cryptStatusOK( status ) )
  521.         {
  522.         cryptInfoPtr = CONTEXT_TO_INFO( *cryptContext );
  523.         if( ( cryptInfoPtr->userID = ( char * ) \
  524.                     malloc( strlen( pgpInfo->userID + 1 ) ) ) == NULL )
  525.             {
  526.             cryptDestroyContext( *cryptContext );
  527.             return( CRYPT_NOMEM );
  528.             }
  529.         strcpy( cryptInfoPtr->userID, pgpInfo->userID );
  530.         }
  531.  
  532.     /* Clean up */
  533. endGetKey:
  534.     zeroise( pgpInfo, sizeof( PGP_INFO ) );
  535.     free( pgpInfo );
  536.  
  537.     return( status );
  538.     }
  539.