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.
pull/3495/head
Hayden Roche 2020-11-12 09:20:48 -06:00
parent 69d642206d
commit bca43654df
6 changed files with 269 additions and 202 deletions

View File

@ -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

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

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