mirror of
https://github.com/openssl/openssl.git
synced 2025-03-31 20:10:45 +08:00
Enhance OCSP_request_verify() so it finds the signers certificate
properly and supports several flags.
This commit is contained in:
parent
d88a26c489
commit
fafc7f9875
6
CHANGES
6
CHANGES
@ -3,6 +3,12 @@
|
||||
|
||||
Changes between 0.9.6 and 0.9.7 [xx XXX 2000]
|
||||
|
||||
*) Function OCSP_request_verify(). This checks the signature on an
|
||||
OCSP request and verifies the signer certificate. The signer
|
||||
certificate is just checked for a generic purpose and OCSP request
|
||||
trust settings.
|
||||
[Steve Henson]
|
||||
|
||||
*) Add OCSP_check_validity() function to check the validity of OCSP
|
||||
responses. OCSP responses are prepared in real time and may only
|
||||
be a few seconds old. Simply checking that the current time lies
|
||||
|
@ -448,7 +448,7 @@ int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd,
|
||||
ASN1_GENERALIZEDTIME *nextupd,
|
||||
long sec, long maxsec);
|
||||
|
||||
int OCSP_request_verify(OCSP_REQUEST *req, EVP_PKEY *pkey);
|
||||
int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store, unsigned long flags);
|
||||
|
||||
int OCSP_parse_url(char *url, char **phost, char **pport, char **ppath, int *pssl);
|
||||
|
||||
@ -461,6 +461,7 @@ OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one);
|
||||
int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd,
|
||||
ASN1_OCTET_STRING **pikeyHash,
|
||||
ASN1_INTEGER **pserial, OCSP_CERTID *cid);
|
||||
int OCSP_request_is_signed(OCSP_REQUEST *req);
|
||||
OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs);
|
||||
OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp,
|
||||
OCSP_CERTID *cid,
|
||||
@ -576,6 +577,7 @@ void ERR_load_OCSP_strings(void);
|
||||
#define OCSP_F_OCSP_MATCH_ISSUERID 109
|
||||
#define OCSP_F_OCSP_PARSE_URL 114
|
||||
#define OCSP_F_OCSP_REQUEST_SIGN 110
|
||||
#define OCSP_F_OCSP_REQUEST_VERIFY 116
|
||||
#define OCSP_F_OCSP_RESPONSE_GET1_BASIC 111
|
||||
#define OCSP_F_OCSP_SENDREQ_BIO 112
|
||||
#define OCSP_F_REQUEST_VERIFY 113
|
||||
@ -596,6 +598,7 @@ void ERR_load_OCSP_strings(void);
|
||||
#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_REQUEST_NOT_SIGNED 128
|
||||
#define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA 111
|
||||
#define OCSP_R_ROOT_CA_NOT_TRUSTED 112
|
||||
#define OCSP_R_SERVER_READ_ERROR 113
|
||||
@ -609,6 +612,7 @@ void ERR_load_OCSP_strings(void);
|
||||
#define OCSP_R_STATUS_TOO_OLD 127
|
||||
#define OCSP_R_UNKNOWN_MESSAGE_DIGEST 119
|
||||
#define OCSP_R_UNKNOWN_NID 120
|
||||
#define OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE 129
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ static ERR_STRING_DATA OCSP_str_functs[]=
|
||||
{ERR_PACK(0,OCSP_F_OCSP_MATCH_ISSUERID,0), "OCSP_MATCH_ISSUERID"},
|
||||
{ERR_PACK(0,OCSP_F_OCSP_PARSE_URL,0), "OCSP_parse_url"},
|
||||
{ERR_PACK(0,OCSP_F_OCSP_REQUEST_SIGN,0), "OCSP_request_sign"},
|
||||
{ERR_PACK(0,OCSP_F_OCSP_REQUEST_VERIFY,0), "OCSP_request_verify"},
|
||||
{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"},
|
||||
@ -102,6 +103,7 @@ static ERR_STRING_DATA OCSP_str_reasons[]=
|
||||
{OCSP_R_NO_RESPONSE_DATA ,"no response data"},
|
||||
{OCSP_R_NO_REVOKED_TIME ,"no revoked time"},
|
||||
{OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE,"private key does not match certificate"},
|
||||
{OCSP_R_REQUEST_NOT_SIGNED ,"request not signed"},
|
||||
{OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA,"response contains no revocation data"},
|
||||
{OCSP_R_ROOT_CA_NOT_TRUSTED ,"root ca not trusted"},
|
||||
{OCSP_R_SERVER_READ_ERROR ,"server read error"},
|
||||
@ -115,6 +117,7 @@ static ERR_STRING_DATA OCSP_str_reasons[]=
|
||||
{OCSP_R_STATUS_TOO_OLD ,"status too old"},
|
||||
{OCSP_R_UNKNOWN_MESSAGE_DIGEST ,"unknown message digest"},
|
||||
{OCSP_R_UNKNOWN_NID ,"unknown nid"},
|
||||
{OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE ,"unsupported requestorname type"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
|
@ -158,24 +158,6 @@ int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
|
||||
return ASN1_INTEGER_cmp(a->serialNumber, b->serialNumber);
|
||||
}
|
||||
|
||||
/* XXX assumes certs in signature are sorted root to leaf XXX */
|
||||
int OCSP_request_verify(OCSP_REQUEST *req, EVP_PKEY *pkey)
|
||||
{
|
||||
STACK_OF(X509) *sk;
|
||||
|
||||
if (!req->optionalSignature) return 0;
|
||||
if (pkey == NULL)
|
||||
{
|
||||
if (!(sk = req->optionalSignature->certs)) return 0;
|
||||
if (!(pkey=X509_get_pubkey(sk_X509_value(sk, sk_X509_num(sk)-1))))
|
||||
{
|
||||
OCSPerr(OCSP_F_REQUEST_VERIFY,OCSP_R_NO_PUBLIC_KEY);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return OCSP_REQUEST_verify(req, pkey);
|
||||
}
|
||||
|
||||
|
||||
/* Parse a URL and split it up into host, port and path components and whether
|
||||
* it is SSL.
|
||||
|
@ -96,6 +96,12 @@ int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int OCSP_request_is_signed(OCSP_REQUEST *req)
|
||||
{
|
||||
if(req->optionalSignature) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create an OCSP response and encode an optional basic response */
|
||||
OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs)
|
||||
{
|
||||
|
@ -67,6 +67,8 @@ static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, unsigned
|
||||
static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret);
|
||||
static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, STACK_OF(OCSP_SINGLERESP) *sresp);
|
||||
static int ocsp_check_delegated(X509 *x, int flags);
|
||||
static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm, STACK_OF(X509) *certs,
|
||||
X509_STORE *st, unsigned long flags);
|
||||
|
||||
/* Verify a basic response message */
|
||||
|
||||
@ -340,3 +342,90 @@ static int ocsp_check_delegated(X509 *x, int flags)
|
||||
OCSPerr(OCSP_F_OCSP_CHECK_DELEGATED, OCSP_R_MISSING_OCSPSIGNING_USAGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Verify an OCSP request. This is fortunately much easier than OCSP
|
||||
* request verify. Just find the signers certificate and verify it
|
||||
* against a given trust value.
|
||||
*/
|
||||
|
||||
int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store, unsigned long flags)
|
||||
{
|
||||
X509 *signer;
|
||||
X509_NAME *nm;
|
||||
GENERAL_NAME *gen;
|
||||
int ret;
|
||||
X509_STORE_CTX ctx;
|
||||
if (!req->optionalSignature)
|
||||
{
|
||||
OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_REQUEST_NOT_SIGNED);
|
||||
return 0;
|
||||
}
|
||||
gen = req->tbsRequest->requestorName;
|
||||
if (gen->type != GEN_DIRNAME)
|
||||
{
|
||||
OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE);
|
||||
return 0;
|
||||
}
|
||||
nm = gen->d.directoryName;
|
||||
ret = ocsp_req_find_signer(&signer, req, nm, certs, store, flags);
|
||||
if (ret <= 0)
|
||||
{
|
||||
OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
|
||||
flags |= OCSP_NOVERIFY;
|
||||
if (!(flags & OCSP_NOSIGS))
|
||||
{
|
||||
EVP_PKEY *skey;
|
||||
skey = X509_get_pubkey(signer);
|
||||
ret = OCSP_REQUEST_verify(req, skey);
|
||||
EVP_PKEY_free(skey);
|
||||
if(ret <= 0)
|
||||
{
|
||||
OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_SIGNATURE_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!(flags & OCSP_NOVERIFY))
|
||||
{
|
||||
if(flags & OCSP_NOCHAIN)
|
||||
X509_STORE_CTX_init(&ctx, store, signer, NULL);
|
||||
else
|
||||
X509_STORE_CTX_init(&ctx, store, signer, req->optionalSignature->certs);
|
||||
|
||||
X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER);
|
||||
X509_STORE_CTX_set_trust(&ctx, X509_TRUST_OCSP_REQUEST);
|
||||
ret = X509_verify_cert(&ctx);
|
||||
X509_STORE_CTX_cleanup(&ctx);
|
||||
if (ret <= 0)
|
||||
{
|
||||
ret = X509_STORE_CTX_get_error(&ctx);
|
||||
OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,OCSP_R_CERTIFICATE_VERIFY_ERROR);
|
||||
ERR_add_error_data(2, "Verify error:",
|
||||
X509_verify_cert_error_string(ret));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm, STACK_OF(X509) *certs,
|
||||
X509_STORE *st, unsigned long flags)
|
||||
{
|
||||
X509 *signer;
|
||||
if(!(flags & OCSP_NOINTERN))
|
||||
{
|
||||
signer = X509_find_by_subject(req->optionalSignature->certs, nm);
|
||||
*psigner = signer;
|
||||
return 1;
|
||||
}
|
||||
|
||||
signer = X509_find_by_subject(certs, nm);
|
||||
if (signer)
|
||||
{
|
||||
*psigner = signer;
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -301,10 +301,11 @@ DECLARE_STACK_OF(X509_TRUST)
|
||||
#define X509_TRUST_EMAIL 4
|
||||
#define X509_TRUST_OBJECT_SIGN 5
|
||||
#define X509_TRUST_OCSP_SIGN 6
|
||||
#define X509_TRUST_OCSP_REQUEST 7
|
||||
|
||||
/* Keep these up to date! */
|
||||
#define X509_TRUST_MIN 1
|
||||
#define X509_TRUST_MAX 6
|
||||
#define X509_TRUST_MAX 7
|
||||
|
||||
|
||||
/* trust_flags values */
|
||||
|
@ -82,7 +82,8 @@ static X509_TRUST trstandard[] = {
|
||||
{X509_TRUST_SSL_CLIENT, 0, trust_1oidany, "SSL Client", NID_client_auth, NULL},
|
||||
{X509_TRUST_SSL_SERVER, 0, trust_1oidany, "SSL Client", NID_server_auth, NULL},
|
||||
{X509_TRUST_EMAIL, 0, trust_1oidany, "S/MIME email", NID_email_protect, NULL},
|
||||
{X509_TRUST_OCSP_SIGN, 0, trust_1oid, "OCSP responder", NID_OCSP_sign, NULL}
|
||||
{X509_TRUST_OCSP_SIGN, 0, trust_1oid, "OCSP responder", NID_OCSP_sign, NULL},
|
||||
{X509_TRUST_OCSP_REQUEST, 0, trust_1oid, "OCSP request", NID_ad_OCSP, NULL}
|
||||
};
|
||||
|
||||
#define X509_TRUST_COUNT (sizeof(trstandard)/sizeof(X509_TRUST))
|
||||
|
Loading…
x
Reference in New Issue
Block a user