diff --git a/certs/ocsp/include.am b/certs/ocsp/include.am index 92a72b81e..1b663075f 100644 --- a/certs/ocsp/include.am +++ b/certs/ocsp/include.am @@ -35,4 +35,5 @@ EXTRA_DIST += \ certs/ocsp/root-ca-cert.pem \ certs/ocsp/test-response.der \ certs/ocsp/test-response-rsapss.der \ - certs/ocsp/test-response-nointern.der + certs/ocsp/test-response-nointern.der \ + certs/ocsp/test-multi-response.der diff --git a/certs/ocsp/renewcerts.sh b/certs/ocsp/renewcerts.sh index d5d411953..22103c4d0 100755 --- a/certs/ocsp/renewcerts.sh +++ b/certs/ocsp/renewcerts.sh @@ -87,6 +87,7 @@ PID=$! openssl ocsp -issuer ./root-ca-cert.pem -cert ./intermediate1-ca-cert.pem -url http://localhost:22221/ -respout test-response.der -noverify openssl ocsp -issuer ./root-ca-cert.pem -cert ./intermediate1-ca-cert.pem -url http://localhost:22221/ -respout test-response-nointern.der -no_intern -noverify +openssl ocsp -issuer ./root-ca-cert.pem -cert ./intermediate1-ca-cert.pem -cert ./intermediate2-ca-cert.pem -url http://localhost:22221/ -respout test-multi-response.der -noverify kill $PID wait $PID diff --git a/certs/ocsp/test-multi-response.der b/certs/ocsp/test-multi-response.der new file mode 100644 index 000000000..09ea5d1be Binary files /dev/null and b/certs/ocsp/test-multi-response.der differ diff --git a/src/ocsp.c b/src/ocsp.c index 1141b9e22..0245c05f6 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -327,6 +327,8 @@ int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz, goto end; } if (ocspRequest != NULL) { + /* Has the chance to bubble up response changing ocspResponse->single to + no longer be pointing at newSingle */ ret = CompareOcspReqResp(ocspRequest, ocspResponse); if (ret != 0) { goto end; @@ -361,14 +363,14 @@ int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz, /* Replace existing certificate entry with updated */ newSingle->status->next = status->next; - XMEMCPY(status, newSingle->status, sizeof(CertStatus)); + XMEMCPY(status, ocspResponse->single->status, sizeof(CertStatus)); } else { /* Save new certificate entry */ status = (CertStatus*)XMALLOC(sizeof(CertStatus), ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS); if (status != NULL) { - XMEMCPY(status, newSingle->status, sizeof(CertStatus)); + XMEMCPY(status, ocspResponse->single->status, sizeof(CertStatus)); status->next = entry->status; entry->status = status; entry->ownStatus = 1; @@ -397,6 +399,7 @@ end: ret = OCSP_LOOKUP_FAIL; } + FreeOcspResponse(ocspResponse); #ifdef WOLFSSL_SMALL_STACK XFREE(newStatus, NULL, DYNAMIC_TYPE_OCSP_STATUS); XFREE(newSingle, NULL, DYNAMIC_TYPE_OCSP_ENTRY); diff --git a/tests/api.c b/tests/api.c index fb7d1a90d..fb3aefd58 100644 --- a/tests/api.c +++ b/tests/api.c @@ -1672,6 +1672,7 @@ static int test_wolfSSL_CheckOCSPResponse(void) { #if defined(HAVE_OCSP) && !defined(NO_RSA) && defined(OPENSSL_ALL) const char* responseFile = "./certs/ocsp/test-response.der"; + const char* responseMultiFile = "./certs/ocsp/test-multi-response.der"; const char* responseNoInternFile = "./certs/ocsp/test-response-nointern.der"; const char* caFile = "./certs/ocsp/root-ca-cert.pem"; OcspResponse* res = NULL; @@ -1720,6 +1721,70 @@ static int test_wolfSSL_CheckOCSPResponse(void) AssertNotNull(res); wolfSSL_OCSP_RESPONSE_free(res); + /* check loading a response with multiple certs */ + { + WOLFSSL_CERT_MANAGER* cm = NULL; + OcspEntry *entry; + CertStatus status[1]; + OcspRequest* request; + + byte serial[] = {0x02}; + + byte issuerHash[] = { + 0x44, 0xA8, 0xDB, 0xD1, 0xBC, 0x97, 0x0A, 0x83, + 0x3B, 0x5B, 0x31, 0x9A, 0x4C, 0xB8, 0xD2, 0x52, + 0x37, 0x15, 0x8A, 0x88 + }; + byte issuerKeyHash[] = { + 0x73, 0xB0, 0x1C, 0xA4, 0x2F, 0x82, 0xCB, 0xCF, + 0x47, 0xA5, 0x38, 0xD7, 0xB0, 0x04, 0x82, 0x3A, + 0x7E, 0x72, 0x15, 0x21 + }; + + entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL, + DYNAMIC_TYPE_OPENSSL); + AssertNotNull(entry); + + XMEMSET(entry, 0, sizeof(OcspEntry)); + XMEMSET(status, 0, sizeof(CertStatus)); + + AssertNotNull(request = wolfSSL_OCSP_REQUEST_new()); + request->serial = (byte*)XMALLOC(sizeof(serial), NULL, + DYNAMIC_TYPE_OCSP_REQUEST); + AssertNotNull(request->serial); + + request->serialSz = sizeof(serial); + XMEMCPY(request->serial, serial, sizeof(serial)); + XMEMCPY(request->issuerHash, issuerHash, sizeof(issuerHash)); + XMEMCPY(request->issuerKeyHash, issuerKeyHash, sizeof(issuerKeyHash)); + + AssertNotNull(cm = wolfSSL_CertManagerNew_ex(NULL)); + AssertIntEQ(wolfSSL_CertManagerEnableOCSP(cm, 0), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CertManagerLoadCA(cm, caFile, NULL), + WOLFSSL_SUCCESS); + + f = XFOPEN(responseMultiFile, "rb"); + AssertTrue(f != XBADFILE); + dataSz = (word32)XFREAD(data, 1, sizeof(data), f); + AssertIntGT(dataSz, 0); + XFCLOSE(f); + + AssertIntEQ(wolfSSL_CertManagerCheckOCSPResponse(cm, data, + dataSz, NULL, status, entry, request), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CertManagerCheckOCSPResponse(cm, data, + dataSz, NULL, entry->status, entry, request), WOLFSSL_SUCCESS); + + /* compare the status found */ + AssertNotNull(entry->status); + AssertIntEQ(status->serialSz, entry->status->serialSz); + AssertIntEQ(XMEMCMP(status->serial, entry->status->serial, + status->serialSz), 0); + + wolfSSL_OCSP_CERTID_free(entry); + wolfSSL_OCSP_REQUEST_free(request); + wolfSSL_CertManagerFree(cm); + } + #if defined(WC_RSA_PSS) { const char* responsePssFile = "./certs/ocsp/test-response-rsapss.der"; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 5ad446442..3838daaa4 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -34226,7 +34226,7 @@ static int DecodeResponseData(byte* source, word32* ioIndex, XMEMSET(single->next->status, 0, sizeof(CertStatus)); /* Entry to be freed. */ - single->isDynamic = 1; + single->next->isDynamic = 1; /* used will be 0 (false) */ single = single->next; @@ -34675,11 +34675,14 @@ void InitOcspResponse(OcspResponse* resp, OcspEntry* single, CertStatus* status, void FreeOcspResponse(OcspResponse* resp) { OcspEntry *single, *next; - for (single = resp->single; single; single = next) { - next = single->next; - if (single->isDynamic) { - XFREE(single->status, resp->heap, DYNAMIC_TYPE_OCSP_STATUS); - XFREE(single, resp->heap, DYNAMIC_TYPE_OCSP_ENTRY); + + if (resp != NULL) { + for (single = resp->single; single; single = next) { + next = single->next; + if (single->isDynamic) { + XFREE(single->status, resp->heap, DYNAMIC_TYPE_OCSP_STATUS); + XFREE(single, resp->heap, DYNAMIC_TYPE_OCSP_ENTRY); + } } } }