Add IP SAN matching

This commit is contained in:
Paul Adelsbach
2026-03-11 14:02:05 -07:00
parent 8b388ba3e3
commit 041bb185c6
7 changed files with 206 additions and 1 deletions
+16
View File
@@ -5435,6 +5435,22 @@ int wolfSSL_want_read(WOLFSSL* ssl);
*/
int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn);
/*!
\ingroup Setup
\brief wolfSSL_connect() wolfSSL_accept()
SAN iPAddress IP
\return SSL_SUCCESS
\return SSL_FAILURE
\param ssl wolfSSL_new() WOLFSSL
\param ipaddr NULL ASCII IP
\sa wolfSSL_check_domain_name
*/
int wolfSSL_check_ip_address(WOLFSSL* ssl, const char* ipaddr);
/*!
\ingroup TLS
+31
View File
@@ -6432,6 +6432,37 @@ int wolfSSL_want_write(WOLFSSL* ssl);
*/
int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn);
/*!
\ingroup Setup
\brief Calling this function before wolfSSL_connect() or wolfSSL_accept()
adds an IP-address identity check against the peer certificate SAN
iPAddress entries.
\return SSL_SUCCESS upon success.
\return SSL_FAILURE if parameters are invalid or memory allocation fails.
\param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new().
\param ipaddr NULL-terminated ASCII IP address string to verify against the
peer certificate.
_Example_
\code
int ret = 0;
WOLFSSL* ssl;
const char* ip = "127.0.0.1";
...
ret = wolfSSL_check_ip_address(ssl, ip);
if (ret != SSL_SUCCESS) {
// failed to enable IP check
}
\endcode
\sa wolfSSL_check_domain_name
*/
int wolfSSL_check_ip_address(WOLFSSL* ssl, const char* ipaddr);
/*!
\ingroup TLS
+13 -1
View File
@@ -8659,6 +8659,7 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl)
FreeHandshakeHashes(ssl);
#endif
XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
XFREE(ssl->buffers.ipasc.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
/* clear keys struct after session */
ForceZero(&ssl->keys, sizeof(Keys));
@@ -16828,7 +16829,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
(char*)ssl->buffers.domainName.buffer,
(ssl->buffers.domainName.buffer == NULL ? 0 :
(word32)XSTRLEN(ssl->buffers.domainName.buffer)),
NULL, 0) != 1) {
NULL, 0, 0) != 1) {
WOLFSSL_MSG("DomainName match failed");
/* try to get peer key still */
ret = DOMAIN_NAME_MISMATCH;
@@ -16838,6 +16839,17 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#endif /* WOLFSSL_ALL_NO_CN_IN_SAN */
}
#ifndef OPENSSL_EXTRA
if (!ssl->options.verifyNone && ssl->buffers.ipasc.buffer) {
if (CheckIPAddr(args->dCert,
(const char*)ssl->buffers.ipasc.buffer) != 0) {
WOLFSSL_MSG("IPAddr match on alt names failed");
ret = IPADDR_MISMATCH;
WOLFSSL_ERROR_VERBOSE(ret);
}
}
#endif
/* decode peer key */
switch (args->dCert->keyOID) {
#ifndef NO_RSA
+42
View File
@@ -7468,6 +7468,48 @@ int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn)
}
}
/* call before SSL_connect, if verifying will add IP SAN check to
date check and signature check */
WOLFSSL_ABI
int wolfSSL_check_ip_address(WOLFSSL* ssl, const char* ipaddr)
{
WOLFSSL_ENTER("wolfSSL_check_ip_address");
if (ssl == NULL || ipaddr == NULL) {
WOLFSSL_MSG("Bad function argument: NULL");
return WOLFSSL_FAILURE;
}
if (ssl->buffers.ipasc.buffer != NULL) {
XFREE(ssl->buffers.ipasc.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
ssl->buffers.ipasc.buffer = NULL;
ssl->buffers.ipasc.length = 0;
}
ssl->buffers.ipasc.length = (word32)XSTRLEN(ipaddr);
ssl->buffers.ipasc.buffer = (byte*)XMALLOC(ssl->buffers.ipasc.length + 1,
ssl->heap, DYNAMIC_TYPE_DOMAIN);
if (ssl->buffers.ipasc.buffer == NULL) {
ssl->error = MEMORY_ERROR;
return WOLFSSL_FAILURE;
}
XMEMCPY(ssl->buffers.ipasc.buffer, ipaddr, ssl->buffers.ipasc.length);
ssl->buffers.ipasc.buffer[ssl->buffers.ipasc.length] = '\0';
#ifdef OPENSSL_EXTRA
if (ssl->param == NULL) {
return WOLFSSL_FAILURE;
}
if (wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(ssl->param, ipaddr) !=
WOLFSSL_SUCCESS) {
return WOLFSSL_FAILURE;
}
#endif
return WOLFSSL_SUCCESS;
}
#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
const char *wolfSSL_get0_peername(WOLFSSL *ssl) {
if (ssl == NULL) {
+100
View File
@@ -15998,6 +15998,8 @@ static int test_wolfSSL_check_domain_basic_client_ssl(WOLFSSL* ssl)
return EXPECT_RESULT();
}
/* Verify wolfSSL_check_domain_name() controls DNS-name matching during
* handshake with expected fail/pass outcomes. */
static int test_wolfSSL_check_domain_basic(void)
{
EXPECT_DECLS;
@@ -16030,6 +16032,102 @@ static int test_wolfSSL_check_domain_basic(void)
}
#endif /* HAVE_SSL_MEMIO_TESTS_DEPENDENCIES */
#if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \
(defined(WOLFSSL_IP_ALT_NAME) || defined(OPENSSL_ALL)) && \
!defined(OPENSSL_COMPATIBLE_DEFAULTS) && !defined(NO_SHA256)
static const char* ipaddr = NULL;
static int test_wolfSSL_check_ip_param_client_ssl(WOLFSSL* ssl)
{
EXPECT_DECLS;
X509_VERIFY_PARAM* param = NULL;
ExpectNotNull(param = SSL_get0_param(ssl));
ExpectIntEQ(X509_VERIFY_PARAM_set1_ip_asc(param, ipaddr), WOLFSSL_SUCCESS);
return EXPECT_RESULT();
}
/* Verify the OpenSSL-compat verify-param path:
* SSL_get0_param() + X509_VERIFY_PARAM_set1_ip_asc() controls IP SAN matching
* during handshake. */
static int test_wolfSSL_check_ip_param_basic(void)
{
EXPECT_DECLS;
test_ssl_cbf func_cb_client;
test_ssl_cbf func_cb_server;
XMEMSET(&func_cb_client, 0, sizeof(func_cb_client));
XMEMSET(&func_cb_server, 0, sizeof(func_cb_server));
func_cb_client.ssl_ready = &test_wolfSSL_check_ip_param_client_ssl;
ipaddr = "127.0.0.2";
/* Expect to fail: cert SAN IP is 127.0.0.1 */
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client,
&func_cb_server, NULL), -1001);
ipaddr = "127.0.0.1";
/* Expect to succeed */
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client,
&func_cb_server, NULL), TEST_SUCCESS);
return EXPECT_RESULT();
}
#else
static int test_wolfSSL_check_ip_param_basic(void)
{
EXPECT_DECLS;
return EXPECT_RESULT();
}
#endif
#if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \
!defined(OPENSSL_COMPATIBLE_DEFAULTS) && !defined(NO_SHA256) && \
defined(WOLFSSL_IP_ALT_NAME)
static const char* ipaddr_api = NULL;
static int test_wolfSSL_check_ip_address_basic_client_ssl(WOLFSSL* ssl)
{
EXPECT_DECLS;
ExpectIntEQ(wolfSSL_check_ip_address(ssl, ipaddr_api), WOLFSSL_SUCCESS);
return EXPECT_RESULT();
}
/* Verify wolfSSL convenience API path:
* wolfSSL_check_ip_address() enables IP SAN matching during handshake,
* including the non-OPENSSL_EXTRA storage/verification flow. */
static int test_wolfSSL_check_ip_address_basic(void)
{
EXPECT_DECLS;
test_ssl_cbf func_cb_client;
test_ssl_cbf func_cb_server;
XMEMSET(&func_cb_client, 0, sizeof(func_cb_client));
XMEMSET(&func_cb_server, 0, sizeof(func_cb_server));
func_cb_client.ssl_ready = &test_wolfSSL_check_ip_address_basic_client_ssl;
ipaddr_api = "127.0.0.2";
/* Expect to fail: cert SAN IP is 127.0.0.1 */
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client,
&func_cb_server, NULL), -1001);
ipaddr_api = "127.0.0.1";
/* Expect to succeed */
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client,
&func_cb_server, NULL), TEST_SUCCESS);
return EXPECT_RESULT();
}
#else
static int test_wolfSSL_check_ip_address_basic(void)
{
EXPECT_DECLS;
return EXPECT_RESULT();
}
#endif
static int test_wolfSSL_BUF(void)
{
EXPECT_DECLS;
@@ -34155,6 +34253,8 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wolfSSL_check_domain),
TEST_DECL(test_wolfSSL_check_domain_basic),
TEST_DECL(test_wolfSSL_check_ip_param_basic),
TEST_DECL(test_wolfSSL_check_ip_address_basic),
TEST_DECL(test_wolfSSL_cert_cb),
TEST_DECL(test_wolfSSL_cert_cb_dyn_ciphers),
TEST_DECL(test_wolfSSL_ciphersuite_auth),
+1
View File
@@ -4891,6 +4891,7 @@ typedef struct Buffers {
ThreadCrypt encrypt[WOLFSSL_THREADED_CRYPT_CNT];
#endif
buffer domainName; /* for client check */
buffer ipasc; /* for client IP SAN check */
buffer clearOutputBuffer;
buffer sig; /* signature data */
buffer digest; /* digest data */
+3
View File
@@ -3356,6 +3356,9 @@ WOLFSSL_API int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx,
/* call before SSL_connect, if verifying will add name check to
date check and signature check */
WOLFSSL_ABI WOLFSSL_API int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn);
/* call before SSL_connect, if verifying will add IP address check to
date check and signature check */
WOLFSSL_ABI WOLFSSL_API int wolfSSL_check_ip_address(WOLFSSL* ssl, const char* ipaddr);
/* need to call once to load library (session cache) */