提交 46a58ab9 编写于 作者: D Dr. Stephen Henson

Modify OCSP nonce behaviour.

上级 94fcd013
...@@ -3,6 +3,15 @@ ...@@ -3,6 +3,15 @@
Changes between 0.9.6 and 0.9.7 [xx XXX 2000] 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 *) Use the cached encoding of an X509_NAME structure rather than
copying it. This is apparently the reason for the libsafe "errors" copying it. This is apparently the reason for the libsafe "errors"
but the code is actually correct. but the code is actually correct.
......
...@@ -515,10 +515,15 @@ int MAIN(int argc, char **argv) ...@@ -515,10 +515,15 @@ int MAIN(int argc, char **argv)
if (!noverify) if (!noverify)
{ {
if (req && (OCSP_check_nonce(req, bs) <= 0)) if (req && ((i = OCSP_check_nonce(req, bs)) <= 0))
{ {
BIO_printf(bio_err, "Nonce Verify error\n"); if (i == -1)
goto end; 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); i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
......
...@@ -415,6 +415,7 @@ OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst, ...@@ -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); 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_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_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs);
int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req); int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req);
...@@ -557,63 +558,43 @@ void ERR_load_OCSP_strings(void); ...@@ -557,63 +558,43 @@ void ERR_load_OCSP_strings(void);
/* Error codes for the OCSP functions. */ /* Error codes for the OCSP functions. */
/* Function codes. */ /* Function codes. */
#define OCSP_F_ASN1_STRING_ENCODE 106 #define OCSP_F_ASN1_STRING_ENCODE 100
#define OCSP_F_BASIC_RESPONSE_NEW 100 #define OCSP_F_CERT_ID_NEW 101
#define OCSP_F_BASIC_RESPONSE_VERIFY 101 #define OCSP_F_D2I_OCSP_NONCE 102
#define OCSP_F_CERT_ID_NEW 102 #define OCSP_F_OCSP_BASIC_ADD1_STATUS 103
#define OCSP_F_CERT_STATUS_NEW 103 #define OCSP_F_OCSP_BASIC_SIGN 104
#define OCSP_F_D2I_OCSP_NONCE 109 #define OCSP_F_OCSP_BASIC_VERIFY 105
#define OCSP_F_OCSP_BASIC_ADD1_STATUS 118 #define OCSP_F_OCSP_CHECK_DELEGATED 106
#define OCSP_F_OCSP_BASIC_SIGN 119 #define OCSP_F_OCSP_CHECK_IDS 107
#define OCSP_F_OCSP_BASIC_VERIFY 113 #define OCSP_F_OCSP_CHECK_ISSUER 108
#define OCSP_F_OCSP_CHECK_DELEGATED 117 #define OCSP_F_OCSP_MATCH_ISSUERID 109
#define OCSP_F_OCSP_CHECK_IDS 114 #define OCSP_F_OCSP_REQUEST_SIGN 110
#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_OCSP_RESPONSE_GET1_BASIC 111 #define OCSP_F_OCSP_RESPONSE_GET1_BASIC 111
#define OCSP_F_OCSP_SENDREQ_BIO 110 #define OCSP_F_OCSP_SENDREQ_BIO 112
#define OCSP_F_REQUEST_VERIFY 104 #define OCSP_F_REQUEST_VERIFY 113
#define OCSP_F_RESPONSE_VERIFY 105
#define OCSP_F_S2I_OCSP_NONCE 107
#define OCSP_F_V2I_OCSP_CRLID 108
/* Reason codes. */ /* Reason codes. */
#define OCSP_R_BAD_DATA 108 #define OCSP_R_BAD_DATA 100
#define OCSP_R_BAD_TAG 100 #define OCSP_R_CERTIFICATE_VERIFY_ERROR 101
#define OCSP_R_CERTIFICATE_VERIFY_ERROR 126 #define OCSP_R_DIGEST_ERR 102
#define OCSP_R_DIGEST_ERR 101 #define OCSP_R_MISSING_OCSPSIGNING_USAGE 103
#define OCSP_R_FAILED_TO_OPEN 109 #define OCSP_R_NOT_BASIC_RESPONSE 104
#define OCSP_R_FAILED_TO_READ 110 #define OCSP_R_NO_CERTIFICATES_IN_CHAIN 105
#define OCSP_R_FAILED_TO_STAT 111 #define OCSP_R_NO_CONTENT 106
#define OCSP_R_MISSING_OCSPSIGNING_USAGE 131 #define OCSP_R_NO_PUBLIC_KEY 107
#define OCSP_R_MISSING_VALUE 112 #define OCSP_R_NO_RESPONSE_DATA 108
#define OCSP_R_NONCE_MISSING_IN_RESPONSE 121 #define OCSP_R_NO_REVOKED_TIME 109
#define OCSP_R_NONCE_VALUE_MISMATCH 122 #define OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 110
#define OCSP_R_NOT_BASIC_RESPONSE 120 #define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA 111
#define OCSP_R_NO_CERTIFICATE 102 #define OCSP_R_ROOT_CA_NOT_TRUSTED 112
#define OCSP_R_NO_CERTIFICATES_IN_CHAIN 128 #define OCSP_R_SERVER_READ_ERROR 113
#define OCSP_R_NO_CONTENT 115 #define OCSP_R_SERVER_RESPONSE_ERROR 114
#define OCSP_R_NO_PUBLIC_KEY 103 #define OCSP_R_SERVER_RESPONSE_PARSE_ERROR 115
#define OCSP_R_NO_RESPONSE_DATA 104 #define OCSP_R_SERVER_WRITE_ERROR 116
#define OCSP_R_NO_REVOKED_TIME 132 #define OCSP_R_SIGNATURE_FAILURE 117
#define OCSP_R_NO_SIGNATURE 105 #define OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND 118
#define OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 133 #define OCSP_R_UNKNOWN_MESSAGE_DIGEST 119
#define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA 129 #define OCSP_R_UNKNOWN_NID 120
#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
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -67,10 +67,7 @@ ...@@ -67,10 +67,7 @@
static ERR_STRING_DATA OCSP_str_functs[]= static ERR_STRING_DATA OCSP_str_functs[]=
{ {
{ERR_PACK(0,OCSP_F_ASN1_STRING_ENCODE,0), "ASN1_STRING_encode"}, {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_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_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_ADD1_STATUS,0), "OCSP_basic_add1_status"},
{ERR_PACK(0,OCSP_F_OCSP_BASIC_SIGN,0), "OCSP_basic_sign"}, {ERR_PACK(0,OCSP_F_OCSP_BASIC_SIGN,0), "OCSP_basic_sign"},
...@@ -78,42 +75,28 @@ static ERR_STRING_DATA OCSP_str_functs[]= ...@@ -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_DELEGATED,0), "OCSP_CHECK_DELEGATED"},
{ERR_PACK(0,OCSP_F_OCSP_CHECK_IDS,0), "OCSP_CHECK_IDS"}, {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_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_MATCH_ISSUERID,0), "OCSP_MATCH_ISSUERID"},
{ERR_PACK(0,OCSP_F_OCSP_REQUEST_SIGN,0), "OCSP_request_sign"}, {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_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_OCSP_SENDREQ_BIO,0), "OCSP_sendreq_bio"},
{ERR_PACK(0,OCSP_F_REQUEST_VERIFY,0), "REQUEST_VERIFY"}, {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} {0,NULL}
}; };
static ERR_STRING_DATA OCSP_str_reasons[]= static ERR_STRING_DATA OCSP_str_reasons[]=
{ {
{OCSP_R_BAD_DATA ,"bad data"}, {OCSP_R_BAD_DATA ,"bad data"},
{OCSP_R_BAD_TAG ,"bad tag"},
{OCSP_R_CERTIFICATE_VERIFY_ERROR ,"certificate verify error"}, {OCSP_R_CERTIFICATE_VERIFY_ERROR ,"certificate verify error"},
{OCSP_R_DIGEST_ERR ,"digest err"}, {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_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_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_CERTIFICATES_IN_CHAIN ,"no certificates in chain"},
{OCSP_R_NO_CONTENT ,"no content"}, {OCSP_R_NO_CONTENT ,"no content"},
{OCSP_R_NO_PUBLIC_KEY ,"no public key"}, {OCSP_R_NO_PUBLIC_KEY ,"no public key"},
{OCSP_R_NO_RESPONSE_DATA ,"no response data"}, {OCSP_R_NO_RESPONSE_DATA ,"no response data"},
{OCSP_R_NO_REVOKED_TIME ,"no revoked time"}, {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_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_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_ROOT_CA_NOT_TRUSTED ,"root ca not trusted"},
{OCSP_R_SERVER_READ_ERROR ,"server read error"}, {OCSP_R_SERVER_READ_ERROR ,"server read error"},
{OCSP_R_SERVER_RESPONSE_ERROR ,"server response error"}, {OCSP_R_SERVER_RESPONSE_ERROR ,"server response error"},
...@@ -121,11 +104,8 @@ static ERR_STRING_DATA OCSP_str_reasons[]= ...@@ -121,11 +104,8 @@ static ERR_STRING_DATA OCSP_str_reasons[]=
{OCSP_R_SERVER_WRITE_ERROR ,"server write error"}, {OCSP_R_SERVER_WRITE_ERROR ,"server write error"},
{OCSP_R_SIGNATURE_FAILURE ,"signature failure"}, {OCSP_R_SIGNATURE_FAILURE ,"signature failure"},
{OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND ,"signer certificate not found"}, {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_MESSAGE_DIGEST ,"unknown message digest"},
{OCSP_R_UNKNOWN_NID ,"unknown nid"}, {OCSP_R_UNKNOWN_NID ,"unknown nid"},
{OCSP_R_UNSUPPORTED_OPTION ,"unsupported option"},
{OCSP_R_VALUE_ALREADY ,"value already"},
{0,NULL} {0,NULL}
}; };
......
...@@ -303,11 +303,11 @@ err: ...@@ -303,11 +303,11 @@ err:
/* Nonce handling functions */ /* 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. * 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; unsigned char *tmpval;
ASN1_OCTET_STRING os; ASN1_OCTET_STRING os;
...@@ -321,7 +321,7 @@ int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len) ...@@ -321,7 +321,7 @@ int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len)
} }
os.data = tmpval; os.data = tmpval;
os.length = len; 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)) &os, 0, X509V3_ADD_REPLACE))
goto err; goto err;
ret = 1; ret = 1;
...@@ -330,9 +330,34 @@ int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len) ...@@ -330,9 +330,34 @@ int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len)
return ret; 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) int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs)
{ {
/* /*
...@@ -343,32 +368,25 @@ 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. * freed immediately anyway.
*/ */
int ret = 0, req_idx, resp_idx; int req_idx, resp_idx;
X509_EXTENSION *req_ext, *resp_ext; X509_EXTENSION *req_ext, *resp_ext;
req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1); 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); resp_idx = OCSP_BASICRESP_get_ext_by_NID(bs, NID_id_pkix_OCSP_Nonce, -1);
/* If both absent its OK */ /* Check both absent */
if((req_idx < 0) && (resp_idx < 0)) return 1; if((req_idx < 0) && (resp_idx < 0))
return 2;
/* Check in request only */
if((req_idx >= 0) && (resp_idx < 0)) if((req_idx >= 0) && (resp_idx < 0))
{ return -1;
OCSPerr(OCSP_F_OCSP_CHECK_NONCE, OCSP_R_NONCE_MISSING_IN_RESPONSE); /* Check in response but not request */
goto err;
}
if((req_idx < 0) && (resp_idx >= 0)) if((req_idx < 0) && (resp_idx >= 0))
{ return 3;
OCSPerr(OCSP_F_OCSP_CHECK_NONCE, OCSP_R_UNEXPECTED_NONCE_IN_RESPONSE); /* Otherwise nonce in request and response so retrieve the extensions */
goto err;
}
req_ext = OCSP_REQUEST_get_ext(req, req_idx); req_ext = OCSP_REQUEST_get_ext(req, req_idx);
resp_ext = OCSP_BASICRESP_get_ext(bs, resp_idx); resp_ext = OCSP_BASICRESP_get_ext(bs, resp_idx);
if(ASN1_OCTET_STRING_cmp(req_ext->value, resp_ext->value)) if(ASN1_OCTET_STRING_cmp(req_ext->value, resp_ext->value))
{ return 0;
OCSPerr(OCSP_F_OCSP_CHECK_NONCE, OCSP_R_NONCE_VALUE_MISMATCH); return 1;
goto err;
}
ret = 1;
err:
return ret;
} }
/* Copy the nonce value (if any) from an OCSP request to /* Copy the nonce value (if any) from an OCSP request to
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册