Skip to content

Commit 99ae809

Browse files
committed
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)
1 parent 15fa0b7 commit 99ae809

7 files changed

Lines changed: 144 additions & 2 deletions

File tree

src/internal.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27084,6 +27084,12 @@ static const char* wolfSSL_ERR_reason_error_string_OpenSSL(unsigned long e)
2708427084
case WOLFSSL_X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
2708527085
return "subject issuer mismatch";
2708627086

27087+
case WOLFSSL_X509_V_ERR_HOSTNAME_MISMATCH:
27088+
return "hostname mismatch";
27089+
27090+
case WOLFSSL_X509_V_ERR_IP_ADDRESS_MISMATCH:
27091+
return "IP address mismatch";
27092+
2708727093
default:
2708827094
return NULL;
2708927095
}

src/x509_str.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,33 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
740740
wolfSSL_sk_X509_free(certsToUse);
741741
}
742742

743+
/* Enforce hostname / IP verification from X509_VERIFY_PARAM if set.
744+
* Always check against the leaf (end-entity) certificate, captured in
745+
* orig before the chain-building loop modified ctx->current_cert. */
746+
if (ctx->param != NULL) {
747+
if (ret == WOLFSSL_SUCCESS && ctx->param->hostName[0] != '\0') {
748+
if (wolfSSL_X509_check_host(orig,
749+
ctx->param->hostName,
750+
XSTRLEN(ctx->param->hostName),
751+
ctx->param->hostFlags, NULL) != WOLFSSL_SUCCESS) {
752+
ctx->error = WOLFSSL_X509_V_ERR_HOSTNAME_MISMATCH;
753+
ctx->error_depth = 0;
754+
ctx->current_cert = orig;
755+
ret = WOLFSSL_FAILURE;
756+
}
757+
}
758+
if (ret == WOLFSSL_SUCCESS && ctx->param->ipasc[0] != '\0') {
759+
if (wolfSSL_X509_check_ip_asc(orig,
760+
ctx->param->ipasc,
761+
ctx->param->hostFlags) != WOLFSSL_SUCCESS) {
762+
ctx->error = WOLFSSL_X509_V_ERR_IP_ADDRESS_MISMATCH;
763+
ctx->error_depth = 0;
764+
ctx->current_cert = orig;
765+
ret = WOLFSSL_FAILURE;
766+
}
767+
}
768+
}
769+
743770
return ret == WOLFSSL_SUCCESS ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
744771
}
745772

tests/api.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27168,6 +27168,8 @@ static int error_test(void)
2716827168
{17, 15},
2716927169
{19, 19},
2717027170
{27, 26 },
27171+
{61, 30},
27172+
{63, 63},
2717127173
#endif
2717227174
{ -9, WC_SPAN1_FIRST_E + 1 },
2717327175
{ -124, -124 },

tests/api/test_x509.c

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,104 @@ int test_x509_GetCAByAKID(void)
244244
return EXPECT_RESULT();
245245
}
246246

247+
/* Regression test: wolfSSL_X509_verify_cert() must honour the hostname set via
248+
* X509_VERIFY_PARAM_set1_host(). Before the fix the hostname was stored in
249+
* ctx->param->hostName but never consulted, so any chain-valid certificate
250+
* would pass regardless of hostname mismatch (RFC 6125 sec. 6.4.1 violation).
251+
*
252+
* Uses existing PEM fixtures:
253+
* svrCertFile - CN=www.wolfssl.com, SAN DNS=example.com, SAN IP=127.0.0.1
254+
* caCertFile - CA that signed svrCertFile
255+
*/
256+
int test_x509_verify_cert_hostname_check(void)
257+
{
258+
EXPECT_DECLS;
259+
#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_RSA)
260+
WOLFSSL_X509_STORE* store = NULL;
261+
WOLFSSL_X509_STORE_CTX* ctx = NULL;
262+
WOLFSSL_X509* ca = NULL;
263+
WOLFSSL_X509* leaf = NULL;
264+
WOLFSSL_X509_VERIFY_PARAM* param = NULL;
265+
266+
ExpectNotNull(store = wolfSSL_X509_STORE_new());
267+
ExpectNotNull(ca = wolfSSL_X509_load_certificate_file(caCertFile,
268+
SSL_FILETYPE_PEM));
269+
ExpectIntEQ(wolfSSL_X509_STORE_add_cert(store, ca), WOLFSSL_SUCCESS);
270+
271+
ExpectNotNull(leaf = wolfSSL_X509_load_certificate_file(svrCertFile,
272+
SSL_FILETYPE_PEM));
273+
274+
/* Case 1: no hostname constraint - must succeed. */
275+
ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new());
276+
ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, leaf, NULL),
277+
WOLFSSL_SUCCESS);
278+
ExpectIntEQ(wolfSSL_X509_verify_cert(ctx), WOLFSSL_SUCCESS);
279+
wolfSSL_X509_STORE_CTX_free(ctx);
280+
ctx = NULL;
281+
282+
/* Case 2: hostname matches a SAN DNS entry - must succeed. */
283+
ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new());
284+
ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, leaf, NULL),
285+
WOLFSSL_SUCCESS);
286+
param = wolfSSL_X509_STORE_CTX_get0_param(ctx);
287+
ExpectNotNull(param);
288+
ExpectIntEQ(wolfSSL_X509_VERIFY_PARAM_set1_host(param, "example.com",
289+
XSTRLEN("example.com")), WOLFSSL_SUCCESS);
290+
ExpectIntEQ(wolfSSL_X509_verify_cert(ctx), WOLFSSL_SUCCESS);
291+
wolfSSL_X509_STORE_CTX_free(ctx);
292+
ctx = NULL;
293+
294+
/* Case 3: hostname does not match - must FAIL with the right error code. */
295+
ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new());
296+
ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, leaf, NULL),
297+
WOLFSSL_SUCCESS);
298+
param = wolfSSL_X509_STORE_CTX_get0_param(ctx);
299+
ExpectNotNull(param);
300+
ExpectIntEQ(wolfSSL_X509_VERIFY_PARAM_set1_host(param, "wrong.com",
301+
XSTRLEN("wrong.com")), WOLFSSL_SUCCESS);
302+
ExpectIntNE(wolfSSL_X509_verify_cert(ctx), WOLFSSL_SUCCESS);
303+
ExpectIntEQ(wolfSSL_X509_STORE_CTX_get_error(ctx),
304+
X509_V_ERR_HOSTNAME_MISMATCH);
305+
ExpectIntEQ(wolfSSL_X509_STORE_CTX_get_error_depth(ctx), 0);
306+
wolfSSL_X509_STORE_CTX_free(ctx);
307+
ctx = NULL;
308+
309+
#ifdef WOLFSSL_IP_ALT_NAME
310+
/* Case 4: IP matches a SAN IP entry - must succeed. */
311+
ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new());
312+
ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, leaf, NULL),
313+
WOLFSSL_SUCCESS);
314+
param = wolfSSL_X509_STORE_CTX_get0_param(ctx);
315+
ExpectNotNull(param);
316+
ExpectIntEQ(wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(param, "127.0.0.1"),
317+
WOLFSSL_SUCCESS);
318+
ExpectIntEQ(wolfSSL_X509_verify_cert(ctx), WOLFSSL_SUCCESS);
319+
wolfSSL_X509_STORE_CTX_free(ctx);
320+
ctx = NULL;
321+
322+
/* Case 5: IP does not match - must FAIL with the right error code. */
323+
ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new());
324+
ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, leaf, NULL),
325+
WOLFSSL_SUCCESS);
326+
param = wolfSSL_X509_STORE_CTX_get0_param(ctx);
327+
ExpectNotNull(param);
328+
ExpectIntEQ(wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(param, "192.168.1.1"),
329+
WOLFSSL_SUCCESS);
330+
ExpectIntNE(wolfSSL_X509_verify_cert(ctx), WOLFSSL_SUCCESS);
331+
ExpectIntEQ(wolfSSL_X509_STORE_CTX_get_error(ctx),
332+
X509_V_ERR_IP_ADDRESS_MISMATCH);
333+
ExpectIntEQ(wolfSSL_X509_STORE_CTX_get_error_depth(ctx), 0);
334+
wolfSSL_X509_STORE_CTX_free(ctx);
335+
ctx = NULL;
336+
#endif /* WOLFSSL_IP_ALT_NAME */
337+
338+
wolfSSL_X509_free(leaf);
339+
wolfSSL_X509_free(ca);
340+
wolfSSL_X509_STORE_free(store);
341+
#endif /* OPENSSL_EXTRA && !NO_FILESYSTEM && !NO_RSA */
342+
return EXPECT_RESULT();
343+
}
344+
247345
int test_x509_set_serialNumber(void)
248346
{
249347
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)

tests/api/test_x509.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@
2525
int test_x509_rfc2818_verification_callback(void);
2626
int test_x509_GetCAByAKID(void);
2727
int test_x509_set_serialNumber(void);
28+
int test_x509_verify_cert_hostname_check(void);
2829

2930
#define TEST_X509_DECLS \
3031
TEST_DECL_GROUP("x509", test_x509_rfc2818_verification_callback), \
3132
TEST_DECL_GROUP("x509", test_x509_GetCAByAKID), \
32-
TEST_DECL_GROUP("x509", test_x509_set_serialNumber)
33+
TEST_DECL_GROUP("x509", test_x509_set_serialNumber), \
34+
TEST_DECL_GROUP("x509", test_x509_verify_cert_hostname_check)
3335

3436
#endif /* WOLFCRYPT_TEST_X509_H */

wolfssl/ssl.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2685,7 +2685,9 @@ enum {
26852685
WOLFSSL_X509_V_ERR_PATH_LENGTH_EXCEEDED = 25,
26862686
WOLFSSL_X509_V_ERR_CERT_REJECTED = 28,
26872687
WOLFSSL_X509_V_ERR_SUBJECT_ISSUER_MISMATCH = 29,
2688-
WC_OSSL_V509_V_ERR_MAX = 30,
2688+
WOLFSSL_X509_V_ERR_HOSTNAME_MISMATCH = 62,
2689+
WOLFSSL_X509_V_ERR_IP_ADDRESS_MISMATCH = 64,
2690+
WC_OSSL_V509_V_ERR_MAX = 65,
26892691

26902692
#ifdef HAVE_OCSP
26912693
/* OCSP Flags */

wolfssl/wolfcrypt/settings.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4819,6 +4819,11 @@ extern void uITRON4_free(void *p) ;
48194819
#error "OPENSSL_ALL can not be defined with OPENSSL_COEXIST"
48204820
#endif
48214821

4822+
/* OPENSSL_ALL requires WOLFSSL_IP_ALT_NAME for IP SAN verification. */
4823+
#if defined(OPENSSL_ALL) && !defined(WOLFSSL_IP_ALT_NAME)
4824+
#error "OPENSSL_ALL requires WOLFSSL_IP_ALT_NAME"
4825+
#endif
4826+
48224827
#if !defined(NO_DSA) && defined(NO_SHA)
48234828
#error "Please disable DSA if disabling SHA-1"
48244829
#endif

0 commit comments

Comments
 (0)