Merge pull request #1654 from SparkiDev/tls13_stapling
TLS 1.3 OCSP Stapling
This commit is contained in:
commit
ae54bae2fa
@ -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
|
||||
|
532
src/internal.c
532
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;
|
||||
|
12
src/ssl.c
12
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(
|
||||
|
177
src/tls.c
177
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,
|
||||
|
81
src/tls13.c
81
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;
|
||||
|
@ -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*);
|
||||
|
Loading…
Reference in New Issue
Block a user