From 0b33bc65cd1bde346eae5b25d6f2d693c115b901 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Mon, 8 Jan 2001 01:21:55 +0000 Subject: [PATCH] Add set of OCSP client functions. All experimental and subject to addition, modifcation or deletion. Add two OCSP nonce utility functions. Fix typo in status code name. --- CHANGES | 24 +++- crypto/ocsp/Makefile.ssl | 4 +- crypto/ocsp/ocsp.h | 41 ++++-- crypto/ocsp/ocsp_cl.c | 291 +++++++++++++++++++++++++++++++++++++++ crypto/ocsp/ocsp_err.c | 6 + crypto/ocsp/ocsp_ext.c | 71 ++++++++++ crypto/ocsp/ocsp_lib.c | 56 ++------ crypto/ocsp/ocsp_prn.c | 4 +- 8 files changed, 437 insertions(+), 60 deletions(-) create mode 100644 crypto/ocsp/ocsp_cl.c diff --git a/CHANGES b/CHANGES index f43b723c8e..0c745b64a7 100644 --- a/CHANGES +++ b/CHANGES @@ -3,7 +3,29 @@ Changes between 0.9.6 and 0.9.7 [xx XXX 2000] - *) Change function OCSP_request_add() to OCSP_request_add0(). + *) Move OCSP client related routines to ocsp_cl.c. These + provide utility functions which an application needing + to issue a request to an OCSP responder and analyse the + response will typically need: as opposed to those which an + OCSP responder itself would need which will be added later. + + OCSP_request_sign() signs an OCSP request with an API similar + to PKCS7_sign(). OCSP_response_status() returns status of OCSP + response. OCSP_response_get1_basic() extracts basic response + from response. OCSP_resp_find_status(): finds and extracts status + information from an OCSP_CERTID structure (which will be created + when the request structure is built). These are built from lower + level functions which work on OCSP_SINGLERESP structures but + wont normally be used unless the application wishes to examine + extensions in the OCSP response for example. + + Replace nonce routines with a pair of functions. + OCSP_request_add1_nonce() adds a nonce value and optionally + generates a random value. OCSP_check_nonce() checks the + validity of the nonce in an OCSP response. + [Steve Henson] + + *) Change function OCSP_request_add() to OCSP_request_add0_id(). This doesn't copy the supplied OCSP_CERTID and avoids the need to free up the newly created id. Change return type to OCSP_ONEREQ to return the internal OCSP_ONEREQ structure. diff --git a/crypto/ocsp/Makefile.ssl b/crypto/ocsp/Makefile.ssl index ef76c81271..1fce558b85 100644 --- a/crypto/ocsp/Makefile.ssl +++ b/crypto/ocsp/Makefile.ssl @@ -23,10 +23,10 @@ APPS= LIB=$(TOP)/libcrypto.a LIBSRC= ocsp_asn.c ocsp_ext.c ocsp_ht.c \ - ocsp_lib.c ocsp_prn.c ocsp_err.c + ocsp_lib.c ocsp_cl.c ocsp_prn.c ocsp_err.c LIBOBJ= ocsp_asn.o ocsp_ext.o ocsp_ht.o \ - ocsp_lib.o ocsp_prn.o ocsp_err.o + ocsp_lib.o ocsp_cl.o ocsp_prn.o ocsp_err.o SRC= $(LIBSRC) diff --git a/crypto/ocsp/ocsp.h b/crypto/ocsp/ocsp.h index 7bc23ba4cf..7d45e9fb10 100644 --- a/crypto/ocsp/ocsp.h +++ b/crypto/ocsp/ocsp.h @@ -72,6 +72,12 @@ extern "C" { #endif +/* Various flags and values */ + +#define OCSP_DEFAULT_NONCE_LENGTH 16 + +#define OCSP_NOCERTS 0x1 + /* CertID ::= SEQUENCE { * hashAlgorithm AlgorithmIdentifier, * issuerNameHash OCTET STRING, -- Hash of Issuer's DN @@ -146,7 +152,7 @@ typedef struct ocsp_request_st * unauthorized (6) --Request unauthorized * } */ -#define OCSP_RESPONSE_STATUS_SUCCESSFULL 0 +#define OCSP_RESPONSE_STATUS_SUCCESSFUL 0 #define OCSP_RESPONSE_STATUS_MALFORMEDREQUEST 1 #define OCSP_RESPONSE_STATUS_INTERNALERROR 2 #define OCSP_RESPONSE_STATUS_TRYLATER 3 @@ -361,21 +367,21 @@ typedef struct ocsp_service_locator_st #define OCSP_REQUEST_sign(o,pkey,md) \ ASN1_item_sign(&OCSP_REQINFO_it,\ o->optionalSignature->signatureAlgorithm,NULL,\ - o->optionalSignature->signature,(char *)o->tbsRequest,pkey,md) + o->optionalSignature->signature,o->tbsRequest,pkey,md) #define OCSP_BASICRESP_sign(o,pkey,md,d) \ ASN1_item_sign(&OCSP_RESPDATA_it,o->signatureAlgorithm,NULL,\ - o->signature,(char *)o->tbsResponseData,pkey,md) + o->signature,o->tbsResponseData,pkey,md) #define OCSP_REQUEST_verify(a,r) ASN1_item_verify(&OCSP_REQINFO_it,\ a->optionalSignature->signatureAlgorithm,\ - a->optionalSignature->signature,(char *)a->tbsRequest,r) + a->optionalSignature->signature,a->tbsRequest,r) #define OCSP_BASICRESP_verify(a,r,d) ASN1_item_verify(&OCSP_RESPDATA_it,\ - a->signatureAlgorithm,a->signature,(char *)a->tbsResponseData,r) + a->signatureAlgorithm,a->signature,a->tbsResponseData,r) #define ASN1_BIT_STRING_digest(data,type,md,len) \ - ASN1_item_digest(&ASN1_BIT_STRING_it,type,(char *)data,md,len) + ASN1_item_digest(&ASN1_BIT_STRING_it,type,data,md,len) #define OCSP_CERTID_dup(cid) (OCSP_CERTID*)ASN1_dup((int(*)())i2d_OCSP_CERTID,\ (char *(*)())d2i_OCSP_CERTID,(char *)(cid)) @@ -395,15 +401,26 @@ OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst, OCSP_CERTSTATUS *OCSP_cert_status_new(int status, int reason, char *tim); -OCSP_ONEREQ *OCSP_request_add0(OCSP_REQUEST *req, OCSP_CERTID *cid); +OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid); +int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len); +int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs); +int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm); +int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert); int OCSP_request_sign(OCSP_REQUEST *req, + X509 *signer, EVP_PKEY *key, const EVP_MD *dgst, - STACK_OF(X509) *certs); + STACK_OF(X509) *certs, + unsigned long flags); + +int OCSP_response_status(OCSP_RESPONSE *resp); +OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp); int OCSP_request_verify(OCSP_REQUEST *req, EVP_PKEY *pkey); +int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b); + OCSP_BASICRESP *OCSP_basic_response_new(int tag, X509* cert); @@ -431,8 +448,6 @@ OCSP_RESPONSE *OCSP_response_new(int status, ASN1_STRING *ASN1_STRING_encode(ASN1_STRING *s, int (*i2d)(), char *data, STACK_OF(ASN1_OBJECT) *sk); -X509_EXTENSION *OCSP_nonce_new(void *p, unsigned int len); - X509_EXTENSION *OCSP_crlID_new(char *url, long *n, char *tim); X509_EXTENSION *OCSP_accept_responses_new(char **oids); @@ -520,6 +535,8 @@ 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_CHECK_NONCE 112 +#define OCSP_F_OCSP_RESPONSE_GET1_BASIC 111 #define OCSP_F_OCSP_SENDREQ_BIO 110 #define OCSP_F_REQUEST_VERIFY 104 #define OCSP_F_RESPONSE_VERIFY 105 @@ -534,6 +551,9 @@ void ERR_load_OCSP_strings(void); #define OCSP_R_FAILED_TO_READ 110 #define OCSP_R_FAILED_TO_STAT 111 #define OCSP_R_MISSING_VALUE 112 +#define OCSP_R_NONCE_MISSING_IN_RESPONSE 121 +#define OCSP_R_NONCE_VALUE_MISMATCH 122 +#define OCSP_R_NOT_BASIC_RESPONSE 120 #define OCSP_R_NO_CERTIFICATE 102 #define OCSP_R_NO_CONTENT 115 #define OCSP_R_NO_PUBLIC_KEY 103 @@ -544,6 +564,7 @@ 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_UNEXPECTED_NONCE_IN_RESPONSE 123 #define OCSP_R_UNKNOWN_NID 107 #define OCSP_R_UNSUPPORTED_OPTION 113 #define OCSP_R_VALUE_ALREADY 114 diff --git a/crypto/ocsp/ocsp_cl.c b/crypto/ocsp/ocsp_cl.c new file mode 100644 index 0000000000..3e73e3bb17 --- /dev/null +++ b/crypto/ocsp/ocsp_cl.c @@ -0,0 +1,291 @@ +/* ocsp_cl.c */ +/* Written by Tom Titchener for the OpenSSL + * project. */ + +/* History: + This file was transfered to Richard Levitte from CertCo by Kathy + Weinhold in mid-spring 2000 to be included in OpenSSL or released + as a patch kit. */ + +/* ==================================================================== + * Copyright (c) 1998-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 + * openssl-core@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 +#include +#include +#include +#include +#include +#include + +/* Utility functions related to sending OCSP requests and extracting + * relevant information from the response. + */ + +/* Add an OCSP_CERTID to an OCSP request. Return new OCSP_ONEREQ + * pointer: useful if we want to add extensions. + */ + +OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid) + { + OCSP_ONEREQ *one = NULL; + + if (!(one = OCSP_ONEREQ_new())) goto err; + if (one->reqCert) OCSP_CERTID_free(one->reqCert); + one->reqCert = cid; + if (req && + !sk_OCSP_ONEREQ_push(req->tbsRequest->requestList, one)) + goto err; + return one; +err: + OCSP_ONEREQ_free(one); + return NULL; + } + +/* Set requestorName from an X509_NAME structure */ + +int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm) + { + GENERAL_NAME *gen; + gen = GENERAL_NAME_new(); + if (!X509_NAME_set(&gen->d.directoryName, nm)) + { + GENERAL_NAME_free(gen); + return 0; + } + gen->type = GEN_DIRNAME; + if (req->tbsRequest->requestorName) + GENERAL_NAME_free(req->tbsRequest->requestorName); + req->tbsRequest->requestorName = gen; + return 1; + } + + +/* Add a certificate to an OCSP request */ + +int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert) + { + OCSP_SIGNATURE *sig; + if (!req->optionalSignature) + req->optionalSignature = OCSP_SIGNATURE_new(); + sig = req->optionalSignature; + if (!sig) return 0; + if (!cert) return 1; + if (!sig->certs && !(sig->certs = sk_X509_new_null())) + return 0; + + if(!sk_X509_push(sig->certs, cert)) return 0; + CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); + return 1; + } + +/* Sign an OCSP request set the requestorName to the subjec + * name of an optional signers certificate and include one + * or more optional certificates in the request. Behaves + * like PKCS7_sign(). + */ + +int OCSP_request_sign(OCSP_REQUEST *req, + X509 *signer, + EVP_PKEY *key, + const EVP_MD *dgst, + STACK_OF(X509) *certs, + unsigned long flags) + { + int i; + OCSP_SIGNATURE *sig; + X509 *x; + + if (signer && + !OCSP_request_set1_name(req, X509_get_subject_name(signer))) + goto err; + + if (!(req->optionalSignature = sig = OCSP_SIGNATURE_new())) goto err; + if (!dgst) dgst = EVP_sha1(); + if (key && !OCSP_REQUEST_sign(req, key, dgst)) goto err; + if (!(flags & OCSP_NOCERTS)) + { + if (!OCSP_request_add1_cert(req, signer)) goto err; + for (i = 0; i < sk_X509_num(certs); i++) + { + x = sk_X509_value(certs, i); + if (!OCSP_request_add1_cert(req, x)) goto err; + } + } + return 1; +err: + OCSP_SIGNATURE_free(req->optionalSignature); + req->optionalSignature = NULL; + return 0; + } + +/* Get response status */ + +int OCSP_response_status(OCSP_RESPONSE *resp) + { + return ASN1_ENUMERATED_get(resp->responseStatus); + } + +/* Extract basic response from OCSP_RESPONSE or NULL if + * no basic response present. + */ + + +OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp) + { + OCSP_RESPBYTES *rb; + rb = resp->responseBytes; + if (!rb) + { + OCSPerr(OCSP_F_OCSP_RESPONSE_GET1_BASIC, OCSP_R_NO_RESPONSE_DATA); + return NULL; + } + if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic) + { + OCSPerr(OCSP_F_OCSP_RESPONSE_GET1_BASIC, OCSP_R_NOT_BASIC_RESPONSE); + return NULL; + } + + return ASN1_item_unpack(rb->response, &OCSP_BASICRESP_it); + } + +/* Return number of OCSP_SINGLERESP reponses present in + * a basic response. + */ + +int OCSP_resp_count(OCSP_BASICRESP *bs) + { + if (!bs) return -1; + return sk_OCSP_SINGLERESP_num(bs->tbsResponseData->responses); + } + +/* Extract an OCSP_SINGLERESP response with a given index */ + +OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx) + { + if (!bs) return NULL; + return sk_OCSP_SINGLERESP_value(bs->tbsResponseData->responses, idx); + } + +/* Look single response matching a given certificate ID */ + +int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last) + { + int i; + STACK_OF(OCSP_SINGLERESP) *sresp; + OCSP_SINGLERESP *single; + if (!bs) return -1; + if (last < 0) last = 0; + else last++; + sresp = bs->tbsResponseData->responses; + for (i = last; i < sk_OCSP_SINGLERESP_num(sresp); i++) + { + single = sk_OCSP_SINGLERESP_value(sresp, i); + if (!OCSP_id_cmp(id, single->certId)) return i; + } + return -1; + } + +/* Extract status information from an OCSP_SINGLERESP structure. + * Note: the revtime and reason values are only set if the + * certificate status is revoked. Returns numerical value of + * status. + */ + +int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason, + ASN1_GENERALIZEDTIME **revtime, + ASN1_GENERALIZEDTIME **thisupd, + ASN1_GENERALIZEDTIME **nextupd) + { + int ret; + OCSP_CERTSTATUS *cst = single->certStatus; + if(!single) return -1; + ret = cst->type; + if (ret == V_OCSP_CERTSTATUS_REVOKED) + { + OCSP_REVOKEDINFO *rev = cst->value.revoked; + if (revtime) *revtime = rev->revocationTime; + if (reason) + { + if(rev->revocationReason) + *reason = ASN1_ENUMERATED_get(rev->revocationReason); + else *reason = -1; + } + } + if(thisupd) *thisupd = single->thisUpdate; + if(nextupd) *nextupd = single->nextUpdate; + return ret; + } + +/* This function combines the previous ones: look a certificate ID and + * if found extract status information. Return 0 is successful. + */ + +int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status, + int *reason, + ASN1_GENERALIZEDTIME **revtime, + ASN1_GENERALIZEDTIME **thisupd, + ASN1_GENERALIZEDTIME **nextupd) + { + int i; + OCSP_SINGLERESP *single; + i = OCSP_resp_find(bs, id, -1); + /* Maybe check for multiple responses and give an error? */ + if(i < 0) return 0; + single = OCSP_resp_get0(bs, i); + i = OCSP_single_get0_status(single, reason, revtime, thisupd, nextupd); + if(reason) *reason = i; + return 1; + } diff --git a/crypto/ocsp/ocsp_err.c b/crypto/ocsp/ocsp_err.c index da0f557275..dd9756a254 100644 --- a/crypto/ocsp/ocsp_err.c +++ b/crypto/ocsp/ocsp_err.c @@ -72,6 +72,8 @@ 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_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_REQUEST_VERIFY,0), "REQUEST_VERIFY"}, {ERR_PACK(0,OCSP_F_RESPONSE_VERIFY,0), "RESPONSE_VERIFY"}, @@ -89,6 +91,9 @@ static ERR_STRING_DATA OCSP_str_reasons[]= {OCSP_R_FAILED_TO_READ ,"failed to read"}, {OCSP_R_FAILED_TO_STAT ,"failed to stat"}, {OCSP_R_MISSING_VALUE ,"missing value"}, +{OCSP_R_NONCE_MISSING_IN_RESPONSE ,"nonce missing in response"}, +{OCSP_R_NONCE_VALUE_MISMATCH ,"nonce value mismatch"}, +{OCSP_R_NOT_BASIC_RESPONSE ,"not basic response"}, {OCSP_R_NO_CERTIFICATE ,"no certificate"}, {OCSP_R_NO_CONTENT ,"no content"}, {OCSP_R_NO_PUBLIC_KEY ,"no public key"}, @@ -99,6 +104,7 @@ 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_UNEXPECTED_NONCE_IN_RESPONSE ,"unexpected nonce in response"}, {OCSP_R_UNKNOWN_NID ,"unknown nid"}, {OCSP_R_UNSUPPORTED_OPTION ,"unsupported option"}, {OCSP_R_VALUE_ALREADY ,"value already"}, diff --git a/crypto/ocsp/ocsp_ext.c b/crypto/ocsp/ocsp_ext.c index ab1e1ca480..36e51ddd91 100644 --- a/crypto/ocsp/ocsp_ext.c +++ b/crypto/ocsp/ocsp_ext.c @@ -66,6 +66,7 @@ #include #include #include +#include #include /* Standard wrapper functions for extensions */ @@ -300,6 +301,76 @@ err: return NULL; } +/* Nonce handling functions */ + +/* Add a nonce to an OCSP request. A nonce can be specificed or if NULL + * a random nonce will be generated. + */ + +int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len) + { + unsigned char *tmpval; + ASN1_OCTET_STRING os; + int ret = 0; + if (len <= 0) len = OCSP_DEFAULT_NONCE_LENGTH; + if (val) tmpval = val; + else + { + if (!(tmpval = OPENSSL_malloc(len))) goto err; + RAND_pseudo_bytes(tmpval, len); + } + os.data = tmpval; + os.length = len; + if(!OCSP_REQUEST_add1_ext_i2d(req, NID_id_pkix_OCSP_Nonce, + &os, 0, X509V3_ADD_REPLACE)) + goto err; + ret = 1; + err: + if(!val) OPENSSL_free(tmpval); + return ret; + } + +/* Check nonce validity in a request and response: the nonce + * must be either absent in both or present and equal in both. + */ +int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs) + { + /* + * Since we are only interested in the presence or absence of + * the nonce and comparing its value there is no need to use + * the X509V3 routines: this way we can avoid them allocating an + * ASN1_OCTET_STRING structure for the value which would be + * freed immediately anyway. + */ + + int ret = 0, req_idx, resp_idx; + X509_EXTENSION *req_ext, *resp_ext; + req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1); + resp_idx = OCSP_BASICRESP_get_ext_by_NID(bs, NID_id_pkix_OCSP_Nonce, -1); + /* If both absent its OK */ + if((req_idx < 0) && (resp_idx < 0)) return 1; + if((req_idx < 0) && (resp_idx >= 0)) + { + OCSPerr(OCSP_F_OCSP_CHECK_NONCE, OCSP_R_NONCE_MISSING_IN_RESPONSE); + goto err; + } + if((req_idx < 0) && (resp_idx >= 0)) + { + OCSPerr(OCSP_F_OCSP_CHECK_NONCE, OCSP_R_UNEXPECTED_NONCE_IN_RESPONSE); + goto err; + } + req_ext = OCSP_REQUEST_get_ext(req, req_idx); + resp_ext = OCSP_BASICRESP_get_ext(bs, resp_idx); + if(ASN1_OCTET_STRING_cmp(req_ext->value, resp_ext->value)) + { + OCSPerr(OCSP_F_OCSP_CHECK_NONCE, OCSP_R_NONCE_VALUE_MISMATCH); + goto err; + } + ret = 1; + err: + return ret; + } + X509_EXTENSION *OCSP_nonce_new(void *p, unsigned int len) { X509_EXTENSION *x=NULL; diff --git a/crypto/ocsp/ocsp_lib.c b/crypto/ocsp/ocsp_lib.c index 2a6c472f23..f9d2978402 100644 --- a/crypto/ocsp/ocsp_lib.c +++ b/crypto/ocsp/ocsp_lib.c @@ -64,6 +64,7 @@ #include #include #include +#include #include #include #include @@ -162,51 +163,16 @@ err: return NULL; } -OCSP_ONEREQ *OCSP_request_add0(OCSP_REQUEST *req, OCSP_CERTID *cid) - { - OCSP_ONEREQ *one = NULL; - - if (!(one = OCSP_ONEREQ_new())) goto err; - if (one->reqCert) OCSP_CERTID_free(one->reqCert); - one->reqCert = cid; - if (req && - !sk_OCSP_ONEREQ_push(req->tbsRequest->requestList, one)) - goto err; - return one; -err: - if (one) OCSP_ONEREQ_free(one); - return NULL; - } - -int OCSP_request_sign(OCSP_REQUEST *req, - EVP_PKEY *key, - const EVP_MD *dgst, - STACK_OF(X509) *certs) - { - int i; - OCSP_SIGNATURE *sig; - - if (!(req->optionalSignature = sig = OCSP_SIGNATURE_new())) goto err; - if (!OCSP_REQUEST_sign(req, key, dgst)) goto err; - if (certs) - { - if (!(sig->certs = sk_X509_dup(certs))) goto err; - for (i = 0; i < sk_X509_num(sig->certs); i++) - { - sk_X509_set(sig->certs, i, - X509_dup(sk_X509_value(certs,i))); - if (! sk_X509_value(sig->certs, i)) - goto err; - } - } - return 1; -err: - if (req->optionalSignature) - { - OCSP_SIGNATURE_free(req->optionalSignature); - req->optionalSignature = NULL; - } - return 0; +int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b) + { + int ret; + ret = OBJ_cmp(a->hashAlgorithm->algorithm, b->hashAlgorithm->algorithm); + if (ret) return ret; + ret = ASN1_OCTET_STRING_cmp(a->issuerNameHash, b->issuerNameHash); + if (ret) return ret; + ret = ASN1_OCTET_STRING_cmp(a->issuerKeyHash, b->issuerKeyHash); + if (ret) return ret; + return ASN1_INTEGER_cmp(a->serialNumber, b->serialNumber); } OCSP_BASICRESP *OCSP_basic_response_new(int type, X509* cert) diff --git a/crypto/ocsp/ocsp_prn.c b/crypto/ocsp/ocsp_prn.c index 533d3010f2..f949e4b8ae 100644 --- a/crypto/ocsp/ocsp_prn.c +++ b/crypto/ocsp/ocsp_prn.c @@ -100,7 +100,7 @@ static char *table2string(long s, OCSP_TBLSTR *ts, int len) static char* ocspResponseStatus2string(long s) { static OCSP_TBLSTR rstat_tbl[] = { - { OCSP_RESPONSE_STATUS_SUCCESSFULL, "successful" }, + { OCSP_RESPONSE_STATUS_SUCCESSFUL, "successful" }, { OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, "malformedrequest" }, { OCSP_RESPONSE_STATUS_INTERNALERROR, "internalerror" }, { OCSP_RESPONSE_STATUS_TRYLATER, "trylater" }, @@ -153,7 +153,6 @@ int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST* o, unsigned long flags) if (BIO_write(bp,"\n Requestor List:\n",21) <= 0) goto err; for (i = 0; i < sk_OCSP_ONEREQ_num(inf->requestList); i++) { - if (!sk_OCSP_ONEREQ_value(inf->requestList, i)) continue; one = sk_OCSP_ONEREQ_value(inf->requestList, i); cid = one->reqCert; ocsp_certid_print(bp, cid, 8); @@ -207,6 +206,7 @@ int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE* o, unsigned long flags) BIO_puts(bp," (unknown response type)\n"); return 1; } + p = ASN1_STRING_data(rb->response); i = ASN1_STRING_length(rb->response); if (!(d2i_OCSP_BASICRESP(&br, &p, i))) goto err; -- 2.39.2