From 980970da868847db46ef7335583aed1f5179a60a Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 4 Mar 2019 11:27:51 -0800 Subject: [PATCH 1/2] Fixes issue with CA path length basic constraint checking for self signed root CA's. ZD 4863 --- src/ssl.c | 1 + wolfcrypt/src/asn.c | 16 +++++++++++----- wolfssl/wolfcrypt/asn.h | 3 ++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index abe0790af..4a640971e 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -4218,6 +4218,7 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) } signer->pathLength = cert->pathLength; signer->pathLengthSet = cert->pathLengthSet; + signer->selfSigned = cert->selfSigned; #ifndef IGNORE_NAME_CONSTRAINTS signer->permittedNames = cert->permittedNames; signer->excludedNames = cert->excludedNames; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 82db202bd..06f0675b2 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -8099,16 +8099,22 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) WOLFSSL_MSG("About to verify certificate signature"); if (cert->ca) { - /* Check if cert is CA type and has path length set */ + /* Check if cert is CA type and signer has path length set */ if (cert->isCA && cert->ca->pathLengthSet) { - /* Check root CA (self-signed) has path length > 0 */ - if (cert->selfSigned) { - if (cert->ca->pathLength != 0) { - WOLFSSL_MSG("Root CA with path length > 0"); + /* Check if signer is root CA (self-signed) */ + if (cert->ca->selfSigned) { + /* Root CA as signer: + * Must have path length > 0 to sign another CA + * If path length == 0 can only sign an end entity + * certificate, not intermediate CA + */ + if (cert->ca->pathLength == 0) { + WOLFSSL_MSG("Root CA with path length == 0"); return ASN_PATHLEN_INV_E; } } else { + /* Intermediate CA signing Intermediate CA */ /* Check path lengths are valid between two CA's */ if (cert->ca->pathLength == 0) { WOLFSSL_MSG("CA with path length 0 signing a CA"); diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index ee5b7cc15..522f2b45c 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -861,7 +861,8 @@ struct Signer { word32 keyOID; /* key type */ word16 keyUsage; byte pathLength; - byte pathLengthSet; + byte pathLengthSet : 1; + byte selfSigned : 1; const byte* publicKey; int nameLen; char* name; /* common name */ From 03e0dd6ca369586c3bfb2229a62309554371dd5b Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 12 Mar 2019 11:05:07 -0700 Subject: [PATCH 2/2] Add back this path length check for self-signed CA as special case for the supplicant only. --- wolfcrypt/src/asn.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 06f0675b2..33a5bab76 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -8101,6 +8101,16 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) if (cert->ca) { /* Check if cert is CA type and signer has path length set */ if (cert->isCA && cert->ca->pathLengthSet) { + #if defined(WOLFSSL_WPAS) && !defined(WOLFSSL_NO_ASN_STRICT) + /* WPA Supplicant - has test case that expects self-signed + root CA to have path length == 0 */ + if (cert->selfSigned) { + if (cert->ca->pathLength != 0) { + WOLFSSL_MSG("Root CA with path length > 0"); + return ASN_PATHLEN_INV_E; + } + } + #endif /* Check if signer is root CA (self-signed) */ if (cert->ca->selfSigned) { /* Root CA as signer: @@ -8127,10 +8137,11 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) } } - #ifdef HAVE_OCSP - /* Need the CA's public key hash for OCSP */ - XMEMCPY(cert->issuerKeyHash, cert->ca->subjectKeyHash, KEYID_SIZE); - #endif /* HAVE_OCSP */ + #ifdef HAVE_OCSP + /* Need the CA's public key hash for OCSP */ + XMEMCPY(cert->issuerKeyHash, cert->ca->subjectKeyHash, + KEYID_SIZE); + #endif /* HAVE_OCSP */ } } }