diff --git a/ctaocrypt/src/asn.c b/ctaocrypt/src/asn.c index db30330bf..3fa53154b 100644 --- a/ctaocrypt/src/asn.c +++ b/ctaocrypt/src/asn.c @@ -3603,13 +3603,18 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) CYASSL_MSG("Parsed Past Key"); - if (cert->srcIdx != cert->sigIndex) { - if (cert->srcIdx < cert->sigIndex) { - /* save extensions */ - cert->extensions = &cert->source[cert->srcIdx]; - cert->extensionsSz = cert->sigIndex - cert->srcIdx; - cert->extensionsIdx = cert->srcIdx; /* for potential later use */ - } + if (cert->srcIdx < cert->sigIndex) { + #ifndef ALLOW_V1_EXTENSIONS + if (cert->version < 2) { + CYASSL_MSG(" v1 and v2 certs not allowed extensions"); + return ASN_VERSION_E; + } + #endif + /* save extensions */ + cert->extensions = &cert->source[cert->srcIdx]; + cert->extensionsSz = cert->sigIndex - cert->srcIdx; + cert->extensionsIdx = cert->srcIdx; /* for potential later use */ + if ((ret = DecodeCertExtensions(cert)) < 0) { if (ret == ASN_CRIT_EXT_E) criticalExt = ret; @@ -6497,6 +6502,12 @@ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) if (ca) { CYASSL_MSG("Found CRL issuer CA"); /* try to confirm/verify signature */ + #ifndef IGNORE_KEY_EXTENSIONS + if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) { + CYASSL_MSG("CA cannot sign CRLs"); + return ASN_CRL_NO_SIGNER_E; + } + #endif /* IGNORE_KEY_EXTENSIONS */ if (!ConfirmSignature(buff + dcrl->certBegin, dcrl->sigIndex - dcrl->certBegin, ca->publicKey, ca->pubKeySize, ca->keyOID, diff --git a/cyassl/ctaocrypt/asn.h b/cyassl/ctaocrypt/asn.h index fe961afdb..751739dd7 100644 --- a/cyassl/ctaocrypt/asn.h +++ b/cyassl/ctaocrypt/asn.h @@ -426,6 +426,7 @@ struct DecodedCert { struct Signer { word32 pubKeySize; word32 keyOID; /* key type */ + word16 keyUsage; byte* publicKey; int nameLen; char* name; /* common name */ diff --git a/cyassl/error-ssl.h b/cyassl/error-ssl.h index 71f4b4ffd..fd34c8896 100644 --- a/cyassl/error-ssl.h +++ b/cyassl/error-ssl.h @@ -115,6 +115,9 @@ enum CyaSSL_ErrorCodes { UNKNOWN_SNI_HOST_NAME_E = -281, /* Unrecognized host name Error */ UNKNOWN_MAX_FRAG_LEN_E = -282, /* Unrecognized max frag len Error */ /* add strings to SetErrorString !!!!! */ + KEYUSE_SIGNATURE_E = -283, /* KeyUse digSignature error */ + KEYUSE_ENCIPHER_E = -285, /* KeyUse keyEncipher error */ + EXTKEYUSE_AUTH_E = -286, /* ExtKeyUse server|client_auth */ /* begin negotiation parameter errors */ UNSUPPORTED_SUITE = -290, /* unsupported cipher suite */ diff --git a/src/internal.c b/src/internal.c index 622a6b8f2..d9134cf29 100644 --- a/src/internal.c +++ b/src/internal.c @@ -3486,6 +3486,42 @@ static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx, } #endif +#ifndef IGNORE_KEY_EXTENSIONS + if (dCert.extKeyUsageSet) { + if ((ssl->specs.kea == rsa_kea) && + (dCert.extKeyUsage & KEYUSE_KEY_ENCIPHER) == 0) { + fatal = 1; + ret = KEYUSE_ENCIPHER_E; + } + if ((ssl->specs.sig_algo == rsa_sa_algo || + ssl->specs.sig_algo == ecc_dsa_sa_algo) && + (dCert.extKeyUsage & KEYUSE_DIGITAL_SIG) == 0) { + CYASSL_MSG("KeyUse Digital Sig not set"); + fatal = 1; + ret = KEYUSE_SIGNATURE_E; + } + } + + if (dCert.extExtKeyUsageSet) { + if (ssl->options.side == CYASSL_CLIENT_END) { + if ((dCert.extExtKeyUsage & + (EXTKEYUSE_ANY | EXTKEYUSE_SERVER_AUTH)) == 0) { + CYASSL_MSG("ExtKeyUse Server Auth not set"); + fatal = 1; + ret = EXTKEYUSE_AUTH_E; + } + } + else { + if ((dCert.extExtKeyUsage & + (EXTKEYUSE_ANY | EXTKEYUSE_CLIENT_AUTH)) == 0) { + CYASSL_MSG("ExtKeyUse Client Auth not set"); + fatal = 1; + ret = EXTKEYUSE_AUTH_E; + } + } + } +#endif /* IGNORE_KEY_EXTENSIONS */ + if (fatal) { FreeDecodedCert(&dCert); ssl->error = ret; @@ -6478,6 +6514,18 @@ void SetErrorString(int error, char* str) XSTRNCPY(str, "Unrecognized host name Error", max); break; + case KEYUSE_SIGNATURE_E: + XSTRNCPY(str, "Key Use digitalSignature not set Error", max); + break; + + case KEYUSE_ENCIPHER_E: + XSTRNCPY(str, "Key Use keyEncipherment not set Error", max); + break; + + case EXTKEYUSE_AUTH_E: + XSTRNCPY(str, "Ext Key Use server/client auth not set Error", max); + break; + default : XSTRNCPY(str, "unknown error number", max); } diff --git a/src/ssl.c b/src/ssl.c index 17b76bc53..37eebe12e 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1496,6 +1496,15 @@ int AddCA(CYASSL_CERT_MANAGER* cm, buffer der, int type, int verify) CYASSL_MSG(" Can't add as CA if not actually one"); ret = NOT_CA_ERROR; } + #ifndef ALLOW_INVALID_CERTSIGN + else if (ret == 0 && cert.isCA == 1 && type != CYASSL_USER_CA && + (cert.extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) { + /* Intermediate CA certs are required to have the keyCertSign + * extension set. User loaded root certs are not. */ + CYASSL_MSG(" Doesn't have key usage certificate signing"); + ret = NOT_CA_ERROR; + } + #endif else if (ret == 0 && AlreadySigner(cm, subjectHash)) { CYASSL_MSG(" Already have this CA, not adding again"); (void)ret; @@ -1516,6 +1525,8 @@ int AddCA(CYASSL_CERT_MANAGER* cm, buffer der, int type, int verify) cert.extSubjKeyId, SHA_DIGEST_SIZE); #endif XMEMCPY(signer->subjectNameHash, cert.subjectHash, SHA_DIGEST_SIZE); + signer->keyUsage = cert.extKeyUsageSet ? cert.extKeyUsage : 0xFFFF; + /* If Key Usage not set, all uses valid. */ signer->next = NULL; /* in case lock fails */ cert.publicKey = 0; /* don't free here */