diff --git a/CHANGES b/CHANGES index 1b028bc758285d821c45aeaaa2b9f4c35acaf49a..9324eb6ec7ab3437491f2f1f7aeaf142092a54ac 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,11 @@ 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'. diff --git a/crypto/ocsp/Makefile.ssl b/crypto/ocsp/Makefile.ssl index 1fce558b8578c2871a3f1f41e02f8408d9cd59bd..e693e31ad07fed5f64dbc3ecb15d056ed2f3d120 100644 --- a/crypto/ocsp/Makefile.ssl +++ b/crypto/ocsp/Makefile.ssl @@ -22,11 +22,11 @@ TEST= 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) diff --git a/crypto/ocsp/ocsp.h b/crypto/ocsp/ocsp.h index 4874561f8fb353d52e2983c196d82ff7ec431b63..1db672d08a806ef54f4af58d84c4a5c4d9a900b1 100644 --- a/crypto/ocsp/ocsp.h +++ b/crypto/ocsp/ocsp.h @@ -77,6 +77,8 @@ extern "C" { #define OCSP_DEFAULT_NONCE_LENGTH 16 #define OCSP_NOCERTS 0x1 +#define OCSP_NOINTERN 0x2 +#define OCSP_NOSIGS 0x4 /* 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_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, + X509_STORE *st, unsigned long flags); 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_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 @@ -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_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 diff --git a/crypto/ocsp/ocsp_err.c b/crypto/ocsp/ocsp_err.c index dd9756a254a44989ef5d81327903c2cf9da01419..70a27561b14a324840bbd3f56a8474a387cb9160 100644 --- a/crypto/ocsp/ocsp_err.c +++ b/crypto/ocsp/ocsp_err.c @@ -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_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"}, @@ -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_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"}, diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c new file mode 100644 index 0000000000000000000000000000000000000000..2ea3f4a923e828dc8440fa674086fe428a09bcb1 --- /dev/null +++ b/crypto/ocsp/ocsp_vfy.c @@ -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 +#include + +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; + } + + diff --git a/crypto/rand/rand_egd.c b/crypto/rand/rand_egd.c index 28fb1f2c600b284f271b6be13daebb2b4478d942..cc674f3783c75c6724fb992fe2f479ffcce8bcad 100644 --- a/crypto/rand/rand_egd.c +++ b/crypto/rand/rand_egd.c @@ -131,7 +131,7 @@ int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes) 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);