mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-02 12:14:38 +02:00
Fixes and cleanups for processing peer certificates:
* Fix with `WOLFSSL_ALT_CERT_CHAINS` to resolve issue with using a trusted intermediate to validate a partial chain. With the alt cert chain enabled a CA may fail with only `ASN_NO_SIGNER_E` and the connection is allowed if the peer's certificate validates to a trusted CA. Eliminates overly complex 1 deep error alternate chain detection logic. Resolves ZD 4525. * Refactor and cleanup of ProcessPeerPerts to combine duplicate code and improve code commenting. * Fix for CA path len check in `ParseCertRelative` to always check for self-signed case (was previously only in NO_SKID case). * Improvement to include self-signed flag in the DecodedCert struct.
This commit is contained in:
699
src/internal.c
699
src/internal.c
@@ -30,7 +30,13 @@
|
|||||||
/*
|
/*
|
||||||
* WOLFSSL_SMALL_CERT_VERIFY:
|
* WOLFSSL_SMALL_CERT_VERIFY:
|
||||||
* Verify the certificate signature without using DecodedCert. Doubles up
|
* Verify the certificate signature without using DecodedCert. Doubles up
|
||||||
* on some code but allows smaller dynamic memory usage.
|
* on some code but allows smaller peak heap memory usage.
|
||||||
|
* Cannot be used with WOLFSSL_NONBLOCK_OCSP.
|
||||||
|
* WOLFSSL_ALT_CERT_CHAINS:
|
||||||
|
* Allows CA's to be presented by peer, but not part of a valid chain.
|
||||||
|
* Default wolfSSL behavior is to require validation of all presented peer
|
||||||
|
* certificates. This also allows loading intermediate CA's as trusted
|
||||||
|
* and ignoring no signer failures for CA's up the chain to root.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef WOLFCRYPT_ONLY
|
#ifndef WOLFCRYPT_ONLY
|
||||||
@@ -8546,13 +8552,10 @@ typedef struct ProcPeerCertArgs {
|
|||||||
int count;
|
int count;
|
||||||
int certIdx;
|
int certIdx;
|
||||||
int lastErr;
|
int lastErr;
|
||||||
#ifdef WOLFSSL_ALT_CERT_CHAINS
|
|
||||||
int lastCaErr;
|
|
||||||
#endif
|
|
||||||
#ifdef WOLFSSL_TLS13
|
#ifdef WOLFSSL_TLS13
|
||||||
byte ctxSz;
|
byte ctxSz;
|
||||||
#endif
|
#endif
|
||||||
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
|
#ifdef OPENSSL_EXTRA
|
||||||
char untrustedDepth;
|
char untrustedDepth;
|
||||||
#endif
|
#endif
|
||||||
word16 fatal:1;
|
word16 fatal:1;
|
||||||
@@ -8779,10 +8782,187 @@ static void FreeProcPeerCertArgs(WOLFSSL* ssl, void* pArgs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args,
|
||||||
|
int certType, int verify, byte** pSubjectHash, int* pAlreadySigner)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
buffer* cert;
|
||||||
|
byte* subjectHash = NULL;
|
||||||
|
int alreadySigner = 0;
|
||||||
|
#ifdef WOLFSSL_SMALL_CERT_VERIFY
|
||||||
|
int sigRet = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ssl == NULL || args == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
/* check to make sure certificate index is valid */
|
||||||
|
if (args->certIdx > args->count)
|
||||||
|
return BUFFER_E;
|
||||||
|
|
||||||
|
/* check if returning from non-blocking OCSP */
|
||||||
|
/* skip this section because cert is already initialized and parsed */
|
||||||
|
#ifdef WOLFSSL_NONBLOCK_OCSP
|
||||||
|
if (args->lastErr == OCSP_WANT_READ) {
|
||||||
|
args->lastErr = 0; /* clear error */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_TRUST_PEER_CERT
|
||||||
|
/* we have trusted peer */
|
||||||
|
if (args->haveTrustPeer) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* get certificate buffer */
|
||||||
|
cert = &args->certs[args->certIdx];
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SMALL_CERT_VERIFY
|
||||||
|
if (verify == VERIFY) {
|
||||||
|
/* for small cert verify, release decoded cert during signature check to
|
||||||
|
reduce peak memory usage */
|
||||||
|
if (args->dCert != NULL) {
|
||||||
|
if (args->dCertInit) {
|
||||||
|
FreeDecodedCert(args->dCert);
|
||||||
|
args->dCertInit = 0;
|
||||||
|
}
|
||||||
|
XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT);
|
||||||
|
args->dCert = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* perform cert parsing and signature check */
|
||||||
|
sigRet = CheckCertSignature(cert->buffer, cert->length,
|
||||||
|
ssl->heap, ssl->ctx->cm);
|
||||||
|
/* fail on errors here after the ParseCertRelative call, so dCert is populated */
|
||||||
|
|
||||||
|
/* verify name only in ParseCertRelative below, signature check done */
|
||||||
|
verify = VERIFY_NAME;
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSL_SMALL_CERT_VERIFY */
|
||||||
|
|
||||||
|
/* make sure the decoded cert structure is allocated and initialized */
|
||||||
|
if (!args->dCertInit) {
|
||||||
|
#ifdef WOLFSSL_SMALL_CERT_VERIFY
|
||||||
|
if (args->dCert == NULL) {
|
||||||
|
args->dCert = (DecodedCert*)XMALLOC(
|
||||||
|
sizeof(DecodedCert), ssl->heap,
|
||||||
|
DYNAMIC_TYPE_DCERT);
|
||||||
|
if (args->dCert == NULL) {
|
||||||
|
return MEMORY_E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
InitDecodedCert(args->dCert, cert->buffer, cert->length, ssl->heap);
|
||||||
|
|
||||||
|
args->dCertInit = 1;
|
||||||
|
args->dCert->sigCtx.devId = ssl->devId;
|
||||||
|
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||||
|
args->dCert->sigCtx.asyncCtx = ssl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PK_CALLBACKS
|
||||||
|
/* setup the PK callback context */
|
||||||
|
ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse Certificate */
|
||||||
|
ret = ParseCertRelative(args->dCert, certType, verify, ssl->ctx->cm);
|
||||||
|
if (ret == 0) {
|
||||||
|
/* get subject and determine if already loaded */
|
||||||
|
#ifndef NO_SKID
|
||||||
|
if (args->dCert->extAuthKeyIdSet)
|
||||||
|
subjectHash = args->dCert->extSubjKeyId;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
subjectHash = args->dCert->subjectHash;
|
||||||
|
alreadySigner = AlreadySigner(ssl->ctx->cm, subjectHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SMALL_CERT_VERIFY
|
||||||
|
/* get signature check failures from above */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = sigRet;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (pSubjectHash)
|
||||||
|
*pSubjectHash = subjectHash;
|
||||||
|
if (pAlreadySigner)
|
||||||
|
*pAlreadySigner = alreadySigner;
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||||
|
if (ret == WC_PENDING_E) {
|
||||||
|
ret = wolfSSL_AsyncPush(ssl,
|
||||||
|
args->dCert->sigCtx.asyncDev);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check key sizes for certs. Is redundant check since
|
||||||
|
ProcessBuffer also performs this check. */
|
||||||
|
static int ProcessPeerCertCheckKey(WOLFSSL* ssl, ProcPeerCertArgs* args)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (ssl->options.verifyNone) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (args->dCert->keyOID) {
|
||||||
|
#ifndef NO_RSA
|
||||||
|
case RSAk:
|
||||||
|
if (ssl->options.minRsaKeySz < 0 ||
|
||||||
|
args->dCert->pubKeySize <
|
||||||
|
(word16)ssl->options.minRsaKeySz) {
|
||||||
|
WOLFSSL_MSG(
|
||||||
|
"RSA key size in cert chain error");
|
||||||
|
ret = RSA_KEY_SIZE_E;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* !NO_RSA */
|
||||||
|
#ifdef HAVE_ECC
|
||||||
|
case ECDSAk:
|
||||||
|
if (ssl->options.minEccKeySz < 0 ||
|
||||||
|
args->dCert->pubKeySize <
|
||||||
|
(word16)ssl->options.minEccKeySz) {
|
||||||
|
WOLFSSL_MSG(
|
||||||
|
"ECC key size in cert chain error");
|
||||||
|
ret = ECC_KEY_SIZE_E;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* HAVE_ECC */
|
||||||
|
#ifdef HAVE_ED25519
|
||||||
|
case ED25519k:
|
||||||
|
if (ssl->options.minEccKeySz < 0 ||
|
||||||
|
ED25519_KEY_SIZE <
|
||||||
|
(word16)ssl->options.minEccKeySz) {
|
||||||
|
WOLFSSL_MSG(
|
||||||
|
"ECC key size in cert chain error");
|
||||||
|
ret = ECC_KEY_SIZE_E;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* HAVE_ED25519 */
|
||||||
|
default:
|
||||||
|
WOLFSSL_MSG("Key size not checked");
|
||||||
|
/* key not being checked for size if not in
|
||||||
|
switch */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
||||||
word32 totalSz)
|
word32 totalSz)
|
||||||
{
|
{
|
||||||
int ret = 0, sigRet = 0;
|
int ret = 0;
|
||||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||||
ProcPeerCertArgs* args = (ProcPeerCertArgs*)ssl->async.args;
|
ProcPeerCertArgs* args = (ProcPeerCertArgs*)ssl->async.args;
|
||||||
typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
|
typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
|
||||||
@@ -8794,11 +8974,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
#else
|
#else
|
||||||
ProcPeerCertArgs args[1];
|
ProcPeerCertArgs args[1];
|
||||||
#endif
|
#endif
|
||||||
|
byte* subjectHash = NULL;
|
||||||
buffer* cert;
|
int alreadySigner = 0;
|
||||||
#ifdef WOLFSSL_TRUST_PEER_CERT
|
|
||||||
byte haveTrustPeer = 0; /* was cert verified by loaded trusted peer cert */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WOLFSSL_ENTER("ProcessPeerCerts");
|
WOLFSSL_ENTER("ProcessPeerCerts");
|
||||||
|
|
||||||
@@ -8931,6 +9108,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
}
|
}
|
||||||
XMEMSET(args->certs, 0, sizeof(buffer) * MAX_CHAIN_DEPTH);
|
XMEMSET(args->certs, 0, sizeof(buffer) * MAX_CHAIN_DEPTH);
|
||||||
#endif /* OPENSSL_EXTRA */
|
#endif /* OPENSSL_EXTRA */
|
||||||
|
|
||||||
/* Certificate List */
|
/* Certificate List */
|
||||||
if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) {
|
if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) {
|
||||||
ERROR_OUT(BUFFER_ERROR, exit_ppc);
|
ERROR_OUT(BUFFER_ERROR, exit_ppc);
|
||||||
@@ -9012,16 +9190,16 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
} /* while (listSz) */
|
} /* while (listSz) */
|
||||||
|
|
||||||
args->count = args->totalCerts;
|
args->count = args->totalCerts;
|
||||||
args->certIdx = 0;
|
args->certIdx = 0; /* select peer cert (first one) */
|
||||||
|
|
||||||
args->dCertInit = 0;
|
args->dCertInit = 0;
|
||||||
#ifndef WOLFSSL_SMALL_CERT_VERIFY
|
#ifndef WOLFSSL_SMALL_CERT_VERIFY
|
||||||
args->dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
|
args->dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
|
||||||
DYNAMIC_TYPE_DCERT);
|
DYNAMIC_TYPE_DCERT);
|
||||||
if (args->dCert == NULL) {
|
if (args->dCert == NULL) {
|
||||||
ERROR_OUT(MEMORY_E, exit_ppc);
|
ERROR_OUT(MEMORY_E, exit_ppc);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Advance state and proceed */
|
/* Advance state and proceed */
|
||||||
ssl->options.asyncState = TLS_ASYNC_BUILD;
|
ssl->options.asyncState = TLS_ASYNC_BUILD;
|
||||||
@@ -9031,343 +9209,129 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
case TLS_ASYNC_BUILD:
|
case TLS_ASYNC_BUILD:
|
||||||
{
|
{
|
||||||
if (args->count > 0) {
|
if (args->count > 0) {
|
||||||
#ifdef WOLFSSL_TRUST_PEER_CERT
|
|
||||||
|
/* check for trusted peer and get untrustedDepth */
|
||||||
|
#if defined(WOLFSSL_TRUST_PEER_CERT) || defined(OPENSSL_EXTRA)
|
||||||
if (args->certIdx == 0) {
|
if (args->certIdx == 0) {
|
||||||
/* if using trusted peer certs check before verify chain
|
#ifdef WOLFSSL_TRUST_PEER_CERT
|
||||||
and CA test */
|
|
||||||
TrustedPeerCert* tp;
|
TrustedPeerCert* tp;
|
||||||
|
int matchType = WC_MATCH_NAME;
|
||||||
cert = &args->certs[args->certIdx];
|
|
||||||
|
|
||||||
if (!args->dCertInit) {
|
|
||||||
#ifdef WOLFSSL_SMALL_CERT_VERIFY
|
|
||||||
if (args->dCert == NULL) {
|
|
||||||
args->dCert = (DecodedCert*)XMALLOC(
|
|
||||||
sizeof(DecodedCert), ssl->heap,
|
|
||||||
DYNAMIC_TYPE_DCERT);
|
|
||||||
if (args->dCert == NULL) {
|
|
||||||
ERROR_OUT(MEMORY_E, exit_ppc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
InitDecodedCert(args->dCert,
|
|
||||||
cert->buffer, cert->length, ssl->heap);
|
|
||||||
args->dCert->sigCtx.devId = ssl->devId; /* setup async dev */
|
|
||||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
|
||||||
args->dCert->sigCtx.asyncCtx = ssl;
|
|
||||||
#endif
|
#endif
|
||||||
args->dCertInit = 1;
|
|
||||||
#ifdef HAVE_PK_CALLBACKS
|
|
||||||
ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
|
|
||||||
if (ret != 0)
|
|
||||||
goto exit_ppc;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = ParseCertRelative(args->dCert, CERT_TYPE, 0,
|
ret = ProcessPeerCertParse(ssl, args, CERT_TYPE, NO_VERIFY,
|
||||||
ssl->ctx->cm);
|
&subjectHash, &alreadySigner);
|
||||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
|
||||||
if (ret == WC_PENDING_E) {
|
|
||||||
ret = wolfSSL_AsyncPush(ssl,
|
|
||||||
args->dCert->sigCtx.asyncDev);
|
|
||||||
goto exit_ppc;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto exit_ppc;
|
goto exit_ppc;
|
||||||
|
|
||||||
|
#ifdef OPENSSL_EXTRA
|
||||||
|
/* Determine untrusted depth */
|
||||||
|
if (!alreadySigner) {
|
||||||
|
args->untrustedDepth = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_TRUST_PEER_CERT
|
||||||
#ifndef NO_SKID
|
#ifndef NO_SKID
|
||||||
if (args->dCert->extAuthKeyIdSet) {
|
if (args->dCert->extAuthKeyIdSet)
|
||||||
tp = GetTrustedPeer(ssl->ctx->cm,
|
matchType = WC_MATCH_SKID;
|
||||||
args->dCert->extSubjKeyId, WC_MATCH_SKID);
|
#endif
|
||||||
}
|
tp = GetTrustedPeer(ssl->ctx->cm, subjectHash, matchType);
|
||||||
else { /* if the cert has no SKID try to match by name */
|
|
||||||
tp = GetTrustedPeer(ssl->ctx->cm,
|
|
||||||
args->dCert->subjectHash, WC_MATCH_NAME);
|
|
||||||
}
|
|
||||||
#else /* NO_SKID */
|
|
||||||
tp = GetTrustedPeer(ssl->ctx->cm, args->dCert->subjectHash,
|
|
||||||
WC_MATCH_NAME);
|
|
||||||
#endif /* NO SKID */
|
|
||||||
WOLFSSL_MSG("Checking for trusted peer cert");
|
WOLFSSL_MSG("Checking for trusted peer cert");
|
||||||
|
|
||||||
if (tp == NULL) {
|
if (tp && MatchTrustedPeer(tp, args->dCert)) {
|
||||||
/* no trusted peer cert */
|
|
||||||
WOLFSSL_MSG("No matching trusted peer cert. "
|
|
||||||
"Checking CAs");
|
|
||||||
FreeDecodedCert(args->dCert);
|
|
||||||
args->dCertInit = 0;
|
|
||||||
#ifdef OPENSSL_EXTRA
|
|
||||||
args->untrustedDepth = 1;
|
|
||||||
#endif
|
|
||||||
} else if (MatchTrustedPeer(tp, args->dCert)){
|
|
||||||
WOLFSSL_MSG("Found matching trusted peer cert");
|
WOLFSSL_MSG("Found matching trusted peer cert");
|
||||||
haveTrustPeer = 1;
|
args->haveTrustPeer = 1;
|
||||||
} else {
|
}
|
||||||
|
else if (tp == NULL) {
|
||||||
|
/* no trusted peer cert */
|
||||||
|
WOLFSSL_MSG("No matching trusted peer cert. Checking CAs");
|
||||||
|
}
|
||||||
|
else {
|
||||||
WOLFSSL_MSG("Trusted peer cert did not match!");
|
WOLFSSL_MSG("Trusted peer cert did not match!");
|
||||||
FreeDecodedCert(args->dCert);
|
}
|
||||||
args->dCertInit = 0;
|
if (!args->haveTrustPeer)
|
||||||
#ifdef OPENSSL_EXTRA
|
|
||||||
args->untrustedDepth = 1;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
{
|
||||||
}
|
/* free cert if not trusted peer */
|
||||||
#endif /* WOLFSSL_TRUST_PEER_CERT */
|
|
||||||
#ifdef OPENSSL_EXTRA
|
|
||||||
#ifdef WOLFSSL_TRUST_PEER_CERT
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (args->certIdx == 0) {
|
|
||||||
byte* subjectHash;
|
|
||||||
cert = &args->certs[args->certIdx];
|
|
||||||
|
|
||||||
if (!args->dCertInit) {
|
|
||||||
#ifdef WOLFSSL_SMALL_CERT_VERIFY
|
|
||||||
if (args->dCert == NULL) {
|
|
||||||
args->dCert = (DecodedCert*)XMALLOC(
|
|
||||||
sizeof(DecodedCert), ssl->heap,
|
|
||||||
DYNAMIC_TYPE_DCERT);
|
|
||||||
if (args->dCert == NULL) {
|
|
||||||
ERROR_OUT(MEMORY_E, exit_ppc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
InitDecodedCert(args->dCert,
|
|
||||||
cert->buffer, cert->length, ssl->heap);
|
|
||||||
args->dCert->sigCtx.devId = ssl->devId;
|
|
||||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
|
||||||
args->dCert->sigCtx.asyncCtx = ssl;
|
|
||||||
#endif
|
|
||||||
args->dCertInit = 1;
|
|
||||||
#ifdef HAVE_PK_CALLBACKS
|
|
||||||
ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
|
|
||||||
if (ret != 0)
|
|
||||||
goto exit_ppc;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = ParseCertRelative(args->dCert, CERT_TYPE, 0,
|
|
||||||
ssl->ctx->cm);
|
|
||||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
|
||||||
if (ret == WC_PENDING_E) {
|
|
||||||
ret = wolfSSL_AsyncPush(ssl,
|
|
||||||
args->dCert->sigCtx.asyncDev);
|
|
||||||
goto exit_ppc;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (ret != 0) {
|
|
||||||
goto exit_ppc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NO_SKID
|
|
||||||
subjectHash = args->dCert->extSubjKeyId;
|
|
||||||
#else
|
|
||||||
subjectHash = args->dCert->subjectHash;
|
|
||||||
#endif
|
|
||||||
if (!AlreadySigner(ssl->ctx->cm, subjectHash))
|
|
||||||
args->untrustedDepth = 1;
|
|
||||||
|
|
||||||
FreeDecodedCert(args->dCert);
|
FreeDecodedCert(args->dCert);
|
||||||
args->dCertInit = 0;
|
args->dCertInit = 0;
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
|
#endif /* WOLFSSL_TRUST_PEER_CERT || OPENSSL_EXTRA */
|
||||||
|
|
||||||
/* verify up to peer's first */
|
/* check certificate up to peer's first */
|
||||||
/* do not verify chain if trusted peer cert found */
|
/* do not verify chain if trusted peer cert found */
|
||||||
while (args->count > 1
|
while (args->count > 1
|
||||||
#ifdef WOLFSSL_TRUST_PEER_CERT
|
#ifdef WOLFSSL_TRUST_PEER_CERT
|
||||||
&& !haveTrustPeer
|
&& !args->haveTrustPeer
|
||||||
#endif /* WOLFSSL_TRUST_PEER_CERT */
|
#endif /* WOLFSSL_TRUST_PEER_CERT */
|
||||||
) {
|
) {
|
||||||
byte *subjectHash;
|
/* select last certificate */
|
||||||
|
|
||||||
args->certIdx = args->count - 1;
|
args->certIdx = args->count - 1;
|
||||||
cert = &args->certs[args->certIdx];
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_SMALL_CERT_VERIFY
|
ret = ProcessPeerCertParse(ssl, args, CERT_TYPE,
|
||||||
sigRet = 0;
|
!ssl->options.verifyNone ? VERIFY : NO_VERIFY,
|
||||||
|
&subjectHash, &alreadySigner);
|
||||||
if (!ssl->options.verifyNone) {
|
|
||||||
if (args->dCert != NULL) {
|
|
||||||
if (args->dCertInit) {
|
|
||||||
FreeDecodedCert(args->dCert);
|
|
||||||
args->dCertInit = 0;
|
|
||||||
}
|
|
||||||
XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT);
|
|
||||||
args->dCert = NULL;
|
|
||||||
}
|
|
||||||
sigRet = CheckCertSignature(cert->buffer, cert->length,
|
|
||||||
ssl->heap, ssl->ctx->cm);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (!args->dCertInit) {
|
|
||||||
#ifdef WOLFSSL_SMALL_CERT_VERIFY
|
|
||||||
if (args->dCert == NULL) {
|
|
||||||
args->dCert = (DecodedCert*)XMALLOC(
|
|
||||||
sizeof(DecodedCert), ssl->heap,
|
|
||||||
DYNAMIC_TYPE_DCERT);
|
|
||||||
if (args->dCert == NULL) {
|
|
||||||
ERROR_OUT(MEMORY_E, exit_ppc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
InitDecodedCert(args->dCert,
|
|
||||||
cert->buffer, cert->length, ssl->heap);
|
|
||||||
args->dCert->sigCtx.devId = ssl->devId; /* setup async dev */
|
|
||||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||||
args->dCert->sigCtx.asyncCtx = ssl;
|
if (ret == WC_PENDING_E)
|
||||||
#endif
|
|
||||||
args->dCertInit = 1;
|
|
||||||
#ifdef HAVE_PK_CALLBACKS
|
|
||||||
ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
|
|
||||||
if (ret != 0)
|
|
||||||
goto exit_ppc;
|
goto exit_ppc;
|
||||||
#endif
|
#endif
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = ProcessPeerCertCheckKey(ssl, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if returning from non-blocking OCSP */
|
if (ret == 0 && args->dCert->isCA == 0) {
|
||||||
#ifdef WOLFSSL_NONBLOCK_OCSP
|
|
||||||
if (args->lastErr != OCSP_WANT_READ)
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef WOLFSSL_SMALL_CERT_VERIFY
|
|
||||||
sigRet = ParseCertRelative(args->dCert, CERT_TYPE,
|
|
||||||
!ssl->options.verifyNone, ssl->ctx->cm);
|
|
||||||
#else
|
|
||||||
ret = ParseCertRelative(args->dCert, CERT_TYPE,
|
|
||||||
!ssl->options.verifyNone ? VERIFY_NAME : NO_VERIFY,
|
|
||||||
ssl->ctx->cm);
|
|
||||||
if (ret != 0) {
|
|
||||||
sigRet = ret;
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
|
||||||
if (sigRet == WC_PENDING_E) {
|
|
||||||
ret = wolfSSL_AsyncPush(ssl,
|
|
||||||
args->dCert->sigCtx.asyncDev);
|
|
||||||
goto exit_ppc;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NO_SKID
|
|
||||||
subjectHash = args->dCert->extSubjKeyId;
|
|
||||||
#else
|
|
||||||
subjectHash = args->dCert->subjectHash;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check key sizes for certs. Is redundent check since
|
|
||||||
ProcessBuffer also performs this check. */
|
|
||||||
if (!ssl->options.verifyNone) {
|
|
||||||
switch (args->dCert->keyOID) {
|
|
||||||
#ifndef NO_RSA
|
|
||||||
case RSAk:
|
|
||||||
if (ssl->options.minRsaKeySz < 0 ||
|
|
||||||
args->dCert->pubKeySize <
|
|
||||||
(word16)ssl->options.minRsaKeySz) {
|
|
||||||
WOLFSSL_MSG(
|
|
||||||
"RSA key size in cert chain error");
|
|
||||||
sigRet = RSA_KEY_SIZE_E;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif /* !NO_RSA */
|
|
||||||
#ifdef HAVE_ECC
|
|
||||||
case ECDSAk:
|
|
||||||
if (ssl->options.minEccKeySz < 0 ||
|
|
||||||
args->dCert->pubKeySize <
|
|
||||||
(word16)ssl->options.minEccKeySz) {
|
|
||||||
WOLFSSL_MSG(
|
|
||||||
"ECC key size in cert chain error");
|
|
||||||
sigRet = ECC_KEY_SIZE_E;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif /* HAVE_ECC */
|
|
||||||
#ifdef HAVE_ED25519
|
|
||||||
case ED25519k:
|
|
||||||
if (ssl->options.minEccKeySz < 0 ||
|
|
||||||
ED25519_KEY_SIZE <
|
|
||||||
(word16)ssl->options.minEccKeySz) {
|
|
||||||
WOLFSSL_MSG(
|
|
||||||
"ECC key size in cert chain error");
|
|
||||||
sigRet = ECC_KEY_SIZE_E;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif /* HAVE_ED25519 */
|
|
||||||
default:
|
|
||||||
WOLFSSL_MSG("Key size not checked");
|
|
||||||
/* key not being checked for size if not in
|
|
||||||
switch */
|
|
||||||
break;
|
|
||||||
} /* switch (dCert->keyOID) */
|
|
||||||
} /* if (!ssl->options.verifyNone) */
|
|
||||||
|
|
||||||
if (sigRet == 0 && args->dCert->isCA == 0) {
|
|
||||||
WOLFSSL_MSG("Chain cert is not a CA, not adding as one");
|
WOLFSSL_MSG("Chain cert is not a CA, not adding as one");
|
||||||
}
|
}
|
||||||
else if (sigRet == 0 && ssl->options.verifyNone) {
|
else if (ret == 0 && ssl->options.verifyNone) {
|
||||||
WOLFSSL_MSG("Chain cert not verified by option, not adding as CA");
|
WOLFSSL_MSG("Chain cert not verified by option, "
|
||||||
|
"not adding as CA");
|
||||||
}
|
}
|
||||||
else if (sigRet == 0 && !AlreadySigner(ssl->ctx->cm, subjectHash)) {
|
else if (ret == 0) {
|
||||||
|
buffer* cert = &args->certs[args->certIdx];
|
||||||
|
|
||||||
|
/* Is valid CA */
|
||||||
|
#if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS)
|
||||||
|
/* if using alternate chain, store the cert used */
|
||||||
|
if (ssl->options.usingAltCertChain) {
|
||||||
|
AddSessionCertToChain(&ssl->session.altChain,
|
||||||
|
cert->buffer, cert->length);
|
||||||
|
}
|
||||||
|
#endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */
|
||||||
|
#ifdef OPENSSL_EXTRA
|
||||||
|
if (args->certIdx > args->untrustedDepth) {
|
||||||
|
args->untrustedDepth = (char)args->certIdx + 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!alreadySigner) {
|
||||||
DerBuffer* add = NULL;
|
DerBuffer* add = NULL;
|
||||||
ret = AllocDer(&add, cert->length, CA_TYPE, ssl->heap);
|
ret = AllocDer(&add, cert->length, CA_TYPE, ssl->heap);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto exit_ppc;
|
goto exit_ppc;
|
||||||
|
|
||||||
WOLFSSL_MSG("Adding CA from chain");
|
|
||||||
|
|
||||||
XMEMCPY(add->buffer, cert->buffer, cert->length);
|
XMEMCPY(add->buffer, cert->buffer, cert->length);
|
||||||
|
|
||||||
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX)
|
/* CA already verified above in ParseCertRelative */
|
||||||
if (args->certIdx > args->untrustedDepth)
|
WOLFSSL_MSG("Adding CA from chain");
|
||||||
args->untrustedDepth = (char)args->certIdx + 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* already verified above */
|
|
||||||
ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA, 0);
|
ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA, 0);
|
||||||
if (ret == 1) {
|
if (ret == WOLFSSL_SUCCESS) {
|
||||||
ret = 0; /* WOLFSSL_SUCCESS for external */
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WOLFSSL_ALT_CERT_CHAINS
|
|
||||||
/* if the previous CA cert failed, clear last error */
|
|
||||||
if (args->lastCaErr != 0) {
|
|
||||||
WOLFSSL_MSG("Using alternate cert chain");
|
|
||||||
ssl->options.usingAltCertChain = 1;
|
|
||||||
|
|
||||||
/* clear last CA fail since CA cert was validated */
|
|
||||||
if (!args->verifyErr)
|
|
||||||
args->lastCaErr = 0;
|
|
||||||
|
|
||||||
#ifdef SESSION_CERTS
|
|
||||||
AddSessionCertToChain(&ssl->session.altChain,
|
|
||||||
cert->buffer, cert->length);
|
|
||||||
#endif /* SESSION_CERTS */
|
|
||||||
}
|
}
|
||||||
#endif
|
else {
|
||||||
|
WOLFSSL_MSG("Verified CA from chain and already had it");
|
||||||
}
|
}
|
||||||
else if (sigRet != 0) {
|
}
|
||||||
|
else {
|
||||||
WOLFSSL_MSG("Failed to verify CA from chain");
|
WOLFSSL_MSG("Failed to verify CA from chain");
|
||||||
#ifdef OPENSSL_EXTRA
|
#ifdef OPENSSL_EXTRA
|
||||||
ssl->peerVerifyRet = X509_V_ERR_INVALID_CA;
|
ssl->peerVerifyRet = X509_V_ERR_INVALID_CA;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
WOLFSSL_MSG("Verified CA from chain and already had it");
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_NONBLOCK_OCSP
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
args->lastErr = 0; /* clear last error */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(HAVE_OCSP) || defined(HAVE_CRL)
|
#if defined(HAVE_OCSP) || defined(HAVE_CRL)
|
||||||
if (ret == 0 && sigRet == 0) {
|
if (ret == 0) {
|
||||||
int doCrlLookup = 1;
|
int doCrlLookup = 1;
|
||||||
#ifdef HAVE_OCSP
|
#ifdef HAVE_OCSP
|
||||||
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
|
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
|
||||||
@@ -9414,39 +9378,41 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_CRL */
|
#endif /* HAVE_CRL */
|
||||||
(void)doCrlLookup;
|
(void)doCrlLookup;
|
||||||
|
|
||||||
if (ret != 0)
|
|
||||||
sigRet = ret;
|
|
||||||
}
|
}
|
||||||
#endif /* HAVE_OCSP || HAVE_CRL */
|
#endif /* HAVE_OCSP || HAVE_CRL */
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_ALT_CERT_CHAINS
|
||||||
|
/* For alternate cert chain, its okay for a CA cert to fail
|
||||||
|
with ASN_NO_SIGNER_E here. The "alternate" certificate
|
||||||
|
chain mode only requires that the peer certificate
|
||||||
|
validate to a trusted CA */
|
||||||
|
if (ret != 0) {
|
||||||
|
if (ret == ASN_NO_SIGNER_E) {
|
||||||
|
if (!ssl->options.usingAltCertChain) {
|
||||||
|
WOLFSSL_MSG("Trying alternate cert chain");
|
||||||
|
ssl->options.usingAltCertChain = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0; /* clear error and continue */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSL_ALT_CERT_CHAINS */
|
||||||
|
|
||||||
/* Do verify callback */
|
/* Do verify callback */
|
||||||
sigRet = DoVerifyCallback(ssl, sigRet, args);
|
ret = DoVerifyCallback(ssl, ret, args);
|
||||||
|
|
||||||
/* Handle error codes */
|
/* Handle error codes */
|
||||||
#ifdef WOLFSSL_ALT_CERT_CHAINS
|
if (ret != 0 && args->lastErr == 0) {
|
||||||
if (args->lastCaErr == 0) {
|
args->lastErr = ret; /* save error from last time */
|
||||||
/* capture CA error and proceed to next cert */
|
ret = 0; /* reset error */
|
||||||
args->lastCaErr = sigRet;
|
|
||||||
sigRet = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
args->lastErr = args->lastCaErr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (sigRet != 0 && args->lastErr == 0) {
|
|
||||||
args->lastErr = sigRet; /* save error from last time */
|
|
||||||
sigRet = 0; /* reset error */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeDecodedCert(args->dCert);
|
FreeDecodedCert(args->dCert);
|
||||||
args->dCertInit = 0;
|
args->dCertInit = 0;
|
||||||
args->count--;
|
args->count--;
|
||||||
} /* while (count > 0 && !haveTrustPeer) */
|
} /* while (count > 0 && !args->haveTrustPeer) */
|
||||||
} /* if (count > 0) */
|
} /* if (count > 0) */
|
||||||
|
|
||||||
if (sigRet != 0)
|
|
||||||
ret = sigRet;
|
|
||||||
/* Check for error */
|
/* Check for error */
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
goto exit_ppc;
|
goto exit_ppc;
|
||||||
@@ -9463,81 +9429,25 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
if (args->count > 0) {
|
if (args->count > 0) {
|
||||||
WOLFSSL_MSG("Verifying Peer's cert");
|
WOLFSSL_MSG("Verifying Peer's cert");
|
||||||
|
|
||||||
|
/* select peer cert (first one) */
|
||||||
args->certIdx = 0;
|
args->certIdx = 0;
|
||||||
cert = &args->certs[args->certIdx];
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_SMALL_CERT_VERIFY
|
ret = ProcessPeerCertParse(ssl, args, CERT_TYPE,
|
||||||
sigRet = 0;
|
!ssl->options.verifyNone ? VERIFY : NO_VERIFY,
|
||||||
|
&subjectHash, &alreadySigner);
|
||||||
if (!ssl->options.verifyNone) {
|
|
||||||
if (args->dCert != NULL) {
|
|
||||||
if (args->dCertInit) {
|
|
||||||
FreeDecodedCert(args->dCert);
|
|
||||||
args->dCertInit = 0;
|
|
||||||
}
|
|
||||||
XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT);
|
|
||||||
args->dCert = NULL;
|
|
||||||
}
|
|
||||||
sigRet = CheckCertSignature(cert->buffer, cert->length,
|
|
||||||
ssl->heap, ssl->ctx->cm);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (!args->dCertInit) {
|
|
||||||
if (args->dCert == NULL) {
|
|
||||||
args->dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert),
|
|
||||||
ssl->heap, DYNAMIC_TYPE_DCERT);
|
|
||||||
if (args->dCert == NULL) {
|
|
||||||
ERROR_OUT(MEMORY_E, exit_ppc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InitDecodedCert(args->dCert,
|
|
||||||
cert->buffer, cert->length, ssl->heap);
|
|
||||||
args->dCert->sigCtx.devId = ssl->devId; /* setup async dev */
|
|
||||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||||
args->dCert->sigCtx.asyncCtx = ssl;
|
if (ret == WC_PENDING_E)
|
||||||
#endif
|
|
||||||
args->dCertInit = 1;
|
|
||||||
#ifdef HAVE_PK_CALLBACKS
|
|
||||||
ret = InitSigPkCb(ssl, &args->dCert->sigCtx);
|
|
||||||
if (ret != 0)
|
|
||||||
goto exit_ppc;
|
goto exit_ppc;
|
||||||
#endif
|
#endif
|
||||||
}
|
if (ret == 0) {
|
||||||
|
|
||||||
#ifdef WOLFSSL_TRUST_PEER_CERT
|
|
||||||
if (!haveTrustPeer)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
/* only parse if not already present in dCert from above */
|
|
||||||
#ifndef WOLFSSL_SMALL_CERT_VERIFY
|
|
||||||
sigRet = ParseCertRelative(args->dCert, CERT_TYPE,
|
|
||||||
!ssl->options.verifyNone, ssl->ctx->cm);
|
|
||||||
#else
|
|
||||||
ret = ParseCertRelative(args->dCert, CERT_TYPE,
|
|
||||||
!ssl->options.verifyNone ? VERIFY_NAME : NO_VERIFY,
|
|
||||||
ssl->ctx->cm);
|
|
||||||
if (ret != 0) {
|
|
||||||
sigRet = ret;
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
|
||||||
if (sigRet == WC_PENDING_E) {
|
|
||||||
ret = wolfSSL_AsyncPush(ssl,
|
|
||||||
args->dCert->sigCtx.asyncDev);
|
|
||||||
goto exit_ppc;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sigRet == 0) {
|
|
||||||
WOLFSSL_MSG("Verified Peer's cert");
|
WOLFSSL_MSG("Verified Peer's cert");
|
||||||
#ifdef OPENSSL_EXTRA
|
#ifdef OPENSSL_EXTRA
|
||||||
ssl->peerVerifyRet = X509_V_OK;
|
ssl->peerVerifyRet = X509_V_OK;
|
||||||
#endif
|
#endif
|
||||||
#if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS)
|
#if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS)
|
||||||
|
/* if using alternate chain, store the cert used */
|
||||||
if (ssl->options.usingAltCertChain) {
|
if (ssl->options.usingAltCertChain) {
|
||||||
|
buffer* cert = &args->certs[args->certIdx];
|
||||||
AddSessionCertToChain(&ssl->session.altChain,
|
AddSessionCertToChain(&ssl->session.altChain,
|
||||||
cert->buffer, cert->length);
|
cert->buffer, cert->length);
|
||||||
}
|
}
|
||||||
@@ -9546,20 +9456,15 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
/* check if fatal error */
|
/* check if fatal error */
|
||||||
if (args->verifyErr) {
|
if (args->verifyErr) {
|
||||||
args->fatal = 1;
|
args->fatal = 1;
|
||||||
if (sigRet == 0) {
|
if (ret == 0) {
|
||||||
sigRet = args->lastErr;
|
ret = args->lastErr;
|
||||||
}
|
}
|
||||||
#ifdef WOLFSSL_ALT_CERT_CHAINS
|
|
||||||
if (sigRet == 0) {
|
|
||||||
sigRet = args->lastCaErr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
args->fatal = 0;
|
args->fatal = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sigRet == ASN_PARSE_E || sigRet == BUFFER_E) {
|
else if (ret == ASN_PARSE_E || ret == BUFFER_E) {
|
||||||
WOLFSSL_MSG("Got Peer cert ASN PARSE or BUFFER ERROR");
|
WOLFSSL_MSG("Got Peer cert ASN PARSE or BUFFER ERROR");
|
||||||
#ifdef OPENSSL_EXTRA
|
#ifdef OPENSSL_EXTRA
|
||||||
SendAlert(ssl, alert_fatal, bad_certificate);
|
SendAlert(ssl, alert_fatal, bad_certificate);
|
||||||
@@ -9599,7 +9504,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
WOLFSSL_MSG(
|
WOLFSSL_MSG(
|
||||||
"Peer sent different cert during scr, fatal");
|
"Peer sent different cert during scr, fatal");
|
||||||
args->fatal = 1;
|
args->fatal = 1;
|
||||||
sigRet = SCR_DIFFERENT_CERT_E;
|
ret = SCR_DIFFERENT_CERT_E;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9612,8 +9517,6 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
#endif /* HAVE_SECURE_RENEGOTIATION */
|
#endif /* HAVE_SECURE_RENEGOTIATION */
|
||||||
} /* if (count > 0) */
|
} /* if (count > 0) */
|
||||||
|
|
||||||
if (sigRet != 0)
|
|
||||||
ret = sigRet;
|
|
||||||
/* Check for error */
|
/* Check for error */
|
||||||
if (args->fatal && ret != 0) {
|
if (args->fatal && ret != 0) {
|
||||||
goto exit_ppc;
|
goto exit_ppc;
|
||||||
@@ -10017,7 +9920,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
ret = args->lastErr;
|
ret = args->lastErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OPENSSL_EXTRA
|
#if defined(OPENSSL_EXTRA)
|
||||||
if (args->untrustedDepth > ssl->options.verifyDepth) {
|
if (args->untrustedDepth > ssl->options.verifyDepth) {
|
||||||
ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG;
|
ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG;
|
||||||
ret = MAX_CHAIN_ERROR;
|
ret = MAX_CHAIN_ERROR;
|
||||||
@@ -22151,7 +22054,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Signtaure length will be written later, when we're sure what it is */
|
/* Signature length will be written later, when we're sure what it is */
|
||||||
|
|
||||||
#ifdef HAVE_FUZZER
|
#ifdef HAVE_FUZZER
|
||||||
if (ssl->fuzzerCb) {
|
if (ssl->fuzzerCb) {
|
||||||
|
@@ -44,8 +44,6 @@ ASN Options:
|
|||||||
Only enabled for OCSP.
|
Only enabled for OCSP.
|
||||||
* WOLFSSL_NO_OCSP_ISSUER_CHECK: Can be defined for backwards compatibility to
|
* WOLFSSL_NO_OCSP_ISSUER_CHECK: Can be defined for backwards compatibility to
|
||||||
disable checking of OCSP subject hash with issuer hash.
|
disable checking of OCSP subject hash with issuer hash.
|
||||||
* WOLFSSL_ALT_CERT_CHAINS: Allows matching multiple CA's to validate
|
|
||||||
chain based on issuer and public key (includes signature confirmation)
|
|
||||||
* WOLFSSL_SMALL_CERT_VERIFY: Verify the certificate signature without using
|
* WOLFSSL_SMALL_CERT_VERIFY: Verify the certificate signature without using
|
||||||
DecodedCert. Doubles up on some code but allows smaller dynamic memory
|
DecodedCert. Doubles up on some code but allows smaller dynamic memory
|
||||||
usage.
|
usage.
|
||||||
@@ -4223,6 +4221,8 @@ void FreeNameSubtrees(Base_entry* names, void* heap)
|
|||||||
|
|
||||||
void FreeDecodedCert(DecodedCert* cert)
|
void FreeDecodedCert(DecodedCert* cert)
|
||||||
{
|
{
|
||||||
|
if (cert == NULL)
|
||||||
|
return;
|
||||||
if (cert->subjectCNStored == 1)
|
if (cert->subjectCNStored == 1)
|
||||||
XFREE(cert->subjectCN, cert->heap, DYNAMIC_TYPE_SUBJECT_CN);
|
XFREE(cert->subjectCN, cert->heap, DYNAMIC_TYPE_SUBJECT_CN);
|
||||||
if (cert->pubKeyStored == 1)
|
if (cert->pubKeyStored == 1)
|
||||||
@@ -5385,7 +5385,7 @@ int ValidateDate(const byte* date, byte format, int dateType)
|
|||||||
GetTime(&diffMM, date, &i);
|
GetTime(&diffMM, date, &i);
|
||||||
timeDiff = diffSign * (diffHH*60 + diffMM) * 60 ;
|
timeDiff = diffSign * (diffHH*60 + diffMM) * 60 ;
|
||||||
} else if (date[i] != 'Z') {
|
} else if (date[i] != 'Z') {
|
||||||
WOLFSSL_MSG("UTCtime, niether Zulu or time differential") ;
|
WOLFSSL_MSG("UTCtime, neither Zulu or time differential") ;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5614,6 +5614,11 @@ int DecodeToKey(DecodedCert* cert, int verify)
|
|||||||
|
|
||||||
WOLFSSL_MSG("Got Subject Name");
|
WOLFSSL_MSG("Got Subject Name");
|
||||||
|
|
||||||
|
/* Determine if self signed */
|
||||||
|
cert->selfSigned = XMEMCMP(cert->issuerHash,
|
||||||
|
cert->subjectHash,
|
||||||
|
KEYID_SIZE) == 0 ? 1 : 0;
|
||||||
|
|
||||||
if ( (ret = GetKey(cert)) < 0)
|
if ( (ret = GetKey(cert)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -7664,8 +7669,7 @@ Signer* GetCAByName(void* signers, byte* hash)
|
|||||||
|
|
||||||
#endif /* WOLFCRYPT_ONLY || NO_CERTS */
|
#endif /* WOLFCRYPT_ONLY || NO_CERTS */
|
||||||
|
|
||||||
#if (defined(WOLFSSL_ALT_CERT_CHAINS) || \
|
#if defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY) && !defined(NO_SKID)
|
||||||
defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY)) && !defined(NO_SKID)
|
|
||||||
static Signer* GetCABySubjectAndPubKey(DecodedCert* cert, void* cm)
|
static Signer* GetCABySubjectAndPubKey(DecodedCert* cert, void* cm)
|
||||||
{
|
{
|
||||||
Signer* ca = NULL;
|
Signer* ca = NULL;
|
||||||
@@ -7955,7 +7959,6 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
|
|||||||
int badDate = 0;
|
int badDate = 0;
|
||||||
int criticalExt = 0;
|
int criticalExt = 0;
|
||||||
word32 confirmOID;
|
word32 confirmOID;
|
||||||
int selfSigned = 0;
|
|
||||||
|
|
||||||
if (cert == NULL) {
|
if (cert == NULL) {
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
@@ -8033,34 +8036,29 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WOLFSSL_NO_TRUSTED_CERTS_VERIFY */
|
#endif /* WOLFSSL_NO_TRUSTED_CERTS_VERIFY */
|
||||||
|
|
||||||
/* alt lookup using subject and public key */
|
|
||||||
#ifdef WOLFSSL_ALT_CERT_CHAINS
|
|
||||||
if (cert->ca == NULL)
|
|
||||||
cert->ca = GetCABySubjectAndPubKey(cert, cm);
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
cert->ca = GetCA(cm, cert->issuerHash);
|
cert->ca = GetCA(cm, cert->issuerHash);
|
||||||
if (XMEMCMP(cert->issuerHash, cert->subjectHash, KEYID_SIZE) == 0)
|
|
||||||
selfSigned = 1;
|
|
||||||
#endif /* !NO_SKID */
|
#endif /* !NO_SKID */
|
||||||
|
|
||||||
WOLFSSL_MSG("About to verify certificate signature");
|
WOLFSSL_MSG("About to verify certificate signature");
|
||||||
|
|
||||||
if (cert->ca) {
|
if (cert->ca) {
|
||||||
|
/* Check if cert is CA type and has path length set */
|
||||||
if (cert->isCA && cert->ca->pathLengthSet) {
|
if (cert->isCA && cert->ca->pathLengthSet) {
|
||||||
if (selfSigned) {
|
/* Check root CA (self-signed) has path length > 0 */
|
||||||
|
if (cert->selfSigned) {
|
||||||
if (cert->ca->pathLength != 0) {
|
if (cert->ca->pathLength != 0) {
|
||||||
WOLFSSL_MSG("Root CA with path length > 0");
|
WOLFSSL_MSG("Root CA with path length > 0");
|
||||||
return ASN_PATHLEN_INV_E;
|
return ASN_PATHLEN_INV_E;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
/* Check path lengths are valid between two CA's */
|
||||||
if (cert->ca->pathLength == 0) {
|
if (cert->ca->pathLength == 0) {
|
||||||
WOLFSSL_MSG("CA with path length 0 signing a CA");
|
WOLFSSL_MSG("CA with path length 0 signing a CA");
|
||||||
return ASN_PATHLEN_INV_E;
|
return ASN_PATHLEN_INV_E;
|
||||||
}
|
}
|
||||||
else if (cert->pathLength >= cert->ca->pathLength) {
|
else if (cert->pathLength >= cert->ca->pathLength) {
|
||||||
|
|
||||||
WOLFSSL_MSG("CA signing CA with longer path length");
|
WOLFSSL_MSG("CA signing CA with longer path length");
|
||||||
return ASN_PATHLEN_INV_E;
|
return ASN_PATHLEN_INV_E;
|
||||||
}
|
}
|
||||||
|
@@ -855,6 +855,7 @@ struct DecodedCert {
|
|||||||
byte extBasicConstSet : 1;
|
byte extBasicConstSet : 1;
|
||||||
byte extSubjAltNameSet : 1;
|
byte extSubjAltNameSet : 1;
|
||||||
byte inhibitAnyOidSet : 1;
|
byte inhibitAnyOidSet : 1;
|
||||||
|
byte selfSigned : 1; /* Indicates subject and issuer are same */
|
||||||
#ifdef WOLFSSL_SEP
|
#ifdef WOLFSSL_SEP
|
||||||
byte extCertPolicySet : 1;
|
byte extCertPolicySet : 1;
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user