提交 eaf8a40d 编写于 作者: T Tomas Mraz

Prefer fetch over legacy get_digestby/get_cipherby

Fixes #14198
Reviewed-by: NRichard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15028)
上级 c0a79e98
......@@ -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);
......
......@@ -22,6 +22,7 @@
#include <errno.h>
#include <ctype.h>
#include <limits.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/x509v3.h>
......@@ -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)
{
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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 <openssl/crmf.h>
......@@ -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;
......
......@@ -11,6 +11,7 @@
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/ess.h>
#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;
}
/*
......
......@@ -7,10 +7,11 @@
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/ocsp.h>
#include "ocsp_local.h"
#include <openssl/err.h>
#include <string.h>
#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)
......
......@@ -8,12 +8,13 @@
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/objects.h>
#include <openssl/ts.h>
#include <openssl/pkcs7.h>
#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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册