From bca43654dfadd8be5eb1a4d7b4ea79bf43676661 Mon Sep 17 00:00:00 2001 From: Hayden Roche Date: Thu, 12 Nov 2020 09:20:48 -0600 Subject: [PATCH] Make changes to OCSP ASN code. - Use OcspEntry in OcspResponse instead of CertStatus. OcspEntry is more analogous to an OCSP SingleResponse, which contains issuer name and key hashes. Correspondingly, remove these hashes from OcspResponse, since they'll now be stored per SingleResponse in an OcspEntry. - Add a hashAlgoOID to OcspEntry (corresponds to hashAlgorithm in CertId in RFC 6960). This makes OcspEntry more closely resemble an OCSP SingleResponse. - Change WOLFSSL_OCSP_CERTID to map to OcspEntry. OcspEntry contains all the information that an OCSP CertID contains, and is a better fit than OcspRequest. - Add a pointer to the raw CertId in an OCSP SingleResponse to OcspEntry, along with a size field to indicate how many bytes the CertId occupies. This will be used in an OpenSSL compatibility function, i2d_OCSP_CERTID, which yields the raw bytes of the CertId. --- src/internal.c | 45 +++++---- src/ocsp.c | 205 ++++++++++++++++++++++++---------------- wolfcrypt/src/asn.c | 157 +++++++++++++++--------------- wolfssl/ocsp.h | 4 +- wolfssl/openssl/ocsp.h | 1 + wolfssl/wolfcrypt/asn.h | 59 +++++++----- 6 files changed, 269 insertions(+), 202 deletions(-) diff --git a/src/internal.c b/src/internal.c index 69a4bb84b..5bac4c1be 100644 --- a/src/internal.c +++ b/src/internal.c @@ -9819,9 +9819,11 @@ static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifdef WOLFSSL_SMALL_STACK CertStatus* status; + OcspEntry* single; OcspResponse* response; #else CertStatus status[1]; + OcspEntry single[1]; OcspResponse response[1]; #endif @@ -9851,21 +9853,25 @@ static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifdef WOLFSSL_SMALL_STACK status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap, - DYNAMIC_TYPE_OCSP_STATUS); + DYNAMIC_TYPE_OCSP_STATUS); + single = (OcspEntry*)XMALLOC(sizeof(OcspEntry), ssl->heap, + DYNAMIC_TYPE_OCSP_ENTRY); response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap, - DYNAMIC_TYPE_OCSP_REQUEST); + DYNAMIC_TYPE_OCSP_REQUEST); - if (status == NULL || response == NULL) { + if (status == NULL || single == NULL || response == NULL) { if (status) - XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS); + XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS); + if (single) + XFREE(single, ssl->heap, DYNAMIC_TYPE_OCSP_ENTRY); if (response) - XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); return MEMORY_ERROR; } #endif - InitOcspResponse(response, status, input +*inOutIdx, status_length, ssl->heap); + InitOcspResponse(response, single, status, input +*inOutIdx, status_length, ssl->heap); if (OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, 0) != 0) ret = BAD_CERTIFICATE_STATUS_ERROR; @@ -9873,9 +9879,9 @@ static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = BAD_CERTIFICATE_STATUS_ERROR; else if (response->responseStatus != OCSP_SUCCESSFUL) ret = BAD_CERTIFICATE_STATUS_ERROR; - else if (response->status->status == CERT_REVOKED) + else if (response->single->status->status == CERT_REVOKED) ret = OCSP_CERT_REVOKED; - else if (response->status->status != CERT_GOOD) + else if (response->single->status->status != CERT_GOOD) ret = BAD_CERTIFICATE_STATUS_ERROR; else { @@ -9885,9 +9891,9 @@ static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx, *inOutIdx += status_length; - FreeOcspResponse(response); #ifdef WOLFSSL_SMALL_STACK XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS); + XFREE(single, ssl->heap, DYNAMIC_TYPE_OCSP_ENTRY); XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); #endif @@ -11849,10 +11855,12 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, byte idx = 0; #ifdef WOLFSSL_SMALL_STACK - CertStatus* status; + CertStatus* status; + OcspEntry* single; OcspResponse* response; #else - CertStatus status[1]; + CertStatus status[1]; + OcspEntry single[1]; OcspResponse response[1]; #endif @@ -11868,12 +11876,16 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifdef WOLFSSL_SMALL_STACK status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap, DYNAMIC_TYPE_OCSP_STATUS); + single = (OcspEntry*)XMALLOC(sizeof(OcspEntry), ssl->heap, + DYNAMIC_TYPE_OCSP_ENTRY); response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap, - DYNAMIC_TYPE_OCSP_REQUEST); + DYNAMIC_TYPE_OCSP_REQUEST); - if (status == NULL || response == NULL) { + if (status == NULL || single == NULL || response == NULL) { if (status) XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS); + if (single) + XFREE(single, ssl->heap, DYNAMIC_TYPE_OCSP_ENTRY); if (response) XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); @@ -11897,13 +11909,13 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, } if (status_length) { - InitOcspResponse(response, status, input +*inOutIdx, - status_length, ssl->heap); + InitOcspResponse(response, single, status, input +*inOutIdx, + status_length, ssl->heap); if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, 0) != 0) || (response->responseStatus != OCSP_SUCCESSFUL) - || (response->status->status != CERT_GOOD)) + || (response->single->status != CERT_GOOD)) ret = BAD_CERTIFICATE_STATUS_ERROR; while (ret == 0) { @@ -11930,6 +11942,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifdef WOLFSSL_SMALL_STACK XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS); + XFREE(single, NULL, DYNAMIC_TYPE_OCSP_ENTRY); XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST); #endif diff --git a/src/ocsp.c b/src/ocsp.c index 6a3adc2ce..e00c6bfd5 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -75,6 +75,9 @@ static void FreeOcspEntry(OcspEntry* entry, void* heap) { CertStatus *status, *next; + if (entry == NULL) + return; + WOLFSSL_ENTER("FreeOcspEntry"); for (status = entry->status; status; status = next) { @@ -83,6 +86,16 @@ static void FreeOcspEntry(OcspEntry* entry, void* heap) if (status->rawOcspResponse) XFREE(status->rawOcspResponse, heap, DYNAMIC_TYPE_OCSP_STATUS); +#ifdef OPENSSL_EXTRA + if (status->serialInt) { + if (status->serialInt->isDynamic) { + XFREE(status->serialInt->data, NULL, DYNAMIC_TYPE_OPENSSL); + } + XFREE(status->serialInt, NULL, DYNAMIC_TYPE_OPENSSL); + } + status->serialInt = NULL; +#endif + XFREE(status, heap, DYNAMIC_TYPE_OCSP_STATUS); } @@ -272,9 +285,11 @@ WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int resp { #ifdef WOLFSSL_SMALL_STACK CertStatus* newStatus; + OcspEntry* newSingle; OcspResponse* ocspResponse; #else CertStatus newStatus[1]; + OcspEntry newSingle[1]; OcspResponse ocspResponse[1]; #endif int ret; @@ -282,21 +297,24 @@ WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int resp #ifdef WOLFSSL_SMALL_STACK newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_OCSP_STATUS); + newSingle = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL, + DYNAMIC_TYPE_OCSP_ENTRY); ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_OCSP_REQUEST); - if (newStatus == NULL || ocspResponse == NULL) { - if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (newStatus == NULL || newSingle == NULL || ocspResponse == NULL) { + if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_OCSP_STATUS); + if (newSingle) XFREE(newSingle, NULL, DYNAMIC_TYPE_OCSP_ENTRY); + if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_OCSP_REQUEST); WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); return MEMORY_E; } #endif - XMEMSET(newStatus, 0, sizeof(CertStatus)); + InitOcspResponse(ocspResponse, newSingle, newStatus, response, responseSz, + ocsp->cm->heap); - InitOcspResponse(ocspResponse, newStatus, response, responseSz, ocsp->cm->heap); ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0); if (ret != 0) { ocsp->error = ret; @@ -325,7 +343,7 @@ WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int resp } } - ret = xstat2err(ocspResponse->status->status); + ret = xstat2err(ocspResponse->single->status->status); if (ret == 0) { validated = 1; } @@ -342,15 +360,15 @@ WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int resp } /* Replace existing certificate entry with updated */ - newStatus->next = status->next; - XMEMCPY(status, newStatus, sizeof(CertStatus)); + newSingle->status->next = status->next; + XMEMCPY(status, newSingle->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, newStatus, sizeof(CertStatus)); + XMEMCPY(status, newSingle->status, sizeof(CertStatus)); status->next = entry->status; entry->status = status; entry->totalStatus++; @@ -378,10 +396,10 @@ end: ret = OCSP_LOOKUP_FAIL; } - FreeOcspResponse(ocspResponse); #ifdef WOLFSSL_SMALL_STACK - XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(newStatus, NULL, DYNAMIC_TYPE_OCSP_STATUS); + XFREE(newSingle, NULL, DYNAMIC_TYPE_OCSP_ENTRY); + XFREE(ocspResponse, NULL, DYNAMIC_TYPE_OCSP_REQUEST); #endif return ret; } @@ -501,21 +519,32 @@ int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs, WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd, WOLFSSL_ASN1_TIME** nextupd) { + WOLFSSL_OCSP_SINGLERESP* single; + if (bs == NULL || id == NULL) return WOLFSSL_FAILURE; - /* Only supporting one certificate status in asn.c. */ - if (CompareOcspReqResp(id, bs) != 0) + single = bs->single; + while (single != NULL) { + if ((XMEMCMP(single->status->serial, id->status->serial, single->status->serialSz) == 0) + && (XMEMCMP(single->issuerHash, id->issuerHash, OCSP_DIGEST_SIZE) == 0) + && (XMEMCMP(single->issuerKeyHash, id->issuerKeyHash, OCSP_DIGEST_SIZE) == 0)) { + break; + } + single = single->next; + } + + if (single == NULL) return WOLFSSL_FAILURE; if (status != NULL) - *status = bs->status->status; + *status = single->status->status; if (thisupd != NULL) - *thisupd = &bs->status->thisDateParsed; + *thisupd = &single->status->thisDateParsed; if (nextupd != NULL) - *nextupd = &bs->status->nextDateParsed; + *nextupd = &single->status->nextDateParsed; - /* TODO: Not needed for Nginx. */ + /* TODO: Not needed for Nginx or httpd */ if (reason != NULL) *reason = 0; if (revtime != NULL) @@ -551,7 +580,7 @@ int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd, void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId) { - FreeOcspRequest(certId); + FreeOcspEntry(certId, NULL); XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); } @@ -560,6 +589,7 @@ WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( const WOLFSSL_X509 *issuer) { WOLFSSL_OCSP_CERTID* certId; + CertStatus* certStatus; DecodedCert cert; WOLFSSL_CERT_MANAGER* cm; int ret; @@ -582,23 +612,37 @@ WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), NULL, DYNAMIC_TYPE_OPENSSL); - if (certId != NULL) { - InitDecodedCert(&cert, subject->derCert->buffer, - subject->derCert->length, NULL); - if (ParseCertRelative(&cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) { + certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_OPENSSL); + + if (certId == NULL || certStatus == NULL) { + if (certId) XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); - certId = NULL; - } - else { - ret = InitOcspRequest(certId, &cert, 0, NULL); - if (ret != 0) { - XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); - certId = NULL; - } - } - FreeDecodedCert(&cert); + if (certStatus) + XFREE(certStatus, NULL, DYNAMIC_TYPE_OPENSSL); + + return NULL; } + XMEMSET(certId, 0, sizeof(WOLFSSL_OCSP_CERTID)); + XMEMSET(certStatus, 0, sizeof(CertStatus)); + + certId->status = certStatus; + + InitDecodedCert(&cert, subject->derCert->buffer, + subject->derCert->length, NULL); + if (ParseCertRelative(&cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) { + XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); + certId = NULL; + } + else { + XMEMCPY(certId->issuerHash, cert.issuerHash, OCSP_DIGEST_SIZE); + XMEMCPY(certId->issuerKeyHash, cert.issuerKeyHash, OCSP_DIGEST_SIZE); + XMEMCPY(certId->status->serial, cert.serial, cert.serialSz); + certId->status->serialSz = cert.serialSz; + } + FreeDecodedCert(&cert); + wolfSSL_CertManagerFree(cm); return certId; @@ -637,11 +681,18 @@ int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs, void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response) { - if (response->status != NULL) - XFREE(response->status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (response == NULL) + return; + + if (response->single != NULL) { + FreeOcspEntry(response->single, NULL); + XFREE(response->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY); + } + if (response->source != NULL) XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL); + + XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST); } #ifndef NO_BIO @@ -725,7 +776,7 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, resp = *response; if (resp == NULL) { resp = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, - DYNAMIC_TYPE_OPENSSL); + DYNAMIC_TYPE_OCSP_REQUEST); if (resp == NULL) return NULL; XMEMSET(resp, 0, sizeof(OcspResponse)); @@ -733,16 +784,26 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, resp->source = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (resp->source == NULL) { - XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL); + XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST); return NULL; } - resp->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (resp->status == NULL) { + resp->single = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL, + DYNAMIC_TYPE_OCSP_ENTRY); + if (resp->single == NULL) { XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL); + XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST); return NULL; } + XMEMSET(resp->single, 0, sizeof(OcspEntry)); + resp->single->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_OCSP_STATUS); + if (resp->single->status == NULL) { + XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + XFREE(resp->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY); + return NULL; + } + XMEMSET(resp->single->status, 0, sizeof(CertStatus)); XMEMCPY(resp->source, *data, len); resp->maxIdx = len; @@ -798,22 +859,22 @@ WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response) WOLFSSL_OCSP_BASICRESP* bs; bs = (WOLFSSL_OCSP_BASICRESP*)XMALLOC(sizeof(WOLFSSL_OCSP_BASICRESP), NULL, - DYNAMIC_TYPE_OPENSSL); + DYNAMIC_TYPE_OCSP_REQUEST); if (bs == NULL) return NULL; XMEMCPY(bs, response, sizeof(OcspResponse)); - bs->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + bs->single = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL, + DYNAMIC_TYPE_OCSP_ENTRY); bs->source = (byte*)XMALLOC(bs->maxIdx, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (bs->status == NULL || bs->source == NULL) { - if (bs->status) XFREE(bs->status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (bs->single == NULL || bs->source == NULL) { + if (bs->single) XFREE(bs->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY); if (bs->source) XFREE(bs->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); wolfSSL_OCSP_RESPONSE_free(bs); bs = NULL; } else { - XMEMCPY(bs->status, response->status, sizeof(CertStatus)); + XMEMCPY(bs->single, response->single, sizeof(OcspEntry)); XMEMCPY(bs->source, response->source, response->maxIdx); } return bs; @@ -854,23 +915,10 @@ WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, if (req == NULL || cid == NULL) return NULL; - FreeOcspRequest(req); - XMEMCPY(req, cid, sizeof(OcspRequest)); - - if (cid->serial != NULL) { - req->serial = (byte*)XMALLOC(cid->serialSz, NULL, - DYNAMIC_TYPE_OCSP_REQUEST); - req->url = (byte*)XMALLOC(cid->urlSz, NULL, DYNAMIC_TYPE_OCSP_REQUEST); - if (req->serial == NULL || req->url == NULL) { - FreeOcspRequest(req); - return NULL; - } - - XMEMCPY(req->serial, cid->serial, cid->serialSz); - XMEMCPY(req->url, cid->url, cid->urlSz); - } - - wolfSSL_OCSP_REQUEST_free(cid); + XMEMCPY(req->issuerHash, cid->issuerHash, KEYID_SIZE); + XMEMCPY(req->issuerKeyHash, cid->issuerKeyHash, KEYID_SIZE); + XMEMCPY(req->serial, cid->status->serial, cid->status->serialSz); + req->serialSz = cid->status->serialSz; return req; } @@ -879,12 +927,11 @@ WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_CERTID_dup(WOLFSSL_OCSP_CERTID* id) { WOLFSSL_OCSP_CERTID* certId; - if (id == NULL) { + if (id == NULL) return NULL; - } certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), - id->heap, DYNAMIC_TYPE_OPENSSL); + NULL, DYNAMIC_TYPE_OPENSSL); if (certId) { XMEMCPY(certId, id, sizeof(WOLFSSL_OCSP_CERTID)); } @@ -985,15 +1032,15 @@ int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING **name, if (ser == NULL) return 0; - if (cid->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) { + if (cid->status->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) { /* allocate data buffer, +2 for type and length */ - ser->data = (unsigned char*)XMALLOC(cid->serialSz + 2, NULL, + ser->data = (unsigned char*)XMALLOC(cid->status->serialSz + 2, NULL, DYNAMIC_TYPE_OPENSSL); if (ser->data == NULL) { wolfSSL_ASN1_INTEGER_free(ser); return 0; } - ser->dataMax = cid->serialSz + 2; + ser->dataMax = cid->status->serialSz + 2; ser->isDynamic = 1; } else { /* Use array instead of dynamic memory */ @@ -1003,16 +1050,16 @@ int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING **name, #ifdef WOLFSSL_QT /* Serial number starts at 0 index of ser->data */ - XMEMCPY(&ser->data[i], cid->serial, cid->serialSz); - ser->length = cid->serialSz; + XMEMCPY(&ser->data[i], cid->status->serial, cid->status->serialSz); + ser->length = cid->status->serialSz; #else ser->data[i++] = ASN_INTEGER; - i += SetLength(cid->serialSz, ser->data + i); - XMEMCPY(&ser->data[i], cid->serial, cid->serialSz); + i += SetLength(cid->status->serialSz, ser->data + i); + XMEMCPY(&ser->data[i], cid->status->serial, cid->status->serialSz); #endif - cid->serialInt = ser; - *serial = cid->serialInt; + cid->status->serialInt = ser; + *serial = ser; } /* Not needed for Apache, return error if user is requesting */ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 56b74573d..6c1d938d5 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -16709,11 +16709,10 @@ static int GetEnumerated(const byte* input, word32* inOutIdx, int *value, } -static int DecodeSingleResponse(byte* source, - word32* ioIndex, OcspResponse* resp, word32 size, int wrapperSz, - CertStatus* cs) +static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size, + int wrapperSz, OcspEntry* single) { - word32 idx = *ioIndex, prevIndex, oid, localIdx; + word32 idx = *ioIndex, prevIndex, oid, localIdx, certIdIdx; int length; int ret; byte tag; @@ -16727,46 +16726,51 @@ static int DecodeSingleResponse(byte* source, return ASN_PARSE_E; /* Wrapper around the CertID */ + certIdIdx = idx; if (GetSequence(source, &idx, &length, size) < 0) return ASN_PARSE_E; - /* Skip the hash algorithm */ - if (GetAlgoId(source, &idx, &oid, oidIgnoreType, size) < 0) - return ASN_PARSE_E; + single->rawCertId = source + certIdIdx; + /* Hash algorithm */ + ret = GetAlgoId(source, &idx, &oid, oidIgnoreType, size); + if (ret < 0) + return ret; + single->hashAlgoOID = oid; /* Save reference to the hash of CN */ ret = GetOctetString(source, &idx, &length, size); if (ret < 0) return ret; - resp->issuerHash = source + idx; + XMEMCPY(single->issuerHash, source + idx, length); idx += length; /* Save reference to the hash of the issuer public key */ ret = GetOctetString(source, &idx, &length, size); if (ret < 0) return ret; - resp->issuerKeyHash = source + idx; + XMEMCPY(single->issuerKeyHash, source + idx, length); idx += length; /* Get serial number */ - if (GetSerialNumber(source, &idx, cs->serial, &cs->serialSz, size) < 0) + if (GetSerialNumber(source, &idx, single->status->serial, &single->status->serialSz, size) < 0) return ASN_PARSE_E; + single->rawCertIdSize = idx - certIdIdx; - if ( idx >= size ) + if (idx >= size) return BUFFER_E; /* CertStatus */ switch (source[idx++]) { case (ASN_CONTEXT_SPECIFIC | CERT_GOOD): - cs->status = CERT_GOOD; + single->status->status = CERT_GOOD; idx++; break; case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_REVOKED): - cs->status = CERT_REVOKED; + single->status->status = CERT_REVOKED; if (GetLength(source, &idx, &length, size) < 0) return ASN_PARSE_E; idx += length; break; case (ASN_CONTEXT_SPECIFIC | CERT_UNKNOWN): - cs->status = CERT_UNKNOWN; + single->status->status = CERT_UNKNOWN; idx++; break; default: @@ -16774,23 +16778,23 @@ static int DecodeSingleResponse(byte* source, } #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) - cs->thisDateAsn = source + idx; + single->status->thisDateAsn = source + idx; localIdx = 0; - if (GetDateInfo(cs->thisDateAsn, &localIdx, NULL, - (byte*)&cs->thisDateParsed.type, - &cs->thisDateParsed.length, size) < 0) + if (GetDateInfo(single->status->thisDateAsn, &localIdx, NULL, + (byte*)&single->status->thisDateParsed.type, + &single->status->thisDateParsed.length, size) < 0) return ASN_PARSE_E; - XMEMCPY(cs->thisDateParsed.data, - cs->thisDateAsn + localIdx - cs->thisDateParsed.length, - cs->thisDateParsed.length); + XMEMCPY(single->status->thisDateParsed.data, + single->status->thisDateAsn + localIdx - single->status->thisDateParsed.length, + single->status->thisDateParsed.length); #endif - if (GetBasicDate(source, &idx, cs->thisDate, - &cs->thisDateFormat, size) < 0) + if (GetBasicDate(source, &idx, single->status->thisDate, + &single->status->thisDateFormat, size) < 0) return ASN_PARSE_E; #ifndef NO_ASN_TIME #ifndef WOLFSSL_NO_OCSP_DATE_CHECK - if (!XVALIDATE_DATE(cs->thisDate, cs->thisDateFormat, BEFORE)) + if (!XVALIDATE_DATE(single->status->thisDate, single->status->thisDateFormat, BEFORE)) return ASN_BEFORE_DATE_E; #endif #endif @@ -16806,23 +16810,23 @@ static int DecodeSingleResponse(byte* source, if (GetLength(source, &idx, &length, size) < 0) return ASN_PARSE_E; #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) - cs->nextDateAsn = source + idx; + single->status->nextDateAsn = source + idx; localIdx = 0; - if (GetDateInfo(cs->nextDateAsn, &localIdx, NULL, - (byte*)&cs->nextDateParsed.type, - &cs->nextDateParsed.length, size) < 0) + if (GetDateInfo(single->status->nextDateAsn, &localIdx, NULL, + (byte*)&single->status->nextDateParsed.type, + &single->status->nextDateParsed.length, size) < 0) return ASN_PARSE_E; - XMEMCPY(cs->nextDateParsed.data, - cs->nextDateAsn + localIdx - cs->nextDateParsed.length, - cs->nextDateParsed.length); + XMEMCPY(single->status->nextDateParsed.data, + single->status->nextDateAsn + localIdx - single->status->nextDateParsed.length, + single->status->nextDateParsed.length); #endif - if (GetBasicDate(source, &idx, cs->nextDate, - &cs->nextDateFormat, size) < 0) + if (GetBasicDate(source, &idx, single->status->nextDate, + &single->status->nextDateFormat, size) < 0) return ASN_PARSE_E; #ifndef NO_ASN_TIME #ifndef WOLFSSL_NO_OCSP_DATE_CHECK - if (!XVALIDATE_DATE(cs->nextDate, cs->nextDateFormat, AFTER)) + if (!XVALIDATE_DATE(single->status->nextDate, single->status->nextDateFormat, AFTER)) return ASN_AFTER_DATE_E; #endif #endif @@ -16933,7 +16937,7 @@ static int DecodeResponseData(byte* source, int ret; byte tag; int wrapperSz; - CertStatus* cs; + OcspEntry* single; WOLFSSL_ENTER("DecodeResponseData"); @@ -16980,20 +16984,21 @@ static int DecodeResponseData(byte* source, return ASN_PARSE_E; localIdx = idx; - cs = resp->status; + single = resp->single; + while (idx - localIdx < (word32)wrapperSz) { - ret = DecodeSingleResponse(source, &idx, resp, size, wrapperSz, cs); + ret = DecodeSingleResponse(source, &idx, size, wrapperSz, single); if (ret < 0) return ret; /* ASN_PARSE_E, ASN_BEFORE_DATE_E, ASN_AFTER_DATE_E */ if (idx - localIdx < (word32)wrapperSz) { - cs->next = (CertStatus*)XMALLOC(sizeof(CertStatus), resp->heap, - DYNAMIC_TYPE_OCSP_STATUS); - if (cs->next == NULL) { + single->next = (OcspEntry*)XMALLOC(sizeof(OcspEntry), resp->heap, + DYNAMIC_TYPE_OCSP_ENTRY); + if (single->next == NULL) { return MEMORY_E; } - cs = cs->next; - XMEMSET(cs, 0, sizeof(CertStatus)); - cs->isDynamic = 1; + single = single->next; + XMEMSET(single, 0, sizeof(OcspEntry)); + single->isDynamic = 1; } } @@ -17105,7 +17110,7 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, #ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK if ((cert.extExtKeyUsage & EXTKEYUSE_OCSP_SIGN) == 0) { if (XMEMCMP(cert.subjectHash, - resp->issuerHash, KEYID_SIZE) == 0) { + resp->single->issuerHash, OCSP_DIGEST_SIZE) == 0) { WOLFSSL_MSG("\tOCSP Response signed by issuer"); } else { @@ -17140,9 +17145,9 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, int sigValid = -1; #ifndef NO_SKID - ca = GetCA(cm, resp->issuerKeyHash); + ca = GetCA(cm, resp->single->issuerKeyHash); #else - ca = GetCA(cm, resp->issuerHash); + ca = GetCA(cm, resp->single->issuerHash); #endif if (ca) { @@ -17167,16 +17172,18 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, } -void InitOcspResponse(OcspResponse* resp, CertStatus* status, - byte* source, word32 inSz, void* heap) +void InitOcspResponse(OcspResponse* resp, OcspEntry* single, CertStatus* status, + byte* source, word32 inSz, void* heap) { WOLFSSL_ENTER("InitOcspResponse"); XMEMSET(status, 0, sizeof(CertStatus)); + XMEMSET(single, 0, sizeof(OcspEntry)); XMEMSET(resp, 0, sizeof(OcspResponse)); + single->status = status; resp->responseStatus = -1; - resp->status = status; + resp->single = single; resp->source = source; resp->maxIdx = inSz; resp->heap = heap; @@ -17184,11 +17191,11 @@ void InitOcspResponse(OcspResponse* resp, CertStatus* status, void FreeOcspResponse(OcspResponse* resp) { - CertStatus *status, *next; - for (status = resp->status; status; status = next) { - next = status->next; - if (status->isDynamic) - XFREE(status, resp->heap, DYNAMIC_TYPE_OCSP_STATUS); + OcspEntry *single, *next; + for (single = resp->single; single; single = next) { + next = single->next; + if (single->isDynamic) + XFREE(single, resp->heap, DYNAMIC_TYPE_OCSP_ENTRY); } } @@ -17464,7 +17471,7 @@ void FreeOcspRequest(OcspRequest* req) int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp) { int cmp; - CertStatus *status, *next, *prev = NULL, *top; + OcspEntry *single, *next, *prev = NULL, *top; WOLFSSL_ENTER("CompareOcspReqResp"); @@ -17472,8 +17479,7 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp) WOLFSSL_MSG("\tReq missing"); return -1; } - if (resp == NULL || resp->issuerHash == NULL || - resp->issuerKeyHash == NULL || resp->status == NULL) { + if (resp == NULL || resp->single == NULL) { WOLFSSL_MSG("\tResp missing"); return 1; } @@ -17498,41 +17504,30 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp) } } - cmp = XMEMCMP(req->issuerHash, resp->issuerHash, KEYID_SIZE); - if (cmp != 0) { - WOLFSSL_MSG("\tissuerHash mismatch"); - return cmp; - } - - cmp = XMEMCMP(req->issuerKeyHash, resp->issuerKeyHash, KEYID_SIZE); - if (cmp != 0) { - WOLFSSL_MSG("\tissuerKeyHash mismatch"); - return cmp; - } - /* match based on found status and return */ - for (status = resp->status; status; status = next) { - cmp = req->serialSz - status->serialSz; + for (single = resp->single; single; single = next) { + cmp = req->serialSz - single->status->serialSz; if (cmp == 0) { - cmp = XMEMCMP(req->serial, status->serial, req->serialSz); - if (cmp == 0) { + if ((XMEMCMP(req->serial, single->status->serial, req->serialSz) == 0) + && (XMEMCMP(req->issuerHash, single->issuerHash, OCSP_DIGEST_SIZE) == 0) + && (XMEMCMP(req->issuerKeyHash, single->issuerKeyHash, OCSP_DIGEST_SIZE) == 0)) { /* match found */ - if (resp->status != status && prev) { + if (resp->single != single && prev) { /* move to top of list */ - top = resp->status; - resp->status = status; - prev->next = status->next; - status->next = top; + top = resp->single; + resp->single = single; + prev->next = single->next; + single->next = top; } break; } } - next = status->next; - prev = status; + next = single->next; + prev = single; } if (cmp != 0) { - WOLFSSL_MSG("\tserial mismatch"); + WOLFSSL_MSG("\trequest and response mismatch"); return cmp; } diff --git a/wolfssl/ocsp.h b/wolfssl/ocsp.h index 3a80f3693..cba383277 100644 --- a/wolfssl/ocsp.h +++ b/wolfssl/ocsp.h @@ -41,7 +41,9 @@ typedef struct WOLFSSL_OCSP WOLFSSL_OCSP; defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY) typedef struct OcspResponse WOLFSSL_OCSP_BASICRESP; -typedef struct OcspRequest WOLFSSL_OCSP_CERTID; +typedef struct OcspEntry WOLFSSL_OCSP_CERTID; + +typedef struct OcspEntry WOLFSSL_OCSP_SINGLERESP; typedef struct OcspRequest WOLFSSL_OCSP_ONEREQ; diff --git a/wolfssl/openssl/ocsp.h b/wolfssl/openssl/ocsp.h index d880f23ca..821a442ee 100644 --- a/wolfssl/openssl/ocsp.h +++ b/wolfssl/openssl/ocsp.h @@ -30,6 +30,7 @@ #define OCSP_REQUEST OcspRequest #define OCSP_RESPONSE OcspResponse #define OCSP_BASICRESP WOLFSSL_OCSP_BASICRESP +#define OCSP_SINGLERESP WOLFSSL_OCSP_SINGLERESP #define OCSP_CERTID WOLFSSL_OCSP_CERTID #define OCSP_ONEREQ WOLFSSL_OCSP_ONEREQ diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 227ad4e06..edb3d0d12 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1258,6 +1258,9 @@ struct CertStatus { byte serial[EXTERNAL_SERIAL_SIZE]; int serialSz; +#ifdef OPENSSL_EXTRA + WOLFSSL_ASN1_INTEGER* serialInt; +#endif int status; @@ -1274,11 +1277,36 @@ struct CertStatus { byte* rawOcspResponse; word32 rawOcspResponseSz; - - /* option bits - using 32-bit for alignment */ - word32 isDynamic:1; /* was allocated cert status */ }; +typedef struct OcspEntry OcspEntry; + +#ifdef NO_SHA +#define OCSP_DIGEST_SIZE WC_SHA256_DIGEST_SIZE +#else +#define OCSP_DIGEST_SIZE WC_SHA_DIGEST_SIZE +#endif + +struct OcspEntry +{ + OcspEntry *next; /* next entry */ + word32 hashAlgoOID; /* hash algo ID */ + byte issuerHash[OCSP_DIGEST_SIZE]; /* issuer hash */ + byte issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */ + CertStatus *status; /* OCSP response list */ + int totalStatus; /* number on list */ + byte* rawCertId; /* raw bytes of the CertID */ + int rawCertIdSize; /* num bytes in raw CertID */ + /* option bits - using 32-bit for alignment */ + word32 isDynamic:1; /* was dynamically allocated */ + +}; + +/* 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 + functions, because OpenSSL's OCSP data structures conform to the + RFC. */ struct OcspResponse { int responseStatus; /* return code from Responder */ @@ -1288,8 +1316,6 @@ struct OcspResponse { byte producedDate[MAX_DATE_SIZE]; /* Date at which this response was signed */ byte producedDateFormat; /* format of the producedDate */ - byte* issuerHash; - byte* issuerKeyHash; byte* cert; word32 certSz; @@ -1298,7 +1324,7 @@ struct OcspResponse { word32 sigSz; /* Length in octets for the sig */ word32 sigOID; /* OID for hash used for sig */ - CertStatus* status; /* certificate status to fill out */ + OcspEntry* single; /* chain of OCSP single responses */ byte* nonce; /* pointer to nonce inside ASN.1 response */ int nonceSz; /* length of the nonce string */ @@ -1330,26 +1356,9 @@ struct OcspRequest { void* ssl; }; -typedef struct OcspEntry OcspEntry; - -#ifdef NO_SHA -#define OCSP_DIGEST_SIZE WC_SHA256_DIGEST_SIZE -#else -#define OCSP_DIGEST_SIZE WC_SHA_DIGEST_SIZE -#endif - -struct OcspEntry -{ - OcspEntry *next; /* next entry */ - byte issuerHash[OCSP_DIGEST_SIZE]; /* issuer hash */ - byte issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */ - CertStatus *status; /* OCSP response list */ - int totalStatus; /* number on list */ -}; - -WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32, void*); +WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, OcspEntry*, CertStatus*, byte*, word32, void*); WOLFSSL_LOCAL void FreeOcspResponse(OcspResponse*); -WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*, void*, void* heap, int); +WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*, void*, void* heap, int); WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte, void*); WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*);