Add set of OCSP client functions. All experimental
authorDr. Stephen Henson <steve@openssl.org>
Mon, 8 Jan 2001 01:21:55 +0000 (01:21 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 8 Jan 2001 01:21:55 +0000 (01:21 +0000)
and subject to addition, modifcation or deletion.

Add two OCSP nonce utility functions.

Fix typo in status code name.

CHANGES
crypto/ocsp/Makefile.ssl
crypto/ocsp/ocsp.h
crypto/ocsp/ocsp_cl.c [new file with mode: 0644]
crypto/ocsp/ocsp_err.c
crypto/ocsp/ocsp_ext.c
crypto/ocsp/ocsp_lib.c
crypto/ocsp/ocsp_prn.c

diff --git a/CHANGES b/CHANGES
index f43b723..0c745b6 100644 (file)
--- 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.
index ef76c81..1fce558 100644 (file)
@@ -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)
 
index 7bc23ba..7d45e9f 100644 (file)
 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 (file)
index 0000000..3e73e3b
--- /dev/null
@@ -0,0 +1,291 @@
+/* ocsp_cl.c */
+/* Written by Tom Titchener <Tom_Titchener@groove.net> 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 <stdio.h>
+#include <cryptlib.h>
+#include <openssl/objects.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/x509v3.h>
+#include <openssl/ocsp.h>
+
+/* 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;
+       }
index da0f557..dd9756a 100644 (file)
@@ -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"},
index ab1e1ca..36e51dd 100644 (file)
@@ -66,6 +66,7 @@
 #include <openssl/objects.h>
 #include <openssl/x509.h>
 #include <openssl/ocsp.h>
+#include <openssl/rand.h>
 #include <openssl/x509v3.h>
 
 /* 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;
index 2a6c472..f9d2978 100644 (file)
@@ -64,6 +64,7 @@
 #include <stdio.h>
 #include <cryptlib.h>
 #include <openssl/objects.h>
+#include <openssl/rand.h>
 #include <openssl/x509.h>
 #include <openssl/pem.h>
 #include <openssl/x509v3.h>
@@ -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)
index 533d301..f949e4b 100644 (file)
@@ -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;