OCSP basic response verify. Very incomplete
authorDr. Stephen Henson <steve@openssl.org>
Thu, 11 Jan 2001 00:52:50 +0000 (00:52 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Thu, 11 Jan 2001 00:52:50 +0000 (00:52 +0000)
but will verify the signatures on a response
and locate the signers certifcate.

Still needs to implement a proper OCSP certificate
verify.

Fix warning in RAND_egd().

CHANGES
crypto/ocsp/Makefile.ssl
crypto/ocsp/ocsp.h
crypto/ocsp/ocsp_err.c
crypto/ocsp/ocsp_vfy.c [new file with mode: 0644]
crypto/rand/rand_egd.c

diff --git a/CHANGES b/CHANGES
index 1b028bc758285d821c45aeaaa2b9f4c35acaf49a..9324eb6ec7ab3437491f2f1f7aeaf142092a54ac 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,11 @@
 
  Changes between 0.9.6 and 0.9.7  [xx XXX 2000]
 
 
  Changes between 0.9.6 and 0.9.7  [xx XXX 2000]
 
+  *) Initial code to implement OCSP basic response verify. This
+     is currently incomplete. Currently just finds the signer's
+     certificate and verifies the signature on the response.
+     [Steve Henson]
+
   *) New SSLeay_version code SSLEAY_DIR to determine the compiled-in
      value of OPENSSLDIR.  This is available via the new '-d' option
      to 'openssl version', and is also included in 'openssl version -a'.
   *) New SSLeay_version code SSLEAY_DIR to determine the compiled-in
      value of OPENSSLDIR.  This is available via the new '-d' option
      to 'openssl version', and is also included in 'openssl version -a'.
index 1fce558b8578c2871a3f1f41e02f8408d9cd59bd..e693e31ad07fed5f64dbc3ecb15d056ed2f3d120 100644 (file)
@@ -22,11 +22,11 @@ TEST=
 APPS=
 
 LIB=$(TOP)/libcrypto.a
 APPS=
 
 LIB=$(TOP)/libcrypto.a
-LIBSRC= ocsp_asn.c ocsp_ext.c ocsp_ht.c \
-       ocsp_lib.c ocsp_cl.c ocsp_prn.c ocsp_err.c
+LIBSRC= ocsp_asn.c ocsp_ext.c ocsp_ht.c ocsp_lib.c ocsp_cl.c \
+       ocsp_prn.c ocsp_vfy.c ocsp_err.c
 
 
-LIBOBJ= ocsp_asn.o ocsp_ext.o ocsp_ht.o \
-       ocsp_lib.o ocsp_cl.o ocsp_prn.o ocsp_err.o
+LIBOBJ= ocsp_asn.o ocsp_ext.o ocsp_ht.o ocsp_lib.o ocsp_cl.o \
+       ocsp_prn.o ocsp_vfy.o ocsp_err.o
 
 SRC= $(LIBSRC)
 
 
 SRC= $(LIBSRC)
 
index 4874561f8fb353d52e2983c196d82ff7ec431b63..1db672d08a806ef54f4af58d84c4a5c4d9a900b1 100644 (file)
@@ -77,6 +77,8 @@ extern "C" {
 #define OCSP_DEFAULT_NONCE_LENGTH      16
 
 #define OCSP_NOCERTS                   0x1
 #define OCSP_DEFAULT_NONCE_LENGTH      16
 
 #define OCSP_NOCERTS                   0x1
+#define OCSP_NOINTERN                  0x2
+#define OCSP_NOSIGS                    0x4
 
 /*   CertID ::= SEQUENCE {
  *       hashAlgorithm            AlgorithmIdentifier,
 
 /*   CertID ::= SEQUENCE {
  *       hashAlgorithm            AlgorithmIdentifier,
@@ -531,6 +533,8 @@ DECLARE_ASN1_FUNCTIONS(OCSP_SERVICELOC)
 
 int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST* a, unsigned long flags);
 
 
 int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST* a, unsigned long flags);
 
+int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
+                               X509_STORE *st, unsigned long flags);
 
 void ERR_load_OCSP_strings(void);
 
 
 void ERR_load_OCSP_strings(void);
 
@@ -548,6 +552,7 @@ void ERR_load_OCSP_strings(void);
 #define OCSP_F_CERT_ID_NEW                              102
 #define OCSP_F_CERT_STATUS_NEW                          103
 #define OCSP_F_D2I_OCSP_NONCE                           109
 #define OCSP_F_CERT_ID_NEW                              102
 #define OCSP_F_CERT_STATUS_NEW                          103
 #define OCSP_F_D2I_OCSP_NONCE                           109
+#define OCSP_F_OCSP_BASIC_VERIFY                        113
 #define OCSP_F_OCSP_CHECK_NONCE                                 112
 #define OCSP_F_OCSP_RESPONSE_GET1_BASIC                         111
 #define OCSP_F_OCSP_SENDREQ_BIO                                 110
 #define OCSP_F_OCSP_CHECK_NONCE                                 112
 #define OCSP_F_OCSP_RESPONSE_GET1_BASIC                         111
 #define OCSP_F_OCSP_SENDREQ_BIO                                 110
@@ -577,6 +582,8 @@ void ERR_load_OCSP_strings(void);
 #define OCSP_R_SERVER_RESPONSE_ERROR                    117
 #define OCSP_R_SERVER_RESPONSE_PARSE_ERROR              118
 #define OCSP_R_SERVER_WRITE_ERROR                       119
 #define OCSP_R_SERVER_RESPONSE_ERROR                    117
 #define OCSP_R_SERVER_RESPONSE_PARSE_ERROR              118
 #define OCSP_R_SERVER_WRITE_ERROR                       119
+#define OCSP_R_SIGNATURE_FAILURE                        124
+#define OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND             125
 #define OCSP_R_UNEXPECTED_NONCE_IN_RESPONSE             123
 #define OCSP_R_UNKNOWN_NID                              107
 #define OCSP_R_UNSUPPORTED_OPTION                       113
 #define OCSP_R_UNEXPECTED_NONCE_IN_RESPONSE             123
 #define OCSP_R_UNKNOWN_NID                              107
 #define OCSP_R_UNSUPPORTED_OPTION                       113
index dd9756a254a44989ef5d81327903c2cf9da01419..70a27561b14a324840bbd3f56a8474a387cb9160 100644 (file)
@@ -72,6 +72,7 @@ static ERR_STRING_DATA OCSP_str_functs[]=
 {ERR_PACK(0,OCSP_F_CERT_ID_NEW,0),     "CERT_ID_NEW"},
 {ERR_PACK(0,OCSP_F_CERT_STATUS_NEW,0), "CERT_STATUS_NEW"},
 {ERR_PACK(0,OCSP_F_D2I_OCSP_NONCE,0),  "D2I_OCSP_NONCE"},
 {ERR_PACK(0,OCSP_F_CERT_ID_NEW,0),     "CERT_ID_NEW"},
 {ERR_PACK(0,OCSP_F_CERT_STATUS_NEW,0), "CERT_STATUS_NEW"},
 {ERR_PACK(0,OCSP_F_D2I_OCSP_NONCE,0),  "D2I_OCSP_NONCE"},
+{ERR_PACK(0,OCSP_F_OCSP_BASIC_VERIFY,0),       "OCSP_basic_verify"},
 {ERR_PACK(0,OCSP_F_OCSP_CHECK_NONCE,0),        "OCSP_check_nonce"},
 {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_OCSP_CHECK_NONCE,0),        "OCSP_check_nonce"},
 {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"},
@@ -104,6 +105,8 @@ static ERR_STRING_DATA OCSP_str_reasons[]=
 {OCSP_R_SERVER_RESPONSE_ERROR            ,"server response error"},
 {OCSP_R_SERVER_RESPONSE_PARSE_ERROR      ,"server response parse error"},
 {OCSP_R_SERVER_WRITE_ERROR               ,"server write error"},
 {OCSP_R_SERVER_RESPONSE_ERROR            ,"server response error"},
 {OCSP_R_SERVER_RESPONSE_PARSE_ERROR      ,"server response parse error"},
 {OCSP_R_SERVER_WRITE_ERROR               ,"server write error"},
+{OCSP_R_SIGNATURE_FAILURE                ,"signature failure"},
+{OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND     ,"signer certificate not found"},
 {OCSP_R_UNEXPECTED_NONCE_IN_RESPONSE     ,"unexpected nonce in response"},
 {OCSP_R_UNKNOWN_NID                      ,"unknown nid"},
 {OCSP_R_UNSUPPORTED_OPTION               ,"unsupported option"},
 {OCSP_R_UNEXPECTED_NONCE_IN_RESPONSE     ,"unexpected nonce in response"},
 {OCSP_R_UNKNOWN_NID                      ,"unknown nid"},
 {OCSP_R_UNSUPPORTED_OPTION               ,"unsupported option"},
diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c
new file mode 100644 (file)
index 0000000..2ea3f4a
--- /dev/null
@@ -0,0 +1,142 @@
+/* ocsp_vfy.c */
+/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <openssl/ocsp.h>
+#include <openssl/err.h>
+
+static X509 *ocsp_find_signer(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
+                               X509_STORE *st, unsigned long flags);
+static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id);
+
+/* Verify a basic response message */
+
+int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
+                               X509_STORE *st, unsigned long flags)
+       {
+       X509 *signer;
+       int ret;
+       signer = ocsp_find_signer(bs, certs, st, flags);
+       if (!signer)
+               {
+               OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
+               return 0;
+               }
+       if(!(flags & OCSP_NOSIGS))
+               {
+               EVP_PKEY *skey;
+               skey = X509_get_pubkey(signer);
+               ret = OCSP_BASICRESP_verify(bs, skey, 0);
+               EVP_PKEY_free(skey);
+               if(ret <= 0)
+                       {
+                       OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNATURE_FAILURE);
+                       return 0;
+                       }
+               }
+       return 1;
+       }
+
+
+static X509 *ocsp_find_signer(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
+                               X509_STORE *st, unsigned long flags)
+       {
+       X509 *signer;
+       OCSP_RESPID *rid = bs->tbsResponseData->responderId;
+       if ((signer = ocsp_find_signer_sk(certs, rid)))
+               return signer;
+       if(!(flags & OCSP_NOINTERN) &&
+           (signer = ocsp_find_signer_sk(bs->certs, rid)))
+               return signer;
+       /* Maybe lookup from store if by subject name */
+
+       return NULL;
+       }
+
+
+static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
+       {
+       int i;
+       unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
+       ASN1_BIT_STRING *key;
+       EVP_MD_CTX ctx;
+       X509 *x;
+
+       /* Easy if lookup by name */
+       if(id->type == V_OCSP_RESPID_NAME)
+               return X509_find_by_subject(certs, id->value.byName);
+
+       /* Lookup by key hash */
+
+       /* If key hash isn't SHA1 length then forget it */
+       if(id->value.byKey->length != SHA_DIGEST_LENGTH) return NULL;
+       keyhash = id->value.byKey->data;
+       /* Calculate hash of each key and compare */
+       for(i = 0; i < sk_X509_num(certs); i++)
+               {
+               x = sk_X509_value(certs, i);
+               key = x->cert_info->key->public_key;
+               EVP_DigestInit(&ctx,EVP_sha1());
+               EVP_DigestUpdate(&ctx,key->data, key->length);
+               EVP_DigestFinal(&ctx,tmphash,NULL);
+               if(!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
+                       return x;
+               }
+       return NULL;
+       }
+
+
index 28fb1f2c600b284f271b6be13daebb2b4478d942..cc674f3783c75c6724fb992fe2f479ffcce8bcad 100644 (file)
@@ -131,7 +131,7 @@ int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
 
 int RAND_egd(const char *path)
        {
 
 int RAND_egd(const char *path)
        {
-       int num, ret;
+       int num, ret = 0;
        unsigned char buf[256];
 
        num = RAND_query_egd_bytes(path, buf, 255);
        unsigned char buf[256];
 
        num = RAND_query_egd_bytes(path, buf, 255);