src/lib/crypto.c
crypto_error_t crypto_session_decode(const uint8_t *data, uint32_t length, alist *keypairs, CRYPTO_SESSION **session)
{
   CRYPTO_SESSION *cs;
   X509_KEYPAIR *keypair;
   STACK_OF(RecipientInfo) *recipients;
   crypto_error_t retval = CRYPTO_ERROR_NONE;
   const unsigned char *p = (const unsigned char *)data;

   /* bacula-fd.conf doesn't contains any key */
   if (!keypairs) {
      return CRYPTO_ERROR_NORECIPIENT;
   }

   cs = (CRYPTO_SESSION *)malloc(sizeof(CRYPTO_SESSION));

   /* Initialize required fields */
   cs->session_key = NULL;

   /* d2i_CryptoData modifies the supplied pointer */
   cs->cryptoData = d2i_CryptoData(NULL, &p, length);

   if (!cs->cryptoData) {
      /* Allocation / Decoding failed in OpenSSL */
      openssl_post_errors(M_ERROR, _("CryptoData decoding failed"));
      retval = CRYPTO_ERROR_INTERNAL;
      goto err;
   }

   recipients = cs->cryptoData->recipientInfo;

   /*
    * Find a matching RecipientInfo structure for a supplied
    * public key
    */
   foreach_alist(keypair, keypairs) {
      RecipientInfo *ri;
      int i;

      /* Private key available? */
      if (keypair->privkey == NULL) {
         continue;
      }

      for (i = 0; i < sk_RecipientInfo_num(recipients); i++) {
         ri = sk_RecipientInfo_value(recipients, i);

         /* Match against the subjectKeyIdentifier */
         if (ASN1_OCTET_STRING_cmp(keypair->keyid, ri->subjectKeyIdentifier) == 0) {
            /* Match found, extract symmetric encryption session data */

            /* RSA is required. */
            assert(EVP_PKEY_base_id(keypair->privkey) == EVP_PKEY_RSA);

            /* If we recieve a RecipientInfo structure that does not use
             * RSA, return an error */
            if (OBJ_obj2nid(ri->keyEncryptionAlgorithm) != NID_rsaEncryption) {
               retval = CRYPTO_ERROR_INVALID_CRYPTO;
               goto err;
            }

            /* Decrypt the session key */
            /* Allocate sufficient space for the largest possible decrypted data */
            cs->session_key = (unsigned char *)malloc(EVP_PKEY_size(keypair->privkey));
            cs->session_key_len = EVP_PKEY_decrypt(cs->session_key, ASN1_STRING_get0_data(ri->encryptedKey),
                                  ASN1_STRING_length(ri->encryptedKey), keypair->privkey);

            if (cs->session_key_len <= 0) {
               openssl_post_errors(M_ERROR, _("Failure decrypting the session key"));
               retval = CRYPTO_ERROR_DECRYPTION;
               goto err;
            }

            /* Session key successfully extracted, return the CRYPTO_SESSION structure */
            *session = cs;
            return CRYPTO_ERROR_NONE;
         }
      }
   }

   /* No matching recipient found */
   return CRYPTO_ERROR_NORECIPIENT;

err:
   crypto_session_free(cs);
   return retval;
}
/*
 * Decodes the CryptoData structure. The length argument is
 * used to specify the size of data.
 *
 * Returns: CRYPTO_SESSION instance on success.
 *          NULL on failure.
 * Returns: CRYPTO_ERROR_NONE and a pointer to a newly allocated CRYPTO_SESSION structure in *session on success.
 *          A crypto_error_t value on failure.
 */
Decodes the CryptoData structure. The length argument is
used to specify the size of data.

CRYPTO_SESSION instance on success.
NULL on failure.
Returns: CRYPTO_ERROR_NONE and a pointer to a newly allocated CRYPTO_SESSION structure in *session on success.
A crypto_error_t value on failure.
Decodes the CryptoData structure . The length argument is used to specify the size of data . CRYPTO_SESSION instance on success . NULL on failure . Returns : CRYPTO_ERROR_NONE and a pointer to a newly allocated CRYPTO_SESSION structure in * session on success . A crypto_error_t value on failure .
crypto_error_t crypto_session_decode(const uint8_t *data, uint32_t length, alist *keypairs, CRYPTO_SESSION **session)
{
   CRYPTO_SESSION *cs;
   X509_KEYPAIR *keypair;
   STACK_OF(RecipientInfo) *recipients;
   crypto_error_t retval = CRYPTO_ERROR_NONE;
   const unsigned char *p = (const unsigned char *)data;
   if (!keypairs) {
      return CRYPTO_ERROR_NORECIPIENT;
   }
   cs = (CRYPTO_SESSION *)malloc(sizeof(CRYPTO_SESSION));
   cs->session_key = NULL;
   cs->cryptoData = d2i_CryptoData(NULL, &p, length);
   if (!cs->cryptoData) {
      openssl_post_errors(M_ERROR, _("CryptoData decoding failed"));
      retval = CRYPTO_ERROR_INTERNAL;
      goto err;
   }
   recipients = cs->cryptoData->recipientInfo;
   foreach_alist(keypair, keypairs) {
      RecipientInfo *ri;
      int i;
      if (keypair->privkey == NULL) {
         continue;
      }
      for (i = 0; i < sk_RecipientInfo_num(recipients); i++) {
         ri = sk_RecipientInfo_value(recipients, i);
         if (ASN1_OCTET_STRING_cmp(keypair->keyid, ri->subjectKeyIdentifier) == 0) {
            assert(EVP_PKEY_base_id(keypair->privkey) == EVP_PKEY_RSA);
            if (OBJ_obj2nid(ri->keyEncryptionAlgorithm) != NID_rsaEncryption) {
               retval = CRYPTO_ERROR_INVALID_CRYPTO;
               goto err;
            }
            cs->session_key = (unsigned char *)malloc(EVP_PKEY_size(keypair->privkey));
            cs->session_key_len = EVP_PKEY_decrypt(cs->session_key, ASN1_STRING_get0_data(ri->encryptedKey),
                                  ASN1_STRING_length(ri->encryptedKey), keypair->privkey);
            if (cs->session_key_len <= 0) {
               openssl_post_errors(M_ERROR, _("Failure decrypting the session key"));
               retval = CRYPTO_ERROR_DECRYPTION;
               goto err;
            }
            *session = cs;
            return CRYPTO_ERROR_NONE;
         }
      }
   }
   return CRYPTO_ERROR_NORECIPIENT;
err:
   crypto_session_free(cs);
   return retval;
}
crypto_error_t crypto_session_decode ( const uint8_t * data , uint32_t length , alist * keypairs , CRYPTO_SESSION * * session ) { CRYPTO_SESSION * cs ; X509_KEYPAIR * keypair ; STACK_OF ( RecipientInfo ) * recipients ; crypto_error_t retval = CRYPTO_ERROR_NONE ; const unsigned char * p = ( const unsigned char * ) data ; if ( ! keypairs ) { return CRYPTO_ERROR_NORECIPIENT ; } cs = ( CRYPTO_SESSION * ) malloc ( sizeof ( CRYPTO_SESSION ) ) ; cs -> session_key = NULL ; cs -> cryptoData = d2i_CryptoData ( NULL , & p , length ) ; if ( ! cs -> cryptoData ) { openssl_post_errors ( M_ERROR , _ ( " " ) ) ; retval = CRYPTO_ERROR_INTERNAL ; goto err ; } recipients = cs -> cryptoData -> recipientInfo ; foreach_alist ( keypair , keypairs ) { RecipientInfo * ri ; int i ; if ( keypair -> privkey == NULL ) { continue ; } for ( i = 0 ; i < sk_RecipientInfo_num ( recipients ) ; i ++ ) { ri = sk_RecipientInfo_value ( recipients , i ) ; if ( ASN1_OCTET_STRING_cmp ( keypair -> keyid , ri -> subjectKeyIdentifier ) == 0 ) { assert ( EVP_PKEY_base_id ( keypair -> privkey ) == EVP_PKEY_RSA ) ; if ( OBJ_obj2nid ( ri -> keyEncryptionAlgorithm ) != NID_rsaEncryption ) { retval = CRYPTO_ERROR_INVALID_CRYPTO ; goto err ; } cs -> session_key = ( unsigned char * ) malloc ( EVP_PKEY_size ( keypair -> privkey ) ) ; cs -> session_key_len = EVP_PKEY_decrypt ( cs -> session_key , ASN1_STRING_get0_data ( ri -> encryptedKey ) , ASN1_STRING_length ( ri -> encryptedKey ) , keypair -> privkey ) ; if ( cs -> session_key_len <= 0 ) { openssl_post_errors ( M_ERROR , _ ( " " ) ) ; retval = CRYPTO_ERROR_DECRYPTION ; goto err ; } * session = cs ; return CRYPTO_ERROR_NONE ; } } } return CRYPTO_ERROR_NORECIPIENT ; err : crypto_session_free ( cs ) ; return retval ; }
Decodes the CryptoData structure.
Decodes the CryptoData structure .
/* bacula-fd.conf doesn't contains any key */ /* Initialize required fields */ /* d2i_CryptoData modifies the supplied pointer */ /* Allocation / Decoding failed in OpenSSL */ /*
    * Find a matching RecipientInfo structure for a supplied
    * public key
    */ /* Private key available? */ /* Match against the subjectKeyIdentifier */ /* Match found, extract symmetric encryption session data */ /* RSA is required. */ /* If we recieve a RecipientInfo structure that does not use
             * RSA, return an error */ /* Decrypt the session key */ /* Allocate sufficient space for the largest possible decrypted data */ /* Session key successfully extracted, return the CRYPTO_SESSION structure */ /* No matching recipient found */