Skip to content

Commit

Permalink
Merge pull request wolfSSL#2640 from dgarske/alt_chain
Browse files Browse the repository at this point in the history
Fixes for Alternate chain processing
  • Loading branch information
toddouska committed Dec 18, 2019
2 parents b891212 + b126802 commit 5a04ee0
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 35 deletions.
95 changes: 61 additions & 34 deletions src/internal.c
Expand Up @@ -9374,6 +9374,29 @@ typedef struct ProcPeerCertArgs {
#endif
} ProcPeerCertArgs;

static void DoCertFatalAlert(WOLFSSL* ssl, int ret)
{
int alertWhy;
if (ssl == NULL || ret == 0) {
return;
}

/* Determine alert reason */
alertWhy = bad_certificate;
if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E) {
alertWhy = certificate_expired;
}
#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD))
else if (ret == CRL_CERT_REVOKED) {
alertWhy = certificate_revoked;
}
#endif

/* send fatal alert and mark connection closed */
SendAlert(ssl, alert_fatal, alertWhy); /* try to send */
ssl->options.isClosed = 1;
}

/* WOLFSSL_ALWAYS_VERIFY_CB: Use verify callback for success or failure cases */
/* WOLFSSL_VERIFY_CB_ALL_CERTS: Issue callback for all intermediate certificates */

Expand All @@ -9384,21 +9407,10 @@ typedef struct ProcPeerCertArgs {

static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args)
{
int verify_ok = 0, alertWhy = 0, use_cb = 0;
int verify_ok = 0, use_cb = 0;

/* Determine return code and alert reason */
if (ret != 0) {
alertWhy = bad_certificate;
if (ret == ASN_AFTER_DATE_E ||
ret == ASN_BEFORE_DATE_E) {
alertWhy = certificate_expired;
}
#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD))
else if (ret == CRL_CERT_REVOKED)
alertWhy = certificate_revoked;
#endif
}
else {
/* Determine if verify was okay */
if (ret == 0) {
verify_ok = 1;
}

Expand Down Expand Up @@ -9649,17 +9661,6 @@ static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args)
#endif
}

if (ret != 0) {
if (!ssl->options.verifyNone) {
/* handle failure */
SendAlert(ssl, alert_fatal, alertWhy); /* try to send */
ssl->options.isClosed = 1;
}

/* Report SSL error */
ssl->error = ret;
}

return ret;
}

Expand Down Expand Up @@ -10191,6 +10192,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
&& !args->haveTrustPeer
#endif /* WOLFSSL_TRUST_PEER_CERT */
) {
int skipAddCA = 0;

/* select last certificate */
args->certIdx = args->count - 1;

Expand Down Expand Up @@ -10281,12 +10284,15 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
#endif /* HAVE_OCSP || HAVE_CRL */

/* Do verify callback */
ret = DoVerifyCallback(ssl, ret, args);

#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 != 0 && args->dCert->isCA) {
if (ret == ASN_NO_SIGNER_E) {
if (!ssl->options.usingAltCertChain) {
WOLFSSL_MSG("Trying alternate cert chain");
Expand All @@ -10295,14 +10301,15 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,

ret = 0; /* clear error and continue */
}

/* do not add to certificate manager */
skipAddCA = 1;
}
#endif /* WOLFSSL_ALT_CERT_CHAINS */

/* Do verify callback */
ret = DoVerifyCallback(ssl, ret, args);

/* If valid CA then add to Certificate Manager */
if (ret == 0 && args->dCert->isCA && !ssl->options.verifyNone) {
if (ret == 0 && args->dCert->isCA &&
!ssl->options.verifyNone && !skipAddCA) {
buffer* cert = &args->certs[args->certIdx];

/* Is valid CA */
Expand Down Expand Up @@ -10332,9 +10339,16 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}

/* Handle error codes */
if (ret != 0 && args->lastErr == 0) {
args->lastErr = ret; /* save error from last time */
ret = 0; /* reset error */
if (ret != 0) {
if (!ssl->options.verifyNone) {
DoCertFatalAlert(ssl, ret);
}
ssl->error = ret; /* Report SSL error */

if (args->lastErr == 0) {
args->lastErr = ret; /* save error from last time */
ret = 0; /* reset error */
}
}

FreeDecodedCert(args->dCert);
Expand Down Expand Up @@ -10906,6 +10920,13 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ret = ssl->error = 0;
}

if (ret != 0) {
if (!ssl->options.verifyNone) {
DoCertFatalAlert(ssl, ret);
}
ssl->error = ret; /* Report SSL error */
}

if (ret == 0 && ssl->options.side == WOLFSSL_CLIENT_END) {
ssl->options.serverState = SERVER_CERT_COMPLETE;
}
Expand Down Expand Up @@ -16776,6 +16797,8 @@ int SendAlert(WOLFSSL* ssl, int severity, int type)
int outputSz;
int dtlsExtra = 0;

WOLFSSL_ENTER("SendAlert");

#ifdef HAVE_WRITE_DUP
if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) {
int notifyErr = 0;
Expand Down Expand Up @@ -16872,7 +16895,11 @@ int SendAlert(WOLFSSL* ssl, int severity, int type)
ssl->buffers.outputBuffer.length += sendSz;
ssl->options.sendAlertState = 1;

return SendBuffered(ssl);
ret = SendBuffered(ssl);

WOLFSSL_LEAVE("SendAlert", ret);

return ret;
}

const char* wolfSSL_ERR_reason_error_string(unsigned long e)
Expand Down
2 changes: 1 addition & 1 deletion src/ssl.c
Expand Up @@ -4815,7 +4815,7 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
}
#ifndef ALLOW_INVALID_CERTSIGN
else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA &&
(cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) {
!cert->selfSigned && (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) {
/* Intermediate CA certs are required to have the keyCertSign
* extension set. User loaded root certs are not. */
WOLFSSL_MSG("\tDoesn't have key usage certificate signing");
Expand Down

0 comments on commit 5a04ee0

Please sign in to comment.