Modify OCSP to use alt MD for cert IDs in responses
authorTodd Short <tshort@akamai.com>
Wed, 19 Apr 2017 19:35:16 +0000 (15:35 -0400)
committerMatt Caswell <matt@openssl.org>
Wed, 3 Apr 2019 14:56:45 +0000 (15:56 +0100)
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 <kaduk@mit.edu>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5274)

apps/ocsp.c
doc/man1/ocsp.pod

index ddcab4c..9f2cf45 100644 (file)
@@ -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);
index c8c3276..4c0aaac 100644 (file)
@@ -88,6 +88,7 @@ B<openssl> B<ocsp>
 [B<-ndays n>]
 [B<-resp_key_id>]
 [B<-nrequest n>]
+[B<-rcid I<digest>>]
 [B<-I<digest>>]
 
 =head1 DESCRIPTION
@@ -304,6 +305,12 @@ status information is immediately available. In this case the age of the
 B<notBefore> field is checked to see it is not older than B<age> seconds old.
 By default this additional check is not performed.
 
+=item B<-rcid I<digest>>
+
+This option sets the digest algorithm to use for certificate identification
+in the OCSP response. Any digest supported by the OpenSSL B<dgst> command can
+be used. The default is the same digest algorithm used in the request.
+
 =item B<-I<digest>>
 
 This option sets digest algorithm to use for certificate identification in the