ocsp: refactor OCSP response decoding and wolfSSL_OCSP_basic_verify

- Search certificate based on responderId
- Verify response signer is authorized for all single responses
- Align with OpenSSL behavior
- Separate wolfSSL_OCSP_basic_verify from verification done during
  decoding
This commit is contained in:
Marco Oliverio
2025-01-31 18:01:55 +00:00
parent d7711f04ab
commit f526679ad5
5 changed files with 369 additions and 149 deletions

View File

@ -13876,7 +13876,7 @@ static int ProcessCSR_ex(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* InitOcspResponse sets single and status to response struct. */
InitOcspResponse(response, single, status, input +*inOutIdx, status_length, ssl->heap);
if (OcspResponseDecode(response, SSL_CM(ssl), ssl->heap, 0) != 0)
if (OcspResponseDecode(response, SSL_CM(ssl), ssl->heap, 0, 0) != 0)
ret = BAD_CERTIFICATE_STATUS_ERROR;
else if (CompareOcspReqResp(request, response) != 0)
ret = BAD_CERTIFICATE_STATUS_ERROR;
@ -16982,7 +16982,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
status_length, ssl->heap);
response->pendingCAs = pendingCAs;
if ((OcspResponseDecode(response, SSL_CM(ssl), ssl->heap,
0) != 0)
0, 0) != 0)
|| (response->responseStatus != OCSP_SUCCESSFUL)
|| (response->single->status->status != CERT_GOOD))
ret = BAD_CERTIFICATE_STATUS_ERROR;

View File

@ -333,7 +333,7 @@ int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz,
ocspResponse->pendingCAs = TLSX_CSR2_GetPendingSigners(((WOLFSSL*)ocspRequest->ssl)->extensions);
}
#endif
ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0);
ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0, 0);
if (ret != 0) {
ocsp->error = ret;
WOLFSSL_LEAVE("OcspResponseDecode failed", ocsp->error);
@ -631,9 +631,6 @@ int CheckOcspResponder(OcspResponse *bs, DecodedCert *cert, void* vp)
if (!passed) {
WOLFSSL_MSG("\tOCSP Responder not authorized");
#ifdef OPENSSL_EXTRA
bs->verifyError = OCSP_BAD_ISSUER;
#endif
ret = BAD_OCSP_RESPONDER;
break;
}
@ -825,69 +822,155 @@ void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse)
wolfSSL_OCSP_RESPONSE_free(basicResponse);
}
static int OcspRespIdMatches(OcspResponse* resp, const byte* NameHash,
const byte* keyHash)
{
if (resp->responderIdType == OCSP_RESPONDER_ID_NAME)
return (XMEMCMP(NameHash, resp->responderId.nameHash,
SIGNER_DIGEST_SIZE) == 0);
else if (resp->responderIdType == OCSP_RESPONDER_ID_KEY)
return (XMEMCMP(keyHash, resp->responderId.keyHash, KEYID_SIZE) == 0);
return 0;
}
static int OcspFindSigner(WOLFSSL_OCSP_BASICRESP *resp,
WOLF_STACK_OF(WOLFSSL_X509) *certs, DecodedCert **signer, int *embedded,
unsigned long flags)
{
WOLFSSL_X509 *signer_x509 = NULL;
DecodedCert *certDecoded;
int i;
certDecoded = (DecodedCert *)XMALLOC(sizeof(*certDecoded), NULL,
DYNAMIC_TYPE_DCERT);
if (certDecoded == NULL)
return MEMORY_E;
for (i = 0; i < wolfSSL_sk_X509_num(certs); i++) {
signer_x509 = wolfSSL_sk_X509_value(certs, i);
InitDecodedCert(certDecoded, signer_x509->derCert->buffer,
signer_x509->derCert->length, NULL);
if (ParseCertRelative(certDecoded, CERT_TYPE, NO_VERIFY,
NULL, NULL) == 0) {
if (OcspRespIdMatches(resp, certDecoded->subjectHash,
certDecoded->subjectKeyHash)) {
*signer = certDecoded;
*embedded = 0;
return 0;
}
}
FreeDecodedCert(certDecoded);
}
if (flags & WOLFSSL_OCSP_NOINTERN) {
XFREE(certDecoded, NULL, DYNAMIC_TYPE_DCERT);
return ASN_NO_SIGNER_E;
}
/* not found in certs, search the cert embedded in the response */
InitDecodedCert(certDecoded, resp->cert, resp->certSz, NULL);
if (ParseCertRelative(certDecoded, CERT_TYPE, NO_VERIFY, NULL, NULL) == 0) {
if (OcspRespIdMatches(resp, certDecoded->subjectHash,
certDecoded->subjectKeyHash)) {
*signer = certDecoded;
*embedded = 1;
return 0;
}
}
FreeDecodedCert(certDecoded);
XFREE(certDecoded, NULL, DYNAMIC_TYPE_DCERT);
return ASN_NO_SIGNER_E;
}
static int OcspVerifySigner(WOLFSSL_OCSP_BASICRESP *resp, DecodedCert *cert,
WOLFSSL_X509_STORE *st, unsigned long flags)
{
#ifdef WOLFSSL_SMALL_STACK
DecodedCert *c = NULL;
#else
DecodedCert c[1];
#endif
int ret = -1;
if (st == NULL)
return ASN_OCSP_CONFIRM_E;
#ifdef WOLFSSL_SMALL_STACK
c = (DecodedCert *)XMALLOC(sizeof(*c), NULL, DYNAMIC_TYPE_DCERT);
if (c == NULL)
return MEMORY_E;
#endif
InitDecodedCert(c, cert->source, cert->maxIdx, NULL);
if (ParseCertRelative(c, CERT_TYPE, VERIFY, st->cm, NULL) != 0) {
ret = ASN_OCSP_CONFIRM_E;
goto out;
}
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
if ((flags & WOLFSSL_OCSP_NOCHECKS) == 0) {
ret = CheckOcspResponder(resp, c, st->cm);
}
else {
ret = 0;
}
#else
(void)resp;
(void)flags;
ret = 0;
#endif
out:
FreeDecodedCert(c);
#ifdef WOLFSSL_SMALL_STACK
XFREE(c, NULL, DYNAMIC_TYPE_DCERT);
#endif
return ret;
}
/* Signature verified in DecodeBasicOcspResponse.
* But no store available to verify certificate. */
int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP* bs,
WOLF_STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags)
WOLF_STACK_OF(WOLFSSL_X509) * certs, WOLFSSL_X509_STORE* st,
unsigned long flags)
{
int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
#ifdef WOLFSSL_SMALL_STACK
DecodedCert *cert;
#else
DecodedCert cert[1];
#endif
byte certInit = 0;
int idx;
int embedded;
DecodedCert *cert = NULL;
(void)certs;
if (flags & WOLFSSL_OCSP_NOVERIFY)
return WOLFSSL_SUCCESS;
#ifdef WOLFSSL_SMALL_STACK
cert = (DecodedCert *)
XMALLOC(sizeof(*cert), (st && st->cm) ? st->cm->heap : NULL,
DYNAMIC_TYPE_DCERT);
if (cert == NULL)
ret = OcspFindSigner(bs, certs, &cert, &embedded, flags);
if (ret != 0) {
WOLFSSL_MSG("OCSP no signer found");
return WOLFSSL_FAILURE;
#endif
if (bs->verifyError != OCSP_VERIFY_ERROR_NONE)
goto out;
if (flags & WOLFSSL_OCSP_TRUSTOTHER) {
for (idx = 0; idx < wolfSSL_sk_X509_num(certs); idx++) {
WOLFSSL_X509* x = wolfSSL_sk_X509_value(certs, idx);
int derSz = 0;
const byte* der = wolfSSL_X509_get_der(x, &derSz);
if (der != NULL && derSz == (int)bs->certSz &&
XMEMCMP(bs->cert, der, (size_t)derSz) == 0) {
ret = WOLFSSL_SUCCESS;
goto out;
}
}
}
InitDecodedCert(cert, bs->cert, bs->certSz, NULL);
certInit = 1;
if (ParseCertRelative(cert, CERT_TYPE, VERIFY, st->cm, NULL) < 0)
goto out;
/* skip certificate verification if cert in certs and TRUST_OTHER is true */
if (!embedded && (flags & WOLFSSL_OCSP_TRUSTOTHER) != 0)
flags |= WOLFSSL_OCSP_NOVERIFY;
if (!(flags & WOLFSSL_OCSP_NOCHECKS)) {
if (CheckOcspResponder(bs, cert, st->cm) != 0)
/* verify response signature */
ret = ConfirmSignature(
&cert->sigCtx,
bs->response, bs->responseSz,
cert->publicKey, cert->pubKeySize, cert->keyOID,
bs->sig, bs->sigSz, bs->sigOID, bs->sigParams, bs->sigParamsSz,
NULL);
if (ret != 0) {
WOLFSSL_MSG("OCSP signature verification failed");
ret = -1;
goto out;
}
ret = WOLFSSL_SUCCESS;
if ((flags & WOLFSSL_OCSP_NOVERIFY) == 0) {
ret = OcspVerifySigner(bs, cert, st, flags);
}
out:
if (certInit)
FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
XFREE(cert, (st && st->cm) ? st->cm->heap : NULL, DYNAMIC_TYPE_DCERT);
#endif
return ret;
XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
return ret == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
}
void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response)
@ -1025,7 +1108,7 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
XMEMCPY(resp->source, *data, (size_t)len);
resp->maxIdx = (word32)len;
ret = OcspResponseDecode(resp, NULL, NULL, 1);
ret = OcspResponseDecode(resp, NULL, NULL, 1, 1);
if (ret != 0 && ret != WC_NO_ERR_TRACE(ASN_OCSP_CONFIRM_E)) {
/* for just converting from a DER to an internal structure the CA may
* not yet be known to this function for signature verification */

View File

@ -4622,7 +4622,11 @@ static int test_wolfSSL_CheckOCSPResponse(void)
wolfSSL_CertManagerFree(cm);
}
#if defined(WC_RSA_PSS)
/* FIPS v2 and below don't support long salts. */
#if defined(WC_RSA_PSS) && \
(!defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
(HAVE_FIPS_VERSION > 2))) && (!defined(HAVE_SELFTEST) || \
(defined(HAVE_SELFTEST_VERSION) && (HAVE_SELFTEST_VERSION > 2)))
{
const char* responsePssFile = "./certs/ocsp/test-response-rsapss.der";

View File

@ -16822,7 +16822,7 @@ static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID,
#endif /* !NO_ASN_CRYPT && !NO_HASH_WRAPPER */
/* Return codes: 0=Success, Negative (see error-crypt.h), ASN_SIG_CONFIRM_E */
static int ConfirmSignature(SignatureCtx* sigCtx,
int ConfirmSignature(SignatureCtx* sigCtx,
const byte* buf, word32 bufSz,
const byte* key, word32 keySz, word32 keyOID,
const byte* sig, word32 sigSz, word32 sigOID,
@ -23634,6 +23634,19 @@ int wc_CertGetPubKey(const byte* cert, word32 certSz,
return ret;
}
#endif
#ifdef HAVE_OCSP
Signer* findSignerByKeyHash(Signer *list, byte *hash)
{
Signer *s;
for (s = list; s != NULL; s = s->next) {
if (XMEMCMP(s->subjectKeyHash, hash, KEYID_SIZE) == 0) {
return s;
}
}
return NULL;
}
#endif /* WOLFSSL_OCSP */
Signer* findSignerByName(Signer *list, byte *hash)
{
Signer *s;
@ -36864,7 +36877,8 @@ static const ASNItem ocspRespDataASN[] = {
/* byName */
/* BYNAME */ { 1, ASN_CONTEXT_SPECIFIC | 1, 1, 0, 2 },
/* byKey */
/* BYKEY */ { 1, ASN_CONTEXT_SPECIFIC | 2, 1, 0, 2 },
/* BYKEY */ { 1, ASN_CONTEXT_SPECIFIC | 2, 1, 1, 2 },
/* BYKEY_OCT */ { 2, ASN_OCTET_STRING, 0, 0, 0 },
/* producedAt */
/* PA */ { 1, ASN_GENERALIZED_TIME, 0, 0, 0, },
/* responses */
@ -36878,6 +36892,7 @@ enum {
OCSPRESPDATAASN_IDX_VER,
OCSPRESPDATAASN_IDX_BYNAME,
OCSPRESPDATAASN_IDX_BYKEY,
OCSPRESPDATAASN_IDX_BYKEY_OCT,
OCSPRESPDATAASN_IDX_PA,
OCSPRESPDATAASN_IDX_RESP,
OCSPRESPDATAASN_IDX_RESPEXT,
@ -36988,6 +37003,7 @@ static int DecodeResponseData(byte* source, word32* ioIndex,
int ret = 0;
byte version;
word32 dateSz = 0;
word32 responderByKeySz = KEYID_SIZE;
word32 idx = *ioIndex;
OcspEntry* single = NULL;
@ -37006,6 +37022,8 @@ static int DecodeResponseData(byte* source, word32* ioIndex,
GetASN_Int8Bit(&dataASN[OCSPRESPDATAASN_IDX_VER], &version);
GetASN_Buffer(&dataASN[OCSPRESPDATAASN_IDX_PA], resp->producedDate,
&dateSz);
GetASN_Buffer(&dataASN[OCSPRESPDATAASN_IDX_BYKEY_OCT],
resp->responderId.keyHash, &responderByKeySz);
/* Decode the ResponseData. */
ret = GetASN_Items(ocspRespDataASN, dataASN, ocspRespDataASN_Length,
1, source, ioIndex, size);
@ -37023,7 +37041,22 @@ static int DecodeResponseData(byte* source, word32* ioIndex,
}
}
if (ret == 0) {
/* TODO: use byName/byKey fields. */
if (dataASN[OCSPRESPDATAASN_IDX_BYNAME].tag != 0) {
resp->responderIdType = OCSP_RESPONDER_ID_NAME;
ret = CalcHashId_ex(
dataASN[OCSPRESPDATAASN_IDX_BYNAME].data.ref.data,
dataASN[OCSPRESPDATAASN_IDX_BYNAME].data.ref.length,
resp->responderId.nameHash, WC_SHA);
} else {
resp->responderIdType = OCSP_RESPONDER_ID_KEY;
if (dataASN[OCSPRESPDATAASN_IDX_BYKEY_OCT].length != KEYID_SIZE) {
ret = ASN_PARSE_E;
} else {
resp->responderIdType = OCSP_RESPONDER_ID_KEY;
}
}
}
if (ret == 0) {
/* Store size of response. */
resp->responseSz = *ioIndex - idx;
/* Store date format/tag. */
@ -37166,8 +37199,133 @@ enum {
#define ocspBasicRespASN_Length (sizeof(ocspBasicRespASN) / sizeof(ASNItem))
#endif /* WOLFSSL_ASN_TEMPLATE */
static int OcspRespIdMatch(OcspResponse *resp, const byte *NameHash,
const byte *keyHash)
{
if (resp->responderIdType == OCSP_RESPONDER_ID_NAME)
return XMEMCMP(NameHash, resp->responderId.nameHash,
SIGNER_DIGEST_SIZE) == 0;
return XMEMCMP(keyHash, resp->responderId.keyHash, KEYID_SIZE) == 0;
}
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
static int OcspRespCheck(OcspResponse *resp, Signer *responder)
{
OcspEntry *s;
s = resp->single;
if (s == NULL)
return -1;
/* singles responses must have the same issuer */
for (; s != NULL; s = s->next) {
if (XMEMCMP(s->issuerKeyHash, responder->subjectKeyHash,
KEYID_SIZE) != 0)
return -1;
}
return 0;
}
#endif
static Signer *OcspFindSigner(OcspResponse *resp, WOLFSSL_CERT_MANAGER *cm)
{
Signer *s;
if (cm == NULL)
return NULL;
if (resp->responderIdType == OCSP_RESPONDER_ID_NAME) {
#ifndef NO_SKID
s = GetCAByName(cm, resp->responderId.nameHash);
#else
s = GetCA(cm, resp->responderId.nameHash);
#endif
if (s)
return s;
}
else {
s = GetCAByKeyHash(cm, resp->responderId.keyHash);
if (s)
return s;
}
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
if (resp->pendingCAs == NULL)
return NULL;
if (resp->responderIdType == OCSP_RESPONDER_ID_NAME) {
s = findSignerByName(resp->pendingCAs, resp->responderId.nameHash);
if (s)
return s;
}
else {
s = findSignerByKeyHash(resp->pendingCAs, resp->responderId.keyHash);
if (s)
return s;
}
#endif
return NULL;
}
static int OcspCheckCert(OcspResponse *resp, int noVerify,
int noVerifySignature, WOLFSSL_CERT_MANAGER *cm, void *heap)
{
int ret = 0;
#ifdef WOLFSSL_SMALL_STACK
DecodedCert *cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (cert == NULL)
return MEMORY_E;
#else
DecodedCert cert[1];
#endif
InitDecodedCert(cert, resp->cert, resp->certSz, heap);
ret = ParseCertRelative(cert, CERT_TYPE,
noVerify ? NO_VERIFY : VERIFY_OCSP_CERT,
cm, resp->pendingCAs);
if (ret < 0) {
WOLFSSL_MSG("\tOCSP Responder certificate parsing failed");
}
if (ret == 0 && OcspRespIdMatch(resp, cert->subjectHash, cert->subjectKeyHash) == 0) {
WOLFSSL_MSG("\tInternal check doesn't match responder ID, ignoring\n");
ret = BAD_OCSP_RESPONDER;
goto out;
}
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
if (ret == 0 && !noVerify) {
ret = CheckOcspResponder(resp, cert, cm);
if (ret < 0) {
WOLFSSL_MSG("\tOCSP Responder certificate issuer check failed");
goto out;
}
}
#endif /* WOLFSSL_NO_OCSP_ISSUER_CHECK */
if (ret == 0 && !noVerifySignature) {
ret = ConfirmSignature(
&cert->sigCtx,
resp->response, resp->responseSz,
cert->publicKey, cert->pubKeySize, cert->keyOID,
resp->sig, resp->sigSz, resp->sigOID, resp->sigParams,
resp->sigParamsSz, NULL);
}
out:
FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
if (cert != NULL) {
XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
#endif
return ret;
}
static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
OcspResponse* resp, word32 size, void* cm, void* heap, int noVerify)
OcspResponse* resp, word32 size, void* cm, void* heap, int noVerify,
int noVerifySignature)
{
#ifndef WOLFSSL_ASN_TEMPLATE
int length;
@ -37267,12 +37425,8 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
}
else {
WOLFSSL_MSG("\tOCSP Responder key usage check failed");
#ifdef OPENSSL_EXTRA
resp->verifyError = OCSP_BAD_ISSUER;
#else
ret = BAD_OCSP_RESPONDER;
break;
#endif
}
}
#endif
@ -37341,8 +37495,6 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
DECL_ASNGETDATA(dataASN, ocspBasicRespASN_Length);
int ret = 0;
word32 idx = *ioIndex;
const byte* sigParams = NULL;
word32 sigParamsSz = 0;
#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
#ifdef WOLFSSL_SMALL_STACK
DecodedCert* cert = NULL;
@ -37375,10 +37527,10 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
}
#ifdef WC_RSA_PSS
if (ret == 0 && (dataASN[OCSPBASICRESPASN_IDX_SIGNATURE_PARAMS].tag != 0)) {
sigParams = GetASNItem_Addr(
resp->sigParams = GetASNItem_Addr(
dataASN[OCSPBASICRESPASN_IDX_SIGNATURE_PARAMS],
source);
sigParamsSz =
resp->sigParamsSz =
GetASNItem_Length(dataASN[OCSPBASICRESPASN_IDX_SIGNATURE_PARAMS],
source);
}
@ -37389,6 +37541,7 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
GetASN_GetRef(&dataASN[OCSPBASICRESPASN_IDX_SIGNATURE], &resp->sig,
&resp->sigSz);
}
resp->certSz = 0;
#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
if ((ret == 0) &&
(dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ].data.ref.data != NULL)) {
@ -37396,73 +37549,34 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
/* Store reference to certificate BER data. */
GetASN_GetRef(&dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ], &resp->cert,
&resp->certSz);
}
/* Allocate a certificate object to decode cert into. */
#ifdef WOLFSSL_SMALL_STACK
cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (cert == NULL) {
ret = MEMORY_E;
if ((ret == 0) && resp->certSz > 0) {
ret = OcspCheckCert(resp, noVerify, noVerifySignature,
(WOLFSSL_CERT_MANAGER*)cm, heap);
if (ret == 0) {
goto out;
}
ret = 0; /* try to verify the OCSP response with CA certs */
}
if ((ret == 0) &&
(dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ].data.ref.data != NULL)) {
#endif
/* Initialize the certificate object. */
InitDecodedCert(cert, resp->cert, resp->certSz, heap);
certInit = 1;
/* Parse the certificate and don't verify if we don't have access to
* Cert Manager. */
ret = ParseCertRelative(cert, CERT_TYPE, noVerify ? NO_VERIFY : VERIFY,
cm, resp->pendingCAs);
if (ret < 0) {
WOLFSSL_MSG("\tOCSP Responder certificate parsing failed");
}
#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */
/* try to verify using cm certs */
if (ret == 0 && !noVerifySignature)
{
ca = OcspFindSigner(resp, (WOLFSSL_CERT_MANAGER*)cm);
if (ca == NULL)
ret = ASN_NO_SIGNER_E;
}
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
if ((ret == 0) &&
(dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ].data.ref.data != NULL) &&
!noVerify) {
ret = CheckOcspResponder(resp, cert, cm);
}
#endif /* WOLFSSL_NO_OCSP_ISSUER_CHECK */
if ((ret == 0) &&
(dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ].data.ref.data != NULL)) {
/* TODO: ConfirmSignature is blocking here */
/* Check the signature of the response. */
ret = ConfirmSignature(&cert->sigCtx, resp->response, resp->responseSz,
cert->publicKey, cert->pubKeySize, cert->keyOID, resp->sig,
resp->sigSz, resp->sigOID, NULL, 0, NULL);
if (ret != 0) {
WOLFSSL_MSG("\tOCSP Confirm signature failed");
ret = ASN_OCSP_CONFIRM_E;
if (ret == 0 && !noVerifySignature) {
if (OcspRespCheck(resp, ca) != 0) {
ret = BAD_OCSP_RESPONDER;
}
}
if ((ret == 0) &&
(dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ].data.ref.data == NULL))
#else
if (ret == 0)
#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */
{
Signer* ca;
#endif
if (ret == 0 && !noVerifySignature) {
int sigValid = -1;
/* Response didn't have a certificate - lookup CA. */
#ifndef NO_SKID
ca = GetCAByKeyHash(cm, resp->single->issuerKeyHash);
#else
ca = GetCA(cm, resp->single->issuerHash);
#endif
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
if (ca == NULL && resp->pendingCAs != NULL) {
ca = findSignerByName(resp->pendingCAs, resp->single->issuerHash);
}
#endif
if (ca) {
SignatureCtx sigCtx;
/* Initialize he signature context. */
InitSignatureCtx(&sigCtx, heap, INVALID_DEVID);
@ -37470,16 +37584,14 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
/* Check the signature of the response CA public key. */
sigValid = ConfirmSignature(&sigCtx, resp->response,
resp->responseSz, ca->publicKey, ca->pubKeySize, ca->keyOID,
resp->sig, resp->sigSz, resp->sigOID, sigParams, sigParamsSz,
NULL);
}
if ((ca == NULL) || (sigValid != 0)) {
/* Didn't find certificate or signature verificate failed. */
resp->sig, resp->sigSz, resp->sigOID, resp->sigParams,
resp->sigParamsSz, NULL);
if (sigValid != 0) {
WOLFSSL_MSG("\tOCSP Confirm signature failed");
ret = ASN_OCSP_CONFIRM_E;
}
}
out:
if (ret == 0) {
/* Update the position to after response data. */
*ioIndex = idx;
@ -37518,6 +37630,9 @@ void InitOcspResponse(OcspResponse* resp, OcspEntry* single, CertStatus* status,
resp->maxIdx = inSz;
resp->heap = heap;
resp->pendingCAs = NULL;
resp->sigParams = NULL;
resp->sigParamsSz = 0;
resp->responderIdType = OCSP_RESPONDER_ID_INVALID;
}
void FreeOcspResponse(OcspResponse* resp)
@ -37571,7 +37686,8 @@ enum {
#define ocspResponseASN_Length (sizeof(ocspResponseASN) / sizeof(ASNItem))
#endif /* WOLFSSL_ASN_TEMPLATE */
int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify)
int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap,
int noVerifyCert, int noVerifySignature)
{
#ifndef WOLFSSL_ASN_TEMPLATE
int ret;
@ -37640,7 +37756,7 @@ int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify)
return ret;
}
ret = DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap, noVerify);
ret = DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap, noVerify, 0);
if (ret < 0) {
WOLFSSL_LEAVE("OcspResponseDecode", ret);
return ret;
@ -37680,7 +37796,7 @@ int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify)
idx = 0;
/* Decode BasicOCSPResponse. */
ret = DecodeBasicOcspResponse(basic, &idx, resp, basicSz, cm, heap,
noVerify);
noVerifyCert, noVerifySignature);
}
/* Only support BasicOCSPResponse. */
else {

View File

@ -2352,7 +2352,12 @@ WOLFSSL_LOCAL int CheckCertSignaturePubKey(const byte* cert, word32 certSz,
WOLFSSL_LOCAL int wc_CertGetPubKey(const byte* cert, word32 certSz,
const unsigned char** pubKey, word32* pubKeySz);
#endif
WOLFSSL_LOCAL int ConfirmSignature(SignatureCtx* sigCtx,
const byte* buf, word32 bufSz,
const byte* key, word32 keySz, word32 keyOID,
const byte* sig, word32 sigSz, word32 sigOID,
const byte* sigParams, word32 sigParamsSz,
byte* rsaKeyIdx);
#ifdef WOLFSSL_CERT_REQ
WOLFSSL_LOCAL int CheckCSRSignaturePubKey(const byte* cert, word32 certSz,
void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID);
@ -2369,6 +2374,7 @@ WOLFSSL_LOCAL int TryDecodeRPKToKey(DecodedCert* cert);
WOLFSSL_LOCAL int wc_GetPubX509(DecodedCert* cert, int verify, int* badDate);
WOLFSSL_LOCAL const byte* OidFromId(word32 id, word32 type, word32* oidSz);
WOLFSSL_LOCAL Signer* findSignerByKeyHash(Signer *list, byte *hash);
WOLFSSL_LOCAL Signer* findSignerByName(Signer *list, byte *hash);
WOLFSSL_LOCAL int FillSigner(Signer* signer, DecodedCert* cert, int type, DerBuffer *der);
WOLFSSL_LOCAL Signer* MakeSigner(void* heap);
@ -2726,6 +2732,11 @@ struct OcspEntry
WC_BITFIELD used:1; /* entry used */
};
enum responderIdType {
OCSP_RESPONDER_ID_INVALID = 0,
OCSP_RESPONDER_ID_NAME = 1,
OCSP_RESPONDER_ID_KEY = 2,
};
/* TODO: Long-term, it would be helpful if we made this struct and other OCSP
structs conform to the ASN spec as described in RFC 6960. It will help
with readability and with implementing OpenSSL compatibility API
@ -2737,6 +2748,12 @@ struct OcspResponse {
byte* response; /* Pointer to beginning of OCSP Response */
word32 responseSz; /* length of the OCSP Response */
enum responderIdType responderIdType;
union {
byte keyHash[KEYID_SIZE];
byte nameHash[KEYID_SIZE];
} responderId ;
byte producedDate[MAX_DATE_SIZE];
/* Date at which this response was signed */
byte producedDateFormat; /* format of the producedDate */
@ -2748,6 +2765,9 @@ struct OcspResponse {
word32 sigSz; /* Length in octets for the sig */
word32 sigOID; /* OID for hash used for sig */
byte* sigParams;
word32 sigParamsSz;
OcspEntry* single; /* chain of OCSP single responses */
byte* nonce; /* pointer to nonce inside ASN.1 response */
@ -2756,9 +2776,6 @@ struct OcspResponse {
byte* source; /* pointer to source buffer, not owned */
word32 maxIdx; /* max offset based on init size */
Signer* pendingCAs;
#ifdef OPENSSL_EXTRA
int verifyError;
#endif
void* heap;
};
@ -2788,7 +2805,7 @@ WOLFSSL_LOCAL void InitOcspResponse(OcspResponse* resp, OcspEntry* single,
CertStatus* status, byte* source, word32 inSz, void* heap);
WOLFSSL_LOCAL void FreeOcspResponse(OcspResponse* resp);
WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap,
int noVerify);
int noVerifyCert, int noVerifySignature);
WOLFSSL_LOCAL int InitOcspRequest(OcspRequest* req, DecodedCert* cert,
byte useNonce, void* heap);