X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Flib%2Fcrypto.c;h=0cb4f9feef60ab448adb04412b99751b037e6ed3;hb=f52b54ffe7b08ecd6f6df6a0e4b7a1a3f9396c4b;hp=66b377ff908e0389346c67ad1cde9cb1e57300f4;hpb=d51e28e9e1a75a0155782fcc9ba0afeaf1f66cba;p=bacula%2Fbacula diff --git a/bacula/src/lib/crypto.c b/bacula/src/lib/crypto.c index 66b377ff90..0cb4f9feef 100644 --- a/bacula/src/lib/crypto.c +++ b/bacula/src/lib/crypto.c @@ -1,37 +1,26 @@ /* - Bacula® - The Network Backup Solution - - Copyright (C) 2005-2007 Free Software Foundation Europe e.V. - - The main author of Bacula is Kern Sibbald, with contributions from - many others, a complete list can be found in the file AUTHORS. - This program is Free Software; you can redistribute it and/or - modify it under the terms of version two of the GNU General Public - License as published by the Free Software Foundation and included - in the file LICENSE. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. - - Bacula® is a registered trademark of John Walker. - The licensor of Bacula is the Free Software Foundation Europe - (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, - Switzerland, email:ftf@fsfeurope.org. + Bacula(R) - The Network Backup Solution + + Copyright (C) 2000-2016 Kern Sibbald + + The original author of Bacula is Kern Sibbald, with contributions + from many others, a complete list can be found in the file AUTHORS. + + You may use this file and others of this release according to the + license defined in the LICENSE file, which includes the Affero General + Public License, v3.0 ("AGPLv3") and some additional permissions and + terms pursuant to its AGPLv3 Section 7. + + This notice must be preserved when any source code is + conveyed and/or propagated. + + Bacula(R) is a registered trademark of Kern Sibbald. */ /* * crypto.c Encryption support functions * * Author: Landon Fuller * - * Version $Id$ - * * This file was contributed to the Bacula project by Landon Fuller. * * Landon Fuller has been granted a perpetual, worldwide, non-exclusive, @@ -49,6 +38,15 @@ #include "jcr.h" #include +/** + * For OpenSSL version 1.x, EVP_PKEY_encrypt no longer + * exists. It was not an official API. + */ +#ifdef HAVE_OPENSSLv1 +#define EVP_PKEY_encrypt EVP_PKEY_encrypt_old +#define EVP_PKEY_decrypt EVP_PKEY_decrypt_old +#endif + /* * Bacula ASN.1 Syntax * @@ -133,8 +131,7 @@ #ifdef HAVE_CRYPTO /* Is encryption enabled? */ #ifdef HAVE_OPENSSL /* How about OpenSSL? */ -/* Are we initialized? */ -static int crypto_initialized = false; +#include "openssl-compat.h" /* ASN.1 Declarations */ #define BACULA_ASN1_VERSION 0 @@ -197,9 +194,11 @@ IMPLEMENT_ASN1_FUNCTIONS(SignerInfo) IMPLEMENT_ASN1_FUNCTIONS(RecipientInfo) IMPLEMENT_ASN1_FUNCTIONS(SignatureData) IMPLEMENT_ASN1_FUNCTIONS(CryptoData) -IMPLEMENT_STACK_OF(SignerInfo) -IMPLEMENT_STACK_OF(RecipientInfo) +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) +DEFINE_STACK_OF(SignerInfo); +DEFINE_STACK_OF(RecipientInfo); +#else /* * SignerInfo and RecipientInfo stack macros, generated by OpenSSL's util/mkstack.pl. */ @@ -225,7 +224,7 @@ IMPLEMENT_STACK_OF(RecipientInfo) #define sk_SignerInfo_is_sorted(st) SKM_sk_is_sorted(SignerInfo, (st)) #define d2i_ASN1_SET_OF_SignerInfo(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ - SKM_ASN1_SET_OF_d2i(SignerInfo, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) + SKM_ASN1_SET_OF_d2i(SignerInfo, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) #define i2d_ASN1_SET_OF_SignerInfo(st, pp, i2d_func, ex_tag, ex_class, is_set) \ SKM_ASN1_SET_OF_i2d(SignerInfo, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) #define ASN1_seq_pack_SignerInfo(st, i2d_func, buf, len) \ @@ -255,7 +254,7 @@ IMPLEMENT_STACK_OF(RecipientInfo) #define sk_RecipientInfo_is_sorted(st) SKM_sk_is_sorted(RecipientInfo, (st)) #define d2i_ASN1_SET_OF_RecipientInfo(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ - SKM_ASN1_SET_OF_d2i(RecipientInfo, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) + SKM_ASN1_SET_OF_d2i(RecipientInfo, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) #define i2d_ASN1_SET_OF_RecipientInfo(st, pp, i2d_func, ex_tag, ex_class, is_set) \ SKM_ASN1_SET_OF_i2d(RecipientInfo, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) #define ASN1_seq_pack_RecipientInfo(st, i2d_func, buf, len) \ @@ -263,6 +262,7 @@ IMPLEMENT_STACK_OF(RecipientInfo) #define ASN1_seq_unpack_RecipientInfo(buf, len, d2i_func, free_func) \ SKM_ASN1_seq_unpack(RecipientInfo, (buf), (len), (d2i_func), (free_func)) /* End of util/mkstack.pl block */ +#endif /* X509 Public/Private Key Pair Structure */ struct X509_Keypair { @@ -275,7 +275,7 @@ struct X509_Keypair { struct Digest { crypto_digest_t type; JCR *jcr; - EVP_MD_CTX ctx; + EVP_MD_CTX *ctx; }; /* Message Signature Structure */ @@ -293,7 +293,7 @@ struct Crypto_Session { /* Symmetric Cipher Context */ struct Cipher_Context { - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; }; /* PEM Password Dispatch Context */ @@ -304,20 +304,16 @@ typedef struct PEM_CB_Context { /* * Extract subjectKeyIdentifier from x509 certificate. - * Returns: On success, an ASN1_OCTET_STRING that must be freed via M_ASN1_OCTET_STRING_free(). + * Returns: On success, an ASN1_OCTET_STRING that must be freed via ASN1_OCTET_STRING_free(). * NULL on failure. */ static ASN1_OCTET_STRING *openssl_cert_keyid(X509 *cert) { X509_EXTENSION *ext; - X509V3_EXT_METHOD *method; + const X509V3_EXT_METHOD *method; ASN1_OCTET_STRING *keyid; int i; -#if (OPENSSL_VERSION_NUMBER >= 0x0090800FL) + const ASN1_STRING *asn1_ext_val; const unsigned char *ext_value_data; -#else - unsigned char *ext_value_data; -#endif - /* Find the index to the subjectKeyIdentifier extension */ i = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1); @@ -334,26 +330,22 @@ static ASN1_OCTET_STRING *openssl_cert_keyid(X509 *cert) { return NULL; } - ext_value_data = ext->value->data; + asn1_ext_val = X509_EXTENSION_get_data(ext); + ext_value_data = ASN1_STRING_get0_data(asn1_ext_val); -#if (OPENSSL_VERSION_NUMBER > 0x00907000L) if (method->it) { /* New style ASN1 */ /* Decode ASN1 item in data */ - keyid = (ASN1_OCTET_STRING *) ASN1_item_d2i(NULL, &ext_value_data, ext->value->length, + keyid = (ASN1_OCTET_STRING *) ASN1_item_d2i(NULL, &ext_value_data, ASN1_STRING_length(asn1_ext_val), ASN1_ITEM_ptr(method->it)); } else { /* Old style ASN1 */ /* Decode ASN1 item in data */ - keyid = (ASN1_OCTET_STRING *) method->d2i(NULL, &ext_value_data, ext->value->length); + keyid = (ASN1_OCTET_STRING *) method->d2i(NULL, &ext_value_data, ASN1_STRING_length(asn1_ext_val)); } -#else - keyid = (ASN1_OCTET_STRING *) method->d2i(NULL, &ext_value_data, ext->value->length); -#endif - return keyid; } @@ -362,7 +354,7 @@ static ASN1_OCTET_STRING *openssl_cert_keyid(X509 *cert) { * Returns: A pointer to a X509 KEYPAIR object on success. * NULL on failure. */ -X509_KEYPAIR *crypto_keypair_new(void) +X509_KEYPAIR *crypto_keypair_new(void) { X509_KEYPAIR *keypair; @@ -386,6 +378,7 @@ X509_KEYPAIR *crypto_keypair_new(void) X509_KEYPAIR *crypto_keypair_dup(X509_KEYPAIR *keypair) { X509_KEYPAIR *newpair; + int ret; newpair = crypto_keypair_new(); @@ -396,27 +389,32 @@ X509_KEYPAIR *crypto_keypair_dup(X509_KEYPAIR *keypair) /* Increment the public key ref count */ if (keypair->pubkey) { - CRYPTO_add(&(keypair->pubkey->references), 1, CRYPTO_LOCK_EVP_PKEY); + ret = EVP_PKEY_up_ref(keypair->pubkey); + if (ret == 0) + goto out_free_new; newpair->pubkey = keypair->pubkey; } /* Increment the private key ref count */ if (keypair->privkey) { - CRYPTO_add(&(keypair->privkey->references), 1, CRYPTO_LOCK_EVP_PKEY); + ret = EVP_PKEY_up_ref(keypair->privkey); + if (ret == 0) + goto out_free_new; newpair->privkey = keypair->privkey; } /* Duplicate the keyid */ if (keypair->keyid) { - newpair->keyid = M_ASN1_OCTET_STRING_dup(keypair->keyid); - if (!newpair->keyid) { - /* Allocation failed */ - crypto_keypair_free(newpair); - return NULL; - } + newpair->keyid = ASN1_OCTET_STRING_dup(keypair->keyid); + if (!newpair->keyid) + goto out_free_new; } return newpair; + +out_free_new: + crypto_keypair_free(newpair); + return NULL; } @@ -451,15 +449,15 @@ int crypto_keypair_load_cert(X509_KEYPAIR *keypair, const char *file) /* Extract the subjectKeyIdentifier extension field */ if ((keypair->keyid = openssl_cert_keyid(cert)) == NULL) { - Jmsg0(get_jcr_from_tid(), M_ERROR, 0, + Jmsg0(NULL, M_ERROR, 0, _("Provided certificate does not include the required subjectKeyIdentifier extension.")); goto err; } /* Validate the public key type (only RSA is supported) */ - if (EVP_PKEY_type(keypair->pubkey->type) != EVP_PKEY_RSA) { - Jmsg1(get_jcr_from_tid(), M_ERROR, 0, - _("Unsupported key type provided: %d\n"), EVP_PKEY_type(keypair->pubkey->type)); + if (EVP_PKEY_base_id(keypair->pubkey) != EVP_PKEY_RSA) { + Jmsg1(NULL, M_ERROR, 0, + _("Unsupported key type provided: %d\n"), EVP_PKEY_id(keypair->pubkey)); goto err; } @@ -579,7 +577,7 @@ void crypto_keypair_free(X509_KEYPAIR *keypair) EVP_PKEY_free(keypair->privkey); } if (keypair->keyid) { - M_ASN1_OCTET_STRING_free(keypair->keyid); + ASN1_OCTET_STRING_free(keypair->keyid); } free(keypair); } @@ -597,10 +595,13 @@ DIGEST *crypto_digest_new(JCR *jcr, crypto_digest_t type) digest = (DIGEST *)malloc(sizeof(DIGEST)); digest->type = type; digest->jcr = jcr; - Dmsg1(50, "crypto_digest_new jcr=%p\n", jcr); + Dmsg1(150, "crypto_digest_new jcr=%p\n", jcr); /* Initialize the OpenSSL message digest context */ - EVP_MD_CTX_init(&digest->ctx); + digest->ctx = EVP_MD_CTX_new(); + if (!digest->ctx) + goto err; + EVP_MD_CTX_reset(digest->ctx); /* Determine the correct OpenSSL message digest type */ switch (type) { @@ -624,7 +625,7 @@ DIGEST *crypto_digest_new(JCR *jcr, crypto_digest_t type) } /* Initialize the backing OpenSSL context */ - if (EVP_DigestInit_ex(&digest->ctx, md, NULL) == 0) { + if (EVP_DigestInit_ex(digest->ctx, md, NULL) == 0) { goto err; } @@ -632,7 +633,7 @@ DIGEST *crypto_digest_new(JCR *jcr, crypto_digest_t type) err: /* This should not happen, but never say never ... */ - Dmsg0(50, "Digest init failed.\n"); + Dmsg0(150, "Digest init failed.\n"); openssl_post_errors(jcr, M_ERROR, _("OpenSSL digest initialization failed")); crypto_digest_free(digest); return NULL; @@ -645,11 +646,11 @@ err: */ bool crypto_digest_update(DIGEST *digest, const uint8_t *data, uint32_t length) { - if (EVP_DigestUpdate(&digest->ctx, data, length) == 0) { - Dmsg0(50, "digest update failed\n"); + if (EVP_DigestUpdate(digest->ctx, data, length) == 0) { + Dmsg0(150, "digest update failed\n"); openssl_post_errors(digest->jcr, M_ERROR, _("OpenSSL digest update failed")); return false; - } else { + } else { return true; } } @@ -663,8 +664,8 @@ bool crypto_digest_update(DIGEST *digest, const uint8_t *data, uint32_t length) */ bool crypto_digest_finalize(DIGEST *digest, uint8_t *dest, uint32_t *length) { - if (!EVP_DigestFinal(&digest->ctx, dest, (unsigned int *)length)) { - Dmsg0(50, "digest finalize failed\n"); + if (!EVP_DigestFinal(digest->ctx, dest, (unsigned int *)length)) { + Dmsg0(150, "digest finalize failed\n"); openssl_post_errors(digest->jcr, M_ERROR, _("OpenSSL digest finalize failed")); return false; } else { @@ -677,7 +678,7 @@ bool crypto_digest_finalize(DIGEST *digest, uint8_t *dest, uint32_t *length) */ void crypto_digest_free(DIGEST *digest) { - EVP_MD_CTX_cleanup(&digest->ctx); + EVP_MD_CTX_free(digest->ctx); free(digest); } @@ -697,7 +698,7 @@ SIGNATURE *crypto_sign_new(JCR *jcr) sig->sigData = SignatureData_new(); sig->jcr = jcr; - Dmsg1(50, "crypto_sign_new jcr=%p\n", jcr); + Dmsg1(150, "crypto_sign_new jcr=%p\n", jcr); if (!sig->sigData) { /* Allocation failed in OpenSSL */ @@ -718,7 +719,7 @@ SIGNATURE *crypto_sign_new(JCR *jcr) * Returns: CRYPTO_ERROR_NONE on success, with the newly allocated DIGEST in digest. * A crypto_error_t value on failure. */ -crypto_error_t crypto_sign_get_digest(SIGNATURE *sig, X509_KEYPAIR *keypair, +crypto_error_t crypto_sign_get_digest(SIGNATURE *sig, X509_KEYPAIR *keypair, crypto_digest_t &type, DIGEST **digest) { STACK_OF(SignerInfo) *signers; @@ -729,9 +730,9 @@ crypto_error_t crypto_sign_get_digest(SIGNATURE *sig, X509_KEYPAIR *keypair, for (i = 0; i < sk_SignerInfo_num(signers); i++) { si = sk_SignerInfo_value(signers, i); - if (M_ASN1_OCTET_STRING_cmp(keypair->keyid, si->subjectKeyIdentifier) == 0) { + if (ASN1_OCTET_STRING_cmp(keypair->keyid, si->subjectKeyIdentifier) == 0) { /* Get the digest algorithm and allocate a digest context */ - Dmsg1(50, "crypto_sign_get_digest jcr=%p\n", sig->jcr); + Dmsg1(150, "crypto_sign_get_digest jcr=%p\n", sig->jcr); switch (OBJ_obj2nid(si->digestAlgorithm)) { case NID_md5: Dmsg0(100, "sign digest algorithm is MD5\n"); @@ -788,23 +789,19 @@ crypto_error_t crypto_sign_verify(SIGNATURE *sig, X509_KEYPAIR *keypair, DIGEST SignerInfo *si; int ok, i; unsigned int sigLen; -#if (OPENSSL_VERSION_NUMBER >= 0x0090800FL) const unsigned char *sigData; -#else - unsigned char *sigData; -#endif signers = sig->sigData->signerInfo; /* Find the signer */ for (i = 0; i < sk_SignerInfo_num(signers); i++) { si = sk_SignerInfo_value(signers, i); - if (M_ASN1_OCTET_STRING_cmp(keypair->keyid, si->subjectKeyIdentifier) == 0) { + if (ASN1_OCTET_STRING_cmp(keypair->keyid, si->subjectKeyIdentifier) == 0) { /* Extract the signature data */ - sigLen = M_ASN1_STRING_length(si->signature); - sigData = M_ASN1_STRING_data(si->signature); + sigLen = ASN1_STRING_length(si->signature); + sigData = ASN1_STRING_get0_data(si->signature); - ok = EVP_VerifyFinal(&digest->ctx, sigData, sigLen, keypair->pubkey); + ok = EVP_VerifyFinal(digest->ctx, sigData, sigLen, keypair->pubkey); if (ok >= 1) { return CRYPTO_ERROR_NONE; } else if (ok == 0) { @@ -866,24 +863,24 @@ int crypto_sign_add_signer(SIGNATURE *sig, DIGEST *digest, X509_KEYPAIR *keypair } /* Drop the string allocated by OpenSSL, and add our subjectKeyIdentifier */ - M_ASN1_OCTET_STRING_free(si->subjectKeyIdentifier); - si->subjectKeyIdentifier = M_ASN1_OCTET_STRING_dup(keypair->keyid); + ASN1_OCTET_STRING_free(si->subjectKeyIdentifier); + si->subjectKeyIdentifier = ASN1_OCTET_STRING_dup(keypair->keyid); /* Set our signature algorithm. We currently require RSA */ - assert(EVP_PKEY_type(keypair->pubkey->type) == EVP_PKEY_RSA); + assert(EVP_PKEY_base_id(keypair->pubkey) == EVP_PKEY_RSA); /* This is slightly evil. Reach into the MD structure and grab the key type */ - si->signatureAlgorithm = OBJ_nid2obj(digest->ctx.digest->pkey_type); + si->signatureAlgorithm = OBJ_nid2obj(EVP_MD_pkey_type(EVP_MD_CTX_md(digest->ctx))); /* Finalize/Sign our Digest */ len = EVP_PKEY_size(keypair->privkey); buf = (unsigned char *) malloc(len); - if (!EVP_SignFinal(&digest->ctx, buf, &len, keypair->privkey)) { + if (!EVP_SignFinal(digest->ctx, buf, &len, keypair->privkey)) { openssl_post_errors(M_ERROR, _("Signature creation failed")); goto err; } /* Add the signature to the SignerInfo structure */ - if (!M_ASN1_OCTET_STRING_set(si->signature, buf, len)) { + if (!ASN1_OCTET_STRING_set(si->signature, buf, len)) { /* Allocation failed in OpenSSL */ goto err; } @@ -939,11 +936,7 @@ int crypto_sign_encode(SIGNATURE *sig, uint8_t *dest, uint32_t *length) SIGNATURE *crypto_sign_decode(JCR *jcr, const uint8_t *sigData, uint32_t length) { SIGNATURE *sig; -#if (OPENSSL_VERSION_NUMBER >= 0x0090800FL) const unsigned char *p = (const unsigned char *) sigData; -#else - unsigned char *p = (unsigned char *)sigData; -#endif sig = (SIGNATURE *)malloc(sizeof(SIGNATURE)); if (!sig) { @@ -1033,7 +1026,7 @@ CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys) ec = EVP_bf_cbc(); break; default: - Jmsg0(get_jcr_from_tid(), M_ERROR, 0, _("Unsupported cipher type specified\n")); + Jmsg0(NULL, M_ERROR, 0, _("Unsupported cipher type specified\n")); crypto_session_free(cs); return NULL; } @@ -1060,7 +1053,7 @@ CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys) } /* Store it in our ASN.1 structure */ - if (!M_ASN1_OCTET_STRING_set(cs->cryptoData->iv, iv, iv_len)) { + if (!ASN1_OCTET_STRING_set(cs->cryptoData->iv, iv, iv_len)) { /* Allocation failed in OpenSSL */ crypto_session_free(cs); free(iv); @@ -1089,11 +1082,11 @@ CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys) ASN1_INTEGER_set(ri->version, BACULA_ASN1_VERSION); /* Drop the string allocated by OpenSSL, and add our subjectKeyIdentifier */ - M_ASN1_OCTET_STRING_free(ri->subjectKeyIdentifier); - ri->subjectKeyIdentifier = M_ASN1_OCTET_STRING_dup(keypair->keyid); + 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_type(keypair->pubkey->type) == EVP_PKEY_RSA); + assert(keypair->pubkey && EVP_PKEY_base_id(keypair->pubkey) == EVP_PKEY_RSA); ri->keyEncryptionAlgorithm = OBJ_nid2obj(NID_rsaEncryption); /* Encrypt the session key */ @@ -1108,7 +1101,7 @@ CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys) } /* Store it in our ASN.1 structure */ - if (!M_ASN1_OCTET_STRING_set(ri->encryptedKey, ekey, ekey_len)) { + if (!ASN1_OCTET_STRING_set(ri->encryptedKey, ekey, ekey_len)) { /* Allocation failed in OpenSSL */ RecipientInfo_free(ri); crypto_session_free(cs); @@ -1161,11 +1154,7 @@ crypto_error_t crypto_session_decode(const uint8_t *data, uint32_t length, alist X509_KEYPAIR *keypair; STACK_OF(RecipientInfo) *recipients; crypto_error_t retval = CRYPTO_ERROR_NONE; -#if (OPENSSL_VERSION_NUMBER >= 0x0090800FL) const unsigned char *p = (const unsigned char *)data; -#else - unsigned char *p = (unsigned char *)data; -#endif /* bacula-fd.conf doesn't contains any key */ if (!keypairs) { @@ -1206,11 +1195,11 @@ crypto_error_t crypto_session_decode(const uint8_t *data, uint32_t length, alist ri = sk_RecipientInfo_value(recipients, i); /* Match against the subjectKeyIdentifier */ - if (M_ASN1_OCTET_STRING_cmp(keypair->keyid, ri->subjectKeyIdentifier) == 0) { + if (ASN1_OCTET_STRING_cmp(keypair->keyid, ri->subjectKeyIdentifier) == 0) { /* Match found, extract symmetric encryption session data */ - + /* RSA is required. */ - assert(EVP_PKEY_type(keypair->privkey->type) == EVP_PKEY_RSA); + assert(EVP_PKEY_base_id(keypair->privkey) == EVP_PKEY_RSA); /* If we recieve a RecipientInfo structure that does not use * RSA, return an error */ @@ -1222,8 +1211,8 @@ crypto_error_t crypto_session_decode(const uint8_t *data, uint32_t length, alist /* 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, M_ASN1_STRING_data(ri->encryptedKey), - M_ASN1_STRING_length(ri->encryptedKey), 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")); @@ -1271,52 +1260,58 @@ CIPHER_CONTEXT *crypto_cipher_new(CRYPTO_SESSION *cs, bool encrypt, uint32_t *bl const EVP_CIPHER *ec; cipher_ctx = (CIPHER_CONTEXT *)malloc(sizeof(CIPHER_CONTEXT)); + if (!cipher_ctx) + return NULL; + + cipher_ctx->ctx = EVP_CIPHER_CTX_new(); + if (!cipher_ctx->ctx) + goto err; /* * Acquire a cipher instance for the given ASN.1 cipher NID */ if ((ec = EVP_get_cipherbyobj(cs->cryptoData->contentEncryptionAlgorithm)) == NULL) { - Jmsg1(get_jcr_from_tid(), M_ERROR, 0, + Jmsg1(NULL, M_ERROR, 0, _("Unsupported contentEncryptionAlgorithm: %d\n"), OBJ_obj2nid(cs->cryptoData->contentEncryptionAlgorithm)); free(cipher_ctx); return NULL; } /* Initialize the OpenSSL cipher context */ - EVP_CIPHER_CTX_init(&cipher_ctx->ctx); + EVP_CIPHER_CTX_reset(cipher_ctx->ctx); if (encrypt) { /* Initialize for encryption */ - if (!EVP_CipherInit_ex(&cipher_ctx->ctx, ec, NULL, NULL, NULL, 1)) { + if (!EVP_CipherInit_ex(cipher_ctx->ctx, ec, NULL, NULL, NULL, 1)) { openssl_post_errors(M_ERROR, _("OpenSSL cipher context initialization failed")); goto err; } } else { /* Initialize for decryption */ - if (!EVP_CipherInit_ex(&cipher_ctx->ctx, ec, NULL, NULL, NULL, 0)) { + if (!EVP_CipherInit_ex(cipher_ctx->ctx, ec, NULL, NULL, NULL, 0)) { openssl_post_errors(M_ERROR, _("OpenSSL cipher context initialization failed")); goto err; } } /* Set the key size */ - if (!EVP_CIPHER_CTX_set_key_length(&cipher_ctx->ctx, cs->session_key_len)) { + if (!EVP_CIPHER_CTX_set_key_length(cipher_ctx->ctx, cs->session_key_len)) { openssl_post_errors(M_ERROR, _("Encryption session provided an invalid symmetric key")); goto err; } /* Validate the IV length */ - if (EVP_CIPHER_iv_length(ec) != M_ASN1_STRING_length(cs->cryptoData->iv)) { + if (EVP_CIPHER_iv_length(ec) != ASN1_STRING_length(cs->cryptoData->iv)) { openssl_post_errors(M_ERROR, _("Encryption session provided an invalid IV")); goto err; } - + /* Add the key and IV to the cipher context */ - if (!EVP_CipherInit_ex(&cipher_ctx->ctx, NULL, NULL, cs->session_key, M_ASN1_STRING_data(cs->cryptoData->iv), -1)) { + if (!EVP_CipherInit_ex(cipher_ctx->ctx, NULL, NULL, cs->session_key, ASN1_STRING_get0_data(cs->cryptoData->iv), -1)) { openssl_post_errors(M_ERROR, _("OpenSSL cipher context key/IV initialization failed")); goto err; } - *blocksize = EVP_CIPHER_CTX_block_size(&cipher_ctx->ctx); + *blocksize = EVP_CIPHER_CTX_block_size(cipher_ctx->ctx); return cipher_ctx; err: @@ -1332,7 +1327,7 @@ err: */ bool crypto_cipher_update(CIPHER_CONTEXT *cipher_ctx, const uint8_t *data, uint32_t length, const uint8_t *dest, uint32_t *written) { - if (!EVP_CipherUpdate(&cipher_ctx->ctx, (unsigned char *)dest, (int *)written, (const unsigned char *)data, length)) { + if (!EVP_CipherUpdate(cipher_ctx->ctx, (unsigned char *)dest, (int *)written, (const unsigned char *)data, length)) { /* This really shouldn't fail */ return false; } else { @@ -1350,7 +1345,7 @@ bool crypto_cipher_update(CIPHER_CONTEXT *cipher_ctx, const uint8_t *data, uint3 */ bool crypto_cipher_finalize (CIPHER_CONTEXT *cipher_ctx, uint8_t *dest, uint32_t *written) { - if (!EVP_CipherFinal_ex(&cipher_ctx->ctx, (unsigned char *)dest, (int *) written)) { + if (!EVP_CipherFinal_ex(cipher_ctx->ctx, (unsigned char *)dest, (int *) written)) { /* This really shouldn't fail */ return false; } else { @@ -1364,83 +1359,10 @@ bool crypto_cipher_finalize (CIPHER_CONTEXT *cipher_ctx, uint8_t *dest, uint32_t */ void crypto_cipher_free (CIPHER_CONTEXT *cipher_ctx) { - EVP_CIPHER_CTX_cleanup(&cipher_ctx->ctx); + EVP_CIPHER_CTX_free(cipher_ctx->ctx); free (cipher_ctx); } - -/* - * Perform global initialization of OpenSSL - * This function is not thread safe. - * Returns: 0 on success - * errno on failure - */ -int init_crypto (void) -{ - int stat; - - if ((stat = openssl_init_threads()) != 0) { - berrno be; - Jmsg1(get_jcr_from_tid(), M_ABORT, 0, - _("Unable to init OpenSSL threading: ERR=%s\n"), be.bstrerror(stat)); - } - - /* Load libssl and libcrypto human-readable error strings */ - SSL_load_error_strings(); - - /* Initialize OpenSSL SSL library */ - SSL_library_init(); - - /* Register OpenSSL ciphers and digests */ - OpenSSL_add_all_algorithms(); - - if (!openssl_seed_prng()) { - Jmsg0(get_jcr_from_tid(), M_ERROR_TERM, 0, _("Failed to seed OpenSSL PRNG\n")); - } - - crypto_initialized = true; - - return stat; -} - -/* - * Perform global cleanup of OpenSSL - * All cryptographic operations must be completed before calling this function. - * This function is not thread safe. - * Returns: 0 on success - * errno on failure - */ -int cleanup_crypto (void) -{ - /* - * Ensure that we've actually been initialized; Doing this here decreases the - * complexity of client's termination/cleanup code. - */ - if (!crypto_initialized) { - return 0; - } - - if (!openssl_save_prng()) { - Jmsg0(get_jcr_from_tid(), M_ERROR, 0, _("Failed to save OpenSSL PRNG\n")); - } - - openssl_cleanup_threads(); - - /* Free libssl and libcrypto error strings */ - ERR_free_strings(); - - /* Free all ciphers and digests */ - EVP_cleanup(); - - /* Free memory used by PRNG */ - RAND_cleanup(); - - crypto_initialized = false; - - return 0; -} - - #else /* HAVE_OPENSSL */ # error No encryption library available #endif /* HAVE_OPENSSL */ @@ -1502,7 +1424,7 @@ bool crypto_digest_update(DIGEST *digest, const uint8_t *data, uint32_t length) if ((ret = SHA1Update(&digest->sha1, (const u_int8_t *) data, length)) == shaSuccess) { return true; } else { - Jmsg1(get_jcr_from_tid(), M_ERROR, 0, _("SHA1Update() returned an error: %d\n"), ret); + Jmsg1(NULL, M_ERROR, 0, _("SHA1Update() returned an error: %d\n"), ret); return false; } break; @@ -1511,7 +1433,7 @@ bool crypto_digest_update(DIGEST *digest, const uint8_t *data, uint32_t length) } } -bool crypto_digest_finalize(DIGEST *digest, uint8_t *dest, uint32_t *length) +bool crypto_digest_finalize(DIGEST *digest, uint8_t *dest, uint32_t *length) { switch (digest->type) { case CRYPTO_DIGEST_MD5: @@ -1545,13 +1467,12 @@ void crypto_digest_free(DIGEST *digest) free(digest); } -/* Dummy routines */ -int init_crypto (void) { return 0; } -int cleanup_crypto (void) { return 0; } - SIGNATURE *crypto_sign_new(JCR *jcr) { return NULL; } -crypto_error_t crypto_sign_get_digest (SIGNATURE *sig, X509_KEYPAIR *keypair, DIGEST **digest) { return CRYPTO_ERROR_INTERNAL; } +crypto_error_t crypto_sign_get_digest (SIGNATURE *sig, X509_KEYPAIR *keypair, + crypto_digest_t &type, DIGEST **digest) + { return CRYPTO_ERROR_INTERNAL; } + crypto_error_t crypto_sign_verify (SIGNATURE *sig, X509_KEYPAIR *keypair, DIGEST *digest) { return CRYPTO_ERROR_INTERNAL; } int crypto_sign_add_signer (SIGNATURE *sig, DIGEST *digest, X509_KEYPAIR *keypair) { return false; } @@ -1596,7 +1517,7 @@ int crypto_default_pem_callback(char *buf, int size, const void *userdata) * Returns the ASCII name of the digest type. * Returns: ASCII name of digest type. */ -const char *crypto_digest_name(DIGEST *digest) +const char *crypto_digest_name(DIGEST *digest) { switch (digest->type) { case CRYPTO_DIGEST_MD5: