mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-06 21:30:50 +02:00
Improve ctx->param handling
- wolfSSL_X509_verify_cert: add host check from `ctx->param` - wolfSSL_X509_verify_cert: Set `ctx->error_depth` on error - Use WOLFSSL_-prefixed error constants (always available) instead of OPENSSL_COEXIST-guarded macros, fixing error code mismatch in coexist builds - Set ctx->current_cert = orig on hostname/IP mismatch so error reporting aligns with error_depth = 0 (leaf cert) - Add IP address verification test cases (match + mismatch)
This commit is contained in:
@@ -27084,6 +27084,12 @@ static const char* wolfSSL_ERR_reason_error_string_OpenSSL(unsigned long e)
|
||||
case WOLFSSL_X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
|
||||
return "subject issuer mismatch";
|
||||
|
||||
case WOLFSSL_X509_V_ERR_HOSTNAME_MISMATCH:
|
||||
return "hostname mismatch";
|
||||
|
||||
case WOLFSSL_X509_V_ERR_IP_ADDRESS_MISMATCH:
|
||||
return "IP address mismatch";
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -740,6 +740,33 @@ exit:
|
||||
wolfSSL_sk_X509_free(certsToUse);
|
||||
}
|
||||
|
||||
/* Enforce hostname / IP verification from X509_VERIFY_PARAM if set.
|
||||
* Always check against the leaf (end-entity) certificate, captured in
|
||||
* orig before the chain-building loop modified ctx->current_cert. */
|
||||
if (ctx->param != NULL) {
|
||||
if (ret == WOLFSSL_SUCCESS && ctx->param->hostName[0] != '\0') {
|
||||
if (wolfSSL_X509_check_host(orig,
|
||||
ctx->param->hostName,
|
||||
XSTRLEN(ctx->param->hostName),
|
||||
ctx->param->hostFlags, NULL) != WOLFSSL_SUCCESS) {
|
||||
ctx->error = WOLFSSL_X509_V_ERR_HOSTNAME_MISMATCH;
|
||||
ctx->error_depth = 0;
|
||||
ctx->current_cert = orig;
|
||||
ret = WOLFSSL_FAILURE;
|
||||
}
|
||||
}
|
||||
if (ret == WOLFSSL_SUCCESS && ctx->param->ipasc[0] != '\0') {
|
||||
if (wolfSSL_X509_check_ip_asc(orig,
|
||||
ctx->param->ipasc,
|
||||
ctx->param->hostFlags) != WOLFSSL_SUCCESS) {
|
||||
ctx->error = WOLFSSL_X509_V_ERR_IP_ADDRESS_MISMATCH;
|
||||
ctx->error_depth = 0;
|
||||
ctx->current_cert = orig;
|
||||
ret = WOLFSSL_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret == WOLFSSL_SUCCESS ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
@@ -27168,6 +27168,8 @@ static int error_test(void)
|
||||
{17, 15},
|
||||
{19, 19},
|
||||
{27, 26 },
|
||||
{61, 30},
|
||||
{63, 63},
|
||||
#endif
|
||||
{ -9, WC_SPAN1_FIRST_E + 1 },
|
||||
{ -124, -124 },
|
||||
|
||||
@@ -244,6 +244,104 @@ int test_x509_GetCAByAKID(void)
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/* Regression test: wolfSSL_X509_verify_cert() must honour the hostname set via
|
||||
* X509_VERIFY_PARAM_set1_host(). Before the fix the hostname was stored in
|
||||
* ctx->param->hostName but never consulted, so any chain-valid certificate
|
||||
* would pass regardless of hostname mismatch (RFC 6125 sec. 6.4.1 violation).
|
||||
*
|
||||
* Uses existing PEM fixtures:
|
||||
* svrCertFile - CN=www.wolfssl.com, SAN DNS=example.com, SAN IP=127.0.0.1
|
||||
* caCertFile - CA that signed svrCertFile
|
||||
*/
|
||||
int test_x509_verify_cert_hostname_check(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_RSA)
|
||||
WOLFSSL_X509_STORE* store = NULL;
|
||||
WOLFSSL_X509_STORE_CTX* ctx = NULL;
|
||||
WOLFSSL_X509* ca = NULL;
|
||||
WOLFSSL_X509* leaf = NULL;
|
||||
WOLFSSL_X509_VERIFY_PARAM* param = NULL;
|
||||
|
||||
ExpectNotNull(store = wolfSSL_X509_STORE_new());
|
||||
ExpectNotNull(ca = wolfSSL_X509_load_certificate_file(caCertFile,
|
||||
SSL_FILETYPE_PEM));
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_add_cert(store, ca), WOLFSSL_SUCCESS);
|
||||
|
||||
ExpectNotNull(leaf = wolfSSL_X509_load_certificate_file(svrCertFile,
|
||||
SSL_FILETYPE_PEM));
|
||||
|
||||
/* Case 1: no hostname constraint - must succeed. */
|
||||
ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new());
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, leaf, NULL),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_X509_verify_cert(ctx), WOLFSSL_SUCCESS);
|
||||
wolfSSL_X509_STORE_CTX_free(ctx);
|
||||
ctx = NULL;
|
||||
|
||||
/* Case 2: hostname matches a SAN DNS entry - must succeed. */
|
||||
ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new());
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, leaf, NULL),
|
||||
WOLFSSL_SUCCESS);
|
||||
param = wolfSSL_X509_STORE_CTX_get0_param(ctx);
|
||||
ExpectNotNull(param);
|
||||
ExpectIntEQ(wolfSSL_X509_VERIFY_PARAM_set1_host(param, "example.com",
|
||||
XSTRLEN("example.com")), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_X509_verify_cert(ctx), WOLFSSL_SUCCESS);
|
||||
wolfSSL_X509_STORE_CTX_free(ctx);
|
||||
ctx = NULL;
|
||||
|
||||
/* Case 3: hostname does not match - must FAIL with the right error code. */
|
||||
ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new());
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, leaf, NULL),
|
||||
WOLFSSL_SUCCESS);
|
||||
param = wolfSSL_X509_STORE_CTX_get0_param(ctx);
|
||||
ExpectNotNull(param);
|
||||
ExpectIntEQ(wolfSSL_X509_VERIFY_PARAM_set1_host(param, "wrong.com",
|
||||
XSTRLEN("wrong.com")), WOLFSSL_SUCCESS);
|
||||
ExpectIntNE(wolfSSL_X509_verify_cert(ctx), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_CTX_get_error(ctx),
|
||||
X509_V_ERR_HOSTNAME_MISMATCH);
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_CTX_get_error_depth(ctx), 0);
|
||||
wolfSSL_X509_STORE_CTX_free(ctx);
|
||||
ctx = NULL;
|
||||
|
||||
#ifdef WOLFSSL_IP_ALT_NAME
|
||||
/* Case 4: IP matches a SAN IP entry - must succeed. */
|
||||
ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new());
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, leaf, NULL),
|
||||
WOLFSSL_SUCCESS);
|
||||
param = wolfSSL_X509_STORE_CTX_get0_param(ctx);
|
||||
ExpectNotNull(param);
|
||||
ExpectIntEQ(wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(param, "127.0.0.1"),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_X509_verify_cert(ctx), WOLFSSL_SUCCESS);
|
||||
wolfSSL_X509_STORE_CTX_free(ctx);
|
||||
ctx = NULL;
|
||||
|
||||
/* Case 5: IP does not match - must FAIL with the right error code. */
|
||||
ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new());
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, leaf, NULL),
|
||||
WOLFSSL_SUCCESS);
|
||||
param = wolfSSL_X509_STORE_CTX_get0_param(ctx);
|
||||
ExpectNotNull(param);
|
||||
ExpectIntEQ(wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(param, "192.168.1.1"),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntNE(wolfSSL_X509_verify_cert(ctx), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_CTX_get_error(ctx),
|
||||
X509_V_ERR_IP_ADDRESS_MISMATCH);
|
||||
ExpectIntEQ(wolfSSL_X509_STORE_CTX_get_error_depth(ctx), 0);
|
||||
wolfSSL_X509_STORE_CTX_free(ctx);
|
||||
ctx = NULL;
|
||||
#endif /* WOLFSSL_IP_ALT_NAME */
|
||||
|
||||
wolfSSL_X509_free(leaf);
|
||||
wolfSSL_X509_free(ca);
|
||||
wolfSSL_X509_STORE_free(store);
|
||||
#endif /* OPENSSL_EXTRA && !NO_FILESYSTEM && !NO_RSA */
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_x509_set_serialNumber(void)
|
||||
{
|
||||
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
|
||||
|
||||
@@ -25,10 +25,12 @@
|
||||
int test_x509_rfc2818_verification_callback(void);
|
||||
int test_x509_GetCAByAKID(void);
|
||||
int test_x509_set_serialNumber(void);
|
||||
int test_x509_verify_cert_hostname_check(void);
|
||||
|
||||
#define TEST_X509_DECLS \
|
||||
TEST_DECL_GROUP("x509", test_x509_rfc2818_verification_callback), \
|
||||
TEST_DECL_GROUP("x509", test_x509_GetCAByAKID), \
|
||||
TEST_DECL_GROUP("x509", test_x509_set_serialNumber)
|
||||
TEST_DECL_GROUP("x509", test_x509_set_serialNumber), \
|
||||
TEST_DECL_GROUP("x509", test_x509_verify_cert_hostname_check)
|
||||
|
||||
#endif /* WOLFCRYPT_TEST_X509_H */
|
||||
|
||||
+3
-1
@@ -2685,7 +2685,9 @@ enum {
|
||||
WOLFSSL_X509_V_ERR_PATH_LENGTH_EXCEEDED = 25,
|
||||
WOLFSSL_X509_V_ERR_CERT_REJECTED = 28,
|
||||
WOLFSSL_X509_V_ERR_SUBJECT_ISSUER_MISMATCH = 29,
|
||||
WC_OSSL_V509_V_ERR_MAX = 30,
|
||||
WOLFSSL_X509_V_ERR_HOSTNAME_MISMATCH = 62,
|
||||
WOLFSSL_X509_V_ERR_IP_ADDRESS_MISMATCH = 64,
|
||||
WC_OSSL_V509_V_ERR_MAX = 65,
|
||||
|
||||
#ifdef HAVE_OCSP
|
||||
/* OCSP Flags */
|
||||
|
||||
@@ -4819,6 +4819,11 @@ extern void uITRON4_free(void *p) ;
|
||||
#error "OPENSSL_ALL can not be defined with OPENSSL_COEXIST"
|
||||
#endif
|
||||
|
||||
/* OPENSSL_ALL requires WOLFSSL_IP_ALT_NAME for IP SAN verification. */
|
||||
#if defined(OPENSSL_ALL) && !defined(WOLFSSL_IP_ALT_NAME)
|
||||
#error "OPENSSL_ALL requires WOLFSSL_IP_ALT_NAME"
|
||||
#endif
|
||||
|
||||
#if !defined(NO_DSA) && defined(NO_SHA)
|
||||
#error "Please disable DSA if disabling SHA-1"
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user