Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -13690,6 +13690,17 @@ int CheckForAltNames(DecodedCert* dCert, const char* domain, word32 domainLen,
continue;
}

/* RFC 6125 Sec. 6.4 / RFC 9525 Sec. 6.3: a DNS-ID reference
* identifier is matched only against dNSName SAN entries, never
* uniformResourceIdentifier (even when the URI value resembles a
* hostname). URI-ID matching requires scheme and host parsing
* (RFC 9525 Sec. 6.5, Sec. 7.2). */
if (!isIP && altName->type == ASN_URI_TYPE) {
WOLFSSL_MSG("\tAltName is uniformResourceIdentifier, "
"skipping for DNS hostname");
continue;
}

if (MatchDomainName(buf, (int)len, domain, domainLen, flags)) {
match = 1;
if (checkCN != NULL) {
Expand Down
23 changes: 17 additions & 6 deletions src/ocsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1283,26 +1283,35 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
XMEMSET(resp, 0, sizeof(OcspResponse));
}

if (resp->source != NULL)
XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
resp->source = (byte*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (resp->source == NULL) {
XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
wolfSSL_OCSP_RESPONSE_free(resp);
if (response != NULL && *response == resp)
*response = NULL;
return NULL;
}
if (resp->single != NULL) {
FreeOcspEntry(resp->single, NULL);
XFREE(resp->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
}
resp->single = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL,
DYNAMIC_TYPE_OCSP_ENTRY);
if (resp->single == NULL) {
XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
wolfSSL_OCSP_RESPONSE_free(resp);
if (response != NULL && *response == resp)
*response = NULL;
return NULL;
}
XMEMSET(resp->single, 0, sizeof(OcspEntry));
resp->single->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
DYNAMIC_TYPE_OCSP_STATUS);
resp->single->ownStatus = 1;
if (resp->single->status == NULL) {
XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(resp->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
wolfSSL_OCSP_RESPONSE_free(resp);
if (response != NULL && *response == resp)
*response = NULL;
return NULL;
}
XMEMSET(resp->single->status, 0, sizeof(CertStatus));
Expand All @@ -1315,6 +1324,8 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
/* for just converting from a DER to an internal structure the CA may
* not yet be known to this function for signature verification */
wolfSSL_OCSP_RESPONSE_free(resp);
if (response != NULL && *response == resp)
*response = NULL;
return NULL;
}

Expand Down
64 changes: 64 additions & 0 deletions tests/api/test_certman.c
Original file line number Diff line number Diff line change
Expand Up @@ -2109,6 +2109,70 @@ int test_wolfSSL_X509_check_host_IP_only_SAN_CN_fallback(void)
return EXPECT_RESULT();
}

int test_wolfSSL_X509_check_host_URI_SAN_not_DNS_match(void)
{
EXPECT_DECLS;
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) && \
defined(OPENSSL_EXTRA) && defined(WOLFSSL_CERT_GEN) && \
defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_ALT_NAMES) && \
!defined(NO_SHA256)
/* RFC 6125 Sec. 6.4 / RFC 9525 Sec. 6.3: DNS-ID reference identifiers
* must be matched only against dNSName SANs, not uniformResourceIdentifier.
* wolfSSL_X509_add_altname() is used to attach a bare-hostname URI SAN
* (the misissue shape that can reach altNames when certificate parsing is
* built without strict URI checks). URI SAN presence still suppresses CN
* fallback per RFC 6125 Sec. 6.4.4. */
WOLFSSL_EVP_PKEY *priv = NULL;
WOLFSSL_X509_NAME* name = NULL;
const char* server_cert = "./certs/test/server-goodcn.pem";
const char hostName[] = "cnhost.local";
const char uriSan[] = "cnhost.local";
byte *pt;
WOLFSSL_X509 *leafUri = NULL;
WOLFSSL_X509 *leafUriDns = NULL;

pt = (byte*)server_key_der_2048;
ExpectNotNull(priv = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL,
(const unsigned char**)&pt, sizeof_server_key_der_2048));

ExpectNotNull(leafUri = wolfSSL_X509_load_certificate_file(server_cert,
WOLFSSL_FILETYPE_PEM));
ExpectNotNull(name = X509_NAME_new());
ExpectIntEQ(X509_NAME_add_entry_by_txt(name, "commonName", MBSTRING_UTF8,
(byte*)hostName, (int)XSTRLEN(hostName), -1, 0), SSL_SUCCESS);
ExpectIntEQ(wolfSSL_X509_set_subject_name(leafUri, name), WOLFSSL_SUCCESS);
X509_NAME_free(name);
name = NULL;
ExpectIntEQ(wolfSSL_X509_add_altname(leafUri, uriSan, ASN_URI_TYPE),
WOLFSSL_SUCCESS);
ExpectIntGT(wolfSSL_X509_sign(leafUri, priv, EVP_sha256()), 0);
ExpectIntEQ(wolfSSL_X509_check_host(leafUri, hostName, XSTRLEN(hostName),
0, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE));

ExpectNotNull(leafUriDns = wolfSSL_X509_load_certificate_file(server_cert,
WOLFSSL_FILETYPE_PEM));
ExpectNotNull(name = X509_NAME_new());
ExpectIntEQ(X509_NAME_add_entry_by_txt(name, "commonName", MBSTRING_UTF8,
(byte*)hostName, (int)XSTRLEN(hostName), -1, 0), SSL_SUCCESS);
ExpectIntEQ(wolfSSL_X509_set_subject_name(leafUriDns, name),
WOLFSSL_SUCCESS);
X509_NAME_free(name);
name = NULL;
ExpectIntEQ(wolfSSL_X509_add_altname(leafUriDns, uriSan, ASN_URI_TYPE),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_X509_add_altname(leafUriDns, hostName, ASN_DNS_TYPE),
WOLFSSL_SUCCESS);
ExpectIntGT(wolfSSL_X509_sign(leafUriDns, priv, EVP_sha256()), 0);
ExpectIntEQ(wolfSSL_X509_check_host(leafUriDns, hostName,
XSTRLEN(hostName), 0, NULL), WOLFSSL_SUCCESS);

wolfSSL_X509_free(leafUri);
wolfSSL_X509_free(leafUriDns);
wolfSSL_EVP_PKEY_free(priv);
#endif
return EXPECT_RESULT();
}

int test_wolfSSL_CertManagerCRL(void)
{
EXPECT_DECLS;
Expand Down
3 changes: 3 additions & 0 deletions tests/api/test_certman.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ int test_wolfSSL_CertManagerNameConstraint_IP_SAN(void);
int test_wolfSSL_CertManagerNameConstraint_RID_SAN(void);
int test_wolfSSL_X509_get_ext_d2i_RID_SAN(void);
int test_wolfSSL_X509_check_host_IP_only_SAN_CN_fallback(void);
int test_wolfSSL_X509_check_host_URI_SAN_not_DNS_match(void);
int test_wolfSSL_CertManagerCRL(void);
int test_wolfSSL_CRL_reason_extensions_cleanup(void);
int test_wolfSSL_CRL_static_revoked_list(void);
Expand Down Expand Up @@ -69,6 +70,8 @@ int test_wolfSSL_CertManagerRejectMD5Cert(void);
TEST_DECL_GROUP("certman", test_wolfSSL_X509_get_ext_d2i_RID_SAN), \
TEST_DECL_GROUP("certman", \
test_wolfSSL_X509_check_host_IP_only_SAN_CN_fallback), \
TEST_DECL_GROUP("certman", \
test_wolfSSL_X509_check_host_URI_SAN_not_DNS_match), \
TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerCRL), \
TEST_DECL_GROUP("certman", test_wolfSSL_CRL_reason_extensions_cleanup), \
TEST_DECL_GROUP("certman", test_wolfSSL_CRL_static_revoked_list), \
Expand Down
9 changes: 9 additions & 0 deletions tests/api/test_ocsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,15 @@ int test_ocsp_basic_verify(void)
ExpectNull(
response = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr, sizeof(resp_bad)));

/* reuse failure must clear caller pointer */
ptr = (const unsigned char*)resp;
ExpectNotNull(
response = wolfSSL_d2i_OCSP_RESPONSE(&response, &ptr, sizeof(resp)));
ptr = (const unsigned char*)resp_bad;
ExpectNull(
wolfSSL_d2i_OCSP_RESPONSE(&response, &ptr, sizeof(resp_bad)));
ExpectNull(response);

ptr = (const unsigned char*)resp;
ExpectNotNull(
response = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr, sizeof(resp)));
Expand Down
4 changes: 4 additions & 0 deletions wolfcrypt/src/asn.c
Original file line number Diff line number Diff line change
Expand Up @@ -18670,6 +18670,10 @@ static int DecodeGeneralName(const byte* input, word32* inOutIdx, byte tag,
* - CheckForAltNames (TLS hostname matching): skips ASN_RID_TYPE
* unconditionally and excludes them from *checkCN, so a cert
* with only registeredID SANs still falls back to CN.
* - CheckForAltNames (TLS hostname matching): skips ASN_URI_TYPE
* for DNS hostname checks (RFC 6125 Sec. 6.4 / RFC 9525 Sec. 6.3)
* but URI SAN presence still suppresses CN fallback (RFC 6125
* Sec. 6.4.4) because URI-ID is a distinct presented identifier.
* - DNS_to_GENERAL_NAME (used by wolfSSL_X509_get_ext) and the
* ALT_NAMES_OID arm of wolfSSL_X509_get_ext_d2i: build a proper
* ASN1_OBJECT in d.registeredID from raw OID bytes regardless
Expand Down
Loading