From be6aeda6474a77e97b344f300334f5fe3612e4b4 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Fri, 20 Mar 2020 14:54:55 +0000 Subject: [PATCH] Add OCSP_RESPID_set_by_key_ex() and OCSP_RESPID_match_ex() OCSP_RESPID_set_by_key() calculates a SHA1 hash of the supplied certificate. We need to be able to specify which libctx and property query string is used to fetch that algorithm so we introduce OCSP_RESPID_set_by_key_ex() which does the same thing but enables you to speicfy the library context and propery query string explicitly. OCSP_RESPID_match() matches with certificates based on the SHA1 hash. Therefore for the same reason we introduce OCSP_RESPID_match_ex(). Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/11407) --- crypto/ocsp/ocsp_srv.c | 57 ++++++++++++++++++------ doc/man3/OCSP_response_status.pod | 72 +++++++++++++++++++------------ include/openssl/ocsp.h | 4 ++ util/libcrypto.num | 2 + 4 files changed, 93 insertions(+), 42 deletions(-) diff --git a/crypto/ocsp/ocsp_srv.c b/crypto/ocsp/ocsp_srv.c index 7e0aca169b..051747b445 100644 --- a/crypto/ocsp/ocsp_srv.c +++ b/crypto/ocsp/ocsp_srv.c @@ -259,45 +259,67 @@ int OCSP_RESPID_set_by_name(OCSP_RESPID *respid, X509 *cert) return 1; } -int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert) +int OCSP_RESPID_set_by_key_ex(OCSP_RESPID *respid, X509 *cert, + OPENSSL_CTX *libctx, const char *propq) { ASN1_OCTET_STRING *byKey = NULL; unsigned char md[SHA_DIGEST_LENGTH]; + EVP_MD *sha1 = EVP_MD_fetch(libctx, "SHA1", propq); + int ret = 0; - /* RFC2560 requires SHA1 */ - if (!X509_pubkey_digest(cert, EVP_sha1(), md, NULL)) + if (sha1 == NULL) return 0; + /* RFC2560 requires SHA1 */ + if (!X509_pubkey_digest(cert, sha1, md, NULL)) + goto err; + byKey = ASN1_OCTET_STRING_new(); if (byKey == NULL) - return 0; + goto err; if (!(ASN1_OCTET_STRING_set(byKey, md, SHA_DIGEST_LENGTH))) { ASN1_OCTET_STRING_free(byKey); - return 0; + goto err; } respid->type = V_OCSP_RESPID_KEY; respid->value.byKey = byKey; - return 1; + ret = 1; + err: + EVP_MD_free(sha1); + return ret; } -int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert) +int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert) { + return OCSP_RESPID_set_by_key_ex(respid, cert, NULL, NULL); +} + +int OCSP_RESPID_match_ex(OCSP_RESPID *respid, X509 *cert, OPENSSL_CTX *libctx, + const char *propq) +{ + EVP_MD *sha1 = NULL; + int ret = 0; + if (respid->type == V_OCSP_RESPID_KEY) { unsigned char md[SHA_DIGEST_LENGTH]; + sha1 = EVP_MD_fetch(libctx, "SHA1", propq); + if (sha1 == NULL) + goto err; + if (respid->value.byKey == NULL) - return 0; + goto err; /* RFC2560 requires SHA1 */ - if (!X509_pubkey_digest(cert, EVP_sha1(), md, NULL)) - return 0; + if (!X509_pubkey_digest(cert, sha1, md, NULL)) + goto err; - return (ASN1_STRING_length(respid->value.byKey) == SHA_DIGEST_LENGTH) - && (memcmp(ASN1_STRING_get0_data(respid->value.byKey), md, - SHA_DIGEST_LENGTH) == 0); + ret = (ASN1_STRING_length(respid->value.byKey) == SHA_DIGEST_LENGTH) + && (memcmp(ASN1_STRING_get0_data(respid->value.byKey), md, + SHA_DIGEST_LENGTH) == 0); } else if (respid->type == V_OCSP_RESPID_NAME) { if (respid->value.byName == NULL) return 0; @@ -306,5 +328,12 @@ int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert) X509_get_subject_name(cert)) == 0; } - return 0; + err: + EVP_MD_free(sha1); + return ret; +} + +int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert) +{ + return OCSP_RESPID_match_ex(respid, cert, NULL, NULL); } diff --git a/doc/man3/OCSP_response_status.pod b/doc/man3/OCSP_response_status.pod index c1de86b199..6c02b55fa1 100644 --- a/doc/man3/OCSP_response_status.pod +++ b/doc/man3/OCSP_response_status.pod @@ -4,8 +4,9 @@ OCSP_response_status, OCSP_response_get1_basic, OCSP_response_create, OCSP_RESPONSE_free, OCSP_RESPID_set_by_name, -OCSP_RESPID_set_by_key, OCSP_RESPID_match, -OCSP_basic_sign, OCSP_basic_sign_ctx - OCSP response functions +OCSP_RESPID_set_by_key_ex, OCSP_RESPID_set_by_key, OCSP_RESPID_match_ex, +OCSP_RESPID_match, OCSP_basic_sign, OCSP_basic_sign_ctx +- OCSP response functions =head1 SYNOPSIS @@ -17,7 +18,11 @@ OCSP_basic_sign, OCSP_basic_sign_ctx - OCSP response functions void OCSP_RESPONSE_free(OCSP_RESPONSE *resp); int OCSP_RESPID_set_by_name(OCSP_RESPID *respid, X509 *cert); + int OCSP_RESPID_set_by_key_ex(OCSP_RESPID *respid, X509 *cert, + OPENSSL_CTX *libctx, const char *propq); int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert); + int OCSP_RESPID_match_ex(OCSP_RESPID *respid, X509 *cert, OPENSSL_CTX *libctx, + const char *propq); int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert); int OCSP_basic_sign(OCSP_BASICRESP *brsp, X509 *signer, EVP_PKEY *key, @@ -28,49 +33,60 @@ OCSP_basic_sign, OCSP_basic_sign_ctx - OCSP response functions =head1 DESCRIPTION -OCSP_response_status() returns the OCSP response status of B. It returns -one of the values: B, -B, -B, B -B, or B. +OCSP_response_status() returns the OCSP response status of I. It returns +one of the values: I, +I, +I, I +I, or I. -OCSP_response_get1_basic() decodes and returns the B structure -contained in B. +OCSP_response_get1_basic() decodes and returns the I structure +contained in I. -OCSP_response_create() creates and returns an B structure for -B and optionally including basic response B. +OCSP_response_create() creates and returns an I structure for +I and optionally including basic response I. -OCSP_RESPONSE_free() frees up OCSP response B. +OCSP_RESPONSE_free() frees up OCSP response I. OCSP_RESPID_set_by_name() sets the name of the OCSP_RESPID to be the same as the -subject name in the supplied X509 certificate B for the OCSP responder. +subject name in the supplied X509 certificate I for the OCSP responder. -OCSP_RESPID_set_by_key() sets the key of the OCSP_RESPID to be the same as the -key in the supplied X509 certificate B for the OCSP responder. The key is -stored as a SHA1 hash. +OCSP_RESPID_set_by_key_ex() sets the key of the OCSP_RESPID to be the same as the +key in the supplied X509 certificate I for the OCSP responder. The key is +stored as a SHA1 hash. To calculate the hash the SHA1 algorithm is fetched using +the library ctx I and the property query string I (see +L for further information). + +OCSP_RESPID_set_by_key() does the same as OCSP_RESPID_set_by_key_ex() except +that the default library context is used with an empty property query string. Note that an OCSP_RESPID can only have one of the name, or the key set. Calling OCSP_RESPID_set_by_name() or OCSP_RESPID_set_by_key() will clear any existing setting. -OCSP_RESPID_match() tests whether the OCSP_RESPID given in B matches -with the X509 certificate B. +OCSP_RESPID_match_ex() tests whether the OCSP_RESPID given in I matches +with the X509 certificate I based on the SHA1 hash. To calculate the hash +the SHA1 algorithm is fetched using the library ctx I and the property +query string I (see L for further +information). + +OCSP_RESPID_match() does the same as OCSP_RESPID_match_ex() except that the +default library context is used with an empty property query string. -OCSP_basic_sign() signs OCSP response B using certificate B, private key -B, digest B and additional certificates B. If the B option -B is set then no certificates will be included in the response. If the -B option B is set then the responder is identified by key ID -rather than by name. OCSP_basic_sign_ctx() also signs OCSP response B but -uses the parameters contained in digest context B. +OCSP_basic_sign() signs OCSP response I using certificate I, private key +I, digest I and additional certificates I. If the I option +I is set then no certificates will be included in the response. If the +I option I is set then the responder is identified by key ID +rather than by name. OCSP_basic_sign_ctx() also signs OCSP response I but +uses the parameters contained in digest context I. =head1 RETURN VALUES OCSP_RESPONSE_status() returns a status value. -OCSP_response_get1_basic() returns an B structure pointer or -B if an error occurred. +OCSP_response_get1_basic() returns an I structure pointer or +I if an error occurred. -OCSP_response_create() returns an B structure pointer or B +OCSP_response_create() returns an I structure pointer or I if an error occurred. OCSP_RESPONSE_free() does not return a value. @@ -85,7 +101,7 @@ or 0 otherwise. =head1 NOTES OCSP_response_get1_basic() is only called if the status of a response is -B. +I. =head1 SEE ALSO diff --git a/include/openssl/ocsp.h b/include/openssl/ocsp.h index 5acd04b6ea..b9f55c0123 100644 --- a/include/openssl/ocsp.h +++ b/include/openssl/ocsp.h @@ -277,7 +277,11 @@ int OCSP_basic_sign_ctx(OCSP_BASICRESP *brsp, X509 *signer, EVP_MD_CTX *ctx, STACK_OF(X509) *certs, unsigned long flags); int OCSP_RESPID_set_by_name(OCSP_RESPID *respid, X509 *cert); +int OCSP_RESPID_set_by_key_ex(OCSP_RESPID *respid, X509 *cert, + OPENSSL_CTX *libctx, const char *propq); int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert); +int OCSP_RESPID_match_ex(OCSP_RESPID *respid, X509 *cert, OPENSSL_CTX *libctx, + const char *propq); int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert); X509_EXTENSION *OCSP_crlID_new(const char *url, long *n, char *tim); diff --git a/util/libcrypto.num b/util/libcrypto.num index ecc735cb94..6ff7179fc6 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5001,3 +5001,5 @@ NCONF_new_with_libctx ? 3_0_0 EXIST::FUNCTION: CONF_modules_load_file_with_libctx ? 3_0_0 EXIST::FUNCTION: OPENSSL_CTX_load_config ? 3_0_0 EXIST::FUNCTION: EVP_PKEY_set_type_by_keymgmt ? 3_0_0 EXIST::FUNCTION: +OCSP_RESPID_set_by_key_ex ? 3_0_0 EXIST::FUNCTION:OCSP +OCSP_RESPID_match_ex ? 3_0_0 EXIST::FUNCTION:OCSP -- 2.39.2