diff --git a/src/internal.c b/src/internal.c index 5d6a8fe3a..d4682d888 100644 --- a/src/internal.c +++ b/src/internal.c @@ -3828,6 +3828,10 @@ void FreeX509(WOLFSSL_X509* x509) wolfSSL_EVP_PKEY_free(x509->key.pkey); x509->key.pkey = NULL; } + if (x509->subjAltNameSrc != NULL) { + XFREE(x509->subjAltNameSrc, x509->heap, DYNAMIC_TYPE_X509_EXT); + x509->subjAltNameSrc= NULL; + } #endif /* OPENSSL_ALL */ #if defined(WOLFSSL_CERT_REQ) && defined(OPENSSL_ALL) if (x509->challengePwAttr) { @@ -10620,6 +10624,19 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) } #endif /* WOLFSSL_CERT_EXT */ #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ +#ifdef OPENSSL_ALL + if (dCert->extSubjAltNameSrc != NULL && dCert->extSubjAltNameSz != 0) { + x509->subjAltNameSrc = (byte*)XMALLOC(dCert->extSubjAltNameSz, x509->heap, + DYNAMIC_TYPE_X509_EXT); + if (x509->subjAltNameSrc != NULL) { + XMEMCPY(x509->subjAltNameSrc, + dCert->extSubjAltNameSrc, dCert->extSubjAltNameSz); + x509->subjAltNameSz = dCert->extSubjAltNameSz; + } + else + ret = MEMORY_E; + } +#endif #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) x509->pkCurveOID = dCert->pkCurveOID; #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ diff --git a/src/ssl.c b/src/ssl.c index 5cb2ff162..88aca2e1a 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -8525,6 +8525,45 @@ void wolfSSL_X509_EXTENSION_free(WOLFSSL_X509_EXTENSION* x) XFREE(x, NULL, DYNAMIC_TYPE_X509_EXT); } +WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_dup(WOLFSSL_X509_EXTENSION* src) +{ + WOLFSSL_X509_EXTENSION* ret = NULL; + int err = 0; + + WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_dup"); + + if (src == NULL) { + err = 1; + } + + if (err == 0) { + ret = wolfSSL_X509_EXTENSION_new(); + if (ret == NULL) { + err = 1; + } + } + if (err == 0 && src->obj != NULL) { + ret->obj = wolfSSL_ASN1_OBJECT_dup(src->obj); + if (ret->obj == NULL) { + err = 1; + } + } + if (err == 0) { + ret->crit = src->crit; + if (wolfSSL_ASN1_STRING_copy(&ret->value, &src->value) != + WOLFSSL_SUCCESS) { + err = 1; + } + } + + if (err == 1 && ret != NULL) { + wolfSSL_X509_EXTENSION_free(ret); + ret = NULL; + } + + return ret; +} + /* Creates and returns a new WOLFSSL_X509_EXTENSION stack. */ WOLFSSL_STACK* wolfSSL_sk_new_x509_ext(void) { @@ -9048,10 +9087,23 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) if (!isSet) break; + #ifdef OPENSSL_ALL + ret = wolfSSL_ASN1_STRING_set(&ext->value, x509->subjAltNameSrc, + x509->subjAltNameSz); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set() failed"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + #endif + sk = (WOLFSSL_GENERAL_NAMES*)XMALLOC( sizeof(WOLFSSL_GENERAL_NAMES), NULL, DYNAMIC_TYPE_ASN1); if (sk == NULL) { + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); return NULL; } XMEMSET(sk, 0, sizeof(WOLFSSL_GENERAL_NAMES)); @@ -9065,6 +9117,8 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) gn = wolfSSL_GENERAL_NAME_new(); if (gn == NULL) { WOLFSSL_MSG("Error creating GENERAL_NAME"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); wolfSSL_sk_free(sk); return NULL; } @@ -9074,6 +9128,8 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) if (wolfSSL_ASN1_STRING_set(gn->d.ia5, dns->name, gn->d.ia5->length) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("ASN1_STRING_set failed"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); wolfSSL_GENERAL_NAME_free(gn); wolfSSL_sk_free(sk); return NULL; @@ -9084,19 +9140,23 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) if (dns != NULL) { if (wolfSSL_sk_GENERAL_NAME_push(sk, gn) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Error pushing onto stack"); - wolfSSL_GENERAL_NAME_free(gn); - wolfSSL_sk_free(sk); - sk = NULL; + WOLFSSL_MSG("Error pushing onto stack"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + wolfSSL_GENERAL_NAME_free(gn); + wolfSSL_sk_free(sk); + return NULL; } } } if (wolfSSL_sk_GENERAL_NAME_push(sk,gn) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Error pushing onto stack"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); wolfSSL_GENERAL_NAME_free(gn); wolfSSL_sk_free(sk); - sk = NULL; + return NULL; } } ext->ext_sk = sk; diff --git a/tests/api.c b/tests/api.c index a1fb0165b..627c435e5 100644 --- a/tests/api.c +++ b/tests/api.c @@ -40440,7 +40440,41 @@ static void test_wolfSSL_X509_get_ext_by_NID(void) AssertIntEQ(rc, -1); wolfSSL_X509_free(x509); +#endif +} +static void test_wolfSSL_X509_get_ext_subj_alt_name(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_RSA) + int rc; + XFILE f; + WOLFSSL_X509* x509; + WOLFSSL_X509_EXTENSION* ext; + WOLFSSL_ASN1_STRING* sanString; + byte* sanDer; + + const byte expectedDer[] = { + 0x30, 0x13, 0x82, 0x0b, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, + 0x63, 0x6f, 0x6d, 0x87, 0x04, 0x7f, 0x00, 0x00, 0x01}; + + printf(testingFmt, "test_wolfSSL_X509_get_ext_subj_alt_name"); + + f = XFOPEN("./certs/server-cert.pem", "rb"); + AssertTrue(f != XBADFILE); + AssertNotNull(x509 = PEM_read_X509(f, NULL, NULL, NULL)); + fclose(f); + + rc = X509_get_ext_by_NID(x509, NID_subject_alt_name, -1); + AssertIntNE(rc, -1); + AssertNotNull(ext = X509_get_ext(x509, rc)); + AssertNotNull(sanString = X509_EXTENSION_get_data(ext)); + AssertIntEQ(ASN1_STRING_length(sanString), sizeof(expectedDer)); + AssertNotNull(sanDer = ASN1_STRING_data(sanString)); + AssertIntEQ(XMEMCMP(sanDer, expectedDer, sizeof(expectedDer)), 0); + + X509_free(x509); + + printf(resultFmt, passed); #endif } @@ -47006,6 +47040,7 @@ void ApiTest(void) test_wolfSSL_X509V3_EXT(); test_wolfSSL_X509_get_ext(); test_wolfSSL_X509_get_ext_by_NID(); + test_wolfSSL_X509_get_ext_subj_alt_name(); test_wolfSSL_X509_get_ext_count(); test_wolfSSL_X509_EXTENSION_new(); test_wolfSSL_X509_EXTENSION_get_object(); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index d8153d330..8163a8528 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -8360,6 +8360,11 @@ static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) return ASN_PARSE_E; } +#ifdef OPENSSL_ALL + cert->extSubjAltNameSrc = input; + cert->extSubjAltNameSz = sz; +#endif + cert->weOwnAltNames = 1; while (length > 0) { diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 60ff15ab2..1f9847108 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3891,6 +3891,9 @@ struct WOLFSSL_X509 { byte* authKeyId; byte* subjKeyId; byte* extKeyUsageSrc; +#ifdef OPENSSL_ALL + byte* subjAltNameSrc; +#endif const byte* CRLInfo; byte* authInfo; #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) @@ -3905,6 +3908,9 @@ struct WOLFSSL_X509 { word32 subjKeyIdSz; word32 extKeyUsageSz; word32 extKeyUsageCount; +#ifdef OPENSSL_ALL + word32 subjAltNameSz; +#endif byte CRLdistSet:1; byte CRLdistCrit:1; diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 0c0e73418..0d9433110 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -495,6 +495,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define X509_EXTENSION_get_object wolfSSL_X509_EXTENSION_get_object #define X509_EXTENSION_get_data wolfSSL_X509_EXTENSION_get_data +#define X509_EXTENSION_dup wolfSSL_X509_EXTENSION_dup #define sk_X509_new wolfSSL_sk_X509_new #define sk_X509_new_null wolfSSL_sk_X509_new diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 600a426c6..82bc9bc8b 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -3777,6 +3777,8 @@ WOLFSSL_API int wolfSSL_X509_get_ext_by_OBJ(const WOLFSSL_X509 *x, WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x, int loc); WOLFSSL_API int wolfSSL_X509_EXTENSION_get_critical(const WOLFSSL_X509_EXTENSION* ex); WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_new(void); +WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_dup( + WOLFSSL_X509_EXTENSION*); WOLFSSL_API int wolfSSL_sk_X509_EXTENSION_push(WOLFSSL_STACK* sk, WOLFSSL_X509_EXTENSION* ext); WOLFSSL_API void wolfSSL_sk_X509_EXTENSION_free(WOLFSSL_STACK* sk); diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 15c8e445d..7df56cbee 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -856,6 +856,10 @@ struct DecodedCert { const byte* extSubjKeyIdSrc; word32 extSubjKeyIdSz; #endif +#ifdef OPENSSL_ALL + const byte* extSubjAltNameSrc; + word32 extSubjAltNameSz; +#endif #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) word32 pkCurveOID; /* Public Key's curve OID */