Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Process multiple OCSP responses #3389

Merged
merged 4 commits into from
Oct 20, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -9844,7 +9844,7 @@ static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
#endif

InitOcspResponse(response, status, input +*inOutIdx, status_length);
InitOcspResponse(response, status, input +*inOutIdx, status_length, ssl->heap);

if (OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, 0) != 0)
ret = BAD_CERTIFICATE_STATUS_ERROR;
Expand All @@ -9864,6 +9864,7 @@ 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(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
Expand Down Expand Up @@ -11835,7 +11836,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,

if (status_length) {
InitOcspResponse(response, status, input +*inOutIdx,
status_length);
status_length, ssl->heap);

if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap,
0) != 0)
Expand All @@ -11854,6 +11855,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
else if (idx == 1) /* server cert must be OK */
ret = BAD_CERTIFICATE_STATUS_ERROR;
}
FreeOcspResponse(response);

*inOutIdx += status_length;
list_length -= status_length;
Expand Down
3 changes: 2 additions & 1 deletion src/ocsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int resp
#endif
XMEMSET(newStatus, 0, sizeof(CertStatus));

InitOcspResponse(ocspResponse, newStatus, response, responseSz);
InitOcspResponse(ocspResponse, newStatus, response, responseSz, ocsp->cm->heap);
ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0);
if (ret != 0) {
ocsp->error = ret;
Expand Down Expand Up @@ -378,6 +378,7 @@ WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int resp
ret = OCSP_LOOKUP_FAIL;
}

FreeOcspResponse(ocspResponse);
#ifdef WOLFSSL_SMALL_STACK
XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
Expand Down
93 changes: 59 additions & 34 deletions wolfcrypt/src/asn.c
Original file line number Diff line number Diff line change
Expand Up @@ -8885,6 +8885,7 @@ static int DecodeCertExtensions(DecodedCert* cert)
case OCSP_NOCHECK_OID:
VERIFY_AND_SET_OID(cert->ocspNoCheckSet);
ret = GetASNNull(input, &idx, sz);
length = 0; /* idx is already incremented, reset length to 0 */
if (ret != 0)
return ASN_PARSE_E;
break;
Expand Down Expand Up @@ -16530,25 +16531,15 @@ static int GetEnumerated(const byte* input, word32* inOutIdx, int *value,


static int DecodeSingleResponse(byte* source,
word32* ioIndex, OcspResponse* resp, word32 size)
word32* ioIndex, OcspResponse* resp, word32 size, CertStatus* cs)
{
word32 idx = *ioIndex, prevIndex, oid, localIdx;
int length, wrapperSz;
CertStatus* cs = resp->status;
word32 idx = *ioIndex, oid, localIdx;
int length;
int ret;
byte tag;

WOLFSSL_ENTER("DecodeSingleResponse");

/* Outer wrapper of the SEQUENCE OF Single Responses. */
if (GetSequence(source, &idx, &wrapperSz, size) < 0)
return ASN_PARSE_E;

prevIndex = idx;

/* When making a request, we only request one status on one certificate
* at a time. There should only be one SingleResponse */

/* Wrapper around the Single Response */
if (GetSequence(source, &idx, &length, size) < 0)
return ASN_PARSE_E;
Expand Down Expand Up @@ -16624,9 +16615,8 @@ static int DecodeSingleResponse(byte* source,

/* The following items are optional. Only check for them if there is more
* unprocessed data in the singleResponse wrapper. */

localIdx = idx;
if (((int)(idx - prevIndex) < wrapperSz) &&
if (idx < size &&
GetASNTag(source, &localIdx, &tag, size) == 0 &&
tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
{
Expand Down Expand Up @@ -16656,17 +16646,6 @@ static int DecodeSingleResponse(byte* source,
#endif
}

localIdx = idx;
if (((int)(idx - prevIndex) < wrapperSz) &&
GetASNTag(source, &localIdx, &tag, size) == 0 &&
tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
{
idx++;
if (GetLength(source, &idx, &length, size) < 0)
return ASN_PARSE_E;
idx += length;
}

*ioIndex = idx;

return 0;
Expand Down Expand Up @@ -16759,6 +16738,8 @@ static int DecodeResponseData(byte* source,
int version;
int ret;
byte tag;
int wrapperSz;
CertStatus* cs;

WOLFSSL_ENTER("DecodeResponseData");

Expand Down Expand Up @@ -16800,8 +16781,26 @@ static int DecodeResponseData(byte* source,
&resp->producedDateFormat, size) < 0)
return ASN_PARSE_E;

if ((ret = DecodeSingleResponse(source, &idx, resp, size)) < 0)
return ret; /* ASN_PARSE_E, ASN_BEFORE_DATE_E, ASN_AFTER_DATE_E */
/* Outer wrapper of the SEQUENCE OF Single Responses. */
if (GetSequence(source, &idx, &wrapperSz, size) < 0)
return ASN_PARSE_E;

localIdx = idx;
cs = resp->status;
while (idx - localIdx < (word32)wrapperSz) {
if ((ret = DecodeSingleResponse(source, &idx, resp, localIdx + wrapperSz, cs)) < 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) {
return MEMORY_E;
}
cs = cs->next;
XMEMSET(cs, 0, sizeof(CertStatus));
cs->isDynamic = 1;
}
}

/*
* Check the length of the ResponseData against the current index to
Expand Down Expand Up @@ -16974,7 +16973,7 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,


void InitOcspResponse(OcspResponse* resp, CertStatus* status,
byte* source, word32 inSz)
byte* source, word32 inSz, void* heap)
{
WOLFSSL_ENTER("InitOcspResponse");

Expand All @@ -16985,6 +16984,17 @@ void InitOcspResponse(OcspResponse* resp, CertStatus* status,
resp->status = status;
resp->source = source;
resp->maxIdx = inSz;
resp->heap = heap;
}

void FreeOcspResponse(OcspResponse* resp)
{
tmael marked this conversation as resolved.
Show resolved Hide resolved
CertStatus *status, *next;
for (status = resp->status; status; status = next) {
next = status->next;
if (status->isDynamic)
XFREE(status, resp->heap, DYNAMIC_TYPE_OCSP_STATUS);
}
}


Expand Down Expand Up @@ -17259,6 +17269,7 @@ void FreeOcspRequest(OcspRequest* req)
int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
{
int cmp;
CertStatus *status, *next, *prev, *top;

WOLFSSL_ENTER("CompareOcspReqResp");

Expand Down Expand Up @@ -17304,13 +17315,27 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
return cmp;
}

cmp = req->serialSz - resp->status->serialSz;
if (cmp != 0) {
WOLFSSL_MSG("\tserialSz mismatch");
return cmp;
/* match based on found status and return */
for (status = resp->status; status; status = next) {
tmael marked this conversation as resolved.
Show resolved Hide resolved
cmp = req->serialSz - status->serialSz;
if (cmp == 0) {
cmp = XMEMCMP(req->serial, status->serial, req->serialSz);
if (cmp == 0) {
/* match found */
if (resp->status != status && prev) {
/* move to top of list */
top = resp->status;
resp->status = status;
prev->next = status->next;
status->next = top;
}
break;
}
}
next = status->next;
prev = status;
}

cmp = XMEMCMP(req->serial, resp->status->serial, req->serialSz);
if (cmp != 0) {
WOLFSSL_MSG("\tserial mismatch");
return cmp;
Expand Down
8 changes: 6 additions & 2 deletions wolfssl/wolfcrypt/asn.h
Original file line number Diff line number Diff line change
Expand Up @@ -1267,8 +1267,10 @@ struct CertStatus {

byte* rawOcspResponse;
word32 rawOcspResponseSz;
};

/* option bits - using 32-bit for alignment */
word32 isDynamic:1; /* was allocated cert status */
};

struct OcspResponse {
int responseStatus; /* return code from Responder */
Expand Down Expand Up @@ -1300,6 +1302,7 @@ struct OcspResponse {
#ifdef OPENSSL_EXTRA
int verifyError;
#endif
void* heap;
};


Expand Down Expand Up @@ -1337,7 +1340,8 @@ struct OcspEntry
int totalStatus; /* number on list */
};

WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32);
WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32, void*);
WOLFSSL_LOCAL void FreeOcspResponse(OcspResponse*);
WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*, void*, void* heap, int);

WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte, void*);
Expand Down