From 0770c882150ea0159cc2b0a2cea2e8ed8442f36f Mon Sep 17 00:00:00 2001 From: Todd Short Date: Wed, 19 Apr 2017 15:35:16 -0400 Subject: [PATCH] Modify OCSP to use alt MD for cert IDs in responses Modify openssl OCSP utility to produce certIDs in responses using other hash algorithms (e.g. SHA256). Added option -rcid for this purpose. Reviewed-by: Ben Kaduk Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/5274) --- apps/ocsp.c | 34 +++++++++++++++++++++++++++------- doc/man1/ocsp.pod | 7 +++++++ 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/apps/ocsp.c b/apps/ocsp.c index ddcab4c22e..9f2cf453be 100644 --- a/apps/ocsp.c +++ b/apps/ocsp.c @@ -99,7 +99,8 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req EVP_PKEY *rkey, const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(X509) *rother, unsigned long flags, - int nmin, int ndays, int badsig); + int nmin, int ndays, int badsig, + const EVP_MD *resp_md); static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser); static BIO *init_responder(const char *port); @@ -138,6 +139,7 @@ typedef enum OPTION_choice { OPT_RESPOUT, OPT_PATH, OPT_ISSUER, OPT_CERT, OPT_SERIAL, OPT_INDEX, OPT_CA, OPT_NMIN, OPT_REQUEST, OPT_NDAYS, OPT_RSIGNER, OPT_RKEY, OPT_ROTHER, OPT_RMD, OPT_RSIGOPT, OPT_HEADER, + OPT_RCID, OPT_V_ENUM, OPT_MD, OPT_MULTI @@ -220,6 +222,7 @@ const OPTIONS ocsp_options[] = { {"rmd", OPT_RMD, 's', "Digest Algorithm to use in signature of OCSP response"}, {"rsigopt", OPT_RSIGOPT, 's', "OCSP response signature parameter in n:v form"}, {"header", OPT_HEADER, 's', "key=value header to add"}, + {"rcid", OPT_RCID, 's', "Use specified algorithm for cert id in response"}, {"", OPT_MD, '-', "Any supported digest algorithm (sha1,sha256, ... )"}, OPT_V_OPTIONS, {NULL} @@ -243,6 +246,7 @@ int ocsp_main(int argc, char **argv) STACK_OF(X509) *issuers = NULL; X509 *issuer = NULL, *cert = NULL; STACK_OF(X509) *rca_cert = NULL; + const EVP_MD *resp_certid_md = NULL; X509 *signer = NULL, *rsigner = NULL; X509_STORE *store = NULL; X509_VERIFY_PARAM *vpm = NULL; @@ -499,6 +503,11 @@ int ocsp_main(int argc, char **argv) if (!X509V3_add_value(header, value, &headers)) goto end; break; + case OPT_RCID: + resp_certid_md = EVP_get_digestbyname(opt_arg()); + if (resp_certid_md == NULL) + goto opthelp; + break; case OPT_MD: if (trailing_md) { BIO_printf(bio_err, @@ -684,7 +693,8 @@ redo_accept: if (rdb != NULL) { make_ocsp_response(bio_err, &resp, req, rdb, rca_cert, rsigner, rkey, - rsign_md, rsign_sigopts, rother, rflags, nmin, ndays, badsig); + rsign_md, rsign_sigopts, rother, rflags, nmin, ndays, badsig, + resp_certid_md); if (cbio != NULL) send_ocsp_response(cbio, resp); } else if (host != NULL) { @@ -1138,7 +1148,8 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req EVP_PKEY *rkey, const EVP_MD *rmd, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(X509) *rother, unsigned long flags, - int nmin, int ndays, int badsig) + int nmin, int ndays, int badsig, + const EVP_MD *resp_md) { ASN1_TIME *thisupd = NULL, *nextupd = NULL; OCSP_CERTID *cid; @@ -1169,6 +1180,8 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req int found = 0; ASN1_OBJECT *cert_id_md_oid; const EVP_MD *cert_id_md; + OCSP_CERTID *cid_resp_md = NULL; + one = OCSP_request_onereq_get0(req, i); cid = OCSP_onereq_get0_id(one); @@ -1184,11 +1197,18 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req X509 *ca_cert = sk_X509_value(ca, jj); OCSP_CERTID *ca_id = OCSP_cert_to_id(cert_id_md, NULL, ca_cert); - if (OCSP_id_issuer_cmp(ca_id, cid) == 0) + if (OCSP_id_issuer_cmp(ca_id, cid) == 0) { found = 1; - + if (resp_md != NULL) + cid_resp_md = OCSP_cert_to_id(resp_md, NULL, ca_cert); + } OCSP_CERTID_free(ca_id); } + OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid); + inf = lookup_serial(db, serial); + + /* at this point, we can have cid be an alias of cid_resp_md */ + cid = (cid_resp_md != NULL) ? cid_resp_md : cid; if (!found) { OCSP_basic_add1_status(bs, cid, @@ -1196,8 +1216,6 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req 0, NULL, thisupd, nextupd); continue; } - OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid); - inf = lookup_serial(db, serial); if (inf == NULL) { OCSP_basic_add1_status(bs, cid, V_OCSP_CERTSTATUS_UNKNOWN, @@ -1212,6 +1230,7 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req ASN1_GENERALIZEDTIME *invtm = NULL; OCSP_SINGLERESP *single; int reason = -1; + unpack_revinfo(&revtm, &reason, &inst, &invtm, inf[DB_rev_date]); single = OCSP_basic_add1_status(bs, cid, V_OCSP_CERTSTATUS_REVOKED, @@ -1227,6 +1246,7 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req ASN1_TIME_free(revtm); ASN1_GENERALIZEDTIME_free(invtm); } + OCSP_CERTID_free(cid_resp_md); } OCSP_copy_nonce(bs, req); diff --git a/doc/man1/ocsp.pod b/doc/man1/ocsp.pod index c8c3276363..4c0aaac17b 100644 --- a/doc/man1/ocsp.pod +++ b/doc/man1/ocsp.pod @@ -88,6 +88,7 @@ B B [B<-ndays n>] [B<-resp_key_id>] [B<-nrequest n>] +[B<-rcid I>] [B<-I>] =head1 DESCRIPTION @@ -304,6 +305,12 @@ status information is immediately available. In this case the age of the B field is checked to see it is not older than B seconds old. By default this additional check is not performed. +=item B<-rcid I> + +This option sets the digest algorithm to use for certificate identification +in the OCSP response. Any digest supported by the OpenSSL B command can +be used. The default is the same digest algorithm used in the request. + =item B<-I> This option sets digest algorithm to use for certificate identification in the