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.
diff --git a/CHANGES b/CHANGES
index f43b723..0c745b6 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 ef76c81..1fce558 100644
--- a/crypto/ocsp/Makefile.ssl
+++ b/crypto/ocsp/Makefile.ssl
@@ -23,10 +23,10 @@
 
 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 7bc23ba..7d45e9f 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 @@
  *       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 @@
 #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_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 @@
 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 @@
 #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 @@
 #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 @@
 #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 0000000..3e73e3b
--- /dev/null
+++ b/crypto/ocsp/ocsp_cl.c
@@ -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;
+	}
diff --git a/crypto/ocsp/ocsp_err.c b/crypto/ocsp/ocsp_err.c
index da0f557..dd9756a 100644
--- a/crypto/ocsp/ocsp_err.c
+++ b/crypto/ocsp/ocsp_err.c
@@ -72,6 +72,8 @@
 {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 @@
 {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 @@
 {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 ab1e1ca..36e51dd 100644
--- a/crypto/ocsp/ocsp_ext.c
+++ b/crypto/ocsp/ocsp_ext.c
@@ -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 @@
 	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 2a6c472..f9d2978 100644
--- a/crypto/ocsp/ocsp_lib.c
+++ b/crypto/ocsp/ocsp_lib.c
@@ -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 @@
 	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 533d301..f949e4b 100644
--- a/crypto/ocsp/ocsp_prn.c
+++ b/crypto/ocsp/ocsp_prn.c
@@ -100,7 +100,7 @@
 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 @@
 	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 @@
 		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;