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*);