diff --git a/apps/include/opt.h b/apps/include/opt.h index c8024975b2d5069f2f8186796a0972ec34c22ece..f9ac5accae195219207b2daed1a212b187473195 100644 --- a/apps/include/opt.h +++ b/apps/include/opt.h @@ -368,7 +368,9 @@ int opt_umax(const char *arg, uintmax_t *result); int opt_pair(const char *arg, const OPT_PAIR * pairs, int *result); int opt_string(const char *name, const char **options); int opt_cipher(const char *name, EVP_CIPHER **cipherp); +int opt_cipher_silent(const char *name, EVP_CIPHER **cipherp); int opt_md(const char *name, EVP_MD **mdp); +int opt_md_silent(const char *name, EVP_MD **mdp); char *opt_name(void); char *opt_arg(void); char *opt_flag(void); diff --git a/apps/lib/opt.c b/apps/lib/opt.c index 0c7405a92158aa76820863c8aa21cecf706868e2..83ae28cdc1e8ccd97e7f91e8d77b862497b40ca6 100644 --- a/apps/lib/opt.c +++ b/apps/lib/opt.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -359,34 +360,56 @@ void print_format_error(int format, unsigned long flags) } /* Parse a cipher name, put it in *EVP_CIPHER; return 0 on failure, else 1. */ -int opt_cipher(const char *name, EVP_CIPHER **cipherp) +int opt_cipher_silent(const char *name, EVP_CIPHER **cipherp) { - *cipherp = EVP_CIPHER_fetch(NULL, name, NULL); - if (*cipherp != NULL) - return 1; - *cipherp = (EVP_CIPHER *)EVP_get_cipherbyname(name); - if (*cipherp != NULL) + EVP_CIPHER_free(*cipherp); + + ERR_set_mark(); + if ((*cipherp = EVP_CIPHER_fetch(NULL, name, NULL)) != NULL + || (*cipherp = (EVP_CIPHER *)EVP_get_cipherbyname(name)) != NULL) { + ERR_pop_to_mark(); return 1; - opt_printf_stderr("%s: Unknown cipher: %s\n", prog, name); + } + ERR_clear_last_mark(); return 0; } +int opt_cipher(const char *name, EVP_CIPHER **cipherp) +{ + int ret; + + if ((ret = opt_cipher_silent(name, cipherp)) == 0) + opt_printf_stderr("%s: Unknown cipher: %s\n", prog, name); + return ret; +} + /* * Parse message digest name, put it in *EVP_MD; return 0 on failure, else 1. */ -int opt_md(const char *name, EVP_MD **mdp) +int opt_md_silent(const char *name, EVP_MD **mdp) { - *mdp = (EVP_MD *)EVP_get_digestbyname(name); - if (*mdp != NULL) - return 1; - *mdp = EVP_MD_fetch(NULL, name, NULL); - if (*mdp != NULL) + EVP_MD_free(*mdp); + + ERR_set_mark(); + if ((*mdp = EVP_MD_fetch(NULL, name, NULL)) != NULL + || (*mdp = (EVP_MD *)EVP_get_digestbyname(name)) != NULL) { + ERR_pop_to_mark(); return 1; - opt_printf_stderr("%s: Unknown option or message digest: %s\n", prog, - name != NULL ? name : "\"\""); + } + ERR_clear_last_mark(); return 0; } +int opt_md(const char *name, EVP_MD **mdp) +{ + int ret; + + if ((ret = opt_md_silent(name, mdp)) == 0) + opt_printf_stderr("%s: Unknown option or message digest: %s\n", prog, + name != NULL ? name : "\"\""); + return ret; +} + /* Look through a list of name/value pairs. */ int opt_pair(const char *name, const OPT_PAIR* pairs, int *result) { diff --git a/apps/req.c b/apps/req.c index 4e1cae6ba6d31f474b936a4c23f7a681c94222c6..89bde55b93d19eca45f859b3cfbc956eefd4390f 100644 --- a/apps/req.c +++ b/apps/req.c @@ -240,7 +240,7 @@ int req_main(int argc, char **argv) X509 *new_x509 = NULL, *CAcert = NULL; X509_REQ *req = NULL; EVP_CIPHER *cipher = NULL; - EVP_MD *md_alg = NULL, *digest = NULL; + EVP_MD *digest = NULL; int ext_copy = EXT_COPY_UNSET; BIO *addext_bio = NULL; char *extensions = NULL; @@ -482,9 +482,8 @@ int req_main(int argc, char **argv) goto end; if (digestname != NULL) { - if (!opt_md(digestname, &md_alg)) + if (!opt_md(digestname, &digest)) goto opthelp; - digest = md_alg; } if (!gen_x509) { @@ -536,14 +535,13 @@ int req_main(int argc, char **argv) if (!add_oid_section(req_conf)) goto end; - if (md_alg == NULL) { + if (digest == NULL) { p = NCONF_get_string(req_conf, section, "default_md"); if (p == NULL) { ERR_clear_error(); } else { - if (!opt_md(p, &md_alg)) + if (!opt_md(p, &digest)) goto opthelp; - digest = md_alg; } } @@ -1058,7 +1056,6 @@ int req_main(int argc, char **argv) BIO_free(addext_bio); BIO_free_all(out); EVP_PKEY_free(pkey); - EVP_MD_free(md_alg); EVP_MD_free(digest); EVP_PKEY_CTX_free(genctx); sk_OPENSSL_STRING_free(pkeyopts); diff --git a/apps/speed.c b/apps/speed.c index 939baf934d86fc56745bc6648fad860bfc74b0d8..5363b0d7f83158daeb08b24c76157ec25ad465e4 100644 --- a/apps/speed.c +++ b/apps/speed.c @@ -502,73 +502,35 @@ static const char *evp_md_name = NULL; static char *evp_mac_ciphername = "aes-128-cbc"; static char *evp_cmac_name = NULL; -static EVP_MD *obtain_md(const char *name, int *fetched) -{ - EVP_MD *md = NULL; - - *fetched = 0; - /* Look through providers' digests */ - ERR_set_mark(); - md = EVP_MD_fetch(NULL, name, NULL); - ERR_pop_to_mark(); - if (md != NULL) { - *fetched = 1; - return md; - } - - return (EVP_MD *)EVP_get_digestbyname(name); -} - static int have_md(const char *name) { - int fetched = 0; int ret = 0; - EVP_MD *md = obtain_md(name, &fetched); + EVP_MD *md = NULL; - if (md != NULL) { + if (opt_md_silent(name, &md)) { EVP_MD_CTX *ctx = EVP_MD_CTX_new(); if (ctx != NULL && EVP_DigestInit(ctx, md) > 0) ret = 1; EVP_MD_CTX_free(ctx); - if (fetched) - EVP_MD_free(md); + EVP_MD_free(md); } return ret; } -static EVP_CIPHER *obtain_cipher(const char *name, int *fetched) -{ - EVP_CIPHER *cipher = NULL; - - *fetched = 0; - /* Look through providers' digests */ - ERR_set_mark(); - cipher = EVP_CIPHER_fetch(NULL, name, NULL); - ERR_pop_to_mark(); - if (cipher != NULL) { - *fetched = 1; - return cipher; - } - - return (EVP_CIPHER *)EVP_get_cipherbyname(name); -} - static int have_cipher(const char *name) { - int fetched = 0; int ret = 0; - EVP_CIPHER *cipher = obtain_cipher(name, &fetched); + EVP_CIPHER *cipher = NULL; - if (cipher != NULL) { + if (opt_cipher_silent(name, &cipher)) { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); if (ctx != NULL && EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, 1) > 0) ret = 1; EVP_CIPHER_CTX_free(ctx); - if (fetched) - EVP_CIPHER_free(cipher); + EVP_CIPHER_free(cipher); } return ret; } @@ -578,10 +540,10 @@ static int EVP_Digest_loop(const char *mdname, int algindex, void *args) loopargs_t *tempargs = *(loopargs_t **) args; unsigned char *buf = tempargs->buf; unsigned char digest[EVP_MAX_MD_SIZE]; - int count, fetched = 0; - EVP_MD *md = obtain_md(mdname, &fetched); + int count; + EVP_MD *md = NULL; - if (md == NULL) + if (!opt_md_silent(mdname, &md)) return -1; for (count = 0; COND(c[algindex][testnum]); count++) { if (!EVP_Digest(buf, (size_t)lengths[testnum], digest, NULL, md, @@ -590,8 +552,7 @@ static int EVP_Digest_loop(const char *mdname, int algindex, void *args) break; } } - if (fetched) - EVP_MD_free(md); + EVP_MD_free(md); return count; } @@ -714,10 +675,9 @@ static EVP_CIPHER_CTX *init_evp_cipher_ctx(const char *ciphername, int keylen) { EVP_CIPHER_CTX *ctx = NULL; - int fetched = 0; - EVP_CIPHER *cipher = obtain_cipher(ciphername, &fetched); + EVP_CIPHER *cipher = NULL; - if (cipher == NULL) + if (!opt_cipher_silent(ciphername, &cipher)) return NULL; if ((ctx = EVP_CIPHER_CTX_new()) == NULL) @@ -742,8 +702,7 @@ static EVP_CIPHER_CTX *init_evp_cipher_ctx(const char *ciphername, } end: - if (fetched) - EVP_CIPHER_free(cipher); + EVP_CIPHER_free(cipher); return ctx; } @@ -1388,7 +1347,6 @@ int speed_main(int argc, char **argv) unsigned int i, k, loopargs_len = 0, async_jobs = 0; int keylen; int buflen; - int fetched_cipher = 0; BIGNUM *bn = NULL; EVP_PKEY_CTX *genctx = NULL; #ifndef NO_FORK @@ -1533,17 +1491,19 @@ int speed_main(int argc, char **argv) BIO_printf(bio_err, "%s: -evp option cannot be used more than once\n", prog); goto opterr; } - evp_cipher = obtain_cipher(opt_arg(), &fetched_cipher); - if (evp_cipher == NULL) { + ERR_set_mark(); + if (!opt_cipher_silent(opt_arg(), &evp_cipher)) { if (have_md(opt_arg())) evp_md_name = opt_arg(); } if (evp_cipher == NULL && evp_md_name == NULL) { + ERR_clear_last_mark(); BIO_printf(bio_err, "%s: %s is an unknown cipher or digest\n", prog, opt_arg()); goto end; } + ERR_pop_to_mark(); doit[D_EVP] = 1; break; case OPT_HMAC: @@ -2294,17 +2254,15 @@ int speed_main(int argc, char **argv) if (doit[D_EVP_CMAC]) { EVP_MAC *mac = EVP_MAC_fetch(NULL, "CMAC", NULL); OSSL_PARAM params[3]; - EVP_CIPHER *cipher; - int fetched = 0; + EVP_CIPHER *cipher = NULL; if (mac == NULL || evp_mac_ciphername == NULL) goto end; - if ((cipher = obtain_cipher(evp_mac_ciphername, &fetched)) == NULL) + if (!opt_cipher(evp_mac_ciphername, &cipher)) goto end; keylen = EVP_CIPHER_key_length(cipher); - if (fetched) - EVP_CIPHER_free(cipher); + EVP_CIPHER_free(cipher); if (keylen <= 0 || keylen > (int)sizeof(key32)) { BIO_printf(bio_err, "\nRequested CMAC cipher with unsupported key length.\n"); goto end; @@ -3360,9 +3318,7 @@ int speed_main(int argc, char **argv) } OPENSSL_free(loopargs); release_engine(e); - if (fetched_cipher) { - EVP_CIPHER_free(evp_cipher); - } + EVP_CIPHER_free(evp_cipher); return ret; } diff --git a/crypto/crmf/crmf_lib.c b/crypto/crmf/crmf_lib.c index 6cea644cfc1d813a472874c48ed3147dfdaf8fa4..e26637d0a43442b857cce8f931c99cbd46e51304 100644 --- a/crypto/crmf/crmf_lib.c +++ b/crypto/crmf/crmf_lib.c @@ -30,6 +30,7 @@ #include "crmf_local.h" #include "internal/constant_time.h" +#include "internal/sizes.h" /* explicit #includes not strictly needed since implied by the above: */ #include @@ -589,24 +590,37 @@ X509 EVP_CIPHER_CTX *evp_ctx = NULL; /* context for symmetric encryption */ unsigned char *ek = NULL; /* decrypted symmetric encryption key */ size_t eksize = 0; /* size of decrypted symmetric encryption key */ - const EVP_CIPHER *cipher = NULL; /* used cipher */ + EVP_CIPHER *cipher = NULL; /* used cipher */ int cikeysize = 0; /* key size from cipher */ unsigned char *iv = NULL; /* initial vector for symmetric encryption */ unsigned char *outbuf = NULL; /* decryption output buffer */ const unsigned char *p = NULL; /* needed for decoding ASN1 */ int n, outlen = 0; EVP_PKEY_CTX *pkctx = NULL; /* private key context */ + char name[OSSL_MAX_NAME_SIZE]; if (ecert == NULL || ecert->symmAlg == NULL || ecert->encSymmKey == NULL || ecert->encValue == NULL || pkey == NULL) { ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT); return NULL; } + /* select symmetric cipher based on algorithm given in message */ - if ((cipher = EVP_get_cipherbyobj(ecert->symmAlg->algorithm)) == NULL) { + OBJ_obj2txt(name, sizeof(name), ecert->symmAlg->algorithm, 0); + + (void)ERR_set_mark(); + cipher = EVP_CIPHER_fetch(NULL, name, NULL); + + if (cipher == NULL) + cipher = (EVP_CIPHER *)EVP_get_cipherbyname(name); + + if (cipher == NULL) { + (void)ERR_clear_last_mark(); ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_CIPHER); goto end; } + (void)ERR_pop_to_mark(); + cikeysize = EVP_CIPHER_key_length(cipher); /* first the symmetric key needs to be decrypted */ pkctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq); @@ -670,6 +684,7 @@ X509 EVP_PKEY_CTX_free(pkctx); OPENSSL_free(outbuf); EVP_CIPHER_CTX_free(evp_ctx); + EVP_CIPHER_free(cipher); OPENSSL_clear_free(ek, eksize); OPENSSL_free(iv); return cert; diff --git a/crypto/ess/ess_lib.c b/crypto/ess/ess_lib.c index ebfe5b93c7f053dbe6817f6711b08d9176808b69..6ded9f6328f2d41e54fbcd87d4adf387bcb09b96 100644 --- a/crypto/ess/ess_lib.c +++ b/crypto/ess/ess_lib.c @@ -11,6 +11,7 @@ #include #include #include +#include "internal/sizes.h" #include "crypto/ess.h" #include "crypto/x509.h" @@ -302,36 +303,48 @@ static int find(const ESS_CERT_ID *cid, const ESS_CERT_ID_V2 *cid_v2, int index, const STACK_OF(X509) *certs) { const X509 *cert; - const EVP_MD *md; + EVP_MD *md = NULL; + char name[OSSL_MAX_NAME_SIZE]; unsigned char cert_digest[EVP_MAX_MD_SIZE]; unsigned int len, cid_hash_len; const ESS_ISSUER_SERIAL *is; int i; + int ret = -1; if (cid == NULL && cid_v2 == NULL) { ERR_raise(ERR_LIB_ESS, ERR_R_PASSED_INVALID_ARGUMENT); return -1; } + if (cid != NULL) + strcpy(name, "SHA1"); + else if (cid_v2->hash_alg == NULL) + strcpy(name, "SHA256"); + else + OBJ_obj2txt(name, sizeof(name), cid_v2->hash_alg->algorithm, 0); + + (void)ERR_set_mark(); + md = EVP_MD_fetch(NULL, name, NULL); + + if (md == NULL) + md = (EVP_MD *)EVP_get_digestbyname(name); + + if (md == NULL) { + (void)ERR_clear_last_mark(); + ERR_raise(ERR_LIB_ESS, ESS_R_ESS_DIGEST_ALG_UNKNOWN); + goto end; + } + (void)ERR_pop_to_mark(); + /* Look for cert with cid in the certs. */ for (i = 0; i < sk_X509_num(certs); ++i) { cert = sk_X509_value(certs, i); - if (cid != NULL) - md = EVP_sha1(); - else - md = cid_v2->hash_alg == NULL ? EVP_sha256() : - EVP_get_digestbyobj(cid_v2->hash_alg->algorithm); - if (md == NULL) { - ERR_raise(ERR_LIB_ESS, ESS_R_ESS_DIGEST_ALG_UNKNOWN); - return -1; - } - cid_hash_len = cid != NULL ? cid->hash->length : cid_v2->hash->length; if (!X509_digest(cert, md, cert_digest, &len) || cid_hash_len != len) { ERR_raise(ERR_LIB_ESS, ESS_R_ESS_CERT_DIGEST_ERROR); - return -1; + goto end; } if (memcmp(cid != NULL ? cid->hash->data : cid_v2->hash->data, @@ -339,16 +352,21 @@ static int find(const ESS_CERT_ID *cid, const ESS_CERT_ID_V2 *cid_v2, is = cid != NULL ? cid->issuer_serial : cid_v2->issuer_serial; /* Well, it's not really required to match the serial numbers. */ if (is == NULL || ess_issuer_serial_cmp(is, cert) == 0) { - if ((i == 0) == (index == 0)) - return i + 1; + if ((i == 0) == (index == 0)) { + ret = i + 1; + goto end; + } ERR_raise(ERR_LIB_ESS, ESS_R_ESS_CERT_ID_WRONG_ORDER); - return -1; + goto end; } } } + ret = 0; ERR_raise(ERR_LIB_ESS, ESS_R_ESS_CERT_ID_NOT_FOUND); - return 0; +end: + EVP_MD_free(md); + return ret; } /* diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c index 02af58437c09306e23342b1847c6f6a94def25e5..4231c3f2b288fb3740ab017be3d4bf767d8d64d4 100644 --- a/crypto/ocsp/ocsp_vfy.c +++ b/crypto/ocsp/ocsp_vfy.c @@ -7,10 +7,11 @@ * https://www.openssl.org/source/license.html */ +#include #include -#include "ocsp_local.h" #include -#include +#include "internal/sizes.h" +#include "ocsp_local.h" static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs, unsigned long flags); @@ -302,42 +303,56 @@ static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret) static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, STACK_OF(OCSP_SINGLERESP) *sresp) { + int ret = -1; + EVP_MD *dgst = NULL; + /* If only one ID to match then do it */ if (cid != NULL) { - const EVP_MD *dgst = EVP_get_digestbyobj(cid->hashAlgorithm.algorithm); + char name[OSSL_MAX_NAME_SIZE]; const X509_NAME *iname; int mdlen; unsigned char md[EVP_MAX_MD_SIZE]; + OBJ_obj2txt(name, sizeof(name), cid->hashAlgorithm.algorithm, 0); + + (void)ERR_set_mark(); + dgst = EVP_MD_fetch(NULL, name, NULL); + if (dgst == NULL) + dgst = (EVP_MD *)EVP_get_digestbyname(name); + if (dgst == NULL) { + (void)ERR_clear_last_mark(); ERR_raise(ERR_LIB_OCSP, OCSP_R_UNKNOWN_MESSAGE_DIGEST); - return -1; + goto end; } + (void)ERR_pop_to_mark(); mdlen = EVP_MD_size(dgst); if (mdlen < 0) { ERR_raise(ERR_LIB_OCSP, OCSP_R_DIGEST_SIZE_ERR); - return -1; + goto end; } if (cid->issuerNameHash.length != mdlen || - cid->issuerKeyHash.length != mdlen) - return 0; + cid->issuerKeyHash.length != mdlen) { + ret = 0; + goto end; + } iname = X509_get_subject_name(cert); - if (!X509_NAME_digest(iname, dgst, md, NULL)) { - ERR_raise(ERR_LIB_OCSP, OCSP_R_DIGEST_NAME_ERR); - return -1; + if (!X509_NAME_digest(iname, dgst, md, NULL)) + goto end; + if (memcmp(md, cid->issuerNameHash.data, mdlen) != 0) { + ret = 0; + goto end; } - if (memcmp(md, cid->issuerNameHash.data, mdlen) != 0) - return 0; if (!X509_pubkey_digest(cert, dgst, md, NULL)) { ERR_raise(ERR_LIB_OCSP, OCSP_R_DIGEST_ERR); - return -1; + goto end; } - if (memcmp(md, cid->issuerKeyHash.data, mdlen) != 0) - return 0; + ret = memcmp(md, cid->issuerKeyHash.data, mdlen) == 0; + goto end; } else { /* We have to match the whole lot */ - int i, ret; + int i; OCSP_CERTID *tmpid; for (i = 0; i < sk_OCSP_SINGLERESP_num(sresp); i++) { @@ -348,6 +363,9 @@ static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, } } return 1; +end: + EVP_MD_free(dgst); + return ret; } static int ocsp_check_delegated(X509 *x) diff --git a/crypto/ts/ts_rsp_verify.c b/crypto/ts/ts_rsp_verify.c index f307e29fda8d51b07049956f914be1f452119f01..09daa2a449c97d53d3a14dc0185e02e9b107eb96 100644 --- a/crypto/ts/ts_rsp_verify.c +++ b/crypto/ts/ts_rsp_verify.c @@ -8,12 +8,13 @@ */ #include -#include "internal/cryptlib.h" #include #include #include -#include "ts_local.h" +#include "internal/cryptlib.h" +#include "internal/sizes.h" #include "crypto/ess.h" +#include "ts_local.h" static int ts_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted, X509 *signer, STACK_OF(X509) **chain); @@ -395,9 +396,10 @@ static int ts_compute_imprint(BIO *data, TS_TST_INFO *tst_info, { TS_MSG_IMPRINT *msg_imprint = tst_info->msg_imprint; X509_ALGOR *md_alg_resp = msg_imprint->hash_algo; - const EVP_MD *md; + EVP_MD *md = NULL; EVP_MD_CTX *md_ctx = NULL; unsigned char buffer[4096]; + char name[OSSL_MAX_NAME_SIZE]; int length; *md_alg = NULL; @@ -405,10 +407,21 @@ static int ts_compute_imprint(BIO *data, TS_TST_INFO *tst_info, if ((*md_alg = X509_ALGOR_dup(md_alg_resp)) == NULL) goto err; - if ((md = EVP_get_digestbyobj((*md_alg)->algorithm)) == NULL) { - ERR_raise(ERR_LIB_TS, TS_R_UNSUPPORTED_MD_ALGORITHM); + + OBJ_obj2txt(name, sizeof(name), md_alg_resp->algorithm, 0); + + (void)ERR_set_mark(); + md = EVP_MD_fetch(NULL, name, NULL); + + if (md == NULL) + md = (EVP_MD *)EVP_get_digestbyname(name); + + if (md == NULL) { + (void)ERR_clear_last_mark(); goto err; } + (void)ERR_pop_to_mark(); + length = EVP_MD_size(md); if (length < 0) goto err; @@ -425,6 +438,8 @@ static int ts_compute_imprint(BIO *data, TS_TST_INFO *tst_info, } if (!EVP_DigestInit(md_ctx, md)) goto err; + EVP_MD_free(md); + md = NULL; while ((length = BIO_read(data, buffer, sizeof(buffer))) > 0) { if (!EVP_DigestUpdate(md_ctx, buffer, length)) goto err; @@ -436,6 +451,7 @@ static int ts_compute_imprint(BIO *data, TS_TST_INFO *tst_info, return 1; err: EVP_MD_CTX_free(md_ctx); + EVP_MD_free(md); X509_ALGOR_free(*md_alg); *md_alg = NULL; OPENSSL_free(*imprint);