adds WOLFSSL_CSR2_OCSP_MULTI support;

This commit is contained in:
Moisés Guimarães
2015-11-30 21:26:00 -03:00
parent 07356af78e
commit 346dcb0fd9
3 changed files with 274 additions and 60 deletions

View File

@@ -4393,7 +4393,13 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#if defined(HAVE_OCSP) || defined(HAVE_CRL)
if (ret == 0) {
int doCrlLookup = 1;
#ifdef HAVE_OCSP
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
if (ssl->status_request_v2)
ret = TLSX_CSR2_InitRequests(ssl->extensions, dCert);
else /* skips OCSP and force CRL check */
#endif
if (ssl->ctx->cm->ocspEnabled && ssl->ctx->cm->ocspCheckAll) {
WOLFSSL_MSG("Doing Non Leaf OCSP check");
ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert, NULL);
@@ -4406,7 +4412,7 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#endif /* HAVE_OCSP */
#ifdef HAVE_CRL
if (doCrlLookup && ssl->ctx->cm->crlEnabled
if (ret == 0 && doCrlLookup && ssl->ctx->cm->crlEnabled
&& ssl->ctx->cm->crlCheckAll) {
WOLFSSL_MSG("Doing Non Leaf CRL check");
ret = CheckCertCRL(ssl->ctx->cm->crl, dCert);
@@ -4858,13 +4864,13 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
case WOLFSSL_CSR2_OCSP: {
OcspRequest* request;
#ifdef WOLFSSL_SMALL_STACK
CertStatus* status;
OcspResponse* response;
#else
CertStatus status[1];
OcspResponse response[1];
#endif
#ifdef WOLFSSL_SMALL_STACK
CertStatus* status;
OcspResponse* response;
#else
CertStatus status[1];
OcspResponse response[1];
#endif
do {
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
@@ -4878,7 +4884,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
if (ssl->status_request_v2) {
request = TLSX_CSR2_GetRequest(ssl->extensions,
WOLFSSL_CSR2_OCSP);
status_type, 0);
ssl->status_request_v2 = 0;
break;
}
@@ -4890,19 +4896,21 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (request == NULL)
return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */
#ifdef WOLFSSL_SMALL_STACK
status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
#ifdef WOLFSSL_SMALL_STACK
status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (status == NULL || response == NULL) {
if (status) XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (response) XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (status == NULL || response == NULL) {
if (status)
XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (response)
XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_ERROR;
}
#endif
return MEMORY_ERROR;
}
#endif
InitOcspResponse(response, status, input +*inOutIdx, status_length);
@@ -4914,13 +4922,109 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
*inOutIdx += status_length;
#ifdef WOLFSSL_SMALL_STACK
XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#ifdef WOLFSSL_SMALL_STACK
XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
}
break;
#endif
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
case WOLFSSL_CSR2_OCSP_MULTI: {
OcspRequest* request;
word32 list_length = status_length;
byte index = 0;
#ifdef WOLFSSL_SMALL_STACK
CertStatus* status;
OcspResponse* response;
#else
CertStatus status[1];
OcspResponse response[1];
#endif
do {
if (ssl->status_request_v2) {
ssl->status_request_v2 = 0;
break;
}
return BUFFER_ERROR;
} while(0);
#ifdef WOLFSSL_SMALL_STACK
status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (status == NULL || response == NULL) {
if (status)
XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (response)
XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_ERROR;
}
#endif
while (list_length && ret == 0) {
if (OPAQUE24_LEN > list_length) {
ret = BUFFER_ERROR;
break;
}
c24to32(input + *inOutIdx, &status_length);
*inOutIdx += OPAQUE24_LEN;
list_length -= OPAQUE24_LEN;
if (status_length > list_length) {
ret = BUFFER_ERROR;
break;
}
if (status_length) {
InitOcspResponse(response, status, input +*inOutIdx,
status_length);
if ((OcspResponseDecode(response, ssl->ctx->cm) != 0)
|| (response->responseStatus != OCSP_SUCCESSFUL)
|| (response->status->status != CERT_GOOD))
ret = BAD_CERTIFICATE_STATUS_ERROR;
while (ret == 0) {
request = TLSX_CSR2_GetRequest(ssl->extensions,
status_type, index++);
if (request == NULL)
ret = BAD_CERTIFICATE_STATUS_ERROR;
else if (CompareOcspReqResp(request, response) == 0)
break;
else if (index == 1)
ret = BAD_CERTIFICATE_STATUS_ERROR;
}
*inOutIdx += status_length;
list_length -= status_length;
}
}
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
ssl->status_request_v2 = 0;
#endif
#ifdef WOLFSSL_SMALL_STACK
XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
}
break;
#endif
default:
@@ -8417,7 +8521,10 @@ int SendCertificateStatus(WOLFSSL* ssl)
#if defined HAVE_CERTIFICATE_STATUS_REQUEST_V2
case WOLFSSL_CSR2_OCSP_MULTI: {
OcspRequest* request = ssl->ctx->certOcspRequest;
buffer response = {NULL, 0};
buffer responses[1 + MAX_CHAIN_DEPTH];
int i = 0;
ForceZero(responses, sizeof(responses));
/* unable to fetch status. skip. */
if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0)
@@ -8483,26 +8590,121 @@ int SendCertificateStatus(WOLFSSL* ssl)
if (ret == 0) {
ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request,
&response);
&responses[0]);
/* Suppressing, not critical */
if (ret == OCSP_CERT_REVOKED
|| ret == OCSP_CERT_UNKNOWN
|| ret == OCSP_LOOKUP_FAIL)
ret = 0;
if (response.buffer) {
if (ret == 0)
ret = BuildCertificateStatus(ssl, status_type,
&response, 1);
XFREE(response.buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
}
if (request != ssl->ctx->certOcspRequest)
XFREE(request, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
if (ret == 0 && (!ssl->ctx->chainOcspRequest[0]
|| ssl->buffers.weOwnCertChain)) {
buffer der = {NULL, 0};
word32 idx = 0;
#ifdef WOLFSSL_SMALL_STACK
DecodedCert* cert = NULL;
#else
DecodedCert cert[1];
#endif
#ifdef WOLFSSL_SMALL_STACK
cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (cert == NULL)
return MEMORY_E;
#endif
while (idx + OPAQUE24_LEN < ssl->buffers.certChain.length) {
c24to32(ssl->buffers.certChain.buffer + idx, &der.length);
idx += OPAQUE24_LEN;
der.buffer = ssl->buffers.certChain.buffer + idx;
idx += der.length;
if (idx > ssl->buffers.certChain.length)
break;
InitDecodedCert(cert, der.buffer, der.length, NULL);
if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY,
ssl->ctx->cm)) != 0) {
WOLFSSL_MSG("ParseCert failed");
break;
}
else {
request = (OcspRequest*)XMALLOC(sizeof(OcspRequest),
NULL, DYNAMIC_TYPE_OCSP_REQUEST);
if (request == NULL) {
ret = MEMORY_E;
break;
}
ret = InitOcspRequest(request, cert, 0);
if (ret != 0) {
XFREE(request, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
break;
}
else if (!ssl->buffers.weOwnCertChain && 0 ==
LockMutex(
&ssl->ctx->cm->ocsp_stapling->ocspLock)) {
if (!ssl->ctx->chainOcspRequest[i])
ssl->ctx->chainOcspRequest[i] = request;
UnLockMutex(
&ssl->ctx->cm->ocsp_stapling->ocspLock);
}
ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling,
request, &responses[i + 1]);
/* Suppressing, not critical */
if (ret == OCSP_CERT_REVOKED
|| ret == OCSP_CERT_UNKNOWN
|| ret == OCSP_LOOKUP_FAIL)
ret = 0;
if (request != ssl->ctx->chainOcspRequest[i])
XFREE(request, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
i++;
}
FreeDecodedCert(cert);
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
}
else {
while (ret == 0 &&
NULL != (request = ssl->ctx->chainOcspRequest[i])) {
ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling,
request, &responses[++i]);
/* Suppressing, not critical */
if (ret == OCSP_CERT_REVOKED
|| ret == OCSP_CERT_UNKNOWN
|| ret == OCSP_LOOKUP_FAIL)
ret = 0;
}
}
if (responses[0].buffer) {
if (ret == 0)
ret = BuildCertificateStatus(ssl, status_type,
responses, i + 1);
for (i = 0; i < 1 + MAX_CHAIN_DEPTH; i++)
if (responses[i].buffer)
XFREE(responses[i].buffer, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
}
}
break;

View File

@@ -2211,7 +2211,8 @@ static void TLSX_CSR2_FreeAll(CertificateStatusRequestItemV2* csr2)
switch (csr2->status_type) {
case WOLFSSL_CSR2_OCSP:
case WOLFSSL_CSR2_OCSP_MULTI:
FreeOcspRequest(&csr2->request.ocsp);
while(csr2->requests--)
FreeOcspRequest(&csr2->request.ocsp[csr2->requests]);
break;
}
@@ -2239,7 +2240,7 @@ static word16 TLSX_CSR2_GetSize(CertificateStatusRequestItemV2* csr2,
case WOLFSSL_CSR2_OCSP_MULTI:
size += ENUM_LEN + 3 * OPAQUE16_LEN;
if (csr2->request.ocsp.nonceSz)
if (csr2->request.ocsp[0].nonceSz)
size += OCSP_NONCE_EXT_SZ;
break;
}
@@ -2272,7 +2273,7 @@ static word16 TLSX_CSR2_Write(CertificateStatusRequestItemV2* csr2,
/* request_length */
length = 2 * OPAQUE16_LEN;
if (csr2->request.ocsp.nonceSz)
if (csr2->request.ocsp[0].nonceSz)
length += OCSP_NONCE_EXT_SZ;
c16toa(length, output + offset);
@@ -2285,9 +2286,9 @@ static word16 TLSX_CSR2_Write(CertificateStatusRequestItemV2* csr2,
/* request extensions */
length = 0;
if (csr2->request.ocsp.nonceSz)
if (csr2->request.ocsp[0].nonceSz)
length = EncodeOcspRequestExtensions(
&csr2->request.ocsp,
&csr2->request.ocsp[0],
output + offset + OPAQUE16_LEN,
OCSP_NONCE_EXT_SZ);
@@ -2342,17 +2343,18 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length,
/* followed by */
case WOLFSSL_CSR2_OCSP_MULTI:
/* propagate nonce */
if (csr2->request.ocsp.nonceSz) {
if (csr2->request.ocsp[0].nonceSz) {
OcspRequest* request =
TLSX_CSR2_GetRequest(ssl->extensions,
csr2->status_type);
csr2->status_type, 0);
if (request) {
XMEMCPY(request->nonce,
csr2->request.ocsp.nonce,
csr2->request.ocsp.nonceSz);
csr2->request.ocsp[0].nonce,
csr2->request.ocsp[0].nonceSz);
request->nonceSz = csr2->request.ocsp.nonceSz;
request->nonceSz =
csr2->request.ocsp[0].nonceSz;
}
}
break;
@@ -2456,21 +2458,29 @@ int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert)
for (; csr2; csr2 = csr2->next) {
switch (csr2->status_type) {
case WOLFSSL_CSR2_OCSP:
if (csr2->requests != 0)
break;
/* followed by */
case WOLFSSL_CSR2_OCSP_MULTI: {
byte nonce[MAX_OCSP_NONCE_SZ];
int nonceSz = csr2->request.ocsp.nonceSz;
if (csr2->requests < 1 + MAX_CHAIN_DEPTH) {
byte nonce[MAX_OCSP_NONCE_SZ];
int nonceSz = csr2->request.ocsp[0].nonceSz;
/* preserve nonce */
XMEMCPY(nonce, csr2->request.ocsp.nonce, nonceSz);
/* preserve nonce, replicating nonce of ocsp[0] */
XMEMCPY(nonce, csr2->request.ocsp[0].nonce, nonceSz);
if ((ret = InitOcspRequest(&csr2->request.ocsp, cert, 0)) != 0)
return ret;
if ((ret = InitOcspRequest(
&csr2->request.ocsp[csr2->requests], cert, 0)) != 0)
return ret;
/* restore nonce */
XMEMCPY(csr2->request.ocsp.nonce, nonce, nonceSz);
csr2->request.ocsp.nonceSz = nonceSz;
/* restore nonce */
XMEMCPY(csr2->request.ocsp[csr2->requests].nonce,
nonce, nonceSz);
csr2->request.ocsp[csr2->requests].nonceSz = nonceSz;
csr2->requests++;
}
}
break;
}
@@ -2479,7 +2489,7 @@ int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert)
return ret;
}
void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type)
void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte index)
{
TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2);
CertificateStatusRequestItemV2* csr2 = extension ? extension->data : NULL;
@@ -2491,7 +2501,8 @@ void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type)
/* followed by */
case WOLFSSL_CSR2_OCSP_MULTI:
return &csr2->request.ocsp;
return index < csr2->requests ? &csr2->request.ocsp[index]
: NULL;
break;
}
}
@@ -2514,7 +2525,7 @@ int TLSX_CSR2_ForceRequest(WOLFSSL* ssl)
case WOLFSSL_CSR2_OCSP_MULTI:
if (ssl->ctx->cm->ocspEnabled)
return CheckOcspRequest(ssl->ctx->cm->ocsp,
&csr2->request.ocsp, NULL);
&csr2->request.ocsp[0], NULL);
else
return OCSP_LOOKUP_FAIL;
}
@@ -2555,9 +2566,9 @@ int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type,
WC_RNG rng;
if (wc_InitRng(&rng) == 0) {
if (wc_RNG_GenerateBlock(&rng, csr2->request.ocsp.nonce,
if (wc_RNG_GenerateBlock(&rng, csr2->request.ocsp[0].nonce,
MAX_OCSP_NONCE_SZ) == 0)
csr2->request.ocsp.nonceSz = MAX_OCSP_NONCE_SZ;
csr2->request.ocsp[0].nonceSz = MAX_OCSP_NONCE_SZ;
wc_FreeRng(&rng);
}

View File

@@ -1603,9 +1603,9 @@ WOLFSSL_LOCAL int TLSX_CSR_ForceRequest(WOLFSSL* ssl);
typedef struct CSRIv2 {
byte status_type;
byte options;
word16 request_length;
word16 requests;
union {
OcspRequest ocsp;
OcspRequest ocsp[1 + MAX_CHAIN_DEPTH];
} request;
struct CSRIv2* next;
} CertificateStatusRequestItemV2;
@@ -1613,7 +1613,8 @@ typedef struct CSRIv2 {
WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequestV2(TLSX** extensions,
byte status_type, byte options);
WOLFSSL_LOCAL int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert);
WOLFSSL_LOCAL void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type);
WOLFSSL_LOCAL void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type,
byte index);
WOLFSSL_LOCAL int TLSX_CSR2_ForceRequest(WOLFSSL* ssl);
#endif