diff --git a/scripts/ocsp-stapling.test b/scripts/ocsp-stapling.test index 02d7908c6..511ae3b00 100755 --- a/scripts/ocsp-stapling.test +++ b/scripts/ocsp-stapling.test @@ -8,6 +8,10 @@ server=login.live.com ca=certs/external/baltimore-cybertrust-root.pem [ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit 1 +./examples/client/client -? 2>&1 | grep -- 'Client not compiled in!' +if [ $? -eq 0 ]; then + exit 0 +fi # is our desired server there? - login.live.com doesn't answers PING #./scripts/ping.test $server 2 @@ -17,6 +21,14 @@ ca=certs/external/baltimore-cybertrust-root.pem RESULT=$? [ $RESULT -ne 0 ] && echo -e "\n\nClient connection failed" && exit 1 + +# Test with example server + +./examples/server/server -? 2>&1 | grep -- 'Server not compiled in!' +if [ $? -eq 0 ]; then + exit 0 +fi + # setup ocsp responder ./certs/ocsp/ocspd-intermediate1-ca-issued-certs.sh & sleep 1 @@ -36,4 +48,22 @@ sleep 1 RESULT=$? [ $RESULT -ne 1 ] && echo -e "\n\nClient connection suceeded $RESULT" && exit 1 + +./examples/client/client -v 4 2>&1 | grep -- 'Bad SSL version' +if [ $? -ne 0 ]; then + # client test against our own server - GOOD CERT + ./examples/server/server -c certs/ocsp/server1-cert.pem -k certs/ocsp/server1-key.pem -v 4 & + sleep 1 + ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -v 4 -F 1 + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "\n\nClient connection failed" && exit 1 + + # client test against our own server - REVOKED CERT + ./examples/server/server -c certs/ocsp/server2-cert.pem -k certs/ocsp/server2-key.pem -v 4 & + sleep 1 + ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -v 4 -F 1 + RESULT=$? + [ $RESULT -ne 1 ] && echo -e "\n\nClient connection suceeded $RESULT" && exit 1 +fi + exit 0 diff --git a/src/internal.c b/src/internal.c index df3d79dfd..8c6afbd39 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8081,6 +8081,87 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) #endif /* KEEP_PEER_CERT || SESSION_CERTS */ +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \ + (defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && !defined(WOLFSSL_NO_TLS12)) +static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 status_length) +{ + int ret = 0; + OcspRequest* request; + + #ifdef WOLFSSL_SMALL_STACK + CertStatus* status; + OcspResponse* response; + #else + CertStatus status[1]; + OcspResponse response[1]; + #endif + + do { + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->status_request) { + request = (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions); + ssl->status_request = 0; + break; + } + #endif + + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + request = (OcspRequest*)TLSX_CSR2_GetRequest(ssl->extensions, + WOLFSSL_CSR2_OCSP, 0); + ssl->status_request_v2 = 0; + break; + } + #endif + + return BUFFER_ERROR; + } while(0); + + if (request == NULL) + return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */ + + #ifdef WOLFSSL_SMALL_STACK + status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap, + DYNAMIC_TYPE_OCSP_STATUS); + response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap, + DYNAMIC_TYPE_OCSP_REQUEST); + + if (status == NULL || response == NULL) { + if (status) + XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS); + if (response) + XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + + return MEMORY_ERROR; + } + #endif + + InitOcspResponse(response, status, input +*inOutIdx, status_length); + + if (OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, 0) != 0) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (CompareOcspReqResp(request, response) != 0) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (response->responseStatus != OCSP_SUCCESSFUL) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (response->status->status == CERT_REVOKED) + ret = OCSP_CERT_REVOKED; + else if (response->status->status != CERT_GOOD) + ret = BAD_CERTIFICATE_STATUS_ERROR; + + *inOutIdx += status_length; + + #ifdef WOLFSSL_SMALL_STACK + XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS); + XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + #endif + + return ret; +} +#endif + + typedef struct ProcPeerCertArgs { buffer* certs; #ifdef WOLFSSL_TLS13 @@ -8353,6 +8434,10 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, args->exts[args->totalCerts].buffer = input + args->idx; args->idx += extSz; listSz -= extSz + OPAQUE16_LEN; + ret = TLSX_Parse(ssl, args->exts[args->totalCerts].buffer, + args->exts[args->totalCerts].length, certificate, NULL); + if (ret < 0) + return ret; } #endif @@ -9028,6 +9113,21 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, args->fatal = TLSX_CSR_InitRequest(ssl->extensions, args->dCert, ssl->heap); doLookup = 0; + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + TLSX* ext = TLSX_Find(ssl->extensions, + TLSX_STATUS_REQUEST); + if (ext != NULL) { + word32 idx = 0; + CertificateStatusRequest* csr = + (CertificateStatusRequest*)ext->data; + ret = ProcessCSR(ssl, csr->response.buffer, + &idx, csr->response.length); + if (ret < 0) + goto exit_ppc; + } + } + #endif } #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 @@ -9644,80 +9744,9 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) /* WOLFSSL_CSR_OCSP overlaps with WOLFSSL_CSR2_OCSP */ - case WOLFSSL_CSR2_OCSP: { - OcspRequest* request; - - #ifdef WOLFSSL_SMALL_STACK - CertStatus* status; - OcspResponse* response; - #else - CertStatus status[1]; - OcspResponse response[1]; - #endif - - do { - #ifdef HAVE_CERTIFICATE_STATUS_REQUEST - if (ssl->status_request) { - request = (OcspRequest*)TLSX_CSR_GetRequest( - ssl->extensions); - ssl->status_request = 0; - break; - } - #endif - - #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 - if (ssl->status_request_v2) { - request = (OcspRequest*)TLSX_CSR2_GetRequest( - ssl->extensions, status_type, 0); - ssl->status_request_v2 = 0; - break; - } - #endif - - return BUFFER_ERROR; - } while(0); - - if (request == NULL) - return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */ - - #ifdef WOLFSSL_SMALL_STACK - status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap, - DYNAMIC_TYPE_OCSP_STATUS); - response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap, - DYNAMIC_TYPE_OCSP_REQUEST); - - if (status == NULL || response == NULL) { - if (status) - XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS); - if (response) - XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST); - - return MEMORY_ERROR; - } - #endif - - InitOcspResponse(response, status, input +*inOutIdx, status_length); - - if (OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, 0) != 0) - ret = BAD_CERTIFICATE_STATUS_ERROR; - else if (CompareOcspReqResp(request, response) != 0) - ret = BAD_CERTIFICATE_STATUS_ERROR; - else if (response->responseStatus != OCSP_SUCCESSFUL) - ret = BAD_CERTIFICATE_STATUS_ERROR; - else if (response->status->status == CERT_REVOKED) - ret = OCSP_CERT_REVOKED; - else if (response->status->status != CERT_GOOD) - ret = BAD_CERTIFICATE_STATUS_ERROR; - - *inOutIdx += status_length; - - #ifdef WOLFSSL_SMALL_STACK - XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS); - XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - #endif - - } - break; + case WOLFSSL_CSR2_OCSP: + ret = ProcessCSR(ssl, input, inOutIdx, status_length); + break; #endif @@ -13724,7 +13753,116 @@ int SendFinished(WOLFSSL* ssl) return ret; } +#endif /* WOLFSSL_NO_TLS12 */ +#ifndef NO_WOLFSSL_SERVER +#if (!defined(WOLFSSL_NO_TLS12) && \ + (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \ + defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST)) +static int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request, + DecodedCert* cert, byte* certData, word32 length) +{ + int ret; + + InitDecodedCert(cert, certData, length, ssl->heap); + /* TODO: Setup async support here */ + ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm); + if (ret != 0) { + WOLFSSL_MSG("ParseCert failed"); + } + if (ret == 0) + ret = InitOcspRequest(request, cert, 0, ssl->heap); + if (ret == 0) { + /* make sure ctx OCSP request is updated */ + if (!ssl->buffers.weOwnCert) { + wolfSSL_Mutex* ocspLock = &ssl->ctx->cm->ocsp_stapling->ocspLock; + if (wc_LockMutex(ocspLock) == 0) { + if (ssl->ctx->certOcspRequest == NULL) + ssl->ctx->certOcspRequest = request; + wc_UnLockMutex(ocspLock); + } + } + } + + FreeDecodedCert(cert); + + return ret; +} + + +int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest, + buffer* response) +{ + int ret = 0; + OcspRequest* request; + + if (ssl == NULL || ocspRequest == NULL || response == NULL) + return BAD_FUNC_ARG; + + request = *ocspRequest; + + XMEMSET(response, 0, sizeof(*response)); + + /* unable to fetch status. skip. */ + if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0) + return 0; + + if (request == NULL || ssl->buffers.weOwnCert) { + DerBuffer* der = ssl->buffers.certificate; + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif + + /* unable to fetch status. skip. */ + if (der->buffer == NULL || der->length == 0) + return 0; + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; + #endif + request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap, + DYNAMIC_TYPE_OCSP_REQUEST); + if (request == NULL) + ret = MEMORY_E; + + if (ret == 0) { + ret = CreateOcspRequest(ssl, request, cert, der->buffer, + der->length); + } + + if (request != NULL) + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); + #endif + } + + if (ret == 0) { + request->ssl = ssl; + ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, response); + + /* Suppressing, not critical */ + if (ret == OCSP_CERT_REVOKED || + ret == OCSP_CERT_UNKNOWN || + ret == OCSP_LOOKUP_FAIL) { + ret = 0; + } + } + + *ocspRequest = request; + + return ret; +} +#endif +#endif /* !NO_WOLFSSL_SERVER */ + +#ifndef WOLFSSL_NO_TLS12 #ifndef NO_CERTS #if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH) @@ -14228,7 +14366,6 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, #endif #endif /* NO_WOLFSSL_SERVER */ - /* handle generation of certificate_status (22) */ int SendCertificateStatus(WOLFSSL* ssl) { @@ -14259,97 +14396,14 @@ int SendCertificateStatus(WOLFSSL* ssl) OcspRequest* request = ssl->ctx->certOcspRequest; buffer response; - XMEMSET(&response, 0, sizeof(response)); + ret = CreateOcspResponse(ssl, &request, &response); + if (ret == 0 && response.buffer) { + ret = BuildCertificateStatus(ssl, status_type, &response, 1); - /* unable to fetch status. skip. */ - if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0) - return 0; - - if (request == NULL || ssl->buffers.weOwnCert) { - DerBuffer* der = ssl->buffers.certificate; - #ifdef WOLFSSL_SMALL_STACK - DecodedCert* cert = NULL; - #else - DecodedCert cert[1]; - #endif - - /* unable to fetch status. skip. */ - if (der->buffer == NULL || der->length == 0) - return 0; - - #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, - DYNAMIC_TYPE_DCERT); - if (cert == NULL) - return MEMORY_E; - #endif - - InitDecodedCert(cert, der->buffer, der->length, ssl->heap); - /* TODO: Setup async support here */ - if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, - ssl->ctx->cm)) != 0) { - WOLFSSL_MSG("ParseCert failed"); - } - else { - request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), - ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - if (request) { - ret = InitOcspRequest(request, cert, 0, ssl->heap); - if (ret == 0) { - /* make sure ctx OCSP request is updated */ - if (!ssl->buffers.weOwnCert) { - wolfSSL_Mutex* ocspLock = - &ssl->ctx->cm->ocsp_stapling->ocspLock; - if (wc_LockMutex(ocspLock) == 0) { - if (ssl->ctx->certOcspRequest == NULL) - ssl->ctx->certOcspRequest = request; - wc_UnLockMutex(ocspLock); - } - } - } - else { - XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - request = NULL; - } - } - else { - ret = MEMORY_E; - } - } - - FreeDecodedCert(cert); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); - #endif + XFREE(response.buffer, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + response.buffer = NULL; } - if (ret == 0) { - request->ssl = ssl; - ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, - &response); - - /* 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, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - response.buffer = NULL; - } - - } - - if (request != ssl->ctx->certOcspRequest) - XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - break; } @@ -14365,85 +14419,7 @@ int SendCertificateStatus(WOLFSSL* ssl) XMEMSET(responses, 0, sizeof(responses)); - /* unable to fetch status. skip. */ - if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0) - return 0; - - if (!request || ssl->buffers.weOwnCert) { - DerBuffer* der = ssl->buffers.certificate; - #ifdef WOLFSSL_SMALL_STACK - DecodedCert* cert = NULL; - #else - DecodedCert cert[1]; - #endif - - /* unable to fetch status. skip. */ - if (der->buffer == NULL || der->length == 0) - return 0; - - #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, - DYNAMIC_TYPE_DCERT); - if (cert == NULL) - return MEMORY_E; - #endif - - InitDecodedCert(cert, der->buffer, der->length, ssl->heap); - /* TODO: Setup async support here */ - if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, - ssl->ctx->cm)) != 0) { - WOLFSSL_MSG("ParseCert failed"); - } - else { - request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), - ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - if (request) { - ret = InitOcspRequest(request, cert, 0, ssl->heap); - if (ret == 0) { - /* make sure ctx OCSP request is updated */ - if (!ssl->buffers.weOwnCert) { - wolfSSL_Mutex* ocspLock = - &ssl->ctx->cm->ocsp_stapling->ocspLock; - if (wc_LockMutex(ocspLock) == 0) { - if (ssl->ctx->certOcspRequest == NULL) - ssl->ctx->certOcspRequest = request; - wc_UnLockMutex(ocspLock); - } - } - } - else { - XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - request = NULL; - } - } - else { - ret = MEMORY_E; - } - } - - FreeDecodedCert(cert); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); - #endif - } - - if (ret == 0) { - request->ssl = ssl; - ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, - &responses[0]); - - /* Suppressing, not critical */ - if (ret == OCSP_CERT_REVOKED || - ret == OCSP_CERT_UNKNOWN || - ret == OCSP_LOOKUP_FAIL) { - ret = 0; - } - } - - if (request != ssl->ctx->certOcspRequest) - XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - + ret = CreateOcspResponse(ssl, &request, &responses[0]); if (ret == 0 && (!ssl->ctx->chainOcspRequest[0] || ssl->buffers.weOwnCertChain)) { buffer der; @@ -14454,14 +14430,20 @@ int SendCertificateStatus(WOLFSSL* ssl) DecodedCert cert[1]; #endif - XMEMSET(&der, 0, sizeof(buffer)); - #ifdef WOLFSSL_SMALL_STACK cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, - DYNAMIC_TYPE_DCERT); + DYNAMIC_TYPE_DCERT); if (cert == NULL) return MEMORY_E; #endif + request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap, + DYNAMIC_TYPE_OCSP_REQUEST); + if (request == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); + #endif + return MEMORY_E; + } while (idx + OPAQUE24_LEN < ssl->buffers.certChain->length) { c24to32(ssl->buffers.certChain->buffer + idx, &der.length); @@ -14473,43 +14455,9 @@ int SendCertificateStatus(WOLFSSL* ssl) if (idx > ssl->buffers.certChain->length) break; - InitDecodedCert(cert, der.buffer, der.length, ssl->heap); - /* TODO: Setup async support here */ - if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, - ssl->ctx->cm)) != 0) { - WOLFSSL_MSG("ParseCert failed"); - break; - } - else { - request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), - ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - if (request == NULL) { - FreeDecodedCert(cert); - - ret = MEMORY_E; - break; - } - - ret = InitOcspRequest(request, cert, 0, ssl->heap); - if (ret == 0) { - /* make sure ctx OCSP request is updated */ - if (!ssl->buffers.weOwnCertChain) { - wolfSSL_Mutex* ocspLock = - &ssl->ctx->cm->ocsp_stapling->ocspLock; - if (wc_LockMutex(ocspLock) == 0) { - if (ssl->ctx->chainOcspRequest[i] == NULL) - ssl->ctx->chainOcspRequest[i] = request; - wc_UnLockMutex(ocspLock); - } - } - } - else { - FreeDecodedCert(cert); - XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - request = NULL; - break; - } - + ret = CreateOcspRequest(ssl, request, cert, der.buffer, + der.length); + if (ret == 0) { request->ssl = ssl; ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &responses[i + 1]); @@ -14521,15 +14469,12 @@ int SendCertificateStatus(WOLFSSL* ssl) ret = 0; } - if (request != ssl->ctx->chainOcspRequest[i]) - XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); i++; } - - FreeDecodedCert(cert); } + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); #ifdef WOLFSSL_SMALL_STACK XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); #endif @@ -14551,14 +14496,17 @@ int SendCertificateStatus(WOLFSSL* ssl) } if (responses[0].buffer) { - if (ret == 0) - ret = BuildCertificateStatus(ssl, status_type, - responses, (byte)i + 1); + if (ret == 0) { + ret = BuildCertificateStatus(ssl, status_type, responses, + (byte)i + 1); + } - for (i = 0; i < 1 + MAX_CHAIN_DEPTH; i++) - if (responses[i].buffer) + for (i = 0; i < 1 + MAX_CHAIN_DEPTH; i++) { + if (responses[i].buffer) { XFREE(responses[i].buffer, ssl->heap, - DYNAMIC_TYPE_OCSP_REQUEST); + DYNAMIC_TYPE_OCSP_REQUEST); + } + } } break; diff --git a/src/ssl.c b/src/ssl.c index b1e46022a..a3e0ceee1 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1913,7 +1913,7 @@ int wolfSSL_UseOCSPStapling(WOLFSSL* ssl, byte status_type, byte options) return BAD_FUNC_ARG; return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type, - options, ssl->heap, ssl->devId); + options, NULL, ssl->heap, ssl->devId); } @@ -1924,7 +1924,7 @@ int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx, byte status_type, return BAD_FUNC_ARG; return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type, - options, ctx->heap, ctx->devId); + options, NULL, ctx->heap, ctx->devId); } #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ @@ -1941,8 +1941,8 @@ int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl, byte status_type, byte options) } -int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, - byte status_type, byte options) +int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, byte status_type, + byte options) { if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END) return BAD_FUNC_ARG; @@ -19659,8 +19659,8 @@ long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type) if (type == TLSEXT_STATUSTYPE_ocsp){ int r = 0; - r = TLSX_UseCertificateStatusRequest(&s->extensions, type, - 0, s->heap, s->devId); + r = TLSX_UseCertificateStatusRequest(&s->extensions, type, 0, s, + s->heap, s->devId); return (long)r; } else { WOLFSSL_MSG( diff --git a/src/tls.c b/src/tls.c index 7fb4e5ca2..ba34353ed 100644 --- a/src/tls.c +++ b/src/tls.c @@ -2651,6 +2651,17 @@ static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest) } } #endif +#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) + if (!isRequest && csr->ssl->options.tls1_3) { + if (csr->response.buffer == NULL) { + OcspRequest* request = &csr->request.ocsp; + int ret = CreateOcspResponse(csr->ssl, &request, &csr->response); + if (ret < 0) + return ret; + } + return OPAQUE8_LEN + OPAQUE24_LEN + csr->response.length; + } +#endif return size; } @@ -2691,6 +2702,17 @@ static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output, return offset; } #endif +#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) + if (!isRequest && csr->ssl->options.tls1_3) { + word16 offset = 0; + output[offset++] = csr->status_type; + c32to24(csr->response.length, output + offset); + offset += OPAQUE24_LEN; + XMEMCPY(output + offset, csr->response.buffer, csr->response.length); + offset += csr->response.length; + return offset; + } +#endif return 0; } @@ -2719,8 +2741,8 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, /* enable extension at ssl level */ ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, - csr->status_type, csr->options, ssl->heap, - ssl->devId); + csr->status_type, csr->options, ssl, + ssl->heap, ssl->devId); if (ret != WOLFSSL_SUCCESS) return ret; @@ -2743,7 +2765,34 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, ssl->status_request = 1; - return length ? BUFFER_ERROR : 0; /* extension_data MUST be empty. */ + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + word32 resp_length; + word32 offset = 0; + ret = 0; + if (OPAQUE8_LEN + OPAQUE24_LEN > length) + ret = BUFFER_ERROR; + if (ret == 0 && input[offset++] != WOLFSSL_CSR_OCSP) + ret = BAD_CERTIFICATE_STATUS_ERROR; + if (ret == 0) { + c24to32(input + offset, &resp_length); + offset += OPAQUE24_LEN; + if (offset + resp_length != length) + ret = BUFFER_ERROR; + } + if (ret == 0) { + csr->response.buffer = input + offset; + csr->response.length = resp_length; + } + + return ret; + } + else + #endif + { + /* extension_data MUST be empty. */ + return length ? BUFFER_ERROR : 0; + } #endif } else { @@ -2796,13 +2845,12 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, /* accept the first good status_type and return */ ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type, - 0, ssl->heap, ssl->devId); + 0, ssl, ssl->heap, ssl->devId); if (ret != WOLFSSL_SUCCESS) return ret; /* throw error */ TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST); ssl->status_request = status_type; - #endif } @@ -2880,7 +2928,8 @@ int TLSX_CSR_ForceRequest(WOLFSSL* ssl) } int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, - byte options, void* heap, int devId) + byte options, WOLFSSL* ssl, void* heap, + int devId) { CertificateStatusRequest* csr = NULL; int ret = 0; @@ -2897,6 +2946,7 @@ int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, csr->status_type = status_type; csr->options = options; + csr->ssl = ssl; switch (csr->status_type) { case WOLFSSL_CSR_OCSP: @@ -3082,7 +3132,8 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, /* enable extension at ssl level */ for (; csr2; csr2 = csr2->next) { ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions, - csr2->status_type, csr2->options, ssl->heap, ssl->devId); + csr2->status_type, csr2->options, ssl->heap, + ssl->devId); if (ret != WOLFSSL_SUCCESS) return ret; @@ -9184,9 +9235,9 @@ int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word16* pLength) else if (msgType == certificate_request) { XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); - TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, * TLSX_CERTIFICATE_AUTHORITIES, OID_FILTERS + * TLSX_STATUS_REQUEST */ } #endif @@ -9281,9 +9332,9 @@ int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word16* pOffset) else if (msgType == certificate_request) { XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); - TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, * TLSX_CERTIFICATE_AUTHORITIES, TLSX_OID_FILTERS + * TLSX_STATUS_REQUEST */ } #endif @@ -9329,7 +9380,7 @@ int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word16* pOffset) #endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */ -#ifndef NO_WOLFSSL_SERVER +#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_SERVER) /** Tells the buffered size of extensions to be sent into the server hello. */ int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength) @@ -9339,58 +9390,69 @@ int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength) byte semaphore[SEMAPHORE_SIZE] = {0}; switch (msgType) { +#ifndef NO_WOLFSSL_SERVER case server_hello: PF_VALIDATE_RESPONSE(ssl, semaphore); -#ifdef WOLFSSL_TLS13 + #ifdef WOLFSSL_TLS13 if (ssl->options.tls1_3) { XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); -#ifndef WOLFSSL_TLS13_DRAFT_18 + #ifndef WOLFSSL_TLS13_DRAFT_18 TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); -#endif + #endif if (!ssl->options.noPskDheKe) TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); - #endif + #endif } else { TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); - #endif + #endif } -#endif + #endif break; -#ifdef WOLFSSL_TLS13 + + #ifdef WOLFSSL_TLS13 case hello_retry_request: XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); -#ifndef WOLFSSL_TLS13_DRAFT_18 + #ifndef WOLFSSL_TLS13_DRAFT_18 TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); -#endif + #endif if (!ssl->options.noPskDheKe) TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE)); break; -#endif -#ifdef WOLFSSL_TLS13 + #endif + + #ifdef WOLFSSL_TLS13 case encrypted_extensions: TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); - #endif + #endif + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); + #endif break; - #ifdef WOLFSSL_EARLY_DATA + + #ifdef WOLFSSL_EARLY_DATA case session_ticket: if (ssl->options.tls1_3) { XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA)); } break; + #endif #endif +#endif + +#ifdef WOLFSSL_TLS13 #ifndef NO_CERT case certificate: XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); @@ -9440,51 +9502,70 @@ int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset byte semaphore[SEMAPHORE_SIZE] = {0}; switch (msgType) { +#ifndef NO_WOLFSSL_SERVER case server_hello: PF_VALIDATE_RESPONSE(ssl, semaphore); -#ifdef WOLFSSL_TLS13 + #ifdef WOLFSSL_TLS13 if (ssl->options.tls1_3) { XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); -#ifndef WOLFSSL_TLS13_DRAFT_18 + #ifndef WOLFSSL_TLS13_DRAFT_18 TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); -#endif + #endif if (!ssl->options.noPskDheKe) TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); - #endif + #endif } else { TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); - #endif + #endif } -#endif + #endif break; -#ifdef WOLFSSL_TLS13 + + #ifdef WOLFSSL_TLS13 case hello_retry_request: XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); -#ifndef WOLFSSL_TLS13_DRAFT_18 + #ifndef WOLFSSL_TLS13_DRAFT_18 TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); -#endif + #endif if (!ssl->options.noPskDheKe) TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); /* Cookie is written below as last extension. */ break; -#endif -#ifdef WOLFSSL_TLS13 + #endif + + #ifdef WOLFSSL_TLS13 case encrypted_extensions: TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); - #endif + #endif + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); + #endif break; - #ifndef NO_CERTS + + #ifdef WOLFSSL_EARLY_DATA + case session_ticket: + if (ssl->options.tls1_3) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA)); + } + break; + #endif + #endif +#endif + + #ifdef WOLFSSL_TLS13 + #ifndef NO_CERTS case certificate: XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); @@ -9492,16 +9573,8 @@ int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset * TLSX_SERVER_CERTIFICATE_TYPE */ break; + #endif #endif - #ifdef WOLFSSL_EARLY_DATA - case session_ticket: - if (ssl->options.tls1_3) { - XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); - TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA)); - } - break; - #endif -#endif } offset += OPAQUE16_LEN; /* extensions length */ @@ -9537,7 +9610,7 @@ int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset return ret; } -#endif /* NO_WOLFSSL_SERVER */ +#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_SERVER */ /** Parses a buffer of TLS extensions. */ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, diff --git a/src/tls13.c b/src/tls13.c index 264274df7..76a676c99 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -4837,15 +4837,17 @@ static word32 NextCert(byte* data, word32 length, word32* idx) /* Add certificate data and empty extension to output up to the fragment size. * + * ssl SSL/TLS object. * cert The certificate data to write out. * len The length of the certificate data. + * extSz Length of the extension data with the certificate. * idx The start of the certificate data to write out. * fragSz The maximum size of this fragment. * output The buffer to write to. * returns the number of bytes written. */ -static word32 AddCertExt(byte* cert, word32 len, word32 idx, word32 fragSz, - byte* output) +static word32 AddCertExt(WOLFSSL* ssl, byte* cert, word32 len, word16 extSz, + word32 idx, word32 fragSz, byte* output) { word32 i = 0; word32 copySz = min(len - idx, fragSz); @@ -4853,12 +4855,25 @@ static word32 AddCertExt(byte* cert, word32 len, word32 idx, word32 fragSz, if (idx < len) { XMEMCPY(output, cert + idx, copySz); i = copySz; + if (copySz == fragSz) + return i; } + copySz = len + extSz - idx - i; - if (copySz + OPAQUE16_LEN <= fragSz) { - /* Empty extension */ - output[i++] = 0; - output[i++] = 0; + if (extSz == OPAQUE16_LEN) { + if (copySz <= fragSz) { + /* Empty extension */ + output[i++] = 0; + output[i++] = 0; + } + } + else { + byte* certExts = ssl->buffers.certExts->buffer + idx + i - len; + /* Put out as much of the extensions' data as will fit in fragment. */ + if (copySz > fragSz - i) + copySz = fragSz - i; + XMEMCPY(output + i, certExts, copySz); + i += copySz; } return i; @@ -4875,6 +4890,7 @@ static int SendTls13Certificate(WOLFSSL* ssl) { int ret = 0; word32 certSz, certChainSz, headerSz, listSz, payloadSz; + word16 extSz = 0; word32 length, maxFragment; word32 len = 0; word32 idx = 0; @@ -4910,14 +4926,30 @@ static int SendTls13Certificate(WOLFSSL* ssl) /* Cert Req Ctx Len | Cert Req Ctx | Cert List Len | Cert Data Len */ headerSz = OPAQUE8_LEN + certReqCtxLen + CERT_HEADER_SZ + CERT_HEADER_SZ; - /* Length of message data with one certificate and empty extensions. */ - length = headerSz + certSz + OPAQUE16_LEN; - /* Length of list data with one certificate and empty extensions. */ - listSz = CERT_HEADER_SZ + certSz + OPAQUE16_LEN; + + ret = TLSX_GetResponseSize(ssl, certificate, &extSz); + if (ret < 0) + return ret; + + /* Create extensions' data if none already present. */ + if (extSz > OPAQUE16_LEN && ssl->buffers.certExts == NULL) { + ret = AllocDer(&ssl->buffers.certExts, extSz, CERT_TYPE, ssl->heap); + if (ret < 0) + return ret; + + ret = TLSX_WriteResponse(ssl, ssl->buffers.certExts->buffer, + certificate, &extSz); + if (ret < 0) + return ret; + } + + /* Length of message data with one certificate and extensions. */ + length = headerSz + certSz + extSz; + /* Length of list data with one certificate and extensions. */ + listSz = CERT_HEADER_SZ + certSz + extSz; /* Send rest of chain if sending cert (chain has leading size/s). */ if (certSz > 0 && ssl->buffers.certChainCnt > 0) { - /* The pointer to the current spot in the cert chain buffer. */ p = ssl->buffers.certChain->buffer; /* Chain length including extensions. */ certChainSz = ssl->buffers.certChain->length + @@ -4943,14 +4975,13 @@ static int SendTls13Certificate(WOLFSSL* ssl) int sendSz = RECORD_HEADER_SZ; if (ssl->fragOffset == 0) { - if (headerSz + certSz + OPAQUE16_LEN + certChainSz <= - maxFragment - HANDSHAKE_HEADER_SZ) { - - fragSz = headerSz + certSz + OPAQUE16_LEN + certChainSz; + if (headerSz + certSz + extSz + certChainSz <= + maxFragment - HANDSHAKE_HEADER_SZ) { + fragSz = headerSz + certSz + extSz + certChainSz; } - else { + else fragSz = maxFragment - HANDSHAKE_HEADER_SZ; - } + sendSz += fragSz + HANDSHAKE_HEADER_SZ; i += HANDSHAKE_HEADER_SZ; } @@ -4996,15 +5027,16 @@ static int SendTls13Certificate(WOLFSSL* ssl) else AddTls13RecordHeader(output, fragSz, handshake, ssl); - if (certSz > 0 && ssl->fragOffset < certSz + OPAQUE16_LEN) { - /* Put in the leaf certificate and empty extension. */ - word32 copySz = AddCertExt(ssl->buffers.certificate->buffer, certSz, - ssl->fragOffset, fragSz, output + i); - + if (certSz > 0 && ssl->fragOffset < certSz + extSz) { + /* Put in the leaf certificate with extensions. */ + word32 copySz = AddCertExt(ssl, ssl->buffers.certificate->buffer, + certSz, extSz, ssl->fragOffset, fragSz, output + i); i += copySz; ssl->fragOffset += copySz; length -= copySz; fragSz -= copySz; + if (ssl->fragOffset == certSz + extSz) + FreeDer(&ssl->buffers.certExts); } if (certChainSz > 0 && fragSz > 0) { /* Put in the CA certificates with empty extensions. */ @@ -5014,6 +5046,8 @@ static int SendTls13Certificate(WOLFSSL* ssl) if (offset == len + OPAQUE16_LEN) { /* Find next CA certificate to write out. */ offset = 0; + /* Point to the start of current cert in chain buffer. */ + p = ssl->buffers.certChain->buffer + idx; len = NextCert(ssl->buffers.certChain->buffer, ssl->buffers.certChain->length, &idx); if (len == 0) @@ -5021,7 +5055,8 @@ static int SendTls13Certificate(WOLFSSL* ssl) } /* Write out certificate and empty extension. */ - l = AddCertExt(p, len, offset, fragSz, output + i); + l = AddCertExt(ssl, p, len, OPAQUE16_LEN, offset, fragSz, + output + i); i += l; ssl->fragOffset += l; length -= l; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 1776350a1..690b9f254 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1991,7 +1991,8 @@ WOLFSSL_LOCAL int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word16* pOffset); #endif -#ifndef NO_WOLFSSL_SERVER +#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_SERVER) +/* TLS 1.3 Certificate messages have extensions. */ WOLFSSL_LOCAL int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength); WOLFSSL_LOCAL int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, @@ -2084,13 +2085,17 @@ WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions, void* heap); typedef struct { byte status_type; byte options; + WOLFSSL* ssl; union { OcspRequest ocsp; } request; +#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) + buffer response; +#endif } CertificateStatusRequest; WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions, - byte status_type, byte options, void* heap, int devId); + byte status_type, byte options, WOLFSSL* ssl, void* heap, int devId); #ifndef NO_CERTS WOLFSSL_LOCAL int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap); @@ -2114,7 +2119,7 @@ typedef struct CSRIv2 { } CertificateStatusRequestItemV2; WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, - byte status_type, byte options, void* heap, int devId); + byte status_type, byte options, void* heap, int devId); #ifndef NO_CERTS WOLFSSL_LOCAL int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, void* heap); @@ -2957,6 +2962,7 @@ typedef struct Buffers { /* chain after self, in DER, with leading size for each cert */ #ifdef WOLFSSL_TLS13 int certChainCnt; + DerBuffer* certExts; #endif #endif #ifdef WOLFSSL_SEND_HRR_COOKIE @@ -3870,6 +3876,10 @@ WOLFSSL_LOCAL int SendTls13ServerHello(WOLFSSL*, byte); #endif WOLFSSL_LOCAL int SendCertificate(WOLFSSL*); WOLFSSL_LOCAL int SendCertificateRequest(WOLFSSL*); +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) +WOLFSSL_LOCAL int CreateOcspResponse(WOLFSSL*, OcspRequest**, buffer*); +#endif WOLFSSL_LOCAL int SendCertificateStatus(WOLFSSL*); WOLFSSL_LOCAL int SendServerKeyExchange(WOLFSSL*); WOLFSSL_LOCAL int SendBuffered(WOLFSSL*);