Merge pull request #3389 from tmael/ocsp_status

Process multiple OCSP responses
This commit is contained in:
toddouska
2020-10-20 15:11:42 -07:00
committed by GitHub
4 changed files with 71 additions and 35 deletions

View File

@@ -9844,7 +9844,7 @@ static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
} }
#endif #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) if (OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, 0) != 0)
ret = BAD_CERTIFICATE_STATUS_ERROR; ret = BAD_CERTIFICATE_STATUS_ERROR;
@@ -9864,6 +9864,7 @@ static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
*inOutIdx += status_length; *inOutIdx += status_length;
FreeOcspResponse(response);
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS); XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS);
XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
@@ -11841,7 +11842,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (status_length) { if (status_length) {
InitOcspResponse(response, status, input +*inOutIdx, InitOcspResponse(response, status, input +*inOutIdx,
status_length); status_length, ssl->heap);
if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap,
0) != 0) 0) != 0)
@@ -11860,6 +11861,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
else if (idx == 1) /* server cert must be OK */ else if (idx == 1) /* server cert must be OK */
ret = BAD_CERTIFICATE_STATUS_ERROR; ret = BAD_CERTIFICATE_STATUS_ERROR;
} }
FreeOcspResponse(response);
*inOutIdx += status_length; *inOutIdx += status_length;
list_length -= status_length; list_length -= status_length;

View File

@@ -296,7 +296,7 @@ WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int resp
#endif #endif
XMEMSET(newStatus, 0, sizeof(CertStatus)); 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); ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0);
if (ret != 0) { if (ret != 0) {
ocsp->error = ret; ocsp->error = ret;
@@ -378,6 +378,7 @@ end:
ret = OCSP_LOOKUP_FAIL; ret = OCSP_LOOKUP_FAIL;
} }
FreeOcspResponse(ocspResponse);
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);

View File

@@ -8887,6 +8887,7 @@ static int DecodeCertExtensions(DecodedCert* cert)
case OCSP_NOCHECK_OID: case OCSP_NOCHECK_OID:
VERIFY_AND_SET_OID(cert->ocspNoCheckSet); VERIFY_AND_SET_OID(cert->ocspNoCheckSet);
ret = GetASNNull(input, &idx, sz); ret = GetASNNull(input, &idx, sz);
length = 0; /* idx is already incremented, reset length to 0 */
if (ret != 0) if (ret != 0)
return ASN_PARSE_E; return ASN_PARSE_E;
break; break;
@@ -16533,25 +16534,18 @@ static int GetEnumerated(const byte* input, word32* inOutIdx, int *value,
static int DecodeSingleResponse(byte* source, static int DecodeSingleResponse(byte* source,
word32* ioIndex, OcspResponse* resp, word32 size) word32* ioIndex, OcspResponse* resp, word32 size, int wrapperSz,
CertStatus* cs)
{ {
word32 idx = *ioIndex, prevIndex, oid, localIdx; word32 idx = *ioIndex, prevIndex, oid, localIdx;
int length, wrapperSz; int length;
CertStatus* cs = resp->status;
int ret; int ret;
byte tag; byte tag;
WOLFSSL_ENTER("DecodeSingleResponse"); WOLFSSL_ENTER("DecodeSingleResponse");
/* Outer wrapper of the SEQUENCE OF Single Responses. */
if (GetSequence(source, &idx, &wrapperSz, size) < 0)
return ASN_PARSE_E;
prevIndex = idx; 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 */ /* Wrapper around the Single Response */
if (GetSequence(source, &idx, &length, size) < 0) if (GetSequence(source, &idx, &length, size) < 0)
return ASN_PARSE_E; return ASN_PARSE_E;
@@ -16627,7 +16621,6 @@ static int DecodeSingleResponse(byte* source,
/* The following items are optional. Only check for them if there is more /* The following items are optional. Only check for them if there is more
* unprocessed data in the singleResponse wrapper. */ * unprocessed data in the singleResponse wrapper. */
localIdx = idx; localIdx = idx;
if (((int)(idx - prevIndex) < wrapperSz) && if (((int)(idx - prevIndex) < wrapperSz) &&
GetASNTag(source, &localIdx, &tag, size) == 0 && GetASNTag(source, &localIdx, &tag, size) == 0 &&
@@ -16659,17 +16652,6 @@ static int DecodeSingleResponse(byte* source,
#endif #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; *ioIndex = idx;
return 0; return 0;
@@ -16762,6 +16744,8 @@ static int DecodeResponseData(byte* source,
int version; int version;
int ret; int ret;
byte tag; byte tag;
int wrapperSz;
CertStatus* cs;
WOLFSSL_ENTER("DecodeResponseData"); WOLFSSL_ENTER("DecodeResponseData");
@@ -16803,8 +16787,27 @@ static int DecodeResponseData(byte* source,
&resp->producedDateFormat, size) < 0) &resp->producedDateFormat, size) < 0)
return ASN_PARSE_E; return ASN_PARSE_E;
if ((ret = DecodeSingleResponse(source, &idx, resp, size)) < 0) /* Outer wrapper of the SEQUENCE OF Single Responses. */
return ret; /* ASN_PARSE_E, ASN_BEFORE_DATE_E, ASN_AFTER_DATE_E */ if (GetSequence(source, &idx, &wrapperSz, size) < 0)
return ASN_PARSE_E;
localIdx = idx;
cs = resp->status;
while (idx - localIdx < (word32)wrapperSz) {
ret = DecodeSingleResponse(source, &idx, resp, size, wrapperSz, cs);
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) {
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 * Check the length of the ResponseData against the current index to
@@ -16977,7 +16980,7 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
void InitOcspResponse(OcspResponse* resp, CertStatus* status, void InitOcspResponse(OcspResponse* resp, CertStatus* status,
byte* source, word32 inSz) byte* source, word32 inSz, void* heap)
{ {
WOLFSSL_ENTER("InitOcspResponse"); WOLFSSL_ENTER("InitOcspResponse");
@@ -16988,6 +16991,17 @@ void InitOcspResponse(OcspResponse* resp, CertStatus* status,
resp->status = status; resp->status = status;
resp->source = source; resp->source = source;
resp->maxIdx = inSz; resp->maxIdx = inSz;
resp->heap = heap;
}
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);
}
} }
@@ -17262,6 +17276,7 @@ void FreeOcspRequest(OcspRequest* req)
int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp) int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
{ {
int cmp; int cmp;
CertStatus *status, *next, *prev = NULL, *top;
WOLFSSL_ENTER("CompareOcspReqResp"); WOLFSSL_ENTER("CompareOcspReqResp");
@@ -17307,13 +17322,27 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
return cmp; return cmp;
} }
cmp = req->serialSz - resp->status->serialSz; /* match based on found status and return */
if (cmp != 0) { for (status = resp->status; status; status = next) {
WOLFSSL_MSG("\tserialSz mismatch"); cmp = req->serialSz - status->serialSz;
return cmp; 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) { if (cmp != 0) {
WOLFSSL_MSG("\tserial mismatch"); WOLFSSL_MSG("\tserial mismatch");
return cmp; return cmp;

View File

@@ -1267,8 +1267,10 @@ struct CertStatus {
byte* rawOcspResponse; byte* rawOcspResponse;
word32 rawOcspResponseSz; word32 rawOcspResponseSz;
};
/* option bits - using 32-bit for alignment */
word32 isDynamic:1; /* was allocated cert status */
};
struct OcspResponse { struct OcspResponse {
int responseStatus; /* return code from Responder */ int responseStatus; /* return code from Responder */
@@ -1300,6 +1302,7 @@ struct OcspResponse {
#ifdef OPENSSL_EXTRA #ifdef OPENSSL_EXTRA
int verifyError; int verifyError;
#endif #endif
void* heap;
}; };
@@ -1337,7 +1340,8 @@ struct OcspEntry
int totalStatus; /* number on list */ 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 OcspResponseDecode(OcspResponse*, void*, void* heap, int);
WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte, void*); WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte, void*);