From 247d5b560963bea537501cedb459be38bc2d79f5 Mon Sep 17 00:00:00 2001 From: toddouska Date: Tue, 6 Dec 2011 15:17:10 -0800 Subject: [PATCH] some root CAs loaded by user won't have basic constraint, allow --- ctaocrypt/src/asn.c | 14 ++++++++++++-- cyassl/ctaocrypt/asn.h | 1 + cyassl/error.h | 1 + cyassl/internal.h | 2 +- src/internal.c | 6 +++++- src/ssl.c | 10 ++++++---- 6 files changed, 26 insertions(+), 8 deletions(-) diff --git a/ctaocrypt/src/asn.c b/ctaocrypt/src/asn.c index f239fb15b..838b33ddf 100644 --- a/ctaocrypt/src/asn.c +++ b/ctaocrypt/src/asn.c @@ -2021,9 +2021,19 @@ static void IsCa(DecodedCert* cert) return; if (oid == BASIC_CA_OID) { + CYASSL_MSG("Found Basic CA constraint"); b = cert->source[cert->srcIdx++]; - if (b != ASN_OCTET_STRING) - return; + + if (b != ASN_OCTET_STRING) { + CYASSL_MSG("Found optional critical flag, moving past"); + cert->srcIdx += ASN_BOOL_SIZE; + b = cert->source[cert->srcIdx++]; + + if (b != ASN_OCTET_STRING) { + CYASSL_MSG("Unkown Basic CA constraint format"); + return; + } + } if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) diff --git a/cyassl/ctaocrypt/asn.h b/cyassl/ctaocrypt/asn.h index 8fd2a16eb..b8c94b4fc 100644 --- a/cyassl/ctaocrypt/asn.h +++ b/cyassl/ctaocrypt/asn.h @@ -107,6 +107,7 @@ enum Misc_ASN { PKCS5v2 = 6, /* PKCS #5 v2.0 */ PKCS12 = 12, /* PKCS #12 */ MAX_UNICODE_SZ = 256, + ASN_BOOL_SIZE = 2, /* including type */ SHA_SIZE = 20, RSA_INTS = 8, /* RSA ints in private key */ MIN_DATE_SIZE = 13, diff --git a/cyassl/error.h b/cyassl/error.h index ee79ae4da..6b11a491e 100644 --- a/cyassl/error.h +++ b/cyassl/error.h @@ -89,6 +89,7 @@ enum CyaSSL_ErrorCodes { ECC_EXPORT_ERROR = -254, /* Bad ECC Export Key */ ECC_SHARED_ERROR = -255, /* Bad ECC Shared Secret */ BAD_MUTEX_ERROR = -256, /* Bad mutex */ + NOT_CA_ERROR = -257, /* Not a CA cert error */ /* add strings to SetErrorString !!!!! */ /* begin negotiation parameter errors */ diff --git a/cyassl/internal.h b/cyassl/internal.h index 1c9c76a48..a50803f76 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -615,7 +615,7 @@ CYASSL_LOCAL int ProcessOldClientHello(CYASSL* ssl, const byte* input, word32* inOutIdx, word32 inSz, word16 sz); CYASSL_LOCAL -int AddCA(CYASSL_CTX* ctx, buffer der); +int AddCA(CYASSL_CTX* ctx, buffer der, int force); CYASSL_LOCAL int AlreadySigner(CYASSL_CTX* ctx, byte* hash); diff --git a/src/internal.c b/src/internal.c index df7f1c5be..0d0befb48 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1526,7 +1526,7 @@ static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx) return MEMORY_E; XMEMCPY(add.buffer, myCert.buffer, myCert.length); - ret = AddCA(ssl->ctx, add); + ret = AddCA(ssl->ctx, add, 0); /* never force chain add */ if (ret == 1) ret = 0; /* SSL_SUCCESS for external */ } else if (ret != 0) { @@ -3257,6 +3257,10 @@ void SetErrorString(int error, char* str) XSTRNCPY(str, "Bad mutex, operation failed", max); break; + case NOT_CA_ERROR: + XSTRNCPY(str, "Not a CA by basic constraint error", max); + break; + default : XSTRNCPY(str, "unknown error number", max); } diff --git a/src/ssl.c b/src/ssl.c index 3a96c40ca..c39c5017a 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -410,7 +410,9 @@ Signer* GetCA(Signer* signers, byte* hash) /* owns der, internal now uses too */ -int AddCA(CYASSL_CTX* ctx, buffer der) +/* force flag means override CA check, ok for root certs that user requested + if they're from a chain we don't want to force, ever */ +int AddCA(CYASSL_CTX* ctx, buffer der, int force) { int ret; DecodedCert cert; @@ -421,9 +423,9 @@ int AddCA(CYASSL_CTX* ctx, buffer der) ret = ParseCert(&cert, CA_TYPE, ctx->verifyPeer, 0); CYASSL_MSG(" Parsed new CA"); - if (ret == 0 && cert.isCA == 0) { + if (ret == 0 && cert.isCA == 0 && !force) { CYASSL_MSG(" Can't add as CA if not actually one"); - ret = -1; + ret = NOT_CA_ERROR; } else if (ret == 0 && AlreadySigner(ctx, cert.subjectHash)) { CYASSL_MSG(" Already have this CA, not adding again"); @@ -864,7 +866,7 @@ int AddCA(CYASSL_CTX* ctx, buffer der) #endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ if (type == CA_TYPE) - return AddCA(ctx, der); /* takes der over */ + return AddCA(ctx, der, 1); /* takes der over, force user request */ else if (type == CERT_TYPE) { if (ssl) { if (ssl->buffers.weOwnCert && ssl->buffers.certificate.buffer)