forked from wolfSSL/wolfssl
Merge pull request #8408 from rizlik/ocsp-resp-refactor
OpenSSL Compat Layer: OCSP response improvments
This commit is contained in:
@@ -2510,6 +2510,7 @@ if(WOLFSSL_EXAMPLES)
|
|||||||
tests/api/test_ripemd.c
|
tests/api/test_ripemd.c
|
||||||
tests/api/test_hash.c
|
tests/api/test_hash.c
|
||||||
tests/api/test_ascon.c
|
tests/api/test_ascon.c
|
||||||
|
tests/api/test_ocsp.c
|
||||||
tests/hash.c
|
tests/hash.c
|
||||||
tests/srp.c
|
tests/srp.c
|
||||||
tests/suites.c
|
tests/suites.c
|
||||||
|
@@ -36,4 +36,5 @@ EXTRA_DIST += \
|
|||||||
certs/ocsp/test-response.der \
|
certs/ocsp/test-response.der \
|
||||||
certs/ocsp/test-response-rsapss.der \
|
certs/ocsp/test-response-rsapss.der \
|
||||||
certs/ocsp/test-response-nointern.der \
|
certs/ocsp/test-response-nointern.der \
|
||||||
certs/ocsp/test-multi-response.der
|
certs/ocsp/test-multi-response.der \
|
||||||
|
certs/ocsp/test-leaf-response.der
|
||||||
|
@@ -100,6 +100,16 @@ openssl ocsp -issuer ./root-ca-cert.pem -cert ./intermediate1-ca-cert.pem -cert
|
|||||||
kill $PID
|
kill $PID
|
||||||
wait $PID
|
wait $PID
|
||||||
|
|
||||||
|
# Create a response DER buffer for testing leaf certificate
|
||||||
|
openssl ocsp -port 22221 -ndays 1000 -index \
|
||||||
|
./index-intermediate1-ca-issued-certs.txt -rsigner ocsp-responder-cert.pem \
|
||||||
|
-rkey ocsp-responder-key.pem -CA intermediate1-ca-cert.pem -partial_chain &
|
||||||
|
PID=$!
|
||||||
|
sleep 1 # Make sure server is ready
|
||||||
|
|
||||||
|
openssl ocsp -issuer ./intermediate1-ca-cert.pem -cert ./server1-cert.pem -url http://localhost:22221/ -respout test-leaf-response.der -noverify
|
||||||
|
kill $PID
|
||||||
|
wait $PID
|
||||||
|
|
||||||
# now start up a responder that signs using rsa-pss
|
# now start up a responder that signs using rsa-pss
|
||||||
openssl ocsp -port 22221 -ndays 1000 -index index-ca-and-intermediate-cas.txt -rsigner ocsp-responder-cert.pem -rkey ocsp-responder-key.pem -CA root-ca-cert.pem -rsigopt rsa_padding_mode:pss &
|
openssl ocsp -port 22221 -ndays 1000 -index index-ca-and-intermediate-cas.txt -rsigner ocsp-responder-cert.pem -rkey ocsp-responder-key.pem -CA root-ca-cert.pem -rsigopt rsa_padding_mode:pss &
|
||||||
|
BIN
certs/ocsp/test-leaf-response.der
Normal file
BIN
certs/ocsp/test-leaf-response.der
Normal file
Binary file not shown.
@@ -9163,7 +9163,6 @@ then
|
|||||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_PRIORITIZE_PSK"
|
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_PRIORITIZE_PSK"
|
||||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CHECK_ALERT_ON_ERR"
|
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CHECK_ALERT_ON_ERR"
|
||||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TICKET_HAVE_ID"
|
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TICKET_HAVE_ID"
|
||||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_OCSP_ISSUER_CHECK"
|
|
||||||
ENABLED_TRUSTED_PEER_CERT=yes
|
ENABLED_TRUSTED_PEER_CERT=yes
|
||||||
else
|
else
|
||||||
CFLAGS=$(printf "%s" "$CFLAGS" | sed 's/-DOPENSSL_COMPATIBLE_DEFAULTS//g')
|
CFLAGS=$(printf "%s" "$CFLAGS" | sed 's/-DOPENSSL_COMPATIBLE_DEFAULTS//g')
|
||||||
|
@@ -8690,6 +8690,13 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl)
|
|||||||
#ifdef OPENSSL_EXTRA
|
#ifdef OPENSSL_EXTRA
|
||||||
XFREE(ssl->param, ssl->heap, DYNAMIC_TYPE_OPENSSL);
|
XFREE(ssl->param, ssl->heap, DYNAMIC_TYPE_OPENSSL);
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(HAVE_OCSP) && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY))
|
||||||
|
if (ssl->ocspResp) {
|
||||||
|
XFREE(ssl->ocspResp, NULL, 0);
|
||||||
|
ssl->ocspResp = NULL;
|
||||||
|
ssl->ocspRespSz = 0;
|
||||||
|
}
|
||||||
|
#endif /* defined(HAVE_OCSP) && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) */
|
||||||
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
|
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
|
||||||
while (ssl->certReqCtx != NULL) {
|
while (ssl->certReqCtx != NULL) {
|
||||||
CertReqCtx* curr = ssl->certReqCtx;
|
CertReqCtx* curr = ssl->certReqCtx;
|
||||||
@@ -9014,6 +9021,14 @@ void FreeHandshakeResources(WOLFSSL* ssl)
|
|||||||
* !WOLFSSL_POST_HANDSHAKE_AUTH */
|
* !WOLFSSL_POST_HANDSHAKE_AUTH */
|
||||||
#endif /* HAVE_TLS_EXTENSIONS && !NO_TLS */
|
#endif /* HAVE_TLS_EXTENSIONS && !NO_TLS */
|
||||||
|
|
||||||
|
#if defined(HAVE_OCSP) && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY))
|
||||||
|
if (ssl->ocspResp != NULL) {
|
||||||
|
XFREE(ssl->ocspResp, NULL, 0);
|
||||||
|
ssl->ocspResp = NULL;
|
||||||
|
ssl->ocspRespSz = 0;
|
||||||
|
}
|
||||||
|
#endif /* defined(HAVE_OCSP) && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) */
|
||||||
|
|
||||||
#ifdef WOLFSSL_STATIC_MEMORY
|
#ifdef WOLFSSL_STATIC_MEMORY
|
||||||
/* when done with handshake decrement current handshake count */
|
/* when done with handshake decrement current handshake count */
|
||||||
if (ssl->heap != NULL) {
|
if (ssl->heap != NULL) {
|
||||||
@@ -13861,7 +13876,7 @@ static int ProcessCSR_ex(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
/* InitOcspResponse sets single and status to response struct. */
|
/* InitOcspResponse sets single and status to response struct. */
|
||||||
InitOcspResponse(response, single, status, input +*inOutIdx, status_length, ssl->heap);
|
InitOcspResponse(response, single, status, input +*inOutIdx, status_length, ssl->heap);
|
||||||
|
|
||||||
if (OcspResponseDecode(response, SSL_CM(ssl), ssl->heap, 0) != 0)
|
if (OcspResponseDecode(response, SSL_CM(ssl), ssl->heap, 0, 0) != 0)
|
||||||
ret = BAD_CERTIFICATE_STATUS_ERROR;
|
ret = BAD_CERTIFICATE_STATUS_ERROR;
|
||||||
else if (CompareOcspReqResp(request, response) != 0)
|
else if (CompareOcspReqResp(request, response) != 0)
|
||||||
ret = BAD_CERTIFICATE_STATUS_ERROR;
|
ret = BAD_CERTIFICATE_STATUS_ERROR;
|
||||||
@@ -16967,7 +16982,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
status_length, ssl->heap);
|
status_length, ssl->heap);
|
||||||
response->pendingCAs = pendingCAs;
|
response->pendingCAs = pendingCAs;
|
||||||
if ((OcspResponseDecode(response, SSL_CM(ssl), ssl->heap,
|
if ((OcspResponseDecode(response, SSL_CM(ssl), ssl->heap,
|
||||||
0) != 0)
|
0, 0) != 0)
|
||||||
|| (response->responseStatus != OCSP_SUCCESSFUL)
|
|| (response->responseStatus != OCSP_SUCCESSFUL)
|
||||||
|| (response->single->status->status != CERT_GOOD))
|
|| (response->single->status->status != CERT_GOOD))
|
||||||
ret = BAD_CERTIFICATE_STATUS_ERROR;
|
ret = BAD_CERTIFICATE_STATUS_ERROR;
|
||||||
@@ -24099,7 +24114,7 @@ int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request,
|
|||||||
ret = InitOcspRequest(request, cert, 0, ssl->heap);
|
ret = InitOcspRequest(request, cert, 0, ssl->heap);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
/* make sure ctx OCSP request is updated */
|
/* make sure ctx OCSP request is updated */
|
||||||
if (!ssl->buffers.weOwnCert) {
|
if (!ssl->buffers.weOwnCert && SSL_CM(ssl) != NULL) {
|
||||||
wolfSSL_Mutex* ocspLock = &SSL_CM(ssl)->ocsp_stapling->ocspLock;
|
wolfSSL_Mutex* ocspLock = &SSL_CM(ssl)->ocsp_stapling->ocspLock;
|
||||||
if (wc_LockMutex(ocspLock) == 0) {
|
if (wc_LockMutex(ocspLock) == 0) {
|
||||||
if (ssl->ctx->certOcspRequest == NULL) {
|
if (ssl->ctx->certOcspRequest == NULL) {
|
||||||
@@ -24840,6 +24855,49 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \
|
||||||
|
(defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
|
||||||
|
defined(WOLFSSL_HAPROXY))
|
||||||
|
static int BuildCertificateStatusWithStatusCB(WOLFSSL* ssl)
|
||||||
|
{
|
||||||
|
WOLFSSL_OCSP *ocsp;
|
||||||
|
void *ioCtx = NULL;
|
||||||
|
buffer response;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ocsp = SSL_CM(ssl)->ocsp_stapling;
|
||||||
|
if (ocsp == NULL || ocsp->statusCb == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
ioCtx = (ssl && ssl->ocspIOCtx != NULL) ?
|
||||||
|
ssl->ocspIOCtx : ocsp->cm->ocspIOCtx;
|
||||||
|
XMEMSET(&response, 0, sizeof(response));
|
||||||
|
WOLFSSL_MSG("Calling ocsp->statusCb");
|
||||||
|
ret = ocsp->statusCb(ssl, ioCtx);
|
||||||
|
switch (ret) {
|
||||||
|
case SSL_TLSEXT_ERR_OK:
|
||||||
|
if (ssl->ocspResp == NULL || ssl->ocspRespSz == 0) {
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
response.buffer = ssl->ocspResp;
|
||||||
|
response.length = ssl->ocspRespSz;
|
||||||
|
ret = BuildCertificateStatus(ssl, WOLFSSL_CSR_OCSP, &response, 1);
|
||||||
|
break;
|
||||||
|
case SSL_TLSEXT_ERR_NOACK:
|
||||||
|
/* No OCSP response to send */
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
case SSL_TLSEXT_ERR_ALERT_FATAL:
|
||||||
|
/* fall through */
|
||||||
|
default:
|
||||||
|
ret = WOLFSSL_FATAL_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST && (defined(OPENSSL_ALL) ||
|
||||||
|
defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) */
|
||||||
#endif /* NO_WOLFSSL_SERVER */
|
#endif /* NO_WOLFSSL_SERVER */
|
||||||
|
|
||||||
/* handle generation of certificate_status (22) */
|
/* handle generation of certificate_status (22) */
|
||||||
@@ -24860,6 +24918,20 @@ int SendCertificateStatus(WOLFSSL* ssl)
|
|||||||
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
|
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
|
||||||
status_type = status_type ? status_type : ssl->status_request_v2;
|
status_type = status_type ? status_type : ssl->status_request_v2;
|
||||||
#endif
|
#endif
|
||||||
|
if (ssl == NULL || SSL_CM(ssl) == NULL) {
|
||||||
|
WOLFSSL_MSG("SendCertificateStatus bad args");
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \
|
||||||
|
(defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
|
||||||
|
defined(WOLFSSL_HAPROXY))
|
||||||
|
if (SSL_CM(ssl)->ocsp_stapling != NULL &&
|
||||||
|
SSL_CM(ssl)->ocsp_stapling->statusCb != NULL) {
|
||||||
|
if (ssl->status_request == WOLFSSL_CSR_OCSP)
|
||||||
|
return BuildCertificateStatusWithStatusCB(ssl);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (status_type) {
|
switch (status_type) {
|
||||||
|
|
||||||
|
257
src/ocsp.c
257
src/ocsp.c
@@ -333,7 +333,7 @@ int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz,
|
|||||||
ocspResponse->pendingCAs = TLSX_CSR2_GetPendingSigners(((WOLFSSL*)ocspRequest->ssl)->extensions);
|
ocspResponse->pendingCAs = TLSX_CSR2_GetPendingSigners(((WOLFSSL*)ocspRequest->ssl)->extensions);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0);
|
ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0, 0);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
ocsp->error = ret;
|
ocsp->error = ret;
|
||||||
WOLFSSL_LEAVE("OcspResponseDecode failed", ocsp->error);
|
WOLFSSL_LEAVE("OcspResponseDecode failed", ocsp->error);
|
||||||
@@ -480,31 +480,6 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
|
|||||||
ioCtx = (ssl && ssl->ocspIOCtx != NULL) ?
|
ioCtx = (ssl && ssl->ocspIOCtx != NULL) ?
|
||||||
ssl->ocspIOCtx : ocsp->cm->ocspIOCtx;
|
ssl->ocspIOCtx : ocsp->cm->ocspIOCtx;
|
||||||
|
|
||||||
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
|
|
||||||
if (ocsp->statusCb != NULL && ssl != NULL) {
|
|
||||||
WOLFSSL_MSG("Calling ocsp->statusCb");
|
|
||||||
ret = ocsp->statusCb(ssl, ioCtx);
|
|
||||||
switch (ret) {
|
|
||||||
case SSL_TLSEXT_ERR_OK:
|
|
||||||
ret = wolfSSL_get_ocsp_response(ssl, &response);
|
|
||||||
ret = CheckOcspResponse(ocsp, response, ret, responseBuffer,
|
|
||||||
status, entry, NULL, heap);
|
|
||||||
XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL);
|
|
||||||
break;
|
|
||||||
case SSL_TLSEXT_ERR_NOACK:
|
|
||||||
ret = OCSP_LOOKUP_FAIL;
|
|
||||||
break;
|
|
||||||
case SSL_TLSEXT_ERR_ALERT_FATAL:
|
|
||||||
default:
|
|
||||||
WOLFSSL_LEAVE("CheckOcspRequest", ocsp->error);
|
|
||||||
ret = WOLFSSL_FATAL_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
WOLFSSL_LEAVE("CheckOcspRequest", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ocsp->cm->ocspUseOverrideURL) {
|
if (ocsp->cm->ocspUseOverrideURL) {
|
||||||
url = ocsp->cm->ocspOverrideURL;
|
url = ocsp->cm->ocspOverrideURL;
|
||||||
if (url != NULL && url[0] != '\0')
|
if (url != NULL && url[0] != '\0')
|
||||||
@@ -656,9 +631,6 @@ int CheckOcspResponder(OcspResponse *bs, DecodedCert *cert, void* vp)
|
|||||||
|
|
||||||
if (!passed) {
|
if (!passed) {
|
||||||
WOLFSSL_MSG("\tOCSP Responder not authorized");
|
WOLFSSL_MSG("\tOCSP Responder not authorized");
|
||||||
#ifdef OPENSSL_EXTRA
|
|
||||||
bs->verifyError = OCSP_BAD_ISSUER;
|
|
||||||
#endif
|
|
||||||
ret = BAD_OCSP_RESPONDER;
|
ret = BAD_OCSP_RESPONDER;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -850,79 +822,174 @@ void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse)
|
|||||||
wolfSSL_OCSP_RESPONSE_free(basicResponse);
|
wolfSSL_OCSP_RESPONSE_free(basicResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int OcspRespIdMatches(OcspResponse* resp, const byte* NameHash,
|
||||||
|
const byte* keyHash)
|
||||||
|
{
|
||||||
|
if (resp->responderIdType == OCSP_RESPONDER_ID_NAME) {
|
||||||
|
return XMEMCMP(NameHash, resp->responderId.nameHash,
|
||||||
|
SIGNER_DIGEST_SIZE) == 0;
|
||||||
|
}
|
||||||
|
else if (resp->responderIdType == OCSP_RESPONDER_ID_KEY) {
|
||||||
|
return XMEMCMP(keyHash, resp->responderId.keyHash, KEYID_SIZE) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int OcspFindSigner(WOLFSSL_OCSP_BASICRESP *resp,
|
||||||
|
WOLF_STACK_OF(WOLFSSL_X509) *certs, DecodedCert **signer, int *embedded,
|
||||||
|
unsigned long flags)
|
||||||
|
{
|
||||||
|
WOLFSSL_X509 *signer_x509 = NULL;
|
||||||
|
DecodedCert *certDecoded;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
certDecoded = (DecodedCert *)XMALLOC(sizeof(*certDecoded), resp->heap,
|
||||||
|
DYNAMIC_TYPE_DCERT);
|
||||||
|
if (certDecoded == NULL)
|
||||||
|
return MEMORY_E;
|
||||||
|
|
||||||
|
for (i = 0; i < wolfSSL_sk_X509_num(certs); i++) {
|
||||||
|
signer_x509 = wolfSSL_sk_X509_value(certs, i);
|
||||||
|
if (signer_x509 == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
InitDecodedCert(certDecoded, signer_x509->derCert->buffer,
|
||||||
|
signer_x509->derCert->length, resp->heap);
|
||||||
|
if (ParseCertRelative(certDecoded, CERT_TYPE, NO_VERIFY,
|
||||||
|
NULL, NULL) == 0) {
|
||||||
|
if (OcspRespIdMatches(resp, certDecoded->subjectHash,
|
||||||
|
certDecoded->subjectKeyHash)) {
|
||||||
|
*signer = certDecoded;
|
||||||
|
*embedded = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeDecodedCert(certDecoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & WOLFSSL_OCSP_NOINTERN) {
|
||||||
|
XFREE(certDecoded, resp->heap, DYNAMIC_TYPE_DCERT);
|
||||||
|
return ASN_NO_SIGNER_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found in certs, search the cert embedded in the response */
|
||||||
|
InitDecodedCert(certDecoded, resp->cert, resp->certSz, resp->heap);
|
||||||
|
if (ParseCertRelative(certDecoded, CERT_TYPE, NO_VERIFY, NULL, NULL) == 0) {
|
||||||
|
if (OcspRespIdMatches(resp, certDecoded->subjectHash,
|
||||||
|
certDecoded->subjectKeyHash)) {
|
||||||
|
*signer = certDecoded;
|
||||||
|
*embedded = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeDecodedCert(certDecoded);
|
||||||
|
|
||||||
|
XFREE(certDecoded, resp->heap, DYNAMIC_TYPE_DCERT);
|
||||||
|
return ASN_NO_SIGNER_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int OcspVerifySigner(WOLFSSL_OCSP_BASICRESP *resp, DecodedCert *cert,
|
||||||
|
WOLFSSL_X509_STORE *st, unsigned long flags)
|
||||||
|
{
|
||||||
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
|
DecodedCert *c = NULL;
|
||||||
|
#else
|
||||||
|
DecodedCert c[1];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
if (st == NULL)
|
||||||
|
return ASN_OCSP_CONFIRM_E;
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
|
c = (DecodedCert *)XMALLOC(sizeof(*c), NULL, DYNAMIC_TYPE_DCERT);
|
||||||
|
if (c == NULL)
|
||||||
|
return MEMORY_E;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
InitDecodedCert(c, cert->source, cert->maxIdx, NULL);
|
||||||
|
if (ParseCertRelative(c, CERT_TYPE, VERIFY, st->cm, NULL) != 0) {
|
||||||
|
ret = ASN_OCSP_CONFIRM_E;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
|
||||||
|
if ((flags & WOLFSSL_OCSP_NOCHECKS) == 0) {
|
||||||
|
ret = CheckOcspResponder(resp, c, st->cm);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
(void)resp;
|
||||||
|
(void)flags;
|
||||||
|
ret = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
err:
|
||||||
|
FreeDecodedCert(c);
|
||||||
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
|
XFREE(c, NULL, DYNAMIC_TYPE_DCERT);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
/* Signature verified in DecodeBasicOcspResponse.
|
/* Signature verified in DecodeBasicOcspResponse.
|
||||||
* But no store available to verify certificate. */
|
* But no store available to verify certificate. */
|
||||||
int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs,
|
int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP* bs,
|
||||||
WOLF_STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags)
|
WOLF_STACK_OF(WOLFSSL_X509) * certs, WOLFSSL_X509_STORE* st,
|
||||||
|
unsigned long flags)
|
||||||
{
|
{
|
||||||
int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
|
int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
int embedded;
|
||||||
DecodedCert *cert;
|
DecodedCert *cert = NULL;
|
||||||
#else
|
|
||||||
DecodedCert cert[1];
|
|
||||||
#endif
|
|
||||||
byte certInit = 0;
|
|
||||||
int idx;
|
|
||||||
|
|
||||||
(void)certs;
|
ret = OcspFindSigner(bs, certs, &cert, &embedded, flags);
|
||||||
|
if (ret != 0) {
|
||||||
if (flags & WOLFSSL_OCSP_NOVERIFY)
|
WOLFSSL_MSG("OCSP no signer found");
|
||||||
return WOLFSSL_SUCCESS;
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
|
||||||
cert = (DecodedCert *)
|
|
||||||
XMALLOC(sizeof(*cert), (st && st->cm) ? st->cm->heap : NULL,
|
|
||||||
DYNAMIC_TYPE_DCERT);
|
|
||||||
if (cert == NULL)
|
|
||||||
return WOLFSSL_FAILURE;
|
return WOLFSSL_FAILURE;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (bs->verifyError != OCSP_VERIFY_ERROR_NONE)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (flags & WOLFSSL_OCSP_TRUSTOTHER) {
|
|
||||||
for (idx = 0; idx < wolfSSL_sk_X509_num(certs); idx++) {
|
|
||||||
WOLFSSL_X509* x = wolfSSL_sk_X509_value(certs, idx);
|
|
||||||
int derSz = 0;
|
|
||||||
const byte* der = wolfSSL_X509_get_der(x, &derSz);
|
|
||||||
if (der != NULL && derSz == (int)bs->certSz &&
|
|
||||||
XMEMCMP(bs->cert, der, (size_t)derSz) == 0) {
|
|
||||||
ret = WOLFSSL_SUCCESS;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InitDecodedCert(cert, bs->cert, bs->certSz, NULL);
|
/* skip certificate verification if cert in certs and TRUST_OTHER is true */
|
||||||
certInit = 1;
|
if (!embedded && (flags & WOLFSSL_OCSP_TRUSTOTHER) != 0)
|
||||||
if (ParseCertRelative(cert, CERT_TYPE, VERIFY, st->cm, NULL) < 0)
|
flags |= WOLFSSL_OCSP_NOVERIFY;
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (!(flags & WOLFSSL_OCSP_NOCHECKS)) {
|
/* verify response signature */
|
||||||
if (CheckOcspResponder(bs, cert, st->cm) != 0)
|
ret = ConfirmSignature(
|
||||||
goto out;
|
&cert->sigCtx,
|
||||||
|
bs->response, bs->responseSz,
|
||||||
|
cert->publicKey, cert->pubKeySize, cert->keyOID,
|
||||||
|
bs->sig, bs->sigSz, bs->sigOID, bs->sigParams, bs->sigParamsSz,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
WOLFSSL_MSG("OCSP signature verification failed");
|
||||||
|
ret = -1;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = WOLFSSL_SUCCESS;
|
if ((flags & WOLFSSL_OCSP_NOVERIFY) == 0) {
|
||||||
out:
|
ret = OcspVerifySigner(bs, cert, st, flags);
|
||||||
if (certInit)
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
FreeDecodedCert(cert);
|
FreeDecodedCert(cert);
|
||||||
|
XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
return ret == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
|
||||||
XFREE(cert, (st && st->cm) ? st->cm->heap : NULL, DYNAMIC_TYPE_DCERT);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response)
|
void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response)
|
||||||
{
|
{
|
||||||
|
OcspEntry *s, *sNext;
|
||||||
if (response == NULL)
|
if (response == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (response->single != NULL) {
|
|
||||||
FreeOcspEntry(response->single, NULL);
|
s = response->single;
|
||||||
XFREE(response->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
|
while (s != NULL) {
|
||||||
|
sNext = s->next;
|
||||||
|
FreeOcspEntry(s, NULL);
|
||||||
|
XFREE(s, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
|
||||||
|
s = sNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
@@ -1045,7 +1112,7 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
|
|||||||
XMEMCPY(resp->source, *data, (size_t)len);
|
XMEMCPY(resp->source, *data, (size_t)len);
|
||||||
resp->maxIdx = (word32)len;
|
resp->maxIdx = (word32)len;
|
||||||
|
|
||||||
ret = OcspResponseDecode(resp, NULL, NULL, 1);
|
ret = OcspResponseDecode(resp, NULL, NULL, 1, 1);
|
||||||
if (ret != 0 && ret != WC_NO_ERR_TRACE(ASN_OCSP_CONFIRM_E)) {
|
if (ret != 0 && ret != WC_NO_ERR_TRACE(ASN_OCSP_CONFIRM_E)) {
|
||||||
/* for just converting from a DER to an internal structure the CA may
|
/* for just converting from a DER to an internal structure the CA may
|
||||||
* not yet be known to this function for signature verification */
|
* not yet be known to this function for signature verification */
|
||||||
@@ -1100,27 +1167,9 @@ const char *wolfSSL_OCSP_response_status_str(long s)
|
|||||||
WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response)
|
WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response)
|
||||||
{
|
{
|
||||||
WOLFSSL_OCSP_BASICRESP* bs;
|
WOLFSSL_OCSP_BASICRESP* bs;
|
||||||
|
const unsigned char *ptr = response->source;
|
||||||
|
|
||||||
bs = (WOLFSSL_OCSP_BASICRESP*)XMALLOC(sizeof(WOLFSSL_OCSP_BASICRESP), NULL,
|
bs = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr, response->maxIdx);
|
||||||
DYNAMIC_TYPE_OCSP_REQUEST);
|
|
||||||
if (bs == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
XMEMCPY(bs, response, sizeof(OcspResponse));
|
|
||||||
bs->single = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL,
|
|
||||||
DYNAMIC_TYPE_OCSP_ENTRY);
|
|
||||||
bs->source = (byte*)XMALLOC(bs->maxIdx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
||||||
if (bs->single == NULL || bs->source == NULL) {
|
|
||||||
XFREE(bs->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
|
|
||||||
bs->single = NULL;
|
|
||||||
wolfSSL_OCSP_RESPONSE_free(bs);
|
|
||||||
bs = NULL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
XMEMCPY(bs->single, response->single, sizeof(OcspEntry));
|
|
||||||
XMEMCPY(bs->source, response->source, response->maxIdx);
|
|
||||||
bs->single->ownStatus = 0;
|
|
||||||
}
|
|
||||||
return bs;
|
return bs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17355,7 +17355,7 @@ void wolfSSL_ERR_load_SSL_strings(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_OCSP
|
#if defined(HAVE_OCSP) && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY))
|
||||||
long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp)
|
long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp)
|
||||||
{
|
{
|
||||||
if (s == NULL || resp == NULL)
|
if (s == NULL || resp == NULL)
|
||||||
@@ -17371,12 +17371,13 @@ long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp,
|
|||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
return WOLFSSL_FAILURE;
|
return WOLFSSL_FAILURE;
|
||||||
|
|
||||||
|
XFREE(s->ocspResp, NULL, 0);
|
||||||
s->ocspResp = resp;
|
s->ocspResp = resp;
|
||||||
s->ocspRespSz = len;
|
s->ocspRespSz = len;
|
||||||
|
|
||||||
return WOLFSSL_SUCCESS;
|
return WOLFSSL_SUCCESS;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_OCSP */
|
#endif /* defined(HAVE_OCSP) && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) */
|
||||||
|
|
||||||
#ifdef HAVE_MAX_FRAGMENT
|
#ifdef HAVE_MAX_FRAGMENT
|
||||||
#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS)
|
#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS)
|
||||||
|
96
src/tls.c
96
src/tls.c
@@ -3238,6 +3238,14 @@ word16 TLSX_CSR_GetSize_ex(CertificateStatusRequest* csr, byte isRequest,
|
|||||||
#endif
|
#endif
|
||||||
#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
|
#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
|
||||||
if (!isRequest && IsAtLeastTLSv1_3(csr->ssl->version)) {
|
if (!isRequest && IsAtLeastTLSv1_3(csr->ssl->version)) {
|
||||||
|
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
|
||||||
|
if (csr->ssl != NULL && SSL_CM(csr->ssl) != NULL &&
|
||||||
|
SSL_CM(csr->ssl)->ocsp_stapling != NULL &&
|
||||||
|
SSL_CM(csr->ssl)->ocsp_stapling->statusCb != NULL &&
|
||||||
|
idx == 0) {
|
||||||
|
return OPAQUE8_LEN + OPAQUE24_LEN + csr->ssl->ocspRespSz;
|
||||||
|
}
|
||||||
|
#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
|
||||||
return (word16)(OPAQUE8_LEN + OPAQUE24_LEN +
|
return (word16)(OPAQUE8_LEN + OPAQUE24_LEN +
|
||||||
csr->responses[idx].length);
|
csr->responses[idx].length);
|
||||||
}
|
}
|
||||||
@@ -3247,6 +3255,70 @@ word16 TLSX_CSR_GetSize_ex(CertificateStatusRequest* csr, byte isRequest,
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)) && \
|
||||||
|
(defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY))
|
||||||
|
static int TLSX_CSR_SetResponseWithStatusCB(WOLFSSL *ssl)
|
||||||
|
{
|
||||||
|
void *ioCtx = NULL;
|
||||||
|
WOLFSSL_OCSP *ocsp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (ssl == NULL || SSL_CM(ssl) == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
ocsp = SSL_CM(ssl)->ocsp_stapling;
|
||||||
|
if (ocsp == NULL || ocsp->statusCb == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
ioCtx = (ssl->ocspIOCtx != NULL) ? ssl->ocspIOCtx : ocsp->cm->ocspIOCtx;
|
||||||
|
ret = ocsp->statusCb(ssl, ioCtx);
|
||||||
|
switch (ret) {
|
||||||
|
case SSL_TLSEXT_ERR_OK:
|
||||||
|
if (ssl->ocspRespSz > 0) {
|
||||||
|
/* ack the extension, status cb provided the response in
|
||||||
|
* ssl->ocspResp */
|
||||||
|
TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST);
|
||||||
|
ssl->status_request = WOLFSSL_CSR_OCSP;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
case SSL_TLSEXT_ERR_NOACK:
|
||||||
|
/* suppressing as not critical */
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
case SSL_TLSEXT_ERR_ALERT_FATAL:
|
||||||
|
default:
|
||||||
|
ret = WOLFSSL_FATAL_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int TLSX_CSR_WriteWithStatusCB(CertificateStatusRequest* csr,
|
||||||
|
byte* output)
|
||||||
|
{
|
||||||
|
WOLFSSL *ssl = csr->ssl;
|
||||||
|
WOLFSSL_OCSP *ocsp;
|
||||||
|
word16 offset = 0;
|
||||||
|
byte *response;
|
||||||
|
int respSz;
|
||||||
|
|
||||||
|
if (ssl == NULL || SSL_CM(ssl) == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
ocsp = SSL_CM(ssl)->ocsp_stapling;
|
||||||
|
if (ocsp == NULL || ocsp->statusCb == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
response = ssl->ocspResp;
|
||||||
|
respSz = ssl->ocspRespSz;
|
||||||
|
if (response == NULL || respSz == 0)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
output[offset++] = WOLFSSL_CSR_OCSP;
|
||||||
|
c32to24(respSz, output + offset);
|
||||||
|
offset += OPAQUE24_LEN;
|
||||||
|
XMEMCPY(output + offset, response, respSz);
|
||||||
|
return offset + respSz;
|
||||||
|
}
|
||||||
|
#endif /* (TLS13 && !NO_WOLFSLL_SERVER) && (OPENSSL_ALL || WOLFSSL_NGINX ||
|
||||||
|
WOLFSSL_HAPROXY) */
|
||||||
|
|
||||||
static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest)
|
static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest)
|
||||||
{
|
{
|
||||||
return TLSX_CSR_GetSize_ex(csr, isRequest, 0);
|
return TLSX_CSR_GetSize_ex(csr, isRequest, 0);
|
||||||
@@ -3299,6 +3371,14 @@ int TLSX_CSR_Write_ex(CertificateStatusRequest* csr, byte* output,
|
|||||||
#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
|
#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
|
||||||
if (!isRequest && IsAtLeastTLSv1_3(csr->ssl->version)) {
|
if (!isRequest && IsAtLeastTLSv1_3(csr->ssl->version)) {
|
||||||
word16 offset = 0;
|
word16 offset = 0;
|
||||||
|
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
|
||||||
|
if (csr->ssl != NULL && SSL_CM(csr->ssl) != NULL &&
|
||||||
|
SSL_CM(csr->ssl)->ocsp_stapling != NULL &&
|
||||||
|
SSL_CM(csr->ssl)->ocsp_stapling->statusCb != NULL &&
|
||||||
|
idx == 0) {
|
||||||
|
return TLSX_CSR_WriteWithStatusCB(csr, output);
|
||||||
|
}
|
||||||
|
#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
|
||||||
output[offset++] = csr->status_type;
|
output[offset++] = csr->status_type;
|
||||||
c32to24(csr->responses[idx].length, output + offset);
|
c32to24(csr->responses[idx].length, output + offset);
|
||||||
offset += OPAQUE24_LEN;
|
offset += OPAQUE24_LEN;
|
||||||
@@ -3574,7 +3654,13 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length,
|
|||||||
|
|
||||||
#if defined(WOLFSSL_TLS13)
|
#if defined(WOLFSSL_TLS13)
|
||||||
if (ssl->options.tls1_3) {
|
if (ssl->options.tls1_3) {
|
||||||
|
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
|
||||||
|
if (ssl != NULL && SSL_CM(ssl) != NULL &&
|
||||||
|
SSL_CM(ssl)->ocsp_stapling != NULL &&
|
||||||
|
SSL_CM(ssl)->ocsp_stapling->statusCb != NULL) {
|
||||||
|
return TLSX_CSR_SetResponseWithStatusCB(ssl);
|
||||||
|
}
|
||||||
|
#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
|
||||||
if (ssl->buffers.certificate == NULL) {
|
if (ssl->buffers.certificate == NULL) {
|
||||||
WOLFSSL_MSG("Certificate buffer not set!");
|
WOLFSSL_MSG("Certificate buffer not set!");
|
||||||
return BUFFER_ERROR;
|
return BUFFER_ERROR;
|
||||||
@@ -4071,6 +4157,14 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, const byte* input, word16 length,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
|
||||||
|
/* OpenSSL status CB supports only CERTIFICATE STATUS REQ V1 */
|
||||||
|
if (ssl != NULL && SSL_CM(ssl) != NULL &&
|
||||||
|
SSL_CM(ssl)->ocsp_stapling != NULL &&
|
||||||
|
SSL_CM(ssl)->ocsp_stapling->statusCb != NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* if using status_request and already sending it, remove it
|
/* if using status_request and already sending it, remove it
|
||||||
* and prefer to use the v2 version */
|
* and prefer to use the v2 version */
|
||||||
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
|
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
|
||||||
|
75
tests/api.c
75
tests/api.c
@@ -301,6 +301,7 @@
|
|||||||
#include <tests/api/test_hash.h>
|
#include <tests/api/test_hash.h>
|
||||||
#include <tests/api/test_ascon.h>
|
#include <tests/api/test_ascon.h>
|
||||||
#include <tests/api/test_dtls.h>
|
#include <tests/api/test_dtls.h>
|
||||||
|
#include <tests/api/test_ocsp.h>
|
||||||
|
|
||||||
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \
|
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \
|
||||||
!defined(NO_RSA) && !defined(SINGLE_THREADED) && \
|
!defined(NO_RSA) && !defined(SINGLE_THREADED) && \
|
||||||
@@ -459,65 +460,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif /* HAVE_PKCS7 */
|
#endif /* HAVE_PKCS7 */
|
||||||
|
|
||||||
typedef int (*ctx_cb)(WOLFSSL_CTX* ctx);
|
|
||||||
typedef int (*ssl_cb)(WOLFSSL* ssl);
|
|
||||||
typedef int (*test_cbType)(WOLFSSL_CTX *ctx, WOLFSSL *ssl);
|
|
||||||
typedef int (*hs_cb)(WOLFSSL_CTX **ctx, WOLFSSL **ssl);
|
|
||||||
|
|
||||||
typedef struct test_ssl_cbf {
|
|
||||||
method_provider method;
|
|
||||||
ctx_cb ctx_ready;
|
|
||||||
ssl_cb ssl_ready;
|
|
||||||
ssl_cb on_result;
|
|
||||||
ctx_cb on_ctx_cleanup;
|
|
||||||
ssl_cb on_cleanup;
|
|
||||||
hs_cb on_handshake;
|
|
||||||
WOLFSSL_CTX* ctx;
|
|
||||||
const char* caPemFile;
|
|
||||||
const char* certPemFile;
|
|
||||||
const char* keyPemFile;
|
|
||||||
const char* crlPemFile;
|
|
||||||
#ifdef WOLFSSL_STATIC_MEMORY
|
|
||||||
byte* mem;
|
|
||||||
word32 memSz;
|
|
||||||
wolfSSL_method_func method_ex;
|
|
||||||
#endif
|
|
||||||
int devId;
|
|
||||||
int return_code;
|
|
||||||
int last_err;
|
|
||||||
unsigned char isSharedCtx:1;
|
|
||||||
unsigned char loadToSSL:1;
|
|
||||||
unsigned char ticNoInit:1;
|
|
||||||
unsigned char doUdp:1;
|
|
||||||
} test_ssl_cbf;
|
|
||||||
|
|
||||||
#define TEST_SSL_MEMIO_BUF_SZ (64 * 1024)
|
|
||||||
typedef struct test_ssl_memio_ctx {
|
|
||||||
WOLFSSL_CTX* s_ctx;
|
|
||||||
WOLFSSL_CTX* c_ctx;
|
|
||||||
WOLFSSL* s_ssl;
|
|
||||||
WOLFSSL* c_ssl;
|
|
||||||
|
|
||||||
const char* c_ciphers;
|
|
||||||
const char* s_ciphers;
|
|
||||||
|
|
||||||
char* c_msg;
|
|
||||||
int c_msglen;
|
|
||||||
char* s_msg;
|
|
||||||
int s_msglen;
|
|
||||||
|
|
||||||
test_ssl_cbf s_cb;
|
|
||||||
test_ssl_cbf c_cb;
|
|
||||||
|
|
||||||
byte c_buff[TEST_SSL_MEMIO_BUF_SZ];
|
|
||||||
int c_len;
|
|
||||||
byte s_buff[TEST_SSL_MEMIO_BUF_SZ];
|
|
||||||
int s_len;
|
|
||||||
} test_ssl_memio_ctx;
|
|
||||||
|
|
||||||
int test_wolfSSL_client_server_nofail_memio(test_ssl_cbf* client_cb,
|
|
||||||
test_ssl_cbf* server_cb, test_cbType client_on_handshake);
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_DUMP_MEMIO_STREAM
|
#ifdef WOLFSSL_DUMP_MEMIO_STREAM
|
||||||
const char* currentTestName;
|
const char* currentTestName;
|
||||||
char tmpDirName[16];
|
char tmpDirName[16];
|
||||||
@@ -4622,7 +4564,11 @@ static int test_wolfSSL_CheckOCSPResponse(void)
|
|||||||
wolfSSL_CertManagerFree(cm);
|
wolfSSL_CertManagerFree(cm);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(WC_RSA_PSS)
|
/* FIPS v2 and below don't support long salts. */
|
||||||
|
#if defined(WC_RSA_PSS) && \
|
||||||
|
(!defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
|
||||||
|
(HAVE_FIPS_VERSION > 2))) && (!defined(HAVE_SELFTEST) || \
|
||||||
|
(defined(HAVE_SELFTEST_VERSION) && (HAVE_SELFTEST_VERSION > 2)))
|
||||||
{
|
{
|
||||||
const char* responsePssFile = "./certs/ocsp/test-response-rsapss.der";
|
const char* responsePssFile = "./certs/ocsp/test-response-rsapss.der";
|
||||||
|
|
||||||
@@ -7261,7 +7207,7 @@ static WC_INLINE int test_ssl_memio_read_cb(WOLFSSL *ssl, char *data, int sz,
|
|||||||
return read_sz;
|
return read_sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WC_INLINE int test_ssl_memio_setup(test_ssl_memio_ctx *ctx)
|
int test_ssl_memio_setup(test_ssl_memio_ctx *ctx)
|
||||||
{
|
{
|
||||||
EXPECT_DECLS_NO_MSGS(-2000);
|
EXPECT_DECLS_NO_MSGS(-2000);
|
||||||
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
|
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
|
||||||
@@ -7461,7 +7407,7 @@ static WC_INLINE int test_ssl_memio_setup(test_ssl_memio_ctx *ctx)
|
|||||||
return EXPECT_RESULT();
|
return EXPECT_RESULT();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int test_ssl_memio_do_handshake(test_ssl_memio_ctx* ctx, int max_rounds,
|
int test_ssl_memio_do_handshake(test_ssl_memio_ctx* ctx, int max_rounds,
|
||||||
int* rounds)
|
int* rounds)
|
||||||
{
|
{
|
||||||
int handshake_complete = 0;
|
int handshake_complete = 0;
|
||||||
@@ -7581,7 +7527,7 @@ static int test_ssl_memio_read_write(test_ssl_memio_ctx* ctx)
|
|||||||
return EXPECT_RESULT();
|
return EXPECT_RESULT();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_ssl_memio_cleanup(test_ssl_memio_ctx* ctx)
|
void test_ssl_memio_cleanup(test_ssl_memio_ctx* ctx)
|
||||||
{
|
{
|
||||||
ctx->c_cb.last_err = wolfSSL_get_error(ctx->c_ssl, 0);
|
ctx->c_cb.last_err = wolfSSL_get_error(ctx->c_ssl, 0);
|
||||||
ctx->s_cb.last_err = wolfSSL_get_error(ctx->s_ssl, 0);
|
ctx->s_cb.last_err = wolfSSL_get_error(ctx->s_ssl, 0);
|
||||||
@@ -99372,6 +99318,9 @@ TEST_CASE testCases[] = {
|
|||||||
TEST_DECL(test_wolfSSL_SSLDisableRead),
|
TEST_DECL(test_wolfSSL_SSLDisableRead),
|
||||||
TEST_DECL(test_wolfSSL_inject),
|
TEST_DECL(test_wolfSSL_inject),
|
||||||
TEST_DECL(test_wolfSSL_dtls_cid_parse),
|
TEST_DECL(test_wolfSSL_dtls_cid_parse),
|
||||||
|
TEST_DECL(test_ocsp_status_callback),
|
||||||
|
TEST_DECL(test_ocsp_basic_verify),
|
||||||
|
TEST_DECL(test_ocsp_response_parsing),
|
||||||
/* This test needs to stay at the end to clean up any caches allocated. */
|
/* This test needs to stay at the end to clean up any caches allocated. */
|
||||||
TEST_DECL(test_wolfSSL_Cleanup)
|
TEST_DECL(test_wolfSSL_Cleanup)
|
||||||
};
|
};
|
||||||
|
453
tests/api/create_ocsp_test_blobs.py
Normal file
453
tests/api/create_ocsp_test_blobs.py
Normal file
@@ -0,0 +1,453 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
This is a simple generator of OCSP responses that will be used to test
|
||||||
|
wolfSSL OCSP implementation
|
||||||
|
"""
|
||||||
|
from pyasn1_modules import rfc6960
|
||||||
|
from pyasn1.codec.der.encoder import encode
|
||||||
|
from pyasn1.codec.der.decoder import decode
|
||||||
|
from pyasn1.type import univ, tag, useful, namedtype
|
||||||
|
from base64 import b64decode
|
||||||
|
from hashlib import sha1, sha256
|
||||||
|
from datetime import datetime
|
||||||
|
from cryptography.hazmat.primitives import serialization, hashes
|
||||||
|
from cryptography.hazmat.primitives.asymmetric import rsa, padding
|
||||||
|
from cryptography import x509
|
||||||
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
|
||||||
|
WOLFSSL_OCSP_CERT_PATH = './certs/ocsp/'
|
||||||
|
|
||||||
|
def response_status(value: int) -> rfc6960.OCSPResponseStatus:
|
||||||
|
return rfc6960.OCSPResponseStatus(value)
|
||||||
|
|
||||||
|
def response_type() -> univ.ObjectIdentifier:
|
||||||
|
return rfc6960.id_pkix_ocsp_basic
|
||||||
|
|
||||||
|
sha256WithRSAEncryption = (1, 2, 840, 113549, 1, 1, 11)
|
||||||
|
sha1_alg_id = (1, 3, 14, 3, 2, 26)
|
||||||
|
def cert_id_sha1_alg_id() -> rfc6960.AlgorithmIdentifier:
|
||||||
|
return algorithm(sha1_alg_id)
|
||||||
|
|
||||||
|
def signature_algorithm() -> rfc6960.AlgorithmIdentifier:
|
||||||
|
return algorithm(sha256WithRSAEncryption)
|
||||||
|
|
||||||
|
def algorithm(value) -> rfc6960.AlgorithmIdentifier:
|
||||||
|
ai = rfc6960.AlgorithmIdentifier()
|
||||||
|
ai['algorithm'] = univ.ObjectIdentifier(value=value)
|
||||||
|
return ai
|
||||||
|
|
||||||
|
def cert_pem_to_der(cert_path: str) -> bytes:
|
||||||
|
beg_cert = '-----BEGIN CERTIFICATE-----'
|
||||||
|
end_cert = '-----END CERTIFICATE-----'
|
||||||
|
with open(cert_path, 'r') as f:
|
||||||
|
pem = f.read()
|
||||||
|
cert = pem.split(beg_cert)[1].split(end_cert)[0]
|
||||||
|
return b64decode(cert)
|
||||||
|
|
||||||
|
def certs(cert_path: list[str]) -> univ.SequenceOf | None:
|
||||||
|
if len(cert_path) == 0:
|
||||||
|
return None
|
||||||
|
certs = rfc6960.BasicOCSPResponse()['certs']
|
||||||
|
for cp in cert_path:
|
||||||
|
cert_der = cert_pem_to_der(cp)
|
||||||
|
cert, _ = decode(bytes(cert_der), asn1Spec=rfc6960.Certificate())
|
||||||
|
certs.append(cert)
|
||||||
|
return certs
|
||||||
|
|
||||||
|
def signature(bitstr: str) -> univ.BitString:
|
||||||
|
return univ.BitString(hexValue=bitstr)
|
||||||
|
|
||||||
|
def resp_id_by_name(cert_path: str) -> rfc6960.ResponderID:
|
||||||
|
cert_der = cert_pem_to_der(cert_path)
|
||||||
|
cert, _ = decode(bytes(cert_der), asn1Spec=rfc6960.Certificate())
|
||||||
|
subj = cert['tbsCertificate']['subject']
|
||||||
|
rid = rfc6960.ResponderID()
|
||||||
|
rdi_name = rid['byName']
|
||||||
|
rdi_name['rdnSequence'] = subj['rdnSequence']
|
||||||
|
return rid
|
||||||
|
|
||||||
|
def resp_id_by_key(cert_path: str) -> rfc6960.ResponderID:
|
||||||
|
cert_der = cert_pem_to_der(cert_path)
|
||||||
|
cert, _ = decode(bytes(cert_der), asn1Spec=rfc6960.Certificate())
|
||||||
|
key = get_key(cert)
|
||||||
|
key_hash = sha1(key.asOctets()).digest()
|
||||||
|
rid = rfc6960.ResponderID()
|
||||||
|
rid['byKey'] = rfc6960.KeyHash(value=key_hash).subtype(explicitTag=
|
||||||
|
tag.Tag(
|
||||||
|
tag.tagClassContext,
|
||||||
|
tag.tagFormatSimple,
|
||||||
|
2))
|
||||||
|
return rid
|
||||||
|
|
||||||
|
def get_key(cert: rfc6960.Certificate) -> univ.BitString:
|
||||||
|
return cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']
|
||||||
|
|
||||||
|
def get_name(cert: rfc6960.Certificate) -> rfc6960.Name:
|
||||||
|
return cert['tbsCertificate']['subject']
|
||||||
|
|
||||||
|
def cert_id_from_hash(issuer_name_hash: bytes, issuer_key_hash: bytes,
|
||||||
|
serial: int) -> rfc6960.CertID:
|
||||||
|
cert_id = rfc6960.CertID()
|
||||||
|
cert_id['hashAlgorithm'] = cert_id_sha1_alg_id()
|
||||||
|
cert_id['issuerNameHash'] = univ.OctetString(value=issuer_name_hash)
|
||||||
|
cert_id['issuerKeyHash'] = univ.OctetString(value=issuer_key_hash)
|
||||||
|
cert_id['serialNumber'] = rfc6960.CertificateSerialNumber(serial)
|
||||||
|
return cert_id
|
||||||
|
|
||||||
|
def cert_id(issuer_cert_path: str, serial: int) -> rfc6960.CertID:
|
||||||
|
issuer_cert = cert_pem_to_der(issuer_cert_path)
|
||||||
|
issuer, _ = decode(bytes(issuer_cert), asn1Spec=rfc6960.Certificate())
|
||||||
|
issuer_name = get_name(issuer)
|
||||||
|
issuer_key = get_key(issuer)
|
||||||
|
issuer_name_hash = sha1(encode(issuer_name)).digest()
|
||||||
|
issuer_key_hash = sha1(issuer_key.asOctets()).digest()
|
||||||
|
cert_id = rfc6960.CertID()
|
||||||
|
cert_id['hashAlgorithm'] = cert_id_sha1_alg_id()
|
||||||
|
cert_id['issuerNameHash'] = univ.OctetString(value=issuer_name_hash)
|
||||||
|
cert_id['issuerKeyHash'] = univ.OctetString(value=issuer_key_hash)
|
||||||
|
cert_id['serialNumber'] = rfc6960.CertificateSerialNumber(serial)
|
||||||
|
|
||||||
|
return cert_id
|
||||||
|
|
||||||
|
CERT_GOOD = 0
|
||||||
|
CERT_REVOKED = 1
|
||||||
|
CERT_UNKNOWN = 2
|
||||||
|
def cert_status(value: int) -> rfc6960.CertStatus:
|
||||||
|
cs = rfc6960.CertStatus()
|
||||||
|
|
||||||
|
if value == CERT_GOOD:
|
||||||
|
good = univ.Null('').subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
||||||
|
tag.tagFormatSimple,
|
||||||
|
0))
|
||||||
|
cs['good'] = good
|
||||||
|
elif value == CERT_REVOKED:
|
||||||
|
revoked = rfc6960.RevokedInfo().subtype(implicitTag=tag.Tag(
|
||||||
|
tag.tagClassContext, tag.tagFormatSimple, 1))
|
||||||
|
revoked['revocationTime'] = useful.GeneralizedTime().fromDateTime(
|
||||||
|
datetime.now())
|
||||||
|
cs['revoked'] = revoked
|
||||||
|
|
||||||
|
return cs
|
||||||
|
|
||||||
|
def single_response(issuer_cert_path: str, serial: int,
|
||||||
|
status: int) -> rfc6960.SingleResponse:
|
||||||
|
cid = cert_id(issuer_cert_path, serial)
|
||||||
|
cs = cert_status(status)
|
||||||
|
sr = rfc6960.SingleResponse().clone()
|
||||||
|
sr.setComponentByName('certID', cid)
|
||||||
|
sr['certStatus'] = cs
|
||||||
|
sr['thisUpdate'] = useful.GeneralizedTime().fromDateTime(datetime.now())
|
||||||
|
return sr
|
||||||
|
|
||||||
|
def response_data(rid: rfc6960.ResponderID | None,
|
||||||
|
responses: list[rfc6960.SingleResponse]) -> rfc6960.ResponseData:
|
||||||
|
rd = rfc6960.ResponseData()
|
||||||
|
rd['version'] = rfc6960.Version('v1').subtype(explicitTag=tag.Tag(
|
||||||
|
tag.tagClassContext, tag.tagFormatSimple, 0))
|
||||||
|
if rid:
|
||||||
|
rd['responderID'] = rid
|
||||||
|
rd['producedAt'] = useful.GeneralizedTime().fromDateTime(datetime.now())
|
||||||
|
rs = univ.SequenceOf(componentType=rfc6960.SingleResponse())
|
||||||
|
rs.extend(responses)
|
||||||
|
rd['responses'] = rs
|
||||||
|
return rd
|
||||||
|
|
||||||
|
def read_key_der_from_pem(key_path: str) -> bytes:
|
||||||
|
with open(key_path, 'r') as f:
|
||||||
|
pem = f.readlines()
|
||||||
|
pem_start = [i for i, line in enumerate(pem) if '-----BEGIN' in line][0]
|
||||||
|
pem_end = [i for i, line in enumerate(pem) if '-----END' in line][0]
|
||||||
|
key = ''.join(pem[pem_start+1:pem_end])
|
||||||
|
return b64decode(key)
|
||||||
|
|
||||||
|
def basic_ocsp_response(rd: rfc6960.ResponseData, sig_alg:
|
||||||
|
rfc6960.AlgorithmIdentifier, sig: univ.BitString,
|
||||||
|
certs: univ.SequenceOf|None = None) -> rfc6960.BasicOCSPResponse:
|
||||||
|
br = rfc6960.BasicOCSPResponse()
|
||||||
|
|
||||||
|
br['tbsResponseData'] = rd
|
||||||
|
br['signatureAlgorithm'] = sig_alg
|
||||||
|
br['signature'] = sig
|
||||||
|
if certs is not None:
|
||||||
|
br['certs'] = certs
|
||||||
|
return br
|
||||||
|
|
||||||
|
def response_bytes(br: rfc6960.BasicOCSPResponse) -> rfc6960.ResponseBytes:
|
||||||
|
rb = rfc6960.ResponseBytes().subtype(explicitTag=tag.Tag(
|
||||||
|
tag.tagClassContext, tag.tagFormatConstructed, 0))
|
||||||
|
rb['responseType'] = response_type()
|
||||||
|
rb['response'] = encode(br)
|
||||||
|
return rb
|
||||||
|
|
||||||
|
def ocsp_response(status: rfc6960.OCSPResponseStatus,
|
||||||
|
response_bytes: rfc6960.ResponseBytes) -> rfc6960.OCSPResponse:
|
||||||
|
orsp = rfc6960.OCSPResponse()
|
||||||
|
orsp['responseStatus'] = status
|
||||||
|
orsp['responseBytes'] = response_bytes
|
||||||
|
return orsp
|
||||||
|
|
||||||
|
def get_priv_key(pem_path) -> rsa.RSAPrivateKey:
|
||||||
|
key_der = read_key_der_from_pem(pem_path)
|
||||||
|
private_key = serialization.load_der_private_key(
|
||||||
|
key_der,
|
||||||
|
password=None,
|
||||||
|
)
|
||||||
|
return private_key
|
||||||
|
|
||||||
|
def sign_repsonse_data(rd: rfc6960.ResponseData,
|
||||||
|
key: rsa.RSAPrivateKey) -> univ.BitString:
|
||||||
|
sig = key.sign(encode(rd), padding.PKCS1v15(), hashes.SHA256())
|
||||||
|
return univ.BitString(hexValue=sig.hex())
|
||||||
|
|
||||||
|
def get_pub_key(cert_path: str) -> rsa.RSAPublicKey:
|
||||||
|
with open(cert_path, 'rb') as f:
|
||||||
|
cert = f.read()
|
||||||
|
cert = x509.load_pem_x509_certificate(cert, default_backend())
|
||||||
|
return cert.public_key()
|
||||||
|
|
||||||
|
def test_signature(ocsp_resp_path: str, key: rsa.RSAPublicKey):
|
||||||
|
with open(ocsp_resp_path, 'rb') as f:
|
||||||
|
ocsp_resp = f.read()
|
||||||
|
ocsp_resp, _ = decode(ocsp_resp, asn1Spec=rfc6960.OCSPResponse())
|
||||||
|
response = ocsp_resp.getComponentByName(
|
||||||
|
'responseBytes').getComponentByName('response')
|
||||||
|
br, _ = decode(response, asn1Spec=rfc6960.BasicOCSPResponse())
|
||||||
|
rd = br.getComponentByName('tbsResponseData')
|
||||||
|
rd_hash = sha256(encode(rd)).digest()
|
||||||
|
di = rfc8017.DigestInfo()
|
||||||
|
di['digestAlgorithm'] = signature_algorithm()
|
||||||
|
di['digest'] = univ.OctetString(rd_hash)
|
||||||
|
sig = br.getComponentByName('signature')
|
||||||
|
key.verify(sig.asOctets(), encode(rd), padding.PKCS1v15(), hashes.SHA256())
|
||||||
|
|
||||||
|
def single_response_from_cert(cert_path: str,
|
||||||
|
status: int) -> rfc6960.SingleResponse:
|
||||||
|
cert_der = cert_pem_to_der(cert_path)
|
||||||
|
cert, _ = decode(bytes(cert_der), asn1Spec=rfc6960.Certificate())
|
||||||
|
serial = cert['tbsCertificate']['serialNumber']
|
||||||
|
issuer = cert['tbsCertificate']['issuer']
|
||||||
|
serialHash = sha1(serial.asOctets()).digest()
|
||||||
|
issuerHash = sha1(encode(issuer)).digest()
|
||||||
|
cid = cert_id_from_hash(issuerHash, serialHash, serial)
|
||||||
|
cs = cert_status(status)
|
||||||
|
sr = rfc6960.SingleResponse().clone()
|
||||||
|
sr.setComponentByName('certID', cid)
|
||||||
|
sr['certStatus'] = cs
|
||||||
|
sr['thisUpdate'] = useful.GeneralizedTime().fromDateTime(datetime.now())
|
||||||
|
return sr
|
||||||
|
|
||||||
|
RESPONSE_STATUS_GOOD = 0
|
||||||
|
|
||||||
|
def write_buffer(name: str, data: bytes, f):
|
||||||
|
f.write(f"unsigned char {name}[] = {{\n")
|
||||||
|
for i in range(0, len(data), 12):
|
||||||
|
f.write(" " + ", ".join(f"0x{b:02x}" for b in data[i:i+12]) + ",\n")
|
||||||
|
f.write("};\n\n")
|
||||||
|
|
||||||
|
def create_response(rd: dict) -> rfc6960.OCSPResponse:
|
||||||
|
"""create a response using definition in rd"""
|
||||||
|
cs = response_status(rd.get('response_status', RESPONSE_STATUS_GOOD))
|
||||||
|
sa = rd.get('signature_algorithm', signature_algorithm())
|
||||||
|
c = certs(rd.get('certs_path', []))
|
||||||
|
rid = None
|
||||||
|
if rd.get('responder_by_name') is not None:
|
||||||
|
rid = resp_id_by_name(
|
||||||
|
rd.get(
|
||||||
|
'responder_cert', WOLFSSL_OCSP_CERT_PATH + 'ocsp-responder-cert.pem'))
|
||||||
|
elif rd.get('responder_by_key', None) is not None:
|
||||||
|
rid = resp_id_by_key(
|
||||||
|
rd.get('responder_cert', WOLFSSL_OCSP_CERT_PATH + 'ocsp-responder-cert.pem'))
|
||||||
|
# implement responder byhash
|
||||||
|
responses = []
|
||||||
|
for entry in rd.get('responses', []):
|
||||||
|
if entry.get('certificate'):
|
||||||
|
sr = single_response_from_cert(entry['certificate'], entry['status'])
|
||||||
|
else:
|
||||||
|
sr = single_response(entry['issuer_cert'], entry['serial'], entry['status'])
|
||||||
|
responses.append(sr)
|
||||||
|
rd_data = response_data(rid, responses)
|
||||||
|
k = get_priv_key(rd.get('responder_key', WOLFSSL_OCSP_CERT_PATH + 'ocsp-responder-key.pem'))
|
||||||
|
s = sign_repsonse_data(rd_data, k)
|
||||||
|
br = basic_ocsp_response(rd_data, sa, s, c)
|
||||||
|
rb = response_bytes(br)
|
||||||
|
ocspr = ocsp_response(cs, rb)
|
||||||
|
return ocspr
|
||||||
|
|
||||||
|
def create_and_write_response(rd: dict, f):
|
||||||
|
ocspr = create_response(rd)
|
||||||
|
encoded_response = encode(ocspr)
|
||||||
|
write_buffer(rd['name'].replace('-', '_').replace('.', '_'), encoded_response, f)
|
||||||
|
|
||||||
|
def add_certificate(cert_path: str, f):
|
||||||
|
cert_der = cert_pem_to_der(cert_path)
|
||||||
|
write_buffer(cert_path.split('/')[-1].replace('-', '_').replace('.', '_'), cert_der, f)
|
||||||
|
|
||||||
|
class badOCSPResponse(univ.Sequence):
|
||||||
|
componentType = namedtype.NamedTypes(
|
||||||
|
namedtype.OptionalNamedType('responseBytes', rfc6960.ResponseBytes().subtype(
|
||||||
|
explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)))
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_bad_response(rd: dict) -> bytes:
|
||||||
|
"""Creates a malformed OCSP response by removing the response status field"""
|
||||||
|
r = create_response(rd)
|
||||||
|
br = badOCSPResponse()
|
||||||
|
br['responseBytes'] = r['responseBytes']
|
||||||
|
return encode(br)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
useful.GeneralizedTime._hasSubsecond = False
|
||||||
|
response_definitions = [
|
||||||
|
{
|
||||||
|
'response_status': 0,
|
||||||
|
'signature_algorithm': signature_algorithm(),
|
||||||
|
'certs_path': [WOLFSSL_OCSP_CERT_PATH + 'ocsp-responder-cert.pem'],
|
||||||
|
'responder_by_name': True,
|
||||||
|
'responses': [
|
||||||
|
{
|
||||||
|
'issuer_cert': WOLFSSL_OCSP_CERT_PATH + 'root-ca-cert.pem',
|
||||||
|
'serial': 0x01,
|
||||||
|
'status': CERT_GOOD
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'responder_key': WOLFSSL_OCSP_CERT_PATH + 'ocsp-responder-key.pem',
|
||||||
|
'name': 'resp'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'response_status': 0,
|
||||||
|
'signature_algorithm': signature_algorithm(),
|
||||||
|
'certs_path': [WOLFSSL_OCSP_CERT_PATH + 'ocsp-responder-cert.pem'],
|
||||||
|
'responder_by_key': True,
|
||||||
|
'responses': [
|
||||||
|
{
|
||||||
|
'issuer_cert': WOLFSSL_OCSP_CERT_PATH + 'root-ca-cert.pem',
|
||||||
|
'serial': 0x01,
|
||||||
|
'status': CERT_GOOD
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'responder_key': WOLFSSL_OCSP_CERT_PATH + 'ocsp-responder-key.pem',
|
||||||
|
'name': 'resp_rid_bykey',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'response_status': 0,
|
||||||
|
'signature_algorithm': signature_algorithm(),
|
||||||
|
'responder_by_name': True,
|
||||||
|
'responses': [
|
||||||
|
{
|
||||||
|
'issuer_cert': WOLFSSL_OCSP_CERT_PATH + 'root-ca-cert.pem',
|
||||||
|
'serial': 0x01,
|
||||||
|
'status': CERT_GOOD
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'responder_key': WOLFSSL_OCSP_CERT_PATH + 'ocsp-responder-key.pem',
|
||||||
|
'name': 'resp_nocert'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'response_status': 0,
|
||||||
|
'signature_algorithm': signature_algorithm(),
|
||||||
|
'responder_by_name': True,
|
||||||
|
'responses': [
|
||||||
|
{
|
||||||
|
'issuer_cert': WOLFSSL_OCSP_CERT_PATH + 'root-ca-cert.pem',
|
||||||
|
'serial': 0x01,
|
||||||
|
'status': CERT_GOOD
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'issuer_cert': WOLFSSL_OCSP_CERT_PATH + 'root-ca-cert.pem',
|
||||||
|
'serial': 0x02,
|
||||||
|
'status': CERT_GOOD
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'responder_key': WOLFSSL_OCSP_CERT_PATH + 'root-ca-key.pem',
|
||||||
|
'responder_cert': WOLFSSL_OCSP_CERT_PATH + 'root-ca-cert.pem',
|
||||||
|
'name': 'resp_multi'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'response_status': 0,
|
||||||
|
'signature_algorithm': signature_algorithm(),
|
||||||
|
'responder_by_name': True,
|
||||||
|
'responses': [
|
||||||
|
{
|
||||||
|
'issuer_cert': WOLFSSL_OCSP_CERT_PATH + 'root-ca-cert.pem',
|
||||||
|
'serial': 0x01,
|
||||||
|
'status': CERT_GOOD
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'issuer_cert': WOLFSSL_OCSP_CERT_PATH + '../ca-cert.pem',
|
||||||
|
'serial': 0x01,
|
||||||
|
'status': CERT_GOOD
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'responder_key': WOLFSSL_OCSP_CERT_PATH + 'root-ca-key.pem',
|
||||||
|
'responder_cert': WOLFSSL_OCSP_CERT_PATH + 'root-ca-cert.pem',
|
||||||
|
'name': 'resp_bad_noauth'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'response_status': 0,
|
||||||
|
'signature_algorithm': signature_algorithm(),
|
||||||
|
'responder_by_name': True,
|
||||||
|
'responses': [
|
||||||
|
{
|
||||||
|
'issuer_cert': WOLFSSL_OCSP_CERT_PATH + 'root-ca-cert.pem',
|
||||||
|
'serial': 0x01,
|
||||||
|
'status': CERT_GOOD
|
||||||
|
},
|
||||||
|
],
|
||||||
|
# unrelated cert
|
||||||
|
'certs_path' : [WOLFSSL_OCSP_CERT_PATH + 'intermediate2-ca-cert.pem'],
|
||||||
|
'responder_cert': WOLFSSL_OCSP_CERT_PATH + 'root-ca-cert.pem',
|
||||||
|
'responder_key': WOLFSSL_OCSP_CERT_PATH + 'root-ca-key.pem',
|
||||||
|
'name': 'resp_bad_embedded_cert'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
with open('./tests/api/ocsp_test_blobs.h', 'w') as f:
|
||||||
|
f.write(
|
||||||
|
"""/*
|
||||||
|
* This file is generated automatically by running ./tests/api/create_ocsp_test_blobs.py.
|
||||||
|
*
|
||||||
|
* ocsp_test_blobs.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2025 wolfSSL Inc.
|
||||||
|
*
|
||||||
|
* This file is part of wolfSSL.
|
||||||
|
*
|
||||||
|
* wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
""")
|
||||||
|
f.write("#ifndef OCSP_TEST_BLOBS_H\n")
|
||||||
|
f.write("#define OCSP_TEST_BLOBS_H\n\n")
|
||||||
|
for rd in response_definitions:
|
||||||
|
create_and_write_response(rd, f)
|
||||||
|
add_certificate(WOLFSSL_OCSP_CERT_PATH + 'ocsp-responder-cert.pem', f)
|
||||||
|
add_certificate(WOLFSSL_OCSP_CERT_PATH + 'root-ca-cert.pem', f)
|
||||||
|
add_certificate(WOLFSSL_OCSP_CERT_PATH + '../ca-cert.pem', f)
|
||||||
|
add_certificate(WOLFSSL_OCSP_CERT_PATH + '../server-cert.pem', f)
|
||||||
|
add_certificate(WOLFSSL_OCSP_CERT_PATH + 'intermediate1-ca-cert.pem', f)
|
||||||
|
br = create_bad_response({
|
||||||
|
'response_status': 0,
|
||||||
|
'responder_by_key': True,
|
||||||
|
'responses': [
|
||||||
|
{
|
||||||
|
'issuer_cert': WOLFSSL_OCSP_CERT_PATH + 'root-ca-cert.pem',
|
||||||
|
'serial': 0x01,
|
||||||
|
'status': CERT_GOOD
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'name': 'resp_bad'
|
||||||
|
})
|
||||||
|
write_buffer('resp_bad', br, f)
|
||||||
|
f.write("#endif /* OCSP_TEST_BLOBS_H */\n")
|
@@ -14,6 +14,7 @@ tests_unit_test_SOURCES += tests/api/test_ripemd.c
|
|||||||
tests_unit_test_SOURCES += tests/api/test_hash.c
|
tests_unit_test_SOURCES += tests/api/test_hash.c
|
||||||
tests_unit_test_SOURCES += tests/api/test_ascon.c
|
tests_unit_test_SOURCES += tests/api/test_ascon.c
|
||||||
tests_unit_test_SOURCES += tests/api/test_dtls.c
|
tests_unit_test_SOURCES += tests/api/test_dtls.c
|
||||||
|
tests_unit_test_SOURCES += tests/api/test_ocsp.c
|
||||||
endif
|
endif
|
||||||
EXTRA_DIST += tests/api/api.h
|
EXTRA_DIST += tests/api/api.h
|
||||||
EXTRA_DIST += tests/api/test_md5.h
|
EXTRA_DIST += tests/api/test_md5.h
|
||||||
@@ -29,4 +30,7 @@ EXTRA_DIST += tests/api/test_ascon.h
|
|||||||
EXTRA_DIST += tests/api/test_ascon.h
|
EXTRA_DIST += tests/api/test_ascon.h
|
||||||
EXTRA_DIST += tests/api/test_ascon_kats.h
|
EXTRA_DIST += tests/api/test_ascon_kats.h
|
||||||
EXTRA_DIST += tests/api/test_dtls.h
|
EXTRA_DIST += tests/api/test_dtls.h
|
||||||
|
EXTRA_DIST += tests/api/test_ocsp.h
|
||||||
|
EXTRA_DIST += tests/api/test_ocsp_test_blobs.h
|
||||||
|
EXTRA_DIST += tests/api/create_ocsp_test_blobs.py
|
||||||
|
|
||||||
|
594
tests/api/test_ocsp.c
Normal file
594
tests/api/test_ocsp.c
Normal file
@@ -0,0 +1,594 @@
|
|||||||
|
/* test_ocsp.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2025 wolfSSL Inc.
|
||||||
|
*
|
||||||
|
* This file is part of wolfSSL.
|
||||||
|
*
|
||||||
|
* wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
#if !defined(WOLFSSL_USER_SETTINGS) && !defined(WOLFSSL_NO_OPTIONS_H)
|
||||||
|
#include <wolfssl/options.h>
|
||||||
|
#endif
|
||||||
|
#include <wolfssl/wolfcrypt/settings.h>
|
||||||
|
|
||||||
|
#include <tests/api/test_ocsp.h>
|
||||||
|
#include <tests/api/test_ocsp_test_blobs.h>
|
||||||
|
#include <tests/unit.h>
|
||||||
|
#include <wolfssl/internal.h>
|
||||||
|
#include <wolfssl/ocsp.h>
|
||||||
|
#include <wolfssl/ssl.h>
|
||||||
|
|
||||||
|
#if defined(HAVE_OCSP)
|
||||||
|
struct ocsp_cb_ctx {
|
||||||
|
byte* response;
|
||||||
|
int responseSz;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct test_conf {
|
||||||
|
unsigned char* resp;
|
||||||
|
int respSz;
|
||||||
|
unsigned char* ca0;
|
||||||
|
int ca0Sz;
|
||||||
|
unsigned char* ca1;
|
||||||
|
int ca1Sz;
|
||||||
|
unsigned char* targetCert;
|
||||||
|
int targetCertSz;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ocsp_cb(void* ctx, const char* url, int urlSz, unsigned char* req,
|
||||||
|
int reqSz, unsigned char** respBuf)
|
||||||
|
{
|
||||||
|
struct ocsp_cb_ctx* cb_ctx = (struct ocsp_cb_ctx*)ctx;
|
||||||
|
(void)url;
|
||||||
|
(void)urlSz;
|
||||||
|
(void)req;
|
||||||
|
(void)reqSz;
|
||||||
|
|
||||||
|
*respBuf = cb_ctx->response;
|
||||||
|
return cb_ctx->responseSz;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_ocsp_response_with_cm(struct test_conf* c, int expectedRet)
|
||||||
|
{
|
||||||
|
EXPECT_DECLS;
|
||||||
|
WOLFSSL_CERT_MANAGER* cm = NULL;
|
||||||
|
struct ocsp_cb_ctx cb_ctx;
|
||||||
|
|
||||||
|
ExpectNotNull(cm = wolfSSL_CertManagerNew());
|
||||||
|
ExpectIntEQ(wolfSSL_CertManagerEnableOCSP(cm,
|
||||||
|
WOLFSSL_OCSP_URL_OVERRIDE | WOLFSSL_OCSP_NO_NONCE),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
ExpectIntEQ(wolfSSL_CertManagerSetOCSPOverrideURL(cm, "http://foo.com"),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
cb_ctx.response = (byte*)c->resp;
|
||||||
|
cb_ctx.responseSz = c->respSz;
|
||||||
|
ExpectIntEQ(
|
||||||
|
wolfSSL_CertManagerSetOCSP_Cb(cm, ocsp_cb, NULL, (void*)&cb_ctx),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
/* add ca in cm */
|
||||||
|
if (c->ca0 != NULL) {
|
||||||
|
ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, c->ca0, c->ca0Sz,
|
||||||
|
WOLFSSL_FILETYPE_ASN1),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
}
|
||||||
|
if (c->ca1 != NULL) {
|
||||||
|
ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, c->ca1, c->ca1Sz,
|
||||||
|
WOLFSSL_FILETYPE_ASN1),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
}
|
||||||
|
/* check cert */
|
||||||
|
ExpectIntEQ(
|
||||||
|
wolfSSL_CertManagerCheckOCSP(cm, c->targetCert, c->targetCertSz),
|
||||||
|
expectedRet);
|
||||||
|
if (cm != NULL)
|
||||||
|
wolfSSL_CertManagerFree(cm);
|
||||||
|
return EXPECT_RESULT();
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_ocsp_response_parsing(void)
|
||||||
|
{
|
||||||
|
EXPECT_DECLS;
|
||||||
|
struct test_conf conf;
|
||||||
|
int expectedRet;
|
||||||
|
|
||||||
|
conf.resp = (unsigned char*)resp;
|
||||||
|
conf.respSz = sizeof(resp);
|
||||||
|
conf.ca0 = root_ca_cert_pem;
|
||||||
|
conf.ca0Sz = sizeof(root_ca_cert_pem);
|
||||||
|
conf.ca1 = NULL;
|
||||||
|
conf.ca1Sz = 0;
|
||||||
|
conf.targetCert = intermediate1_ca_cert_pem;
|
||||||
|
conf.targetCertSz = sizeof(intermediate1_ca_cert_pem);
|
||||||
|
ExpectIntEQ(test_ocsp_response_with_cm(&conf, WOLFSSL_SUCCESS),
|
||||||
|
TEST_SUCCESS);
|
||||||
|
|
||||||
|
conf.resp = (unsigned char*)resp_multi;
|
||||||
|
conf.respSz = sizeof(resp_multi);
|
||||||
|
conf.ca0 = root_ca_cert_pem;
|
||||||
|
conf.ca0Sz = sizeof(root_ca_cert_pem);
|
||||||
|
conf.ca1 = NULL;
|
||||||
|
conf.ca1Sz = 0;
|
||||||
|
conf.targetCert = intermediate1_ca_cert_pem;
|
||||||
|
conf.targetCertSz = sizeof(intermediate1_ca_cert_pem);
|
||||||
|
ExpectIntEQ(test_ocsp_response_with_cm(&conf, WOLFSSL_SUCCESS),
|
||||||
|
TEST_SUCCESS);
|
||||||
|
|
||||||
|
conf.resp = (unsigned char*)resp_bad_noauth;
|
||||||
|
conf.respSz = sizeof(resp_bad_noauth);
|
||||||
|
conf.ca0 = root_ca_cert_pem;
|
||||||
|
conf.ca0Sz = sizeof(root_ca_cert_pem);
|
||||||
|
conf.ca1 = ca_cert_pem;
|
||||||
|
conf.ca1Sz = sizeof(ca_cert_pem);
|
||||||
|
conf.targetCert = server_cert_pem;
|
||||||
|
conf.targetCertSz = sizeof(server_cert_pem);
|
||||||
|
expectedRet = OCSP_LOOKUP_FAIL;
|
||||||
|
#ifdef WOLFSSL_NO_OCSP_ISSUER_CHECK
|
||||||
|
expectedRet = WOLFSSL_SUCCESS;
|
||||||
|
#endif
|
||||||
|
ExpectIntEQ(test_ocsp_response_with_cm(&conf, expectedRet), TEST_SUCCESS);
|
||||||
|
|
||||||
|
/* Test response with unusable internal cert but that can be verified in CM
|
||||||
|
*/
|
||||||
|
conf.resp = (unsigned char*)resp_bad_embedded_cert;
|
||||||
|
conf.respSz = sizeof(resp_bad_embedded_cert);
|
||||||
|
conf.ca0 = root_ca_cert_pem;
|
||||||
|
conf.ca0Sz = sizeof(root_ca_cert_pem);
|
||||||
|
conf.ca1 = NULL;
|
||||||
|
conf.ca1Sz = 0;
|
||||||
|
conf.targetCert = intermediate1_ca_cert_pem;
|
||||||
|
conf.targetCertSz = sizeof(intermediate1_ca_cert_pem);
|
||||||
|
ExpectIntEQ(test_ocsp_response_with_cm(&conf, WOLFSSL_SUCCESS),
|
||||||
|
TEST_SUCCESS);
|
||||||
|
|
||||||
|
return EXPECT_SUCCESS();
|
||||||
|
}
|
||||||
|
#else /* HAVE_OCSP */
|
||||||
|
int test_ocsp_response_parsing(void)
|
||||||
|
{
|
||||||
|
return TEST_SKIPPED;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_OCSP */
|
||||||
|
|
||||||
|
#if defined(HAVE_OCSP) && (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA))
|
||||||
|
static int test_ocsp_create_x509store(WOLFSSL_X509_STORE** store,
|
||||||
|
unsigned char* ca, int caSz)
|
||||||
|
{
|
||||||
|
EXPECT_DECLS;
|
||||||
|
WOLFSSL_X509* cert = NULL;
|
||||||
|
|
||||||
|
ExpectNotNull(*store = wolfSSL_X509_STORE_new());
|
||||||
|
ExpectNotNull(cert = wolfSSL_X509_d2i(&cert, ca, caSz));
|
||||||
|
ExpectIntEQ(wolfSSL_X509_STORE_add_cert(*store, cert), WOLFSSL_SUCCESS);
|
||||||
|
wolfSSL_X509_free(cert);
|
||||||
|
return EXPECT_RESULT();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_create_stack_of_x509(WOLF_STACK_OF(WOLFSSL_X509) * *certs,
|
||||||
|
unsigned char* der, int derSz)
|
||||||
|
{
|
||||||
|
EXPECT_DECLS;
|
||||||
|
WOLFSSL_X509* cert = NULL;
|
||||||
|
|
||||||
|
ExpectNotNull(*certs = wolfSSL_sk_X509_new_null());
|
||||||
|
ExpectNotNull(cert = wolfSSL_X509_d2i(&cert, der, derSz));
|
||||||
|
ExpectIntEQ(wolfSSL_sk_X509_push(*certs, cert), 1);
|
||||||
|
return EXPECT_RESULT();
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_ocsp_basic_verify(void)
|
||||||
|
{
|
||||||
|
EXPECT_DECLS;
|
||||||
|
WOLF_STACK_OF(WOLFSSL_X509)* certs = NULL;
|
||||||
|
WOLFSSL_X509_STORE* store = NULL;
|
||||||
|
const unsigned char* ptr = NULL;
|
||||||
|
OcspResponse* response = NULL;
|
||||||
|
DecodedCert cert;
|
||||||
|
int expectedRet;
|
||||||
|
|
||||||
|
wc_InitDecodedCert(&cert, ocsp_responder_cert_pem,
|
||||||
|
sizeof(ocsp_responder_cert_pem), NULL);
|
||||||
|
ExpectIntEQ(wc_ParseCert(&cert, CERT_TYPE, 0, NULL), 0);
|
||||||
|
|
||||||
|
/* just decoding */
|
||||||
|
ptr = (const unsigned char*)resp;
|
||||||
|
ExpectNotNull(
|
||||||
|
response = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr, sizeof(resp)));
|
||||||
|
ExpectIntEQ(response->responseStatus, 0);
|
||||||
|
ExpectIntEQ(response->responderIdType, OCSP_RESPONDER_ID_NAME);
|
||||||
|
ExpectBufEQ(response->responderId.nameHash, cert.subjectHash,
|
||||||
|
OCSP_DIGEST_SIZE);
|
||||||
|
wolfSSL_OCSP_RESPONSE_free(response);
|
||||||
|
|
||||||
|
/* responder Id by key hash */
|
||||||
|
ptr = (const unsigned char*)resp_rid_bykey;
|
||||||
|
ExpectNotNull(response = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr,
|
||||||
|
sizeof(resp_rid_bykey)));
|
||||||
|
ExpectIntEQ(response->responseStatus, 0);
|
||||||
|
ExpectIntEQ(response->responderIdType, OCSP_RESPONDER_ID_KEY);
|
||||||
|
ExpectBufEQ(response->responderId.keyHash, cert.subjectKeyHash,
|
||||||
|
OCSP_DIGEST_SIZE);
|
||||||
|
wolfSSL_OCSP_RESPONSE_free(response);
|
||||||
|
|
||||||
|
/* decoding with no embedded certificates */
|
||||||
|
ptr = (const unsigned char*)resp_nocert;
|
||||||
|
ExpectNotNull(
|
||||||
|
response = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr, sizeof(resp_nocert)));
|
||||||
|
ExpectIntEQ(response->responseStatus, 0);
|
||||||
|
wolfSSL_OCSP_RESPONSE_free(response);
|
||||||
|
|
||||||
|
/* decoding an invalid response */
|
||||||
|
ptr = (const unsigned char*)resp_bad;
|
||||||
|
ExpectNull(
|
||||||
|
response = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr, sizeof(resp_bad)));
|
||||||
|
|
||||||
|
ptr = (const unsigned char*)resp;
|
||||||
|
ExpectNotNull(
|
||||||
|
response = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr, sizeof(resp)));
|
||||||
|
/* no verify signer certificate */
|
||||||
|
ExpectIntEQ(wolfSSL_OCSP_basic_verify(response, NULL, NULL, OCSP_NOVERIFY),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
/* verify that the signature is checked */
|
||||||
|
if (EXPECT_SUCCESS()) {
|
||||||
|
response->sig[0] ^= 0xff;
|
||||||
|
}
|
||||||
|
ExpectIntEQ(wolfSSL_OCSP_basic_verify(response, NULL, NULL, OCSP_NOVERIFY),
|
||||||
|
WOLFSSL_FAILURE);
|
||||||
|
wolfSSL_OCSP_RESPONSE_free(response);
|
||||||
|
|
||||||
|
/* populate a store with root-ca-cert */
|
||||||
|
ExpectIntEQ(test_ocsp_create_x509store(&store, root_ca_cert_pem,
|
||||||
|
sizeof(root_ca_cert_pem)),
|
||||||
|
TEST_SUCCESS);
|
||||||
|
|
||||||
|
/* populate a WOLF_STACK_OF(WOLFSSL_X509) with responder certificate */
|
||||||
|
ExpectIntEQ(test_create_stack_of_x509(&certs, ocsp_responder_cert_pem,
|
||||||
|
sizeof(ocsp_responder_cert_pem)),
|
||||||
|
TEST_SUCCESS);
|
||||||
|
|
||||||
|
/* cert not embedded, cert in certs, validated using store */
|
||||||
|
ptr = (const unsigned char*)resp_nocert;
|
||||||
|
ExpectNotNull(
|
||||||
|
response = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr, sizeof(resp_nocert)));
|
||||||
|
ExpectIntEQ(wolfSSL_OCSP_basic_verify(response, certs, store, 0),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
wolfSSL_OCSP_RESPONSE_free(response);
|
||||||
|
|
||||||
|
/* cert embedded, verified using store */
|
||||||
|
ptr = (const unsigned char*)resp;
|
||||||
|
ExpectNotNull(
|
||||||
|
response = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr, sizeof(resp)));
|
||||||
|
ExpectIntEQ(wolfSSL_OCSP_basic_verify(response, NULL, store, 0),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
/* make invalid signature */
|
||||||
|
if (EXPECT_SUCCESS()) {
|
||||||
|
response->sig[0] ^= 0xff;
|
||||||
|
}
|
||||||
|
ExpectIntEQ(wolfSSL_OCSP_basic_verify(response, NULL, store, 0),
|
||||||
|
WOLFSSL_FAILURE);
|
||||||
|
if (EXPECT_SUCCESS()) {
|
||||||
|
response->sig[0] ^= 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cert embedded and in certs, no store needed bc OCSP_TRUSTOTHER */
|
||||||
|
ExpectIntEQ(
|
||||||
|
wolfSSL_OCSP_basic_verify(response, certs, NULL, OCSP_TRUSTOTHER),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
/* this should also pass */
|
||||||
|
ExpectIntEQ(
|
||||||
|
wolfSSL_OCSP_basic_verify(response, certs, store, OCSP_NOINTERN),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
/* this should not */
|
||||||
|
ExpectIntNE(wolfSSL_OCSP_basic_verify(response, NULL, store, OCSP_NOINTERN),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
wolfSSL_OCSP_RESPONSE_free(response);
|
||||||
|
|
||||||
|
/* cert not embedded, not certs */
|
||||||
|
ptr = (const unsigned char*)resp_nocert;
|
||||||
|
ExpectNotNull(
|
||||||
|
response = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr, sizeof(resp_nocert)));
|
||||||
|
ExpectIntNE(wolfSSL_OCSP_basic_verify(response, NULL, store, 0),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
wolfSSL_OCSP_RESPONSE_free(response);
|
||||||
|
|
||||||
|
wolfSSL_sk_X509_pop_free(certs, wolfSSL_X509_free);
|
||||||
|
wolfSSL_X509_STORE_free(store);
|
||||||
|
|
||||||
|
ExpectIntEQ(test_ocsp_create_x509store(&store, root_ca_cert_pem,
|
||||||
|
sizeof(root_ca_cert_pem)),
|
||||||
|
TEST_SUCCESS);
|
||||||
|
ExpectIntEQ(test_create_stack_of_x509(&certs, root_ca_cert_pem,
|
||||||
|
sizeof(root_ca_cert_pem)),
|
||||||
|
TEST_SUCCESS);
|
||||||
|
|
||||||
|
/* multiple responses in a ocsp response */
|
||||||
|
ptr = (const unsigned char*)resp_multi;
|
||||||
|
ExpectNotNull(
|
||||||
|
response = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr, sizeof(resp_multi)));
|
||||||
|
ExpectIntEQ(wolfSSL_OCSP_basic_verify(response, certs, store, 0),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
wolfSSL_OCSP_RESPONSE_free(response);
|
||||||
|
|
||||||
|
/* cert in certs, cert verified on store, not authorized to verify all
|
||||||
|
* responses */
|
||||||
|
ptr = (const unsigned char*)resp_bad_noauth;
|
||||||
|
ExpectNotNull(response = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr,
|
||||||
|
sizeof(resp_bad_noauth)));
|
||||||
|
|
||||||
|
expectedRet = WOLFSSL_FAILURE;
|
||||||
|
#ifdef WOLFSSL_NO_OCSP_ISSUER_CHECK
|
||||||
|
expectedRet = WOLFSSL_SUCCESS;
|
||||||
|
#endif
|
||||||
|
ExpectIntEQ(wolfSSL_OCSP_basic_verify(response, certs, store, 0),
|
||||||
|
expectedRet);
|
||||||
|
/* should pass with OCSP_NOCHECKS ...*/
|
||||||
|
ExpectIntEQ(
|
||||||
|
wolfSSL_OCSP_basic_verify(response, certs, store, OCSP_NOCHECKS),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
/* or with OSCP_TRUSTOTHER */
|
||||||
|
ExpectIntEQ(
|
||||||
|
wolfSSL_OCSP_basic_verify(response, certs, store, OCSP_TRUSTOTHER),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
wolfSSL_OCSP_RESPONSE_free(response);
|
||||||
|
|
||||||
|
wc_FreeDecodedCert(&cert);
|
||||||
|
wolfSSL_sk_X509_pop_free(certs, wolfSSL_X509_free);
|
||||||
|
wolfSSL_X509_STORE_free(store);
|
||||||
|
|
||||||
|
return EXPECT_RESULT();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int test_ocsp_basic_verify(void)
|
||||||
|
{
|
||||||
|
return TEST_SKIPPED;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_OCSP && (OPENSSL_ALL || OPENSSL_EXTRA) */
|
||||||
|
|
||||||
|
#if defined(HAVE_OCSP) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \
|
||||||
|
defined(HAVE_CERTIFICATE_STATUS_REQUEST) && !defined(WOLFSSL_NO_TLS12) && \
|
||||||
|
defined(OPENSSL_ALL)
|
||||||
|
|
||||||
|
struct _test_ocsp_status_callback_ctx {
|
||||||
|
byte* ocsp_resp;
|
||||||
|
int ocsp_resp_sz;
|
||||||
|
int invoked;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int test_ocsp_status_callback_cb(WOLFSSL* ssl, void* ctx)
|
||||||
|
{
|
||||||
|
struct _test_ocsp_status_callback_ctx* _ctx =
|
||||||
|
(struct _test_ocsp_status_callback_ctx*)ctx;
|
||||||
|
byte* allocated;
|
||||||
|
|
||||||
|
_ctx->invoked++;
|
||||||
|
allocated = (byte*)XMALLOC(_ctx->ocsp_resp_sz, NULL, 0);
|
||||||
|
if (allocated == NULL)
|
||||||
|
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||||
|
XMEMCPY(allocated, _ctx->ocsp_resp, _ctx->ocsp_resp_sz);
|
||||||
|
SSL_set_tlsext_status_ocsp_resp(ssl, allocated, _ctx->ocsp_resp_sz);
|
||||||
|
return SSL_TLSEXT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_ocsp_status_callback_cb_noack(WOLFSSL* ssl, void* ctx)
|
||||||
|
{
|
||||||
|
struct _test_ocsp_status_callback_ctx* _ctx =
|
||||||
|
(struct _test_ocsp_status_callback_ctx*)ctx;
|
||||||
|
(void)ssl;
|
||||||
|
|
||||||
|
_ctx->invoked++;
|
||||||
|
return SSL_TLSEXT_ERR_NOACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_ocsp_status_callback_cb_err(WOLFSSL* ssl, void* ctx)
|
||||||
|
{
|
||||||
|
struct _test_ocsp_status_callback_ctx* _ctx =
|
||||||
|
(struct _test_ocsp_status_callback_ctx*)ctx;
|
||||||
|
(void)ssl;
|
||||||
|
|
||||||
|
_ctx->invoked++;
|
||||||
|
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_ocsp_status_callback_test_setup(
|
||||||
|
struct _test_ocsp_status_callback_ctx* cb_ctx,
|
||||||
|
struct test_ssl_memio_ctx* test_ctx, method_provider cm, method_provider sm)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
cb_ctx->invoked = 0;
|
||||||
|
XMEMSET(test_ctx, 0, sizeof(*test_ctx));
|
||||||
|
test_ctx->c_cb.caPemFile = "./certs/ocsp/root-ca-cert.pem";
|
||||||
|
test_ctx->s_cb.certPemFile = "./certs/ocsp/server1-cert.pem";
|
||||||
|
test_ctx->s_cb.keyPemFile = "./certs/ocsp/server1-key.pem";
|
||||||
|
test_ctx->c_cb.method = cm;
|
||||||
|
test_ctx->s_cb.method = sm;
|
||||||
|
ret = test_ssl_memio_setup(test_ctx);
|
||||||
|
wolfSSL_set_verify(test_ctx->c_ssl, WOLFSSL_VERIFY_DEFAULT, NULL);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_ocsp_status_callback(void)
|
||||||
|
{
|
||||||
|
struct test_params {
|
||||||
|
method_provider c_method;
|
||||||
|
method_provider s_method;
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* responseFile = "./certs/ocsp/test-leaf-response.der";
|
||||||
|
struct _test_ocsp_status_callback_ctx cb_ctx;
|
||||||
|
struct test_ssl_memio_ctx test_ctx;
|
||||||
|
int enable_client_ocsp;
|
||||||
|
int enable_must_staple;
|
||||||
|
XFILE f = XBADFILE;
|
||||||
|
byte data[4096];
|
||||||
|
unsigned int i;
|
||||||
|
EXPECT_DECLS;
|
||||||
|
|
||||||
|
struct test_params params[] = {
|
||||||
|
{wolfTLSv1_2_client_method, wolfTLSv1_2_server_method},
|
||||||
|
#if defined(WOLFSSL_TLS13)
|
||||||
|
{wolfTLSv1_3_client_method, wolfTLSv1_3_server_method},
|
||||||
|
#endif
|
||||||
|
#if defined(WOLFSSL_DTLS)
|
||||||
|
{wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method},
|
||||||
|
#endif
|
||||||
|
#if defined(WOLFSSL_DTLS13)
|
||||||
|
{wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method},
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
XMEMSET(&cb_ctx, 0, sizeof(cb_ctx));
|
||||||
|
f = XFOPEN(responseFile, "rb");
|
||||||
|
if (f == XBADFILE)
|
||||||
|
return -1;
|
||||||
|
cb_ctx.ocsp_resp_sz = (word32)XFREAD(data, 1, 4096, f);
|
||||||
|
if (f != XBADFILE) {
|
||||||
|
XFCLOSE(f);
|
||||||
|
f = XBADFILE;
|
||||||
|
}
|
||||||
|
cb_ctx.ocsp_resp = data;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(params) / sizeof(params[0]); i++) {
|
||||||
|
for (enable_client_ocsp = 0; enable_client_ocsp <= 1;
|
||||||
|
enable_client_ocsp++) {
|
||||||
|
ExpectIntEQ(test_ocsp_status_callback_test_setup(&cb_ctx, &test_ctx,
|
||||||
|
params[i].c_method, params[i].s_method),
|
||||||
|
TEST_SUCCESS);
|
||||||
|
ExpectIntEQ(SSL_CTX_set_tlsext_status_cb(test_ctx.s_ctx,
|
||||||
|
test_ocsp_status_callback_cb),
|
||||||
|
SSL_SUCCESS);
|
||||||
|
ExpectIntEQ(
|
||||||
|
SSL_CTX_set_tlsext_status_arg(test_ctx.s_ctx, (void*)&cb_ctx),
|
||||||
|
SSL_SUCCESS);
|
||||||
|
if (enable_client_ocsp) {
|
||||||
|
ExpectIntEQ(wolfSSL_UseOCSPStapling(test_ctx.c_ssl,
|
||||||
|
WOLFSSL_CSR_OCSP, 0),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(test_ctx.c_ctx),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
ExpectIntEQ(wolfSSL_CTX_EnableOCSPMustStaple(test_ctx.c_ctx),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
}
|
||||||
|
ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL),
|
||||||
|
TEST_SUCCESS);
|
||||||
|
ExpectIntEQ(cb_ctx.invoked, enable_client_ocsp ? 1 : 0);
|
||||||
|
test_ssl_memio_cleanup(&test_ctx);
|
||||||
|
if (!EXPECT_SUCCESS())
|
||||||
|
return EXPECT_RESULT();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
|
||||||
|
/* test client sending both OCSPv1 and OCSPv2/MultiOCSP */
|
||||||
|
/* StatusCb only supports OCSPv1 */
|
||||||
|
ExpectIntEQ(test_ocsp_status_callback_test_setup(&cb_ctx, &test_ctx,
|
||||||
|
wolfTLSv1_2_client_method, wolfTLSv1_2_server_method),
|
||||||
|
TEST_SUCCESS);
|
||||||
|
ExpectIntEQ(SSL_CTX_set_tlsext_status_cb(test_ctx.s_ctx,
|
||||||
|
test_ocsp_status_callback_cb),
|
||||||
|
SSL_SUCCESS);
|
||||||
|
ExpectIntEQ(SSL_CTX_set_tlsext_status_arg(test_ctx.s_ctx, (void*)&cb_ctx),
|
||||||
|
SSL_SUCCESS);
|
||||||
|
ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(test_ctx.c_ctx),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
ExpectIntEQ(wolfSSL_CTX_EnableOCSPMustStaple(test_ctx.c_ctx),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
ExpectIntEQ(wolfSSL_UseOCSPStapling(test_ctx.c_ssl, WOLFSSL_CSR_OCSP, 0),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
ExpectIntEQ(
|
||||||
|
wolfSSL_UseOCSPStaplingV2(test_ctx.c_ssl, WOLFSSL_CSR2_OCSP_MULTI, 0),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
wolfSSL_set_verify(test_ctx.c_ssl, WOLFSSL_VERIFY_DEFAULT, NULL);
|
||||||
|
ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS);
|
||||||
|
ExpectIntEQ(cb_ctx.invoked, 1);
|
||||||
|
test_ssl_memio_cleanup(&test_ctx);
|
||||||
|
|
||||||
|
if (!EXPECT_SUCCESS())
|
||||||
|
return EXPECT_RESULT();
|
||||||
|
#endif /* defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) */
|
||||||
|
/* test cb returning NO_ACK, not acking the OCSP */
|
||||||
|
for (i = 0; i < sizeof(params) / sizeof(params[0]); i++) {
|
||||||
|
for (enable_must_staple = 0; enable_must_staple <= 1;
|
||||||
|
enable_must_staple++) {
|
||||||
|
ExpectIntEQ(test_ocsp_status_callback_test_setup(&cb_ctx, &test_ctx,
|
||||||
|
params[i].c_method, params[i].s_method),
|
||||||
|
TEST_SUCCESS);
|
||||||
|
ExpectIntEQ(SSL_CTX_set_tlsext_status_cb(test_ctx.s_ctx,
|
||||||
|
test_ocsp_status_callback_cb_noack),
|
||||||
|
SSL_SUCCESS);
|
||||||
|
ExpectIntEQ(
|
||||||
|
SSL_CTX_set_tlsext_status_arg(test_ctx.s_ctx, (void*)&cb_ctx),
|
||||||
|
SSL_SUCCESS);
|
||||||
|
ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(test_ctx.c_ctx),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
ExpectIntEQ(
|
||||||
|
wolfSSL_UseOCSPStapling(test_ctx.c_ssl, WOLFSSL_CSR_OCSP, 0),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
if (enable_must_staple)
|
||||||
|
ExpectIntEQ(wolfSSL_CTX_EnableOCSPMustStaple(test_ctx.c_ctx),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
wolfSSL_set_verify(test_ctx.c_ssl, WOLFSSL_VERIFY_DEFAULT, NULL);
|
||||||
|
ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL),
|
||||||
|
enable_must_staple ? TEST_FAIL : TEST_SUCCESS);
|
||||||
|
ExpectIntEQ(cb_ctx.invoked, 1);
|
||||||
|
test_ssl_memio_cleanup(&test_ctx);
|
||||||
|
if (!EXPECT_SUCCESS())
|
||||||
|
return EXPECT_RESULT();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test cb returning err aborting handshake */
|
||||||
|
for (i = 0; i < sizeof(params) / sizeof(params[0]); i++) {
|
||||||
|
for (enable_client_ocsp = 0; enable_client_ocsp <= 1;
|
||||||
|
enable_client_ocsp++) {
|
||||||
|
ExpectIntEQ(test_ocsp_status_callback_test_setup(&cb_ctx, &test_ctx,
|
||||||
|
params[i].c_method, params[i].s_method),
|
||||||
|
TEST_SUCCESS);
|
||||||
|
ExpectIntEQ(SSL_CTX_set_tlsext_status_cb(test_ctx.s_ctx,
|
||||||
|
test_ocsp_status_callback_cb_err),
|
||||||
|
SSL_SUCCESS);
|
||||||
|
ExpectIntEQ(
|
||||||
|
SSL_CTX_set_tlsext_status_arg(test_ctx.s_ctx, (void*)&cb_ctx),
|
||||||
|
SSL_SUCCESS);
|
||||||
|
if (enable_client_ocsp)
|
||||||
|
ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(test_ctx.c_ctx),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
ExpectIntEQ(
|
||||||
|
wolfSSL_UseOCSPStapling(test_ctx.c_ssl, WOLFSSL_CSR_OCSP, 0),
|
||||||
|
WOLFSSL_SUCCESS);
|
||||||
|
wolfSSL_set_verify(test_ctx.c_ssl, WOLFSSL_VERIFY_DEFAULT, NULL);
|
||||||
|
ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL),
|
||||||
|
enable_client_ocsp ? TEST_FAIL : TEST_SUCCESS);
|
||||||
|
ExpectIntEQ(cb_ctx.invoked, enable_client_ocsp ? 1 : 0);
|
||||||
|
test_ssl_memio_cleanup(&test_ctx);
|
||||||
|
if (!EXPECT_SUCCESS())
|
||||||
|
return EXPECT_RESULT();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXPECT_RESULT();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
int test_ocsp_status_callback(void)
|
||||||
|
{
|
||||||
|
return TEST_SKIPPED;
|
||||||
|
}
|
||||||
|
#endif /* defined(HAVE_OCSP) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) \
|
||||||
|
&& defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \
|
||||||
|
!defined(WOLFSSL_NO_TLS12) \
|
||||||
|
&& defined(OPENSSL_ALL) */
|
29
tests/api/test_ocsp.h
Normal file
29
tests/api/test_ocsp.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/* test_ocsp.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2025 wolfSSL Inc.
|
||||||
|
*
|
||||||
|
* This file is part of wolfSSL.
|
||||||
|
*
|
||||||
|
* wolfSSL is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* wolfSSL is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WOLFSSL_TEST_OCSP_H
|
||||||
|
#define WOLFSSL_TEST_OCSP_H
|
||||||
|
|
||||||
|
int test_ocsp_status_callback(void);
|
||||||
|
int test_ocsp_basic_verify(void);
|
||||||
|
int test_ocsp_response_parsing(void);
|
||||||
|
#endif /* WOLFSSL_TEST_OCSP_H */
|
||||||
|
|
1224
tests/api/test_ocsp_test_blobs.h
Normal file
1224
tests/api/test_ocsp_test_blobs.h
Normal file
File diff suppressed because it is too large
Load Diff
72
tests/unit.h
72
tests/unit.h
@@ -340,6 +340,78 @@
|
|||||||
#define DoExpectBufEQ(x, y, z) DoExpectBuf(x, y, z, ==, !=)
|
#define DoExpectBufEQ(x, y, z) DoExpectBuf(x, y, z, ==, !=)
|
||||||
#define DoExpectBufNE(x, y, z) DoExpectBuf(x, y, z, !=, ==)
|
#define DoExpectBufNE(x, y, z) DoExpectBuf(x, y, z, !=, ==)
|
||||||
|
|
||||||
|
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \
|
||||||
|
!defined(NO_RSA) && \
|
||||||
|
!defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) && \
|
||||||
|
!defined(WOLFSSL_TIRTOS)
|
||||||
|
#define HAVE_SSL_MEMIO_TESTS_DEPENDENCIES
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SSL_MEMIO_TESTS_DEPENDENCIES
|
||||||
|
|
||||||
|
typedef int (*ctx_cb)(WOLFSSL_CTX* ctx);
|
||||||
|
typedef int (*ssl_cb)(WOLFSSL* ssl);
|
||||||
|
typedef int (*test_cbType)(WOLFSSL_CTX *ctx, WOLFSSL *ssl);
|
||||||
|
typedef int (*hs_cb)(WOLFSSL_CTX **ctx, WOLFSSL **ssl);
|
||||||
|
|
||||||
|
typedef struct test_ssl_cbf {
|
||||||
|
method_provider method;
|
||||||
|
ctx_cb ctx_ready;
|
||||||
|
ssl_cb ssl_ready;
|
||||||
|
ssl_cb on_result;
|
||||||
|
ctx_cb on_ctx_cleanup;
|
||||||
|
ssl_cb on_cleanup;
|
||||||
|
hs_cb on_handshake;
|
||||||
|
WOLFSSL_CTX* ctx;
|
||||||
|
const char* caPemFile;
|
||||||
|
const char* certPemFile;
|
||||||
|
const char* keyPemFile;
|
||||||
|
const char* crlPemFile;
|
||||||
|
#ifdef WOLFSSL_STATIC_MEMORY
|
||||||
|
byte* mem;
|
||||||
|
word32 memSz;
|
||||||
|
wolfSSL_method_func method_ex;
|
||||||
|
#endif
|
||||||
|
int devId;
|
||||||
|
int return_code;
|
||||||
|
int last_err;
|
||||||
|
unsigned char isSharedCtx:1;
|
||||||
|
unsigned char loadToSSL:1;
|
||||||
|
unsigned char ticNoInit:1;
|
||||||
|
unsigned char doUdp:1;
|
||||||
|
} test_ssl_cbf;
|
||||||
|
|
||||||
|
#define TEST_SSL_MEMIO_BUF_SZ (64 * 1024)
|
||||||
|
typedef struct test_ssl_memio_ctx {
|
||||||
|
WOLFSSL_CTX* s_ctx;
|
||||||
|
WOLFSSL_CTX* c_ctx;
|
||||||
|
WOLFSSL* s_ssl;
|
||||||
|
WOLFSSL* c_ssl;
|
||||||
|
|
||||||
|
const char* c_ciphers;
|
||||||
|
const char* s_ciphers;
|
||||||
|
|
||||||
|
char* c_msg;
|
||||||
|
int c_msglen;
|
||||||
|
char* s_msg;
|
||||||
|
int s_msglen;
|
||||||
|
|
||||||
|
test_ssl_cbf s_cb;
|
||||||
|
test_ssl_cbf c_cb;
|
||||||
|
|
||||||
|
byte c_buff[TEST_SSL_MEMIO_BUF_SZ];
|
||||||
|
int c_len;
|
||||||
|
byte s_buff[TEST_SSL_MEMIO_BUF_SZ];
|
||||||
|
int s_len;
|
||||||
|
} test_ssl_memio_ctx;
|
||||||
|
|
||||||
|
int test_ssl_memio_setup(test_ssl_memio_ctx *ctx);
|
||||||
|
int test_ssl_memio_do_handshake(test_ssl_memio_ctx* ctx, int max_rounds,
|
||||||
|
int* rounds);
|
||||||
|
void test_ssl_memio_cleanup(test_ssl_memio_ctx* ctx);
|
||||||
|
int test_wolfSSL_client_server_nofail_memio(test_ssl_cbf* client_cb,
|
||||||
|
test_ssl_cbf* server_cb, test_cbType client_on_handshake);
|
||||||
|
#endif /* HAVE_SSL_MEMIO_TESTS_DEPENDENCIES */
|
||||||
|
|
||||||
void ApiTest_PrintTestCases(void);
|
void ApiTest_PrintTestCases(void);
|
||||||
int ApiTest_RunIdx(int idx);
|
int ApiTest_RunIdx(int idx);
|
||||||
int ApiTest_RunName(char* name);
|
int ApiTest_RunName(char* name);
|
||||||
|
@@ -16822,7 +16822,7 @@ static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID,
|
|||||||
#endif /* !NO_ASN_CRYPT && !NO_HASH_WRAPPER */
|
#endif /* !NO_ASN_CRYPT && !NO_HASH_WRAPPER */
|
||||||
|
|
||||||
/* Return codes: 0=Success, Negative (see error-crypt.h), ASN_SIG_CONFIRM_E */
|
/* Return codes: 0=Success, Negative (see error-crypt.h), ASN_SIG_CONFIRM_E */
|
||||||
static int ConfirmSignature(SignatureCtx* sigCtx,
|
int ConfirmSignature(SignatureCtx* sigCtx,
|
||||||
const byte* buf, word32 bufSz,
|
const byte* buf, word32 bufSz,
|
||||||
const byte* key, word32 keySz, word32 keyOID,
|
const byte* key, word32 keySz, word32 keyOID,
|
||||||
const byte* sig, word32 sigSz, word32 sigOID,
|
const byte* sig, word32 sigSz, word32 sigOID,
|
||||||
@@ -23634,6 +23634,19 @@ int wc_CertGetPubKey(const byte* cert, word32 certSz,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_OCSP
|
||||||
|
Signer* findSignerByKeyHash(Signer *list, byte *hash)
|
||||||
|
{
|
||||||
|
Signer *s;
|
||||||
|
for (s = list; s != NULL; s = s->next) {
|
||||||
|
if (XMEMCMP(s->subjectKeyHash, hash, KEYID_SIZE) == 0) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSL_OCSP */
|
||||||
|
|
||||||
Signer* findSignerByName(Signer *list, byte *hash)
|
Signer* findSignerByName(Signer *list, byte *hash)
|
||||||
{
|
{
|
||||||
Signer *s;
|
Signer *s;
|
||||||
@@ -36864,7 +36877,8 @@ static const ASNItem ocspRespDataASN[] = {
|
|||||||
/* byName */
|
/* byName */
|
||||||
/* BYNAME */ { 1, ASN_CONTEXT_SPECIFIC | 1, 1, 0, 2 },
|
/* BYNAME */ { 1, ASN_CONTEXT_SPECIFIC | 1, 1, 0, 2 },
|
||||||
/* byKey */
|
/* byKey */
|
||||||
/* BYKEY */ { 1, ASN_CONTEXT_SPECIFIC | 2, 1, 0, 2 },
|
/* BYKEY */ { 1, ASN_CONTEXT_SPECIFIC | 2, 1, 1, 2 },
|
||||||
|
/* BYKEY_OCT */ { 2, ASN_OCTET_STRING, 0, 0, 0 },
|
||||||
/* producedAt */
|
/* producedAt */
|
||||||
/* PA */ { 1, ASN_GENERALIZED_TIME, 0, 0, 0, },
|
/* PA */ { 1, ASN_GENERALIZED_TIME, 0, 0, 0, },
|
||||||
/* responses */
|
/* responses */
|
||||||
@@ -36878,6 +36892,7 @@ enum {
|
|||||||
OCSPRESPDATAASN_IDX_VER,
|
OCSPRESPDATAASN_IDX_VER,
|
||||||
OCSPRESPDATAASN_IDX_BYNAME,
|
OCSPRESPDATAASN_IDX_BYNAME,
|
||||||
OCSPRESPDATAASN_IDX_BYKEY,
|
OCSPRESPDATAASN_IDX_BYKEY,
|
||||||
|
OCSPRESPDATAASN_IDX_BYKEY_OCT,
|
||||||
OCSPRESPDATAASN_IDX_PA,
|
OCSPRESPDATAASN_IDX_PA,
|
||||||
OCSPRESPDATAASN_IDX_RESP,
|
OCSPRESPDATAASN_IDX_RESP,
|
||||||
OCSPRESPDATAASN_IDX_RESPEXT,
|
OCSPRESPDATAASN_IDX_RESPEXT,
|
||||||
@@ -36922,16 +36937,40 @@ static int DecodeResponseData(byte* source, word32* ioIndex,
|
|||||||
version = 0;
|
version = 0;
|
||||||
|
|
||||||
localIdx = idx;
|
localIdx = idx;
|
||||||
if (GetASNTag(source, &localIdx, &tag, size) == 0 &&
|
if (GetASNTag(source, &localIdx, &tag, size) != 0)
|
||||||
( tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1) ||
|
return ASN_PARSE_E;
|
||||||
tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2) ))
|
|
||||||
|
resp->responderIdType = OCSP_RESPONDER_ID_INVALID;
|
||||||
|
/* parse byName */
|
||||||
|
if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1))
|
||||||
{
|
{
|
||||||
idx++; /* advance past ASN tag */
|
idx++; /* advance past ASN tag */
|
||||||
if (GetLength(source, &idx, &length, size) < 0)
|
if (GetLength(source, &idx, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
/* compute the hash of the name */
|
||||||
|
resp->responderIdType = OCSP_RESPONDER_ID_NAME;
|
||||||
|
ret = CalcHashId_ex(source + idx, length,
|
||||||
|
resp->responderId.nameHash, WC_SHA);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
idx += length;
|
idx += length;
|
||||||
}
|
}
|
||||||
else
|
else if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2))
|
||||||
|
{
|
||||||
|
idx++; /* advance past ASN tag */
|
||||||
|
if (GetLength(source, &idx, &length, size) < 0)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
if (GetOctetString(source, &idx, &length, size) < 0)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
if (length != KEYID_SIZE)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
resp->responderIdType = OCSP_RESPONDER_ID_KEY;
|
||||||
|
XMEMCPY(resp->responderId.keyHash, source + idx, length);
|
||||||
|
idx += length;
|
||||||
|
}
|
||||||
|
if (resp->responderIdType == OCSP_RESPONDER_ID_INVALID)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
/* save pointer to the producedAt time */
|
/* save pointer to the producedAt time */
|
||||||
@@ -36967,6 +37006,7 @@ static int DecodeResponseData(byte* source, word32* ioIndex,
|
|||||||
XMEMSET(single->next->status, 0, sizeof(CertStatus));
|
XMEMSET(single->next->status, 0, sizeof(CertStatus));
|
||||||
|
|
||||||
single->next->isDynamic = 1;
|
single->next->isDynamic = 1;
|
||||||
|
single->next->ownStatus = 1;
|
||||||
|
|
||||||
single = single->next;
|
single = single->next;
|
||||||
}
|
}
|
||||||
@@ -36987,6 +37027,7 @@ static int DecodeResponseData(byte* source, word32* ioIndex,
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
byte version;
|
byte version;
|
||||||
word32 dateSz = 0;
|
word32 dateSz = 0;
|
||||||
|
word32 responderByKeySz = KEYID_SIZE;
|
||||||
word32 idx = *ioIndex;
|
word32 idx = *ioIndex;
|
||||||
OcspEntry* single = NULL;
|
OcspEntry* single = NULL;
|
||||||
|
|
||||||
@@ -37005,6 +37046,8 @@ static int DecodeResponseData(byte* source, word32* ioIndex,
|
|||||||
GetASN_Int8Bit(&dataASN[OCSPRESPDATAASN_IDX_VER], &version);
|
GetASN_Int8Bit(&dataASN[OCSPRESPDATAASN_IDX_VER], &version);
|
||||||
GetASN_Buffer(&dataASN[OCSPRESPDATAASN_IDX_PA], resp->producedDate,
|
GetASN_Buffer(&dataASN[OCSPRESPDATAASN_IDX_PA], resp->producedDate,
|
||||||
&dateSz);
|
&dateSz);
|
||||||
|
GetASN_Buffer(&dataASN[OCSPRESPDATAASN_IDX_BYKEY_OCT],
|
||||||
|
resp->responderId.keyHash, &responderByKeySz);
|
||||||
/* Decode the ResponseData. */
|
/* Decode the ResponseData. */
|
||||||
ret = GetASN_Items(ocspRespDataASN, dataASN, ocspRespDataASN_Length,
|
ret = GetASN_Items(ocspRespDataASN, dataASN, ocspRespDataASN_Length,
|
||||||
1, source, ioIndex, size);
|
1, source, ioIndex, size);
|
||||||
@@ -37022,7 +37065,22 @@ static int DecodeResponseData(byte* source, word32* ioIndex,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
/* TODO: use byName/byKey fields. */
|
if (dataASN[OCSPRESPDATAASN_IDX_BYNAME].tag != 0) {
|
||||||
|
resp->responderIdType = OCSP_RESPONDER_ID_NAME;
|
||||||
|
ret = CalcHashId_ex(
|
||||||
|
dataASN[OCSPRESPDATAASN_IDX_BYNAME].data.ref.data,
|
||||||
|
dataASN[OCSPRESPDATAASN_IDX_BYNAME].data.ref.length,
|
||||||
|
resp->responderId.nameHash, WC_SHA);
|
||||||
|
} else {
|
||||||
|
resp->responderIdType = OCSP_RESPONDER_ID_KEY;
|
||||||
|
if (dataASN[OCSPRESPDATAASN_IDX_BYKEY_OCT].length != KEYID_SIZE) {
|
||||||
|
ret = ASN_PARSE_E;
|
||||||
|
} else {
|
||||||
|
resp->responderIdType = OCSP_RESPONDER_ID_KEY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret == 0) {
|
||||||
/* Store size of response. */
|
/* Store size of response. */
|
||||||
resp->responseSz = *ioIndex - idx;
|
resp->responseSz = *ioIndex - idx;
|
||||||
/* Store date format/tag. */
|
/* Store date format/tag. */
|
||||||
@@ -37056,6 +37114,7 @@ static int DecodeResponseData(byte* source, word32* ioIndex,
|
|||||||
|
|
||||||
/* Entry to be freed. */
|
/* Entry to be freed. */
|
||||||
single->next->isDynamic = 1;
|
single->next->isDynamic = 1;
|
||||||
|
single->next->ownStatus = 1;
|
||||||
/* used will be 0 (false) */
|
/* used will be 0 (false) */
|
||||||
|
|
||||||
single = single->next;
|
single = single->next;
|
||||||
@@ -37164,8 +37223,135 @@ enum {
|
|||||||
#define ocspBasicRespASN_Length (sizeof(ocspBasicRespASN) / sizeof(ASNItem))
|
#define ocspBasicRespASN_Length (sizeof(ocspBasicRespASN) / sizeof(ASNItem))
|
||||||
#endif /* WOLFSSL_ASN_TEMPLATE */
|
#endif /* WOLFSSL_ASN_TEMPLATE */
|
||||||
|
|
||||||
|
static int OcspRespIdMatch(OcspResponse *resp, const byte *NameHash,
|
||||||
|
const byte *keyHash)
|
||||||
|
{
|
||||||
|
if (resp->responderIdType == OCSP_RESPONDER_ID_NAME)
|
||||||
|
return XMEMCMP(NameHash, resp->responderId.nameHash,
|
||||||
|
SIGNER_DIGEST_SIZE) == 0;
|
||||||
|
return XMEMCMP(keyHash, resp->responderId.keyHash, KEYID_SIZE) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
|
||||||
|
static int OcspRespCheck(OcspResponse *resp, Signer *responder)
|
||||||
|
{
|
||||||
|
OcspEntry *s;
|
||||||
|
|
||||||
|
s = resp->single;
|
||||||
|
if (s == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* singles responses must have the same issuer */
|
||||||
|
for (; s != NULL; s = s->next) {
|
||||||
|
if (XMEMCMP(s->issuerKeyHash, responder->subjectKeyHash,
|
||||||
|
KEYID_SIZE) != 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static Signer *OcspFindSigner(OcspResponse *resp, WOLFSSL_CERT_MANAGER *cm)
|
||||||
|
{
|
||||||
|
Signer *s;
|
||||||
|
|
||||||
|
if (cm == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (resp->responderIdType == OCSP_RESPONDER_ID_NAME) {
|
||||||
|
#ifndef NO_SKID
|
||||||
|
s = GetCAByName(cm, resp->responderId.nameHash);
|
||||||
|
#else
|
||||||
|
s = GetCA(cm, resp->responderId.nameHash);
|
||||||
|
#endif
|
||||||
|
if (s)
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s = GetCAByKeyHash(cm, resp->responderId.keyHash);
|
||||||
|
if (s)
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
|
||||||
|
if (resp->pendingCAs == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (resp->responderIdType == OCSP_RESPONDER_ID_NAME) {
|
||||||
|
s = findSignerByName(resp->pendingCAs, resp->responderId.nameHash);
|
||||||
|
if (s)
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s = findSignerByKeyHash(resp->pendingCAs, resp->responderId.keyHash);
|
||||||
|
if (s)
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int OcspCheckCert(OcspResponse *resp, int noVerify,
|
||||||
|
int noVerifySignature, WOLFSSL_CERT_MANAGER *cm, void *heap)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
|
DecodedCert *cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
|
||||||
|
DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
if (cert == NULL)
|
||||||
|
return MEMORY_E;
|
||||||
|
#else
|
||||||
|
DecodedCert cert[1];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
InitDecodedCert(cert, resp->cert, resp->certSz, heap);
|
||||||
|
ret = ParseCertRelative(cert, CERT_TYPE,
|
||||||
|
noVerify ? NO_VERIFY : VERIFY_OCSP_CERT,
|
||||||
|
cm, resp->pendingCAs);
|
||||||
|
if (ret < 0) {
|
||||||
|
WOLFSSL_MSG("\tOCSP Responder certificate parsing failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0 &&
|
||||||
|
OcspRespIdMatch(resp,
|
||||||
|
cert->subjectHash, cert->subjectKeyHash) == 0) {
|
||||||
|
WOLFSSL_MSG("\tInternal check doesn't match responder ID, ignoring\n");
|
||||||
|
ret = BAD_OCSP_RESPONDER;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
|
||||||
|
if (ret == 0 && !noVerify) {
|
||||||
|
ret = CheckOcspResponder(resp, cert, cm);
|
||||||
|
if (ret != 0) {
|
||||||
|
WOLFSSL_MSG("\tOCSP Responder certificate issuer check failed");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSL_NO_OCSP_ISSUER_CHECK */
|
||||||
|
if (ret == 0 && !noVerifySignature) {
|
||||||
|
ret = ConfirmSignature(
|
||||||
|
&cert->sigCtx,
|
||||||
|
resp->response, resp->responseSz,
|
||||||
|
cert->publicKey, cert->pubKeySize, cert->keyOID,
|
||||||
|
resp->sig, resp->sigSz, resp->sigOID, resp->sigParams,
|
||||||
|
resp->sigParamsSz, NULL);
|
||||||
|
}
|
||||||
|
err:
|
||||||
|
FreeDecodedCert(cert);
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
|
if (cert != NULL) {
|
||||||
|
XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
|
static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
|
||||||
OcspResponse* resp, word32 size, void* cm, void* heap, int noVerify)
|
OcspResponse* resp, word32 size, void* cm, void* heap, int noVerify,
|
||||||
|
int noVerifySignature)
|
||||||
{
|
{
|
||||||
#ifndef WOLFSSL_ASN_TEMPLATE
|
#ifndef WOLFSSL_ASN_TEMPLATE
|
||||||
int length;
|
int length;
|
||||||
@@ -37175,8 +37361,7 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
|
|||||||
#endif
|
#endif
|
||||||
int ret;
|
int ret;
|
||||||
int sigLength;
|
int sigLength;
|
||||||
const byte* sigParams = NULL;
|
int sigValid = 0;
|
||||||
word32 sigParamsSz = 0;
|
|
||||||
WOLFSSL_ENTER("DecodeBasicOcspResponse");
|
WOLFSSL_ENTER("DecodeBasicOcspResponse");
|
||||||
(void)heap;
|
(void)heap;
|
||||||
|
|
||||||
@@ -37200,16 +37385,16 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
|
|||||||
else if (resp->sigOID == CTC_RSASSAPSS) {
|
else if (resp->sigOID == CTC_RSASSAPSS) {
|
||||||
word32 sz;
|
word32 sz;
|
||||||
int len;
|
int len;
|
||||||
const byte* params;
|
byte* params;
|
||||||
|
|
||||||
sz = idx;
|
sz = idx;
|
||||||
params = source + idx;
|
params = source + idx;
|
||||||
if (GetSequence(source, &idx, &len, size) < 0)
|
if (GetSequence(source, &idx, &len, size) < 0)
|
||||||
ret = ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
idx += len;
|
idx += len;
|
||||||
sigParams = params;
|
resp->sigParams = params;
|
||||||
sigParamsSz = idx - sz;
|
resp->sigParamsSz = idx - sz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -37229,107 +37414,43 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
|
|||||||
#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
|
#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
|
||||||
if (idx < end_index)
|
if (idx < end_index)
|
||||||
{
|
{
|
||||||
int cert_inited = 0;
|
if (DecodeCerts(source, &idx, resp, size) < 0)
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
return ASN_PARSE_E;
|
||||||
DecodedCert *cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
|
|
||||||
DYNAMIC_TYPE_TMP_BUFFER);
|
|
||||||
if (cert == NULL)
|
|
||||||
return MEMORY_E;
|
|
||||||
#else
|
|
||||||
DecodedCert cert[1];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
do {
|
ret = OcspCheckCert(resp, noVerify, noVerifySignature, cm, heap);
|
||||||
if (DecodeCerts(source, &idx, resp, size) < 0) {
|
if (ret == 0) {
|
||||||
ret = ASN_PARSE_E;
|
sigValid = 1;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
InitDecodedCert(cert, resp->cert, resp->certSz, heap);
|
|
||||||
cert_inited = 1;
|
|
||||||
|
|
||||||
/* Don't verify if we don't have access to Cert Manager. */
|
|
||||||
ret = ParseCertRelative(cert, CERT_TYPE,
|
|
||||||
noVerify ? NO_VERIFY : VERIFY_OCSP_CERT,
|
|
||||||
cm, resp->pendingCAs);
|
|
||||||
if (ret < 0) {
|
|
||||||
WOLFSSL_MSG("\tOCSP Responder certificate parsing failed");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
|
|
||||||
if ((cert->extExtKeyUsage & EXTKEYUSE_OCSP_SIGN) == 0) {
|
|
||||||
if (XMEMCMP(cert->subjectHash,
|
|
||||||
resp->single->issuerHash, OCSP_DIGEST_SIZE) == 0) {
|
|
||||||
WOLFSSL_MSG("\tOCSP Response signed by issuer");
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
WOLFSSL_MSG("\tOCSP Responder key usage check failed");
|
WOLFSSL_MSG("OCSP Internal cert can't verify the response\n");
|
||||||
#ifdef OPENSSL_EXTRA
|
/* try to verify the OCSP response with CA certs */
|
||||||
resp->verifyError = OCSP_BAD_ISSUER;
|
ret = 0;
|
||||||
#else
|
|
||||||
ret = BAD_OCSP_RESPONDER;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ConfirmSignature is blocking here */
|
|
||||||
ret = ConfirmSignature(
|
|
||||||
&cert->sigCtx,
|
|
||||||
resp->response, resp->responseSz,
|
|
||||||
cert->publicKey, cert->pubKeySize, cert->keyOID,
|
|
||||||
resp->sig, resp->sigSz, resp->sigOID, sigParams, sigParamsSz,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (ret != 0) {
|
|
||||||
WOLFSSL_MSG("\tOCSP Confirm signature failed");
|
|
||||||
ret = ASN_OCSP_CONFIRM_E;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while(0);
|
|
||||||
|
|
||||||
if (cert_inited)
|
|
||||||
FreeDecodedCert(cert);
|
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
|
||||||
XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ret != 0)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */
|
#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */
|
||||||
{
|
if (!noVerifySignature && !sigValid) {
|
||||||
Signer* ca;
|
Signer* ca;
|
||||||
int sigValid = -1;
|
|
||||||
|
|
||||||
#ifndef NO_SKID
|
|
||||||
ca = GetCAByKeyHash(cm, resp->single->issuerKeyHash);
|
|
||||||
#else
|
|
||||||
ca = GetCA(cm, resp->single->issuerHash);
|
|
||||||
#endif
|
|
||||||
#if defined(HAVE_CERTIFICATE_STATUS_V2)
|
|
||||||
if (ca == NULL && resp->pendingCAs != NULL) {
|
|
||||||
ca = findSignerByName(resp->pendingCAs, resp->single->issuerHash);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (ca) {
|
|
||||||
SignatureCtx sigCtx;
|
SignatureCtx sigCtx;
|
||||||
|
ca = OcspFindSigner(resp, cm);
|
||||||
|
if (ca == NULL)
|
||||||
|
return ASN_NO_SIGNER_E;
|
||||||
|
|
||||||
|
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
|
||||||
|
if (OcspRespCheck(resp, ca) != 0)
|
||||||
|
return BAD_OCSP_RESPONDER;
|
||||||
|
#endif
|
||||||
InitSignatureCtx(&sigCtx, heap, INVALID_DEVID);
|
InitSignatureCtx(&sigCtx, heap, INVALID_DEVID);
|
||||||
|
|
||||||
/* ConfirmSignature is blocking here */
|
/* ConfirmSignature is blocking here */
|
||||||
sigValid = ConfirmSignature(&sigCtx, resp->response,
|
sigValid = ConfirmSignature(&sigCtx, resp->response,
|
||||||
resp->responseSz, ca->publicKey, ca->pubKeySize, ca->keyOID,
|
resp->responseSz, ca->publicKey, ca->pubKeySize, ca->keyOID,
|
||||||
resp->sig, resp->sigSz, resp->sigOID, sigParams, sigParamsSz,
|
resp->sig, resp->sigSz, resp->sigOID, resp->sigParams,
|
||||||
NULL);
|
resp->sigParamsSz, NULL);
|
||||||
}
|
if (sigValid != 0) {
|
||||||
if (ca == NULL || sigValid != 0) {
|
|
||||||
WOLFSSL_MSG("\tOCSP Confirm signature failed");
|
WOLFSSL_MSG("\tOCSP Confirm signature failed");
|
||||||
return ASN_OCSP_CONFIRM_E;
|
return ASN_OCSP_CONFIRM_E;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)noVerify;
|
(void)noVerify;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37339,16 +37460,8 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
|
|||||||
DECL_ASNGETDATA(dataASN, ocspBasicRespASN_Length);
|
DECL_ASNGETDATA(dataASN, ocspBasicRespASN_Length);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
word32 idx = *ioIndex;
|
word32 idx = *ioIndex;
|
||||||
const byte* sigParams = NULL;
|
Signer* ca = NULL;
|
||||||
word32 sigParamsSz = 0;
|
int sigValid = 0;
|
||||||
#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
|
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
|
||||||
DecodedCert* cert = NULL;
|
|
||||||
#else
|
|
||||||
DecodedCert cert[1];
|
|
||||||
#endif
|
|
||||||
int certInit = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WOLFSSL_ENTER("DecodeBasicOcspResponse");
|
WOLFSSL_ENTER("DecodeBasicOcspResponse");
|
||||||
(void)heap;
|
(void)heap;
|
||||||
@@ -37373,10 +37486,10 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
|
|||||||
}
|
}
|
||||||
#ifdef WC_RSA_PSS
|
#ifdef WC_RSA_PSS
|
||||||
if (ret == 0 && (dataASN[OCSPBASICRESPASN_IDX_SIGNATURE_PARAMS].tag != 0)) {
|
if (ret == 0 && (dataASN[OCSPBASICRESPASN_IDX_SIGNATURE_PARAMS].tag != 0)) {
|
||||||
sigParams = GetASNItem_Addr(
|
resp->sigParams = GetASNItem_Addr(
|
||||||
dataASN[OCSPBASICRESPASN_IDX_SIGNATURE_PARAMS],
|
dataASN[OCSPBASICRESPASN_IDX_SIGNATURE_PARAMS],
|
||||||
source);
|
source);
|
||||||
sigParamsSz =
|
resp->sigParamsSz =
|
||||||
GetASNItem_Length(dataASN[OCSPBASICRESPASN_IDX_SIGNATURE_PARAMS],
|
GetASNItem_Length(dataASN[OCSPBASICRESPASN_IDX_SIGNATURE_PARAMS],
|
||||||
source);
|
source);
|
||||||
}
|
}
|
||||||
@@ -37387,6 +37500,7 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
|
|||||||
GetASN_GetRef(&dataASN[OCSPBASICRESPASN_IDX_SIGNATURE], &resp->sig,
|
GetASN_GetRef(&dataASN[OCSPBASICRESPASN_IDX_SIGNATURE], &resp->sig,
|
||||||
&resp->sigSz);
|
&resp->sigSz);
|
||||||
}
|
}
|
||||||
|
resp->certSz = 0;
|
||||||
#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
|
#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
|
||||||
if ((ret == 0) &&
|
if ((ret == 0) &&
|
||||||
(dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ].data.ref.data != NULL)) {
|
(dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ].data.ref.data != NULL)) {
|
||||||
@@ -37394,106 +37508,52 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
|
|||||||
/* Store reference to certificate BER data. */
|
/* Store reference to certificate BER data. */
|
||||||
GetASN_GetRef(&dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ], &resp->cert,
|
GetASN_GetRef(&dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ], &resp->cert,
|
||||||
&resp->certSz);
|
&resp->certSz);
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate a certificate object to decode cert into. */
|
if ((ret == 0) && resp->certSz > 0) {
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
ret = OcspCheckCert(resp, noVerify, noVerifySignature,
|
||||||
cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap,
|
(WOLFSSL_CERT_MANAGER*)cm, heap);
|
||||||
DYNAMIC_TYPE_TMP_BUFFER);
|
if (ret == 0) {
|
||||||
if (cert == NULL) {
|
sigValid = 1;
|
||||||
ret = MEMORY_E;
|
|
||||||
}
|
}
|
||||||
|
ret = 0; /* try to verify the OCSP response with CA certs */
|
||||||
}
|
}
|
||||||
if ((ret == 0) &&
|
#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */
|
||||||
(dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ].data.ref.data != NULL)) {
|
/* try to verify using cm certs */
|
||||||
#endif
|
if (ret == 0 && !noVerifySignature && !sigValid)
|
||||||
/* Initialize the certificate object. */
|
{
|
||||||
InitDecodedCert(cert, resp->cert, resp->certSz, heap);
|
ca = OcspFindSigner(resp, (WOLFSSL_CERT_MANAGER*)cm);
|
||||||
certInit = 1;
|
if (ca == NULL)
|
||||||
/* Parse the certificate and don't verify if we don't have access to
|
ret = ASN_NO_SIGNER_E;
|
||||||
* Cert Manager. */
|
|
||||||
ret = ParseCertRelative(cert, CERT_TYPE, noVerify ? NO_VERIFY : VERIFY,
|
|
||||||
cm, resp->pendingCAs);
|
|
||||||
if (ret < 0) {
|
|
||||||
WOLFSSL_MSG("\tOCSP Responder certificate parsing failed");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
|
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
|
||||||
if ((ret == 0) &&
|
if (ret == 0 && !noVerifySignature && !sigValid) {
|
||||||
(dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ].data.ref.data != NULL) &&
|
if (OcspRespCheck(resp, ca) != 0) {
|
||||||
!noVerify) {
|
ret = BAD_OCSP_RESPONDER;
|
||||||
ret = CheckOcspResponder(resp, cert, cm);
|
|
||||||
}
|
|
||||||
#endif /* WOLFSSL_NO_OCSP_ISSUER_CHECK */
|
|
||||||
if ((ret == 0) &&
|
|
||||||
(dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ].data.ref.data != NULL)) {
|
|
||||||
/* TODO: ConfirmSignature is blocking here */
|
|
||||||
/* Check the signature of the response. */
|
|
||||||
ret = ConfirmSignature(&cert->sigCtx, resp->response, resp->responseSz,
|
|
||||||
cert->publicKey, cert->pubKeySize, cert->keyOID, resp->sig,
|
|
||||||
resp->sigSz, resp->sigOID, NULL, 0, NULL);
|
|
||||||
if (ret != 0) {
|
|
||||||
WOLFSSL_MSG("\tOCSP Confirm signature failed");
|
|
||||||
ret = ASN_OCSP_CONFIRM_E;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((ret == 0) &&
|
#endif
|
||||||
(dataASN[OCSPBASICRESPASN_IDX_CERTS_SEQ].data.ref.data == NULL))
|
if (ret == 0 && !noVerifySignature && !sigValid) {
|
||||||
#else
|
|
||||||
if (ret == 0)
|
|
||||||
#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */
|
|
||||||
{
|
|
||||||
Signer* ca;
|
|
||||||
int sigValid = -1;
|
|
||||||
|
|
||||||
/* Response didn't have a certificate - lookup CA. */
|
|
||||||
#ifndef NO_SKID
|
|
||||||
ca = GetCAByKeyHash(cm, resp->single->issuerKeyHash);
|
|
||||||
#else
|
|
||||||
ca = GetCA(cm, resp->single->issuerHash);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
|
|
||||||
if (ca == NULL && resp->pendingCAs != NULL) {
|
|
||||||
ca = findSignerByName(resp->pendingCAs, resp->single->issuerHash);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ca) {
|
|
||||||
SignatureCtx sigCtx;
|
SignatureCtx sigCtx;
|
||||||
|
/* Initialize the signature context. */
|
||||||
/* Initialize he signature context. */
|
|
||||||
InitSignatureCtx(&sigCtx, heap, INVALID_DEVID);
|
InitSignatureCtx(&sigCtx, heap, INVALID_DEVID);
|
||||||
|
|
||||||
/* TODO: ConfirmSignature is blocking here */
|
/* TODO: ConfirmSignature is blocking here */
|
||||||
/* Check the signature of the response CA public key. */
|
/* Check the signature of the response CA public key. */
|
||||||
sigValid = ConfirmSignature(&sigCtx, resp->response,
|
sigValid = ConfirmSignature(&sigCtx, resp->response,
|
||||||
resp->responseSz, ca->publicKey, ca->pubKeySize, ca->keyOID,
|
resp->responseSz, ca->publicKey, ca->pubKeySize, ca->keyOID,
|
||||||
resp->sig, resp->sigSz, resp->sigOID, sigParams, sigParamsSz,
|
resp->sig, resp->sigSz, resp->sigOID, resp->sigParams,
|
||||||
NULL);
|
resp->sigParamsSz, NULL);
|
||||||
}
|
if (sigValid != 0) {
|
||||||
if ((ca == NULL) || (sigValid != 0)) {
|
|
||||||
/* Didn't find certificate or signature verificate failed. */
|
|
||||||
WOLFSSL_MSG("\tOCSP Confirm signature failed");
|
WOLFSSL_MSG("\tOCSP Confirm signature failed");
|
||||||
ret = ASN_OCSP_CONFIRM_E;
|
ret = ASN_OCSP_CONFIRM_E;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
/* Update the position to after response data. */
|
/* Update the position to after response data. */
|
||||||
*ioIndex = idx;
|
*ioIndex = idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
|
|
||||||
if (certInit) {
|
|
||||||
FreeDecodedCert(cert);
|
|
||||||
}
|
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
|
||||||
if (cert != NULL) {
|
|
||||||
/* Dispose of certificate object. */
|
|
||||||
XFREE(cert, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
FREE_ASNGETDATA(dataASN, heap);
|
FREE_ASNGETDATA(dataASN, heap);
|
||||||
return ret;
|
return ret;
|
||||||
#endif /* WOLFSSL_ASN_TEMPLATE */
|
#endif /* WOLFSSL_ASN_TEMPLATE */
|
||||||
@@ -37516,6 +37576,9 @@ void InitOcspResponse(OcspResponse* resp, OcspEntry* single, CertStatus* status,
|
|||||||
resp->maxIdx = inSz;
|
resp->maxIdx = inSz;
|
||||||
resp->heap = heap;
|
resp->heap = heap;
|
||||||
resp->pendingCAs = NULL;
|
resp->pendingCAs = NULL;
|
||||||
|
resp->sigParams = NULL;
|
||||||
|
resp->sigParamsSz = 0;
|
||||||
|
resp->responderIdType = OCSP_RESPONDER_ID_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeOcspResponse(OcspResponse* resp)
|
void FreeOcspResponse(OcspResponse* resp)
|
||||||
@@ -37569,7 +37632,8 @@ enum {
|
|||||||
#define ocspResponseASN_Length (sizeof(ocspResponseASN) / sizeof(ASNItem))
|
#define ocspResponseASN_Length (sizeof(ocspResponseASN) / sizeof(ASNItem))
|
||||||
#endif /* WOLFSSL_ASN_TEMPLATE */
|
#endif /* WOLFSSL_ASN_TEMPLATE */
|
||||||
|
|
||||||
int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify)
|
int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap,
|
||||||
|
int noVerifyCert, int noVerifySignature)
|
||||||
{
|
{
|
||||||
#ifndef WOLFSSL_ASN_TEMPLATE
|
#ifndef WOLFSSL_ASN_TEMPLATE
|
||||||
int ret;
|
int ret;
|
||||||
@@ -37638,7 +37702,8 @@ int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap, noVerify);
|
ret = DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap,
|
||||||
|
noVerifyCert, noVerifySignature);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
WOLFSSL_LEAVE("OcspResponseDecode", ret);
|
WOLFSSL_LEAVE("OcspResponseDecode", ret);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -37678,7 +37743,7 @@ int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify)
|
|||||||
idx = 0;
|
idx = 0;
|
||||||
/* Decode BasicOCSPResponse. */
|
/* Decode BasicOCSPResponse. */
|
||||||
ret = DecodeBasicOcspResponse(basic, &idx, resp, basicSz, cm, heap,
|
ret = DecodeBasicOcspResponse(basic, &idx, resp, basicSz, cm, heap,
|
||||||
noVerify);
|
noVerifyCert, noVerifySignature);
|
||||||
}
|
}
|
||||||
/* Only support BasicOCSPResponse. */
|
/* Only support BasicOCSPResponse. */
|
||||||
else {
|
else {
|
||||||
|
@@ -6133,13 +6133,11 @@ struct WOLFSSL {
|
|||||||
void* ocspIOCtx;
|
void* ocspIOCtx;
|
||||||
byte ocspProducedDate[MAX_DATE_SZ];
|
byte ocspProducedDate[MAX_DATE_SZ];
|
||||||
int ocspProducedDateFormat;
|
int ocspProducedDateFormat;
|
||||||
#ifdef OPENSSL_EXTRA
|
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
|
||||||
byte* ocspResp;
|
byte* ocspResp;
|
||||||
int ocspRespSz;
|
int ocspRespSz;
|
||||||
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
|
|
||||||
char* url;
|
char* url;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#if defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST)
|
#if defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST)
|
||||||
word32 response_idx;
|
word32 response_idx;
|
||||||
#endif
|
#endif
|
||||||
|
@@ -2352,7 +2352,12 @@ WOLFSSL_LOCAL int CheckCertSignaturePubKey(const byte* cert, word32 certSz,
|
|||||||
WOLFSSL_LOCAL int wc_CertGetPubKey(const byte* cert, word32 certSz,
|
WOLFSSL_LOCAL int wc_CertGetPubKey(const byte* cert, word32 certSz,
|
||||||
const unsigned char** pubKey, word32* pubKeySz);
|
const unsigned char** pubKey, word32* pubKeySz);
|
||||||
#endif
|
#endif
|
||||||
|
WOLFSSL_LOCAL int ConfirmSignature(SignatureCtx* sigCtx,
|
||||||
|
const byte* buf, word32 bufSz,
|
||||||
|
const byte* key, word32 keySz, word32 keyOID,
|
||||||
|
const byte* sig, word32 sigSz, word32 sigOID,
|
||||||
|
const byte* sigParams, word32 sigParamsSz,
|
||||||
|
byte* rsaKeyIdx);
|
||||||
#ifdef WOLFSSL_CERT_REQ
|
#ifdef WOLFSSL_CERT_REQ
|
||||||
WOLFSSL_LOCAL int CheckCSRSignaturePubKey(const byte* cert, word32 certSz,
|
WOLFSSL_LOCAL int CheckCSRSignaturePubKey(const byte* cert, word32 certSz,
|
||||||
void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID);
|
void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID);
|
||||||
@@ -2369,6 +2374,7 @@ WOLFSSL_LOCAL int TryDecodeRPKToKey(DecodedCert* cert);
|
|||||||
WOLFSSL_LOCAL int wc_GetPubX509(DecodedCert* cert, int verify, int* badDate);
|
WOLFSSL_LOCAL int wc_GetPubX509(DecodedCert* cert, int verify, int* badDate);
|
||||||
|
|
||||||
WOLFSSL_LOCAL const byte* OidFromId(word32 id, word32 type, word32* oidSz);
|
WOLFSSL_LOCAL const byte* OidFromId(word32 id, word32 type, word32* oidSz);
|
||||||
|
WOLFSSL_LOCAL Signer* findSignerByKeyHash(Signer *list, byte *hash);
|
||||||
WOLFSSL_LOCAL Signer* findSignerByName(Signer *list, byte *hash);
|
WOLFSSL_LOCAL Signer* findSignerByName(Signer *list, byte *hash);
|
||||||
WOLFSSL_LOCAL int FillSigner(Signer* signer, DecodedCert* cert, int type, DerBuffer *der);
|
WOLFSSL_LOCAL int FillSigner(Signer* signer, DecodedCert* cert, int type, DerBuffer *der);
|
||||||
WOLFSSL_LOCAL Signer* MakeSigner(void* heap);
|
WOLFSSL_LOCAL Signer* MakeSigner(void* heap);
|
||||||
@@ -2726,6 +2732,11 @@ struct OcspEntry
|
|||||||
WC_BITFIELD used:1; /* entry used */
|
WC_BITFIELD used:1; /* entry used */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum responderIdType {
|
||||||
|
OCSP_RESPONDER_ID_INVALID = 0,
|
||||||
|
OCSP_RESPONDER_ID_NAME = 1,
|
||||||
|
OCSP_RESPONDER_ID_KEY = 2,
|
||||||
|
};
|
||||||
/* TODO: Long-term, it would be helpful if we made this struct and other OCSP
|
/* TODO: Long-term, it would be helpful if we made this struct and other OCSP
|
||||||
structs conform to the ASN spec as described in RFC 6960. It will help
|
structs conform to the ASN spec as described in RFC 6960. It will help
|
||||||
with readability and with implementing OpenSSL compatibility API
|
with readability and with implementing OpenSSL compatibility API
|
||||||
@@ -2737,6 +2748,12 @@ struct OcspResponse {
|
|||||||
byte* response; /* Pointer to beginning of OCSP Response */
|
byte* response; /* Pointer to beginning of OCSP Response */
|
||||||
word32 responseSz; /* length of the OCSP Response */
|
word32 responseSz; /* length of the OCSP Response */
|
||||||
|
|
||||||
|
enum responderIdType responderIdType;
|
||||||
|
union {
|
||||||
|
byte keyHash[KEYID_SIZE];
|
||||||
|
byte nameHash[KEYID_SIZE];
|
||||||
|
} responderId ;
|
||||||
|
|
||||||
byte producedDate[MAX_DATE_SIZE];
|
byte producedDate[MAX_DATE_SIZE];
|
||||||
/* Date at which this response was signed */
|
/* Date at which this response was signed */
|
||||||
byte producedDateFormat; /* format of the producedDate */
|
byte producedDateFormat; /* format of the producedDate */
|
||||||
@@ -2748,6 +2765,9 @@ struct OcspResponse {
|
|||||||
word32 sigSz; /* Length in octets for the sig */
|
word32 sigSz; /* Length in octets for the sig */
|
||||||
word32 sigOID; /* OID for hash used for sig */
|
word32 sigOID; /* OID for hash used for sig */
|
||||||
|
|
||||||
|
byte* sigParams;
|
||||||
|
word32 sigParamsSz;
|
||||||
|
|
||||||
OcspEntry* single; /* chain of OCSP single responses */
|
OcspEntry* single; /* chain of OCSP single responses */
|
||||||
|
|
||||||
byte* nonce; /* pointer to nonce inside ASN.1 response */
|
byte* nonce; /* pointer to nonce inside ASN.1 response */
|
||||||
@@ -2756,9 +2776,6 @@ struct OcspResponse {
|
|||||||
byte* source; /* pointer to source buffer, not owned */
|
byte* source; /* pointer to source buffer, not owned */
|
||||||
word32 maxIdx; /* max offset based on init size */
|
word32 maxIdx; /* max offset based on init size */
|
||||||
Signer* pendingCAs;
|
Signer* pendingCAs;
|
||||||
#ifdef OPENSSL_EXTRA
|
|
||||||
int verifyError;
|
|
||||||
#endif
|
|
||||||
void* heap;
|
void* heap;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2788,7 +2805,7 @@ WOLFSSL_LOCAL void InitOcspResponse(OcspResponse* resp, OcspEntry* single,
|
|||||||
CertStatus* status, byte* source, word32 inSz, void* heap);
|
CertStatus* status, byte* source, word32 inSz, void* heap);
|
||||||
WOLFSSL_LOCAL void FreeOcspResponse(OcspResponse* resp);
|
WOLFSSL_LOCAL void FreeOcspResponse(OcspResponse* resp);
|
||||||
WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap,
|
WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap,
|
||||||
int noVerify);
|
int noVerifyCert, int noVerifySignature);
|
||||||
|
|
||||||
WOLFSSL_LOCAL int InitOcspRequest(OcspRequest* req, DecodedCert* cert,
|
WOLFSSL_LOCAL int InitOcspRequest(OcspRequest* req, DecodedCert* cert,
|
||||||
byte useNonce, void* heap);
|
byte useNonce, void* heap);
|
||||||
|
Reference in New Issue
Block a user