Enhance OCSP_request_verify() so it finds the signers certificate
authorDr. Stephen Henson <steve@openssl.org>
Mon, 26 Feb 2001 14:17:58 +0000 (14:17 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 26 Feb 2001 14:17:58 +0000 (14:17 +0000)
properly and supports several flags.

CHANGES
crypto/ocsp/ocsp.h
crypto/ocsp/ocsp_err.c
crypto/ocsp/ocsp_lib.c
crypto/ocsp/ocsp_srv.c
crypto/ocsp/ocsp_vfy.c
crypto/x509/x509.h
crypto/x509/x509_trs.c

diff --git a/CHANGES b/CHANGES
index becaab4..6a2480b 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,12 @@
 
  Changes between 0.9.6 and 0.9.7  [xx XXX 2000]
 
+  *) Function OCSP_request_verify(). This checks the signature on an
+     OCSP request and verifies the signer certificate. The signer
+     certificate is just checked for a generic purpose and OCSP request
+     trust settings.
+     [Steve Henson]
+
   *) Add OCSP_check_validity() function to check the validity of OCSP
      responses. OCSP responses are prepared in real time and may only
      be a few seconds old. Simply checking that the current time lies
index bccdf77..02b0a72 100644 (file)
@@ -448,7 +448,7 @@ int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd,
                        ASN1_GENERALIZEDTIME *nextupd,
                        long sec, long maxsec);
 
-int OCSP_request_verify(OCSP_REQUEST *req, EVP_PKEY *pkey);
+int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store, unsigned long flags);
 
 int OCSP_parse_url(char *url, char **phost, char **pport, char **ppath, int *pssl);
 
@@ -461,6 +461,7 @@ OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one);
 int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd,
                        ASN1_OCTET_STRING **pikeyHash,
                        ASN1_INTEGER **pserial, OCSP_CERTID *cid);
+int OCSP_request_is_signed(OCSP_REQUEST *req);
 OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs);
 OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp,
                                                OCSP_CERTID *cid,
@@ -576,6 +577,7 @@ void ERR_load_OCSP_strings(void);
 #define OCSP_F_OCSP_MATCH_ISSUERID                      109
 #define OCSP_F_OCSP_PARSE_URL                           114
 #define OCSP_F_OCSP_REQUEST_SIGN                        110
+#define OCSP_F_OCSP_REQUEST_VERIFY                      116
 #define OCSP_F_OCSP_RESPONSE_GET1_BASIC                         111
 #define OCSP_F_OCSP_SENDREQ_BIO                                 112
 #define OCSP_F_REQUEST_VERIFY                           113
@@ -596,6 +598,7 @@ void ERR_load_OCSP_strings(void);
 #define OCSP_R_NO_RESPONSE_DATA                                 108
 #define OCSP_R_NO_REVOKED_TIME                          109
 #define OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE   110
+#define OCSP_R_REQUEST_NOT_SIGNED                       128
 #define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA     111
 #define OCSP_R_ROOT_CA_NOT_TRUSTED                      112
 #define OCSP_R_SERVER_READ_ERROR                        113
@@ -609,6 +612,7 @@ void ERR_load_OCSP_strings(void);
 #define OCSP_R_STATUS_TOO_OLD                           127
 #define OCSP_R_UNKNOWN_MESSAGE_DIGEST                   119
 #define OCSP_R_UNKNOWN_NID                              120
+#define OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE           129
 
 #ifdef  __cplusplus
 }
index 1cbf9ca..4c4d830 100644 (file)
@@ -79,6 +79,7 @@ static ERR_STRING_DATA OCSP_str_functs[]=
 {ERR_PACK(0,OCSP_F_OCSP_MATCH_ISSUERID,0),     "OCSP_MATCH_ISSUERID"},
 {ERR_PACK(0,OCSP_F_OCSP_PARSE_URL,0),  "OCSP_parse_url"},
 {ERR_PACK(0,OCSP_F_OCSP_REQUEST_SIGN,0),       "OCSP_request_sign"},
+{ERR_PACK(0,OCSP_F_OCSP_REQUEST_VERIFY,0),     "OCSP_request_verify"},
 {ERR_PACK(0,OCSP_F_OCSP_RESPONSE_GET1_BASIC,0),        "OCSP_response_get1_basic"},
 {ERR_PACK(0,OCSP_F_OCSP_SENDREQ_BIO,0),        "OCSP_sendreq_bio"},
 {ERR_PACK(0,OCSP_F_REQUEST_VERIFY,0),  "REQUEST_VERIFY"},
@@ -102,6 +103,7 @@ static ERR_STRING_DATA OCSP_str_reasons[]=
 {OCSP_R_NO_RESPONSE_DATA                 ,"no response data"},
 {OCSP_R_NO_REVOKED_TIME                  ,"no revoked time"},
 {OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE,"private key does not match certificate"},
+{OCSP_R_REQUEST_NOT_SIGNED               ,"request not signed"},
 {OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA,"response contains no revocation data"},
 {OCSP_R_ROOT_CA_NOT_TRUSTED              ,"root ca not trusted"},
 {OCSP_R_SERVER_READ_ERROR                ,"server read error"},
@@ -115,6 +117,7 @@ static ERR_STRING_DATA OCSP_str_reasons[]=
 {OCSP_R_STATUS_TOO_OLD                   ,"status too old"},
 {OCSP_R_UNKNOWN_MESSAGE_DIGEST           ,"unknown message digest"},
 {OCSP_R_UNKNOWN_NID                      ,"unknown nid"},
+{OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE   ,"unsupported requestorname type"},
 {0,NULL}
        };
 
index 0ddf1b2..1ff8f4f 100644 (file)
@@ -158,24 +158,6 @@ int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
        return ASN1_INTEGER_cmp(a->serialNumber, b->serialNumber);
        }
 
-/* XXX assumes certs in signature are sorted root to leaf XXX */
-int OCSP_request_verify(OCSP_REQUEST *req, EVP_PKEY *pkey)
-        {
-       STACK_OF(X509) *sk;
-
-       if (!req->optionalSignature) return 0;
-       if (pkey == NULL)
-               {
-               if (!(sk = req->optionalSignature->certs)) return 0;
-               if (!(pkey=X509_get_pubkey(sk_X509_value(sk, sk_X509_num(sk)-1))))
-                       {
-                       OCSPerr(OCSP_F_REQUEST_VERIFY,OCSP_R_NO_PUBLIC_KEY);
-                       return 0;
-                       }
-               }
-       return OCSP_REQUEST_verify(req, pkey);
-        }
-
 
 /* Parse a URL and split it up into host, port and path components and whether
  * it is SSL.
index 3ecbfc8..fffa134 100644 (file)
@@ -96,6 +96,12 @@ int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd,
        return 1;
        }
 
+int OCSP_request_is_signed(OCSP_REQUEST *req)
+       {
+       if(req->optionalSignature) return 1;
+       return 0;
+       }
+
 /* Create an OCSP response and encode an optional basic response */
 OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs)
         {
index c4f513a..da4c5b2 100644 (file)
@@ -67,6 +67,8 @@ static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, unsigned
 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);
 static int ocsp_check_delegated(X509 *x, int flags);
+static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm, STACK_OF(X509) *certs,
+                               X509_STORE *st, unsigned long flags);
 
 /* Verify a basic response message */
 
@@ -340,3 +342,90 @@ static int ocsp_check_delegated(X509 *x, int flags)
        OCSPerr(OCSP_F_OCSP_CHECK_DELEGATED, OCSP_R_MISSING_OCSPSIGNING_USAGE);
        return 0;
        }
+
+/* Verify an OCSP request. This is fortunately much easier than OCSP
+ * request verify. Just find the signers certificate and verify it
+ * against a given trust value.
+ */
+
+int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store, unsigned long flags)
+        {
+       X509 *signer;
+       X509_NAME *nm;
+       GENERAL_NAME *gen;
+       int ret;
+       X509_STORE_CTX ctx;
+       if (!req->optionalSignature) 
+               {
+               OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_REQUEST_NOT_SIGNED);
+               return 0;
+               }
+       gen = req->tbsRequest->requestorName;
+       if (gen->type != GEN_DIRNAME)
+               {
+               OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE);
+               return 0;
+               }
+       nm = gen->d.directoryName;
+       ret = ocsp_req_find_signer(&signer, req, nm, certs, store, flags);
+       if (ret <= 0)
+               {
+               OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
+               return 0;
+               }
+       if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
+               flags |= OCSP_NOVERIFY;
+       if (!(flags & OCSP_NOSIGS))
+               {
+               EVP_PKEY *skey;
+               skey = X509_get_pubkey(signer);
+               ret = OCSP_REQUEST_verify(req, skey);
+               EVP_PKEY_free(skey);
+               if(ret <= 0)
+                       {
+                       OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_SIGNATURE_FAILURE);
+                       return 0;
+                       }
+               }
+       if (!(flags & OCSP_NOVERIFY))
+               {
+               if(flags & OCSP_NOCHAIN)
+                       X509_STORE_CTX_init(&ctx, store, signer, NULL);
+               else
+                       X509_STORE_CTX_init(&ctx, store, signer, req->optionalSignature->certs);
+
+               X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER);
+               X509_STORE_CTX_set_trust(&ctx, X509_TRUST_OCSP_REQUEST);
+               ret = X509_verify_cert(&ctx);
+               X509_STORE_CTX_cleanup(&ctx);
+                if (ret <= 0)
+                       {
+                       ret = X509_STORE_CTX_get_error(&ctx);   
+                       OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,OCSP_R_CERTIFICATE_VERIFY_ERROR);
+                       ERR_add_error_data(2, "Verify error:",
+                                       X509_verify_cert_error_string(ret));
+                        return 0;
+                       }
+               }
+       return 1;
+        }
+
+static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm, STACK_OF(X509) *certs,
+                               X509_STORE *st, unsigned long flags)
+       {
+       X509 *signer;
+       if(!(flags & OCSP_NOINTERN))
+               {
+               signer = X509_find_by_subject(req->optionalSignature->certs, nm);
+               *psigner = signer;
+               return 1;
+               }
+
+       signer = X509_find_by_subject(certs, nm);
+       if (signer)
+               {
+               *psigner = signer;
+               return 2;
+               }
+       return 0;
+       }
index 66ce268..1aeea20 100644 (file)
@@ -301,10 +301,11 @@ DECLARE_STACK_OF(X509_TRUST)
 #define X509_TRUST_EMAIL       4
 #define X509_TRUST_OBJECT_SIGN 5
 #define X509_TRUST_OCSP_SIGN   6
+#define X509_TRUST_OCSP_REQUEST        7
 
 /* Keep these up to date! */
 #define X509_TRUST_MIN         1
-#define X509_TRUST_MAX         6
+#define X509_TRUST_MAX         7
 
 
 /* trust_flags values */
index 7a41bc2..4f48b55 100644 (file)
@@ -82,7 +82,8 @@ static X509_TRUST trstandard[] = {
 {X509_TRUST_SSL_CLIENT, 0, trust_1oidany, "SSL Client", NID_client_auth, NULL},
 {X509_TRUST_SSL_SERVER, 0, trust_1oidany, "SSL Client", NID_server_auth, NULL},
 {X509_TRUST_EMAIL, 0, trust_1oidany, "S/MIME email", NID_email_protect, NULL},
-{X509_TRUST_OCSP_SIGN, 0, trust_1oid, "OCSP responder", NID_OCSP_sign, NULL}
+{X509_TRUST_OCSP_SIGN, 0, trust_1oid, "OCSP responder", NID_OCSP_sign, NULL},
+{X509_TRUST_OCSP_REQUEST, 0, trust_1oid, "OCSP request", NID_ad_OCSP, NULL}
 };
 
 #define X509_TRUST_COUNT       (sizeof(trstandard)/sizeof(X509_TRUST))