diff --git a/tests/api.c b/tests/api.c index 74264c400..553b74d38 100644 --- a/tests/api.c +++ b/tests/api.c @@ -25982,6 +25982,18 @@ static void test_wolfSSL_X509_sign(void) XFCLOSE(tmpFile); #endif + /* test invalid version number */ +#if defined(OPENSSL_ALL) + #ifdef WOLFSSL_ALT_NAMES + AssertIntEQ(X509_get_ext_count(x509), 1); + #endif + AssertIntNE(X509_set_version(x509, 6L), 0); + AssertIntGT(X509_sign(x509, priv, EVP_sha256()), 0); + + /* uses ParseCert which fails on bad version number */ + AssertIntEQ(X509_get_ext_count(x509), SSL_FAILURE); +#endif + #ifndef WOLFSSL_ALT_NAMES /* Valid case - size should be 798 */ AssertIntEQ(ret, 798); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 9f04abb88..310d5ce31 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -841,8 +841,18 @@ static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version, return ASN_PARSE_E; if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + int ret; + *inOutIdx = ++idx; /* skip header */ - return GetMyVersion(input, inOutIdx, version, maxIdx); + ret = GetMyVersion(input, inOutIdx, version, maxIdx); + if (ret >= 0) { + /* check if version is expected value rfc 5280 4.1 {0, 1, 2} */ + if (*version > MAX_X509_VERSION || *version < MIN_X509_VERSION) { + WOLFSSL_MSG("Unexpected certificate version"); + ret = ASN_VERSION_E; + } + } + return ret; } /* go back as is */ diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 686d09c29..b92c494ca 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -371,6 +371,8 @@ enum Misc_ASN { TRAILING_ZERO = 1, /* Used for size of zero pad */ ASN_TAG_SZ = 1, /* single byte ASN.1 tag */ MIN_VERSION_SZ = 3, /* Min bytes needed for GetMyVersion */ + MAX_X509_VERSION = 3, /* Max X509 version allowed */ + MIN_X509_VERSION = 0, /* Min X509 version allowed */ #if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ defined(OPENSSL_EXTRA) || defined(HAVE_PKCS7)