TLS 1.3 OCSP Stapling

Introduce support for OCSP stapling in TLS 1.3.
Note: OCSP Stapling v2 is not used in TLS 1.3.
Added tests.
Allow extensions to be sent with first certificate.
Fix writing out of certificate chains in TLS 1.3.
Tidy up the OCSP stapling code to remove duplication as much as
possible.
This commit is contained in:
Sean Parkinson
2018-07-02 16:59:23 +10:00
parent ac3eb470f9
commit 0bf3a89992
6 changed files with 472 additions and 376 deletions

View File

@@ -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

View File

@@ -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
@@ -9010,6 +9095,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
@@ -9610,80 +9710,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
@@ -13690,7 +13719,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)
@@ -14194,7 +14332,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)
{
@@ -14225,97 +14362,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;
}
@@ -14331,85 +14385,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;
@@ -14420,14 +14396,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);
@@ -14439,43 +14421,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]);
@@ -14487,15 +14435,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
@@ -14517,14 +14462,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;

View File

@@ -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;
@@ -19597,8 +19597,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(

177
src/tls.c
View File

@@ -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,

View File

@@ -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;

View File

@@ -1990,7 +1990,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,
@@ -2083,13 +2084,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);
@@ -2113,7 +2118,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);
@@ -2936,6 +2941,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
@@ -3849,6 +3855,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*);