src/lib/crypto.c
CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys)
{
   CRYPTO_SESSION *cs;
   X509_KEYPAIR *keypair;
   const EVP_CIPHER *ec;
   unsigned char *iv;
   int iv_len;

   /* Allocate our session description structures */
   cs = (CRYPTO_SESSION *)malloc(sizeof(CRYPTO_SESSION));

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

   /* Allocate a CryptoData structure */
   cs->cryptoData = CryptoData_new();

   if (!cs->cryptoData) {
      /* Allocation failed in OpenSSL */
      free(cs);
      return NULL;
   }

   /* Set the ASN.1 structure version number */
   ASN1_INTEGER_set(cs->cryptoData->version, BACULA_ASN1_VERSION);

   /*
    * Acquire a cipher instance and set the ASN.1 cipher NID
    */
   switch (cipher) {
   case CRYPTO_CIPHER_AES_128_CBC:
      /* AES 128 bit CBC */
      cs->cryptoData->contentEncryptionAlgorithm = OBJ_nid2obj(NID_aes_128_cbc);
      ec = EVP_aes_128_cbc();
      break;
#ifndef HAVE_OPENSSL_EXPORT_LIBRARY
   case CRYPTO_CIPHER_AES_192_CBC:
      /* AES 192 bit CBC */
      cs->cryptoData->contentEncryptionAlgorithm = OBJ_nid2obj(NID_aes_192_cbc);
      ec = EVP_aes_192_cbc();
      break;
   case CRYPTO_CIPHER_AES_256_CBC:
      /* AES 256 bit CBC */
      cs->cryptoData->contentEncryptionAlgorithm = OBJ_nid2obj(NID_aes_256_cbc);
      ec = EVP_aes_256_cbc();
      break;
#endif
   case CRYPTO_CIPHER_BLOWFISH_CBC:
      /* Blowfish CBC */
      cs->cryptoData->contentEncryptionAlgorithm = OBJ_nid2obj(NID_bf_cbc);
      ec = EVP_bf_cbc();
      break;
   default:
      Jmsg0(NULL, M_ERROR, 0, _("Unsupported cipher type specified\n"));
      crypto_session_free(cs);
      return NULL;
   }

   /* Generate a symmetric session key */
   cs->session_key_len = EVP_CIPHER_key_length(ec);
   cs->session_key = (unsigned char *) malloc(cs->session_key_len);
   if (RAND_bytes(cs->session_key, cs->session_key_len) <= 0) {
      /* OpenSSL failure */
      crypto_session_free(cs);
      return NULL;
   }

   /* Generate an IV if possible */
   if ((iv_len = EVP_CIPHER_iv_length(ec))) {
      iv = (unsigned char *)malloc(iv_len);

      /* Generate random IV */
      if (RAND_bytes(iv, iv_len) <= 0) {
         /* OpenSSL failure */
         crypto_session_free(cs);
         free(iv);
         return NULL;
      }

      /* Store it in our ASN.1 structure */
      if (!ASN1_OCTET_STRING_set(cs->cryptoData->iv, iv, iv_len)) {
         /* Allocation failed in OpenSSL */
         crypto_session_free(cs);
         free(iv);
         return NULL;
      }
      free(iv);
   }

   /*
    * Create RecipientInfo structures for supplied
    * public keys.
    */
   foreach_alist(keypair, pubkeys) {
      RecipientInfo *ri;
      unsigned char *ekey;
      int ekey_len;

      ri = RecipientInfo_new();
      if (!ri) {
         /* Allocation failed in OpenSSL */
         crypto_session_free(cs);
         return NULL;
      }

      /* Set the ASN.1 structure version number */
      ASN1_INTEGER_set(ri->version, BACULA_ASN1_VERSION);

      /* Drop the string allocated by OpenSSL, and add our subjectKeyIdentifier */
      ASN1_OCTET_STRING_free(ri->subjectKeyIdentifier);
      ri->subjectKeyIdentifier = ASN1_OCTET_STRING_dup(keypair->keyid);

      /* Set our key encryption algorithm. We currently require RSA */
      assert(keypair->pubkey && EVP_PKEY_base_id(keypair->pubkey) == EVP_PKEY_RSA);
      ri->keyEncryptionAlgorithm = OBJ_nid2obj(NID_rsaEncryption);

      /* Encrypt the session key */
      ekey = (unsigned char *)malloc(EVP_PKEY_size(keypair->pubkey));

      if ((ekey_len = EVP_PKEY_encrypt(ekey, cs->session_key, cs->session_key_len, keypair->pubkey)) <= 0) {
         /* OpenSSL failure */
         RecipientInfo_free(ri);
         crypto_session_free(cs);
         free(ekey);
         return NULL;
      }

      /* Store it in our ASN.1 structure */
      if (!ASN1_OCTET_STRING_set(ri->encryptedKey, ekey, ekey_len)) {
         /* Allocation failed in OpenSSL */
         RecipientInfo_free(ri);
         crypto_session_free(cs);
         free(ekey);
         return NULL;
      }

      /* Free the encrypted key buffer */
      free(ekey);

      /* Push the new RecipientInfo structure onto the stack */
      sk_RecipientInfo_push(cs->cryptoData->recipientInfo, ri);
   }

   return cs;
}
/*
 * Create a new encryption session.
 *  Returns: A pointer to a CRYPTO_SESSION object on success.
 *           NULL on failure.
 *
 *  Note! Bacula malloc() fails if out of memory.
 */
Create a new encryption session.
Returns: A pointer to a CRYPTO_SESSION object on success.
NULL on failure.

Note. Bacula malloc() fails if out of memory.
Create a new encryption session . Returns : A pointer to a CRYPTO_SESSION object on success . NULL on failure . Note . Bacula malloc () fails if out of memory .
CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys)
{
   CRYPTO_SESSION *cs;
   X509_KEYPAIR *keypair;
   const EVP_CIPHER *ec;
   unsigned char *iv;
   int iv_len;
   cs = (CRYPTO_SESSION *)malloc(sizeof(CRYPTO_SESSION));
   cs->session_key = NULL;
   cs->cryptoData = CryptoData_new();
   if (!cs->cryptoData) {
      free(cs);
      return NULL;
   }
   ASN1_INTEGER_set(cs->cryptoData->version, BACULA_ASN1_VERSION);
   switch (cipher) {
   case CRYPTO_CIPHER_AES_128_CBC:
      cs->cryptoData->contentEncryptionAlgorithm = OBJ_nid2obj(NID_aes_128_cbc);
      ec = EVP_aes_128_cbc();
      break;
#ifndef HAVE_OPENSSL_EXPORT_LIBRARY
   case CRYPTO_CIPHER_AES_192_CBC:
      cs->cryptoData->contentEncryptionAlgorithm = OBJ_nid2obj(NID_aes_192_cbc);
      ec = EVP_aes_192_cbc();
      break;
   case CRYPTO_CIPHER_AES_256_CBC:
      cs->cryptoData->contentEncryptionAlgorithm = OBJ_nid2obj(NID_aes_256_cbc);
      ec = EVP_aes_256_cbc();
      break;
#endif
   case CRYPTO_CIPHER_BLOWFISH_CBC:
      cs->cryptoData->contentEncryptionAlgorithm = OBJ_nid2obj(NID_bf_cbc);
      ec = EVP_bf_cbc();
      break;
   default:
      Jmsg0(NULL, M_ERROR, 0, _("Unsupported cipher type specified\n"));
      crypto_session_free(cs);
      return NULL;
   }
   cs->session_key_len = EVP_CIPHER_key_length(ec);
   cs->session_key = (unsigned char *) malloc(cs->session_key_len);
   if (RAND_bytes(cs->session_key, cs->session_key_len) <= 0) {
      crypto_session_free(cs);
      return NULL;
   }
   if ((iv_len = EVP_CIPHER_iv_length(ec))) {
      iv = (unsigned char *)malloc(iv_len);
      if (RAND_bytes(iv, iv_len) <= 0) {
         crypto_session_free(cs);
         free(iv);
         return NULL;
      }
      if (!ASN1_OCTET_STRING_set(cs->cryptoData->iv, iv, iv_len)) {
         crypto_session_free(cs);
         free(iv);
         return NULL;
      }
      free(iv);
   }
   foreach_alist(keypair, pubkeys) {
      RecipientInfo *ri;
      unsigned char *ekey;
      int ekey_len;
      ri = RecipientInfo_new();
      if (!ri) {
         crypto_session_free(cs);
         return NULL;
      }
      ASN1_INTEGER_set(ri->version, BACULA_ASN1_VERSION);
      ASN1_OCTET_STRING_free(ri->subjectKeyIdentifier);
      ri->subjectKeyIdentifier = ASN1_OCTET_STRING_dup(keypair->keyid);
      assert(keypair->pubkey && EVP_PKEY_base_id(keypair->pubkey) == EVP_PKEY_RSA);
      ri->keyEncryptionAlgorithm = OBJ_nid2obj(NID_rsaEncryption);
      ekey = (unsigned char *)malloc(EVP_PKEY_size(keypair->pubkey));
      if ((ekey_len = EVP_PKEY_encrypt(ekey, cs->session_key, cs->session_key_len, keypair->pubkey)) <= 0) {
         RecipientInfo_free(ri);
         crypto_session_free(cs);
         free(ekey);
         return NULL;
      }
      if (!ASN1_OCTET_STRING_set(ri->encryptedKey, ekey, ekey_len)) {
         RecipientInfo_free(ri);
         crypto_session_free(cs);
         free(ekey);
         return NULL;
      }
      free(ekey);
      sk_RecipientInfo_push(cs->cryptoData->recipientInfo, ri);
   }
   return cs;
}
CRYPTO_SESSION * crypto_session_new ( crypto_cipher_t cipher , alist * pubkeys ) { CRYPTO_SESSION * cs ; X509_KEYPAIR * keypair ; const EVP_CIPHER * ec ; unsigned char * iv ; int iv_len ; cs = ( CRYPTO_SESSION * ) malloc ( sizeof ( CRYPTO_SESSION ) ) ; cs -> session_key = NULL ; cs -> cryptoData = CryptoData_new ( ) ; if ( ! cs -> cryptoData ) { free ( cs ) ; return NULL ; } ASN1_INTEGER_set ( cs -> cryptoData -> version , BACULA_ASN1_VERSION ) ; switch ( cipher ) { case CRYPTO_CIPHER_AES_128_CBC : cs -> cryptoData -> contentEncryptionAlgorithm = OBJ_nid2obj ( NID_aes_128_cbc ) ; ec = EVP_aes_128_cbc ( ) ; break ; #ifndef HAVE_OPENSSL_EXPORT_LIBRARY case CRYPTO_CIPHER_AES_192_CBC : cs -> cryptoData -> contentEncryptionAlgorithm = OBJ_nid2obj ( NID_aes_192_cbc ) ; ec = EVP_aes_192_cbc ( ) ; break ; case CRYPTO_CIPHER_AES_256_CBC : cs -> cryptoData -> contentEncryptionAlgorithm = OBJ_nid2obj ( NID_aes_256_cbc ) ; ec = EVP_aes_256_cbc ( ) ; break ; #endif case CRYPTO_CIPHER_BLOWFISH_CBC : cs -> cryptoData -> contentEncryptionAlgorithm = OBJ_nid2obj ( NID_bf_cbc ) ; ec = EVP_bf_cbc ( ) ; break ; default : Jmsg0 ( NULL , M_ERROR , 0 , _ ( " \n " ) ) ; crypto_session_free ( cs ) ; return NULL ; } cs -> session_key_len = EVP_CIPHER_key_length ( ec ) ; cs -> session_key = ( unsigned char * ) malloc ( cs -> session_key_len ) ; if ( RAND_bytes ( cs -> session_key , cs -> session_key_len ) <= 0 ) { crypto_session_free ( cs ) ; return NULL ; } if ( ( iv_len = EVP_CIPHER_iv_length ( ec ) ) ) { iv = ( unsigned char * ) malloc ( iv_len ) ; if ( RAND_bytes ( iv , iv_len ) <= 0 ) { crypto_session_free ( cs ) ; free ( iv ) ; return NULL ; } if ( ! ASN1_OCTET_STRING_set ( cs -> cryptoData -> iv , iv , iv_len ) ) { crypto_session_free ( cs ) ; free ( iv ) ; return NULL ; } free ( iv ) ; } foreach_alist ( keypair , pubkeys ) { RecipientInfo * ri ; unsigned char * ekey ; int ekey_len ; ri = RecipientInfo_new ( ) ; if ( ! ri ) { crypto_session_free ( cs ) ; return NULL ; } ASN1_INTEGER_set ( ri -> version , BACULA_ASN1_VERSION ) ; ASN1_OCTET_STRING_free ( ri -> subjectKeyIdentifier ) ; ri -> subjectKeyIdentifier = ASN1_OCTET_STRING_dup ( keypair -> keyid ) ; assert ( keypair -> pubkey && EVP_PKEY_base_id ( keypair -> pubkey ) == EVP_PKEY_RSA ) ; ri -> keyEncryptionAlgorithm = OBJ_nid2obj ( NID_rsaEncryption ) ; ekey = ( unsigned char * ) malloc ( EVP_PKEY_size ( keypair -> pubkey ) ) ; if ( ( ekey_len = EVP_PKEY_encrypt ( ekey , cs -> session_key , cs -> session_key_len , keypair -> pubkey ) ) <= 0 ) { RecipientInfo_free ( ri ) ; crypto_session_free ( cs ) ; free ( ekey ) ; return NULL ; } if ( ! ASN1_OCTET_STRING_set ( ri -> encryptedKey , ekey , ekey_len ) ) { RecipientInfo_free ( ri ) ; crypto_session_free ( cs ) ; free ( ekey ) ; return NULL ; } free ( ekey ) ; sk_RecipientInfo_push ( cs -> cryptoData -> recipientInfo , ri ) ; } return cs ; }
Create a new encryption session.
Create a new encryption session .
/* Allocate our session description structures */ /* Initialize required fields */ /* Allocate a CryptoData structure */ /* Allocation failed in OpenSSL */ /* Set the ASN.1 structure version number */ /*
    * Acquire a cipher instance and set the ASN.1 cipher NID
    */ /* AES 128 bit CBC */ /* AES 192 bit CBC */ /* AES 256 bit CBC */ /* Blowfish CBC */ /* Generate a symmetric session key */ /* OpenSSL failure */ /* Generate an IV if possible */ /* Generate random IV */ /* OpenSSL failure */ /* Store it in our ASN.1 structure */ /* Allocation failed in OpenSSL */ /*
    * Create RecipientInfo structures for supplied
    * public keys.
    */ /* Allocation failed in OpenSSL */ /* Set the ASN.1 structure version number */ /* Drop the string allocated by OpenSSL, and add our subjectKeyIdentifier */ /* Set our key encryption algorithm. We currently require RSA */ /* Encrypt the session key */ /* OpenSSL failure */ /* Store it in our ASN.1 structure */ /* Allocation failed in OpenSSL */ /* Free the encrypted key buffer */ /* Push the new RecipientInfo structure onto the stack */