From b5206e8504c01cb1eaade4f4e20b2a89de25e2d9 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Mon, 1 Jul 2024 13:56:26 +0200 Subject: [PATCH] csrv2multi: pending ca list --- src/internal.c | 71 ++++++++++++++++++++-- src/ocsp.c | 29 +++++++-- src/ssl.c | 105 +++++++++++--------------------- src/tls.c | 87 +++++++++++++++++++++++++++ wolfcrypt/src/asn.c | 129 +++++++++++++++++++++++++++++++++++++--- wolfssl/internal.h | 7 +++ wolfssl/wolfcrypt/asn.h | 6 +- 7 files changed, 347 insertions(+), 87 deletions(-) diff --git a/src/internal.c b/src/internal.c index eb6fd5aa0e..691643241e 100644 --- a/src/internal.c +++ b/src/internal.c @@ -14022,6 +14022,7 @@ static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args, buffer* cert; byte* subjectHash = NULL; int alreadySigner = 0; + Signer *extraSigners = NULL; #if defined(HAVE_RPK) int cType; #endif @@ -14123,9 +14124,13 @@ PRAGMA_GCC_DIAG_POP return ret; #endif } - +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (verify != NO_VERIFY && TLSX_CSR2_IsMulti(ssl->extensions)) { + extraSigners = TLSX_CSR2_GetPendingSigners(ssl->extensions); + } +#endif /* Parse Certificate */ - ret = ParseCertRelative(args->dCert, certType, verify, SSL_CM(ssl)); + ret = ParseCertRelativeEx(args->dCert, certType, verify, SSL_CM(ssl), extraSigners); #if defined(HAVE_RPK) /* if cert type has negotiated with peer, confirm the cert received has @@ -14358,6 +14363,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, byte* subjectHash = NULL; int alreadySigner = 0; +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + int addToPendingCAs = 0; +#endif WOLFSSL_ENTER("ProcessPeerCerts"); #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) @@ -14783,9 +14791,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (ret == 0) { #ifdef HAVE_OCSP #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 - if (ssl->status_request_v2) { + addToPendingCAs = 0; + if (ssl->status_request_v2 && TLSX_CSR2_IsMulti(ssl->extensions)) { ret = TLSX_CSR2_InitRequests(ssl->extensions, args->dCert, 0, ssl->heap); + addToPendingCAs = 1; } else /* skips OCSP and force CRL check */ #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ @@ -14930,6 +14940,45 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, skipAddCA = 1; } #endif +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (ret == 0 && addToPendingCAs && !alreadySigner) { + DecodedCert dCertAdd; + DerBuffer *derBuffer; + buffer* cert = &args->certs[args->certIdx]; + Signer *s; + InitDecodedCert(&dCertAdd, cert->buffer, cert->length, ssl->heap); + ret = ParseCert(&dCertAdd, CA_TYPE, NO_VERIFY, SSL_CM(ssl)); + if (ret != 0) { + FreeDecodedCert(&dCertAdd); + goto exit_ppc; + } + ret = AllocDer(&derBuffer, cert->length, CA_TYPE, ssl->heap); + if (ret != 0 || derBuffer == NULL) { + FreeDecodedCert(&dCertAdd); + goto exit_ppc; + } + XMEMCPY(derBuffer->buffer, cert->buffer, cert->length); + s = MakeSigner(SSL_CM(ssl)->heap); + if (s == NULL) { + FreeDecodedCert(&dCertAdd); + ret = MEMORY_E; + goto exit_ppc; + } + ret = FillSigner(s, &dCertAdd, CA_TYPE, derBuffer); + FreeDecodedCert(&dCertAdd); + FreeDer(&derBuffer); + if (ret != 0) { + FreeSigner(s, SSL_CM(ssl)->heap); + goto exit_ppc; + } + skipAddCA = 1; + ret = TLSX_CSR2_AddPendingSigner(ssl->extensions, s); + if (ret != 0) { + FreeSigner(s, ssl->heap); + goto exit_ppc; + } + } +#endif /* If valid CA then add to Certificate Manager */ if (ret == 0 && args->dCert->isCA && @@ -16082,6 +16131,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, OcspRequest* request; word32 list_length = status_length; byte idx = 0; + Signer *pendingCAs = NULL; #ifdef WOLFSSL_SMALL_STACK CertStatus* status; @@ -16098,6 +16148,8 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, ssl->status_request_v2 = 0; + pendingCAs = TLSX_CSR2_GetPendingSigners(ssl->extensions); + #ifdef WOLFSSL_SMALL_STACK status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap, DYNAMIC_TYPE_OCSP_STATUS); @@ -16136,7 +16188,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (status_length) { InitOcspResponse(response, single, status, input +*inOutIdx, status_length, ssl->heap); - + response->pendingCAs = pendingCAs; if ((OcspResponseDecode(response, SSL_CM(ssl), ssl->heap, 0) != 0) || (response->responseStatus != OCSP_SUCCESSFUL) @@ -16180,6 +16232,17 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = BUFFER_ERROR; } +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (ret == 0) { + if (TLSX_CSR2_MergePendingCA(ssl) < 0) { + WOLFSSL_MSG("Failed to merge pending CAs"); + } + } + else { + TLSX_CSR2_ClearPendingCA(ssl); + } +#endif + if (ret != 0) { WOLFSSL_ERROR_VERBOSE(ret); SendAlert(ssl, alert_fatal, bad_certificate_status_response); diff --git a/src/ocsp.c b/src/ocsp.c index e6966eb40c..681f95b8bc 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -328,7 +328,12 @@ int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz, #endif InitOcspResponse(ocspResponse, newSingle, newStatus, response, (word32)responseSz, ocsp->cm->heap); - +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (ocspRequest != NULL && ocspRequest->ssl != NULL && + TLSX_CSR2_IsMulti(((WOLFSSL*)ocspRequest->ssl)->extensions)) { + ocspResponse->pendingCAs = TLSX_CSR2_GetPendingSigners(((WOLFSSL*)ocspRequest->ssl)->extensions); + } +#endif ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0); if (ret != 0) { ocsp->error = ret; @@ -555,7 +560,7 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, #ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK static int CheckOcspResponderChain(OcspEntry* single, DecodedCert *cert, - void* vp) { + void* vp, Signer* pendingCAs) { /* Attempt to build a chain up to cert's issuer */ WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp; Signer* ca = NULL; @@ -574,8 +579,16 @@ static int CheckOcspResponderChain(OcspEntry* single, DecodedCert *cert, /* End loop if no more issuers found or if we have found a self * signed cert (ca == prev) */ - for (ca = GetCAByName(cm, single->issuerHash); ca != NULL && ca != prev; - prev = ca, ca = GetCAByName(cm, ca->issuerNameHash)) { + ca = GetCAByName(cm, single->issuerHash); +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (ca == NULL && pendingCAs != NULL) { + ca = findSignerByName(pendingCAs, single->issuerHash); + } +#else + (void)pendingCAs; +#endif + for (; ca != NULL && ca != prev; + prev = ca) { if (XMEMCMP(cert->issuerHash, ca->issuerNameHash, OCSP_DIGEST_SIZE) == 0) { WOLFSSL_MSG("\tOCSP Response signed by authorized " @@ -584,6 +597,12 @@ static int CheckOcspResponderChain(OcspEntry* single, DecodedCert *cert, passed = 1; break; } + ca = GetCAByName(cm, ca->issuerNameHash); +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (ca == NULL && pendingCAs != NULL) { + ca = findSignerByName(pendingCAs, single->issuerHash); + } +#endif } return passed; } @@ -632,7 +651,7 @@ int CheckOcspResponder(OcspResponse *bs, DecodedCert *cert, void* vp) } #ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK else if (vp != NULL) { - passed = CheckOcspResponderChain(single, cert, vp); + passed = CheckOcspResponderChain(single, cert, vp, bs->pendingCAs); } #endif } diff --git a/src/ssl.c b/src/ssl.c index 7af8bc4ac5..1289eca259 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -5283,6 +5283,38 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) } #endif /* WOLFSSL_TRUST_PEER_CERT */ +int AddSigner(WOLFSSL_CERT_MANAGER* cm, Signer *s) +{ + byte* subjectHash; + Signer* signers; + word32 row; + + if (cm == NULL || s == NULL) + return BAD_FUNC_ARG; + +#ifndef NO_SKID + subjectHash = s->subjectKeyIdHash; +#else + subjectHash = s->subjectNameHash; +#endif + + if (AlreadySigner(cm, subjectHash)) { + FreeSigner(s, cm->heap); + return 0; + } + + row = HashSigner(subjectHash); + + if (wc_LockMutex(&cm->caLock) != 0) + return BAD_MUTEX_E; + + signers = cm->caTable[row]; + s->next = signers; + cm->caTable[row] = s; + + wc_UnLockMutex(&cm->caLock); + return 0; +} /* owns der, internal now uses too */ /* type flag ids from user or from chain received during verify @@ -5437,76 +5469,8 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) if (!signer) ret = MEMORY_ERROR; } - -#ifdef WOLFSSL_DUAL_ALG_CERTS - if (ret == 0 && signer != NULL) { - if (cert->extSapkiSet && cert->sapkiLen > 0) { - /* Allocated space for alternative public key. */ - signer->sapkiDer = (byte*)XMALLOC(cert->sapkiLen, cm->heap, - DYNAMIC_TYPE_PUBLIC_KEY); - if (signer->sapkiDer == NULL) { - ret = MEMORY_E; - } - else { - XMEMCPY(signer->sapkiDer, cert->sapkiDer, cert->sapkiLen); - signer->sapkiLen = cert->sapkiLen; - signer->sapkiOID = cert->sapkiOID; - } - } - } -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - -#if defined(WOLFSSL_AKID_NAME) || defined(HAVE_CRL) - if (ret == 0 && signer != NULL) - ret = CalcHashId(cert->serial, cert->serialSz, signer->serialHash); -#endif - if (ret == 0 && signer != NULL) { - #ifdef WOLFSSL_SIGNER_DER_CERT - ret = AllocDer(&signer->derCert, der->length, der->type, NULL); - } if (ret == 0 && signer != NULL) { - XMEMCPY(signer->derCert->buffer, der->buffer, der->length); - #endif - signer->keyOID = cert->keyOID; - if (cert->pubKeyStored) { - signer->publicKey = cert->publicKey; - signer->pubKeySize = cert->pubKeySize; - } - - if (cert->subjectCNStored) { - signer->nameLen = cert->subjectCNLen; - signer->name = cert->subjectCN; - } - signer->maxPathLen = cert->maxPathLen; - signer->selfSigned = cert->selfSigned; - #ifndef IGNORE_NAME_CONSTRAINTS - signer->permittedNames = cert->permittedNames; - signer->excludedNames = cert->excludedNames; - #endif - #ifndef NO_SKID - XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId, - SIGNER_DIGEST_SIZE); - #endif - XMEMCPY(signer->subjectNameHash, cert->subjectHash, - SIGNER_DIGEST_SIZE); - #if defined(HAVE_OCSP) || defined(HAVE_CRL) - XMEMCPY(signer->issuerNameHash, cert->issuerHash, - SIGNER_DIGEST_SIZE); - #endif - #ifdef HAVE_OCSP - XMEMCPY(signer->subjectKeyHash, cert->subjectKeyHash, - KEYID_SIZE); - #endif - signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage - : 0xFFFF; - signer->next = NULL; /* If Key Usage not set, all uses valid. */ - cert->publicKey = 0; /* in case lock fails don't free here. */ - cert->subjectCN = 0; - #ifndef IGNORE_NAME_CONSTRAINTS - cert->permittedNames = NULL; - cert->excludedNames = NULL; - #endif - signer->type = (byte)type; + ret = FillSigner(signer, cert, type, der); #ifndef NO_SKID row = HashSigner(signer->subjectKeyIdHash); @@ -5514,7 +5478,8 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) row = HashSigner(signer->subjectNameHash); #endif - if (wc_LockMutex(&cm->caLock) == 0) { + + if (ret == 0 && wc_LockMutex(&cm->caLock) == 0) { signer->next = cm->caTable[row]; cm->caTable[row] = signer; /* takes ownership */ wc_UnLockMutex(&cm->caLock); diff --git a/src/tls.c b/src/tls.c index 558afea0d4..d233241119 100644 --- a/src/tls.c +++ b/src/tls.c @@ -3579,10 +3579,20 @@ int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 +static void TLSX_CSR2_FreePendingSigners(Signer *s, void* heap) +{ + Signer* next; + while(s) { + next = s->next; + FreeSigner(s, heap); + s = next; + } +} static void TLSX_CSR2_FreeAll(CertificateStatusRequestItemV2* csr2, void* heap) { CertificateStatusRequestItemV2* next; + TLSX_CSR2_FreePendingSigners(csr2->pendingSigners, heap); for (; csr2; csr2 = next) { next = csr2->next; @@ -3853,6 +3863,83 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, const byte* input, word16 length, return 0; } +static CertificateStatusRequestItemV2* TLSX_CSR2_GetMulti(TLSX *extensions) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; + + for (; csr2; csr2 = csr2->next) { + if (csr2->status_type == WOLFSSL_CSR2_OCSP_MULTI) + return csr2; + } + return NULL; +} + +int TLSX_CSR2_IsMulti(TLSX *extensions) +{ + return TLSX_CSR2_GetMulti(extensions) != NULL; +} + +int TLSX_CSR2_AddPendingSigner(TLSX *extensions, Signer *s) +{ + CertificateStatusRequestItemV2* csr2; + + csr2 = TLSX_CSR2_GetMulti(extensions); + if (!csr2) + return -1; + + s->next = csr2->pendingSigners; + csr2->pendingSigners = s; + return 0; +} + +Signer* TLSX_CSR2_GetPendingSigners(TLSX *extensions) +{ + CertificateStatusRequestItemV2* csr2; + + csr2 = TLSX_CSR2_GetMulti(extensions); + if (!csr2) + return NULL; + + return csr2->pendingSigners; +} + +int TLSX_CSR2_ClearPendingCA(WOLFSSL *ssl) +{ + CertificateStatusRequestItemV2* csr2; + + csr2 = TLSX_CSR2_GetMulti(ssl->extensions); + if (csr2 == NULL) + return 0; + + TLSX_CSR2_FreePendingSigners(csr2->pendingSigners, SSL_CM(ssl)->heap); + csr2->pendingSigners = NULL; + return 0; +} + +int TLSX_CSR2_MergePendingCA(WOLFSSL* ssl) +{ + CertificateStatusRequestItemV2* csr2; + Signer *s, *next; + int r = 0; + + csr2 = TLSX_CSR2_GetMulti(ssl->extensions); + if (csr2 == NULL) + return 0; + + s = csr2->pendingSigners; + while (s != NULL) { + next = s->next; + r = AddSigner(SSL_CM(ssl), s); + if (r != 0) + FreeSigner(s, SSL_CM(ssl)->heap); + s = next; + } + csr2->pendingSigners = NULL; + return r; +} + int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, void* heap) { diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 87e68a4e6c..22f16642b3 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -23388,8 +23388,18 @@ int wc_CertGetPubKey(const byte* cert, word32 certSz, return ret; } #endif +Signer* findSignerByName(Signer *list, byte *hash) +{ + Signer *s; + for (s = list; s != NULL; s = s->next) { + if (XMEMCMP(s->subjectNameHash, hash, SIGNER_DIGEST_SIZE) == 0) { + return s; + } + } + return NULL; +} -int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) +int ParseCertRelativeEx(DecodedCert* cert, int type, int verify, void* cm, Signer *extraCAList) { int ret = 0; #ifndef WOLFSSL_ASN_TEMPLATE @@ -23402,6 +23412,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) int idx = 0; #endif byte* sce_tsip_encRsaKeyIdx; + (void)extraCAList; if (cert == NULL) { return BAD_FUNC_ARG; @@ -23720,8 +23731,13 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) if (!cert->selfSigned || (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE)) { cert->ca = NULL; +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (extraCAList != NULL) { + cert->ca = findSignerByName(extraCAList, cert->issuerHash); + } +#endif #ifndef NO_SKID - if (cert->extAuthKeyIdSet) { + if (cert->ca == NULL && cert->extAuthKeyIdSet) { cert->ca = GetCA(cm, cert->extAuthKeyId); #ifdef WOLFSSL_AKID_NAME if (cert->ca == NULL) { @@ -24040,6 +24056,93 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) return ret; } +int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) +{ + return ParseCertRelativeEx(cert, type, verify, cm, NULL); +} + +int FillSigner(Signer* signer, DecodedCert* cert, int type, DerBuffer *der) +{ + int ret = 0; + + if (signer == NULL || cert == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_DUAL_ALG_CERTS + if (ret == 0 && signer != NULL) { + if (cert->extSapkiSet && cert->sapkiLen > 0) { + /* Allocated space for alternative public key. */ + signer->sapkiDer = (byte*)XMALLOC(cert->sapkiLen, cm->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (signer->sapkiDer == NULL) { + ret = MEMORY_E; + } + else { + XMEMCPY(signer->sapkiDer, cert->sapkiDer, cert->sapkiLen); + signer->sapkiLen = cert->sapkiLen; + signer->sapkiOID = cert->sapkiOID; + } + } + } +#endif /* WOLFSSL_DUAL_ALG_CERTS */ + +#if defined(WOLFSSL_AKID_NAME) || defined(HAVE_CRL) + if (ret == 0 && signer != NULL) + ret = CalcHashId(cert->serial, cert->serialSz, signer->serialHash); +#endif + if (ret == 0 && signer != NULL) { + #ifdef WOLFSSL_SIGNER_DER_CERT + ret = AllocDer(&signer->derCert, der->length, der->type, NULL); + } + if (ret == 0 && signer != NULL) { + XMEMCPY(signer->derCert->buffer, der->buffer, der->length); + #else + (void)der; + #endif + signer->keyOID = cert->keyOID; + if (cert->pubKeyStored) { + signer->publicKey = cert->publicKey; + signer->pubKeySize = cert->pubKeySize; + } + + if (cert->subjectCNStored) { + signer->nameLen = cert->subjectCNLen; + signer->name = cert->subjectCN; + } + signer->maxPathLen = cert->maxPathLen; + signer->selfSigned = cert->selfSigned; + #ifndef IGNORE_NAME_CONSTRAINTS + signer->permittedNames = cert->permittedNames; + signer->excludedNames = cert->excludedNames; + #endif + #ifndef NO_SKID + XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId, + SIGNER_DIGEST_SIZE); + #endif + XMEMCPY(signer->subjectNameHash, cert->subjectHash, + SIGNER_DIGEST_SIZE); + #if defined(HAVE_OCSP) || defined(HAVE_CRL) + XMEMCPY(signer->issuerNameHash, cert->issuerHash, + SIGNER_DIGEST_SIZE); + #endif + #ifdef HAVE_OCSP + XMEMCPY(signer->subjectKeyHash, cert->subjectKeyHash, + KEYID_SIZE); + #endif + signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage + : 0xFFFF; + signer->next = NULL; /* If Key Usage not set, all uses valid. */ + cert->publicKey = 0; /* in case lock fails don't free here. */ + cert->subjectCN = 0; + #ifndef IGNORE_NAME_CONSTRAINTS + cert->permittedNames = NULL; + cert->excludedNames = NULL; + #endif + signer->type = (byte)type; + } + return ret; +} + /* Create and init an new signer */ Signer* MakeSigner(void* heap) { @@ -36458,9 +36561,9 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, cert_inited = 1; /* Don't verify if we don't have access to Cert Manager. */ - ret = ParseCertRelative(cert, CERT_TYPE, + ret = ParseCertRelativeEx(cert, CERT_TYPE, noVerify ? NO_VERIFY : VERIFY_OCSP_CERT, - cm); + cm, resp->pendingCAs); if (ret < 0) { WOLFSSL_MSG("\tOCSP Responder certificate parsing failed"); break; @@ -36519,7 +36622,11 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, #else ca = GetCA(cm, resp->single->issuerHash); #endif - +#if defined(HAVE_CERTIFICATE_STATUS_V2) + if (ca == NULL && resp->pendingCAs != NULL) { + ca = findSignerByName(resp->pendingCAs, resp->single->issuerHash); + } +#endif if (ca) { SignatureCtx sigCtx; InitSignatureCtx(&sigCtx, heap, INVALID_DEVID); @@ -36616,8 +36723,8 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, 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); + ret = ParseCertRelativeEx(cert, CERT_TYPE, noVerify ? NO_VERIFY : VERIFY, + cm, resp->pendingCAs); if (ret < 0) { WOLFSSL_MSG("\tOCSP Responder certificate parsing failed"); } @@ -36656,6 +36763,13 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, #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; @@ -36713,6 +36827,7 @@ void InitOcspResponse(OcspResponse* resp, OcspEntry* single, CertStatus* status, resp->source = source; resp->maxIdx = inSz; resp->heap = heap; + resp->pendingCAs = NULL; } void FreeOcspResponse(OcspResponse* resp) diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 7bac1f6cf8..4b3d7f52ed 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3194,11 +3194,17 @@ typedef struct CSRIv2 { OcspRequest ocsp[1 + MAX_CHAIN_DEPTH]; } request; struct CSRIv2* next; + Signer *pendingSigners; } CertificateStatusRequestItemV2; WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, byte options, void* heap, int devId); #ifndef NO_CERTS +WOLFSSL_LOCAL int TLSX_CSR2_IsMulti(TLSX *extensions); +WOLFSSL_LOCAL int TLSX_CSR2_AddPendingSigner(TLSX *extensions, Signer *s); +WOLFSSL_LOCAL Signer* TLSX_CSR2_GetPendingSigners(TLSX *extensions); +WOLFSSL_LOCAL int TLSX_CSR2_ClearPendingCA(WOLFSSL *ssl); +WOLFSSL_LOCAL int TLSX_CSR2_MergePendingCA(WOLFSSL* ssl); WOLFSSL_LOCAL int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, void* heap); #endif @@ -4054,6 +4060,7 @@ int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 inSz, word16 sz); #ifndef NO_CERTS + WOLFSSL_LOCAL int AddSigner(WOLFSSL_CERT_MANAGER* cm, Signer *s); WOLFSSL_LOCAL int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify); WOLFSSL_LOCAL diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 20c41b7628..893ee882c3 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -2188,6 +2188,8 @@ WOLFSSL_ASN_API int AddSignature(byte* buf, int bodySz, const byte* sig, int sig int sigAlgoType); WOLFSSL_LOCAL int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm); +WOLFSSL_LOCAL int ParseCertRelativeEx(DecodedCert* cert, int type, int verify, + void* cm, Signer *extraCa); WOLFSSL_LOCAL int DecodeToKey(DecodedCert* cert, int verify); #ifdef WOLFSSL_ASN_TEMPLATE WOLFSSL_LOCAL int DecodeCert(DecodedCert* cert, int verify, int* criticalExt); @@ -2196,6 +2198,8 @@ 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* findSignerByName(Signer *list, byte *hash); +WOLFSSL_LOCAL int FillSigner(Signer* signer, DecodedCert* cert, int type, DerBuffer *der); WOLFSSL_LOCAL Signer* MakeSigner(void* heap); WOLFSSL_LOCAL void FreeSigner(Signer* signer, void* heap); WOLFSSL_LOCAL void FreeSignerTable(Signer** table, int rows, void* heap); @@ -2565,7 +2569,7 @@ 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