diff --git a/src/internal.c b/src/internal.c index 163c34d5e..0503ae722 100644 --- a/src/internal.c +++ b/src/internal.c @@ -526,6 +526,10 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method) /* In case contexts are held in array and don't want to free actual ctx */ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) { + int i; + + (void)i; + XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD); if (ctx->suites) XFREE(ctx->suites, ctx->heap, DYNAMIC_TYPE_SUITES); @@ -534,22 +538,39 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH); XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH); #endif + #ifndef NO_CERTS XFREE(ctx->privateKey.buffer, ctx->heap, DYNAMIC_TYPE_KEY); XFREE(ctx->certificate.buffer, ctx->heap, DYNAMIC_TYPE_CERT); XFREE(ctx->certChain.buffer, ctx->heap, DYNAMIC_TYPE_CERT); wolfSSL_CertManagerFree(ctx->cm); #endif + #ifdef HAVE_TLS_EXTENSIONS TLSX_FreeAll(ctx->extensions); - #ifdef HAVE_CERTIFICATE_STATUS_REQUEST - if (ctx->certOcspRequest) { - FreeOcspRequest(ctx->certOcspRequest); - XFREE(ctx->certOcspRequest, NULL, DYNAMIC_TYPE_OCSP_REQUEST); - } - #endif +#ifndef NO_WOLFSSL_SERVER + +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (ctx->certOcspRequest) { + FreeOcspRequest(ctx->certOcspRequest); + XFREE(ctx->certOcspRequest, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + } #endif + +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + for (i = 0; i < MAX_CHAIN_DEPTH; i++) { + if (ctx->chainOcspRequest[i]) { + FreeOcspRequest(ctx->chainOcspRequest[i]); + XFREE(ctx->chainOcspRequest[i], NULL, DYNAMIC_TYPE_OCSP_REQUEST); + } + } +#endif + +#endif /* NO_WOLFSSL_SERVER */ + +#endif /* HAVE_TLS_EXTENSIONS */ } @@ -4464,14 +4485,21 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (fatal == 0) { int doLookup = 1; -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + /* TODO CSR2 */ if (ssl->options.side == WOLFSSL_CLIENT_END) { +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST if (ssl->status_request) { fatal = TLSX_CSR_InitRequest(ssl->extensions, dCert); doLookup = 0; } - } #endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + fatal = TLSX_CSR2_InitRequests(ssl->extensions, dCert); + doLookup = 0; + } +#endif + } #ifdef HAVE_OCSP if (doLookup && ssl->ctx->cm->ocspEnabled) { @@ -4827,7 +4855,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* WOLFSSL_CSR_OCSP overlaps with WOLFSSL_CSR2_OCSP */ case WOLFSSL_CSR2_OCSP: { - OcspRequest* request = TLSX_CSR_GetRequest(ssl->extensions); + OcspRequest* request; #ifdef WOLFSSL_SMALL_STACK CertStatus* status; @@ -4840,12 +4868,15 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, do { #ifdef HAVE_CERTIFICATE_STATUS_REQUEST if (ssl->status_request) { + request = TLSX_CSR_GetRequest(ssl->extensions); ssl->status_request = 0; break; } #endif #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 if (ssl->status_request_v2) { + request = TLSX_CSR2_GetRequest(ssl->extensions, + WOLFSSL_CSR2_OCSP); ssl->status_request_v2 = 0; break; } @@ -4853,6 +4884,9 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, return BUFFER_ERROR; } while(0); + if (request == NULL) + return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */ + #ifdef WOLFSSL_SMALL_STACK status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -5132,6 +5166,15 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) if ((ret = TLSX_CSR_ForceRequest(ssl)) != 0) return ret; } +#endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + int ret; + + WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange"); + if ((ret = TLSX_CSR2_ForceRequest(ssl)) != 0) + return ret; + } #endif } diff --git a/src/tls.c b/src/tls.c index ba8bd1a7d..177cb73f5 100644 --- a/src/tls.c +++ b/src/tls.c @@ -2329,6 +2329,36 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, if (!csr2) return BUFFER_ERROR; /* unexpected extension */ + + /* enable extension at ssl level */ + for (; csr2; csr2 = csr2->next) { + ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions, + csr2->status_type, csr2->options); + if (ret != SSL_SUCCESS) + return ret; + + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + /* followed by */ + case WOLFSSL_CSR2_OCSP_MULTI: + /* propagate nonce */ + if (csr2->request.ocsp.nonceSz) { + OcspRequest* request = + TLSX_CSR2_GetRequest(ssl->extensions, + csr2->status_type); + + if (request) { + XMEMCPY(request->nonce, + csr2->request.ocsp.nonce, + csr2->request.ocsp.nonceSz); + + request->nonceSz = csr2->request.ocsp.nonceSz; + } + } + break; + } + } + } ssl->status_request_v2 = 1; @@ -2417,6 +2447,82 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, return 0; } +int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? extension->data : NULL; + int ret = 0; + + for (; csr2; csr2 = csr2->next) { + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + /* followed by */ + + case WOLFSSL_CSR2_OCSP_MULTI: { + byte nonce[MAX_OCSP_NONCE_SZ]; + int nonceSz = csr2->request.ocsp.nonceSz; + + /* preserve nonce */ + XMEMCPY(nonce, csr2->request.ocsp.nonce, nonceSz); + + if ((ret = InitOcspRequest(&csr2->request.ocsp, cert, 0)) != 0) + return ret; + + /* restore nonce */ + XMEMCPY(csr2->request.ocsp.nonce, nonce, nonceSz); + csr2->request.ocsp.nonceSz = nonceSz; + } + break; + } + } + + return ret; +} + +void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? extension->data : NULL; + + for (; csr2; csr2 = csr2->next) { + if (csr2->status_type == status_type) { + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + /* followed by */ + + case WOLFSSL_CSR2_OCSP_MULTI: + return &csr2->request.ocsp; + break; + } + } + } + + return NULL; +} + +int TLSX_CSR2_ForceRequest(WOLFSSL* ssl) +{ + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? extension->data : NULL; + + /* forces only the first one */ + if (csr2) { + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + /* followed by */ + + case WOLFSSL_CSR2_OCSP_MULTI: + if (ssl->ctx->cm->ocspEnabled) + return CheckOcspRequest(ssl->ctx->cm->ocsp, + &csr2->request.ocsp, NULL); + else + return OCSP_LOOKUP_FAIL; + } + } + + return 0; +} + int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, byte options) { diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 67a535060..9e592fb26 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1589,11 +1589,11 @@ typedef struct { } request; } CertificateStatusRequest; -WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions, +WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, byte options); -WOLFSSL_LOCAL int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert); -WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions); -WOLFSSL_LOCAL int TLSX_CSR_ForceRequest(WOLFSSL* ssl); +WOLFSSL_LOCAL int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert); +WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions); +WOLFSSL_LOCAL int TLSX_CSR_ForceRequest(WOLFSSL* ssl); #endif @@ -1610,8 +1610,11 @@ typedef struct CSRIv2 { struct CSRIv2* next; } CertificateStatusRequestItemV2; -WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, +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 int TLSX_CSR2_ForceRequest(WOLFSSL* ssl); #endif @@ -1790,8 +1793,14 @@ struct WOLFSSL_CTX { #endif #ifdef HAVE_TLS_EXTENSIONS TLSX* extensions; /* RFC 6066 TLS Extensions data */ - #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) && !defined(NO_WOLFSSL_SERVER) - OcspRequest* certOcspRequest; + #ifndef NO_WOLFSSL_SERVER + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + OcspRequest* certOcspRequest; + #endif + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + OcspRequest* chainOcspRequest[MAX_CHAIN_DEPTH]; + #endif #endif #if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SEVER) SessionTicketEncCb ticketEncCb; /* enc/dec session ticket Cb */