Commit 46a58ab9 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Modify OCSP nonce behaviour.

parent 94fcd013
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -3,6 +3,15 @@

 Changes between 0.9.6 and 0.9.7  [xx XXX 2000]

  *) New nonce behavior. The return value of OCSP_check_nonce() now 
     reflects the various checks performed. Applications can decide
     whether to tolerate certain situations such as an absent nonce
     in a response when one was present in a request: the ocsp application
     just prints out a warning. New function OCSP_add1_basic_nonce()
     this is to allow responders to include a nonce in a response even if
     the request is nonce-less.
     [Steve Henson]

  *) Use the cached encoding of an X509_NAME structure rather than
     copying it. This is apparently the reason for the libsafe "errors"
     but the code is actually correct.
+8 −3
Original line number Diff line number Diff line
@@ -515,11 +515,16 @@ int MAIN(int argc, char **argv)

	if (!noverify)
		{
		if (req && (OCSP_check_nonce(req, bs) <= 0))
		if (req && ((i = OCSP_check_nonce(req, bs)) <= 0))
			{
			if (i == -1)
				BIO_printf(bio_err, "WARNING: no nonce in response\n");
			else
				{
				BIO_printf(bio_err, "Nonce Verify error\n");
				goto end;
				}
			}

		i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
                if (i < 0) i = OCSP_basic_verify(bs, NULL, store, 0);
+35 −54
Original line number Diff line number Diff line
@@ -415,6 +415,7 @@ OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
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_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len);
int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs);
int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req);

@@ -557,63 +558,43 @@ void ERR_load_OCSP_strings(void);
/* Error codes for the OCSP functions. */

/* Function codes. */
#define OCSP_F_ASN1_STRING_ENCODE			 106
#define OCSP_F_BASIC_RESPONSE_NEW			 100
#define OCSP_F_BASIC_RESPONSE_VERIFY			 101
#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_ADD1_STATUS			 118
#define OCSP_F_OCSP_BASIC_SIGN				 119
#define OCSP_F_OCSP_BASIC_VERIFY			 113
#define OCSP_F_OCSP_CHECK_DELEGATED			 117
#define OCSP_F_OCSP_CHECK_IDS				 114
#define OCSP_F_OCSP_CHECK_ISSUER			 115
#define OCSP_F_OCSP_CHECK_NONCE				 112
#define OCSP_F_OCSP_MATCH_ISSUERID			 116
#define OCSP_F_OCSP_REQUEST_SIGN			 120
#define OCSP_F_ASN1_STRING_ENCODE			 100
#define OCSP_F_CERT_ID_NEW				 101
#define OCSP_F_D2I_OCSP_NONCE				 102
#define OCSP_F_OCSP_BASIC_ADD1_STATUS			 103
#define OCSP_F_OCSP_BASIC_SIGN				 104
#define OCSP_F_OCSP_BASIC_VERIFY			 105
#define OCSP_F_OCSP_CHECK_DELEGATED			 106
#define OCSP_F_OCSP_CHECK_IDS				 107
#define OCSP_F_OCSP_CHECK_ISSUER			 108
#define OCSP_F_OCSP_MATCH_ISSUERID			 109
#define OCSP_F_OCSP_REQUEST_SIGN			 110
#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
#define OCSP_F_S2I_OCSP_NONCE				 107
#define OCSP_F_V2I_OCSP_CRLID				 108
#define OCSP_F_OCSP_SENDREQ_BIO				 112
#define OCSP_F_REQUEST_VERIFY				 113

/* Reason codes. */
#define OCSP_R_BAD_DATA					 108
#define OCSP_R_BAD_TAG					 100
#define OCSP_R_CERTIFICATE_VERIFY_ERROR			 126
#define OCSP_R_DIGEST_ERR				 101
#define OCSP_R_FAILED_TO_OPEN				 109
#define OCSP_R_FAILED_TO_READ				 110
#define OCSP_R_FAILED_TO_STAT				 111
#define OCSP_R_MISSING_OCSPSIGNING_USAGE		 131
#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_CERTIFICATES_IN_CHAIN			 128
#define OCSP_R_NO_CONTENT				 115
#define OCSP_R_NO_PUBLIC_KEY				 103
#define OCSP_R_NO_RESPONSE_DATA				 104
#define OCSP_R_NO_REVOKED_TIME				 132
#define OCSP_R_NO_SIGNATURE				 105
#define OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE	 133
#define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA	 129
#define OCSP_R_REVOKED_NO_TIME				 106
#define OCSP_R_ROOT_CA_NOT_TRUSTED			 127
#define OCSP_R_SERVER_READ_ERROR			 116
#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_MESSAGE_DIGEST			 130
#define OCSP_R_UNKNOWN_NID				 107
#define OCSP_R_UNSUPPORTED_OPTION			 113
#define OCSP_R_VALUE_ALREADY				 114
#define OCSP_R_BAD_DATA					 100
#define OCSP_R_CERTIFICATE_VERIFY_ERROR			 101
#define OCSP_R_DIGEST_ERR				 102
#define OCSP_R_MISSING_OCSPSIGNING_USAGE		 103
#define OCSP_R_NOT_BASIC_RESPONSE			 104
#define OCSP_R_NO_CERTIFICATES_IN_CHAIN			 105
#define OCSP_R_NO_CONTENT				 106
#define OCSP_R_NO_PUBLIC_KEY				 107
#define OCSP_R_NO_RESPONSE_DATA				 108
#define OCSP_R_NO_REVOKED_TIME				 109
#define OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE	 110
#define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA	 111
#define OCSP_R_ROOT_CA_NOT_TRUSTED			 112
#define OCSP_R_SERVER_READ_ERROR			 113
#define OCSP_R_SERVER_RESPONSE_ERROR			 114
#define OCSP_R_SERVER_RESPONSE_PARSE_ERROR		 115
#define OCSP_R_SERVER_WRITE_ERROR			 116
#define OCSP_R_SIGNATURE_FAILURE			 117
#define OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND		 118
#define OCSP_R_UNKNOWN_MESSAGE_DIGEST			 119
#define OCSP_R_UNKNOWN_NID				 120

#ifdef  __cplusplus
}
+0 −20
Original line number Diff line number Diff line
@@ -67,10 +67,7 @@
static ERR_STRING_DATA OCSP_str_functs[]=
	{
{ERR_PACK(0,OCSP_F_ASN1_STRING_ENCODE,0),	"ASN1_STRING_encode"},
{ERR_PACK(0,OCSP_F_BASIC_RESPONSE_NEW,0),	"BASIC_RESPONSE_NEW"},
{ERR_PACK(0,OCSP_F_BASIC_RESPONSE_VERIFY,0),	"BASIC_RESPONSE_VERIFY"},
{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_ADD1_STATUS,0),	"OCSP_basic_add1_status"},
{ERR_PACK(0,OCSP_F_OCSP_BASIC_SIGN,0),	"OCSP_basic_sign"},
@@ -78,42 +75,28 @@ static ERR_STRING_DATA OCSP_str_functs[]=
{ERR_PACK(0,OCSP_F_OCSP_CHECK_DELEGATED,0),	"OCSP_CHECK_DELEGATED"},
{ERR_PACK(0,OCSP_F_OCSP_CHECK_IDS,0),	"OCSP_CHECK_IDS"},
{ERR_PACK(0,OCSP_F_OCSP_CHECK_ISSUER,0),	"OCSP_CHECK_ISSUER"},
{ERR_PACK(0,OCSP_F_OCSP_CHECK_NONCE,0),	"OCSP_check_nonce"},
{ERR_PACK(0,OCSP_F_OCSP_MATCH_ISSUERID,0),	"OCSP_MATCH_ISSUERID"},
{ERR_PACK(0,OCSP_F_OCSP_REQUEST_SIGN,0),	"OCSP_request_sign"},
{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"},
{ERR_PACK(0,OCSP_F_S2I_OCSP_NONCE,0),	"S2I_OCSP_NONCE"},
{ERR_PACK(0,OCSP_F_V2I_OCSP_CRLID,0),	"V2I_OCSP_CRLID"},
{0,NULL}
	};

static ERR_STRING_DATA OCSP_str_reasons[]=
	{
{OCSP_R_BAD_DATA                         ,"bad data"},
{OCSP_R_BAD_TAG                          ,"bad tag"},
{OCSP_R_CERTIFICATE_VERIFY_ERROR         ,"certificate verify error"},
{OCSP_R_DIGEST_ERR                       ,"digest err"},
{OCSP_R_FAILED_TO_OPEN                   ,"failed to open"},
{OCSP_R_FAILED_TO_READ                   ,"failed to read"},
{OCSP_R_FAILED_TO_STAT                   ,"failed to stat"},
{OCSP_R_MISSING_OCSPSIGNING_USAGE        ,"missing ocspsigning usage"},
{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_CERTIFICATES_IN_CHAIN         ,"no certificates in chain"},
{OCSP_R_NO_CONTENT                       ,"no content"},
{OCSP_R_NO_PUBLIC_KEY                    ,"no public key"},
{OCSP_R_NO_RESPONSE_DATA                 ,"no response data"},
{OCSP_R_NO_REVOKED_TIME                  ,"no revoked time"},
{OCSP_R_NO_SIGNATURE                     ,"no signature"},
{OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE,"private key does not match certificate"},
{OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA,"response contains no revocation data"},
{OCSP_R_REVOKED_NO_TIME                  ,"revoked no time"},
{OCSP_R_ROOT_CA_NOT_TRUSTED              ,"root ca not trusted"},
{OCSP_R_SERVER_READ_ERROR                ,"server read error"},
{OCSP_R_SERVER_RESPONSE_ERROR            ,"server response error"},
@@ -121,11 +104,8 @@ static ERR_STRING_DATA OCSP_str_reasons[]=
{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_MESSAGE_DIGEST           ,"unknown message digest"},
{OCSP_R_UNKNOWN_NID                      ,"unknown nid"},
{OCSP_R_UNSUPPORTED_OPTION               ,"unsupported option"},
{OCSP_R_VALUE_ALREADY                    ,"value already"},
{0,NULL}
	};

+41 −23
Original line number Diff line number Diff line
@@ -303,11 +303,11 @@ err:

/* Nonce handling functions */

/* Add a nonce to an OCSP request. A nonce can be specificed or if NULL
/* Add a nonce to an extension stack. 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)
static int ocsp_add1_nonce(STACK_OF(X509_EXTENSION) **exts, unsigned char *val, int len)
	{
	unsigned char *tmpval;
	ASN1_OCTET_STRING os;
@@ -321,7 +321,7 @@ int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len)
		}
	os.data = tmpval;
	os.length = len;
	if(!OCSP_REQUEST_add1_ext_i2d(req, NID_id_pkix_OCSP_Nonce,
	if(!X509V3_add1_i2d(exts, NID_id_pkix_OCSP_Nonce,
			&os, 0, X509V3_ADD_REPLACE))
				goto err;
	ret = 1;
@@ -330,9 +330,34 @@ int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len)
	return ret;
	}

/* Check nonce validity in a request and response: the nonce
 * must be either absent in both or present and equal in both. 

/* Add nonce to an OCSP request */

int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len)
	{
	return ocsp_add1_nonce(&req->tbsRequest->requestExtensions, val, len);
	}

/* Same as above but for a response */

int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len)
	{
	return ocsp_add1_nonce(&resp->tbsResponseData->responseExtensions, val, len);
	}

/* Check nonce validity in a request and response.
 * Return value reflects result:
 *  1: nonces present and equal.
 *  2: nonces both absent.
 *  3: nonce present in response only.
 *  0: nonces both present and not equal.
 * -1: nonce in request only.
 *
 *  For most responders clients can check return > 0.
 *  If responder doesn't handle nonces return != 0 may be
 *  necessary. return == 0 is always an error.
 */

int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs)
	{
	/*
@@ -343,32 +368,25 @@ int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs)
	 * freed immediately anyway.
	 */

	int ret = 0, req_idx, resp_idx;
	int 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;
	/* Check both absent */
	if((req_idx < 0) && (resp_idx < 0))
		return 2;
	/* Check in request only */
	if((req_idx >= 0) && (resp_idx < 0))
		{
		OCSPerr(OCSP_F_OCSP_CHECK_NONCE, OCSP_R_NONCE_MISSING_IN_RESPONSE);
		goto err;
		}
		return -1;
	/* Check in response but not request */
	if((req_idx < 0) && (resp_idx >= 0))
		{
		OCSPerr(OCSP_F_OCSP_CHECK_NONCE, OCSP_R_UNEXPECTED_NONCE_IN_RESPONSE);
		goto err;
		}
		return 3;
	/* Otherwise nonce in request and response so retrieve the extensions */
	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;
		return 0;
	return 1;
	}

/* Copy the nonce value (if any) from an OCSP request to