Skip to content

Commit 08e5344

Browse files
committed
Add IP SAN matching
1 parent b02ddde commit 08e5344

7 files changed

Lines changed: 206 additions & 1 deletion

File tree

doc/dox_comments/header_files-ja/ssl.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5435,6 +5435,22 @@ int wolfSSL_want_read(WOLFSSL* ssl);
54355435
*/
54365436
int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn);
54375437

5438+
/*!
5439+
\ingroup Setup
5440+
5441+
\brief wolfSSL_connect() または wolfSSL_accept() の前にこの関数を呼ぶと、
5442+
ピア証明書の SAN iPAddress エントリに対する IP アドレス検証を追加します。
5443+
5444+
\return SSL_SUCCESS 成功。
5445+
\return SSL_FAILURE パラメータ不正またはメモリ確保失敗。
5446+
5447+
\param ssl wolfSSL_new() で作成された WOLFSSL 構造体へのポインタ。
5448+
\param ipaddr 検証する NULL 終端 ASCII IP アドレス文字列。
5449+
5450+
\sa wolfSSL_check_domain_name
5451+
*/
5452+
int wolfSSL_check_ip_address(WOLFSSL* ssl, const char* ipaddr);
5453+
54385454
/*!
54395455
\ingroup TLS
54405456

doc/dox_comments/header_files/ssl.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6432,6 +6432,37 @@ int wolfSSL_want_write(WOLFSSL* ssl);
64326432
*/
64336433
int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn);
64346434

6435+
/*!
6436+
\ingroup Setup
6437+
6438+
\brief Calling this function before wolfSSL_connect() or wolfSSL_accept()
6439+
adds an IP-address identity check against the peer certificate SAN
6440+
iPAddress entries.
6441+
6442+
\return SSL_SUCCESS upon success.
6443+
\return SSL_FAILURE if parameters are invalid or memory allocation fails.
6444+
6445+
\param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new().
6446+
\param ipaddr NULL-terminated ASCII IP address string to verify against the
6447+
peer certificate.
6448+
6449+
_Example_
6450+
\code
6451+
int ret = 0;
6452+
WOLFSSL* ssl;
6453+
const char* ip = "127.0.0.1";
6454+
...
6455+
6456+
ret = wolfSSL_check_ip_address(ssl, ip);
6457+
if (ret != SSL_SUCCESS) {
6458+
// failed to enable IP check
6459+
}
6460+
\endcode
6461+
6462+
\sa wolfSSL_check_domain_name
6463+
*/
6464+
int wolfSSL_check_ip_address(WOLFSSL* ssl, const char* ipaddr);
6465+
64356466
/*!
64366467
\ingroup TLS
64376468

src/internal.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8627,6 +8627,7 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl)
86278627
FreeHandshakeHashes(ssl);
86288628
#endif
86298629
XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
8630+
XFREE(ssl->buffers.ipasc.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
86308631

86318632
/* clear keys struct after session */
86328633
ForceZero(&ssl->keys, sizeof(Keys));
@@ -16792,7 +16793,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
1679216793
(char*)ssl->buffers.domainName.buffer,
1679316794
(ssl->buffers.domainName.buffer == NULL ? 0 :
1679416795
(word32)XSTRLEN(ssl->buffers.domainName.buffer)),
16795-
NULL, 0) != 1) {
16796+
NULL, 0, 0) != 1) {
1679616797
WOLFSSL_MSG("DomainName match failed");
1679716798
/* try to get peer key still */
1679816799
ret = DOMAIN_NAME_MISMATCH;
@@ -16802,6 +16803,17 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
1680216803
#endif /* WOLFSSL_ALL_NO_CN_IN_SAN */
1680316804
}
1680416805

16806+
#ifndef OPENSSL_EXTRA
16807+
if (!ssl->options.verifyNone && ssl->buffers.ipasc.buffer) {
16808+
if (CheckIPAddr(args->dCert,
16809+
(const char*)ssl->buffers.ipasc.buffer) != 0) {
16810+
WOLFSSL_MSG("IPAddr match on alt names failed");
16811+
ret = IPADDR_MISMATCH;
16812+
WOLFSSL_ERROR_VERBOSE(ret);
16813+
}
16814+
}
16815+
#endif
16816+
1680516817
/* decode peer key */
1680616818
switch (args->dCert->keyOID) {
1680716819
#ifndef NO_RSA

src/ssl.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7462,6 +7462,48 @@ int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn)
74627462
}
74637463
}
74647464

7465+
/* call before SSL_connect, if verifying will add IP SAN check to
7466+
date check and signature check */
7467+
WOLFSSL_ABI
7468+
int wolfSSL_check_ip_address(WOLFSSL* ssl, const char* ipaddr)
7469+
{
7470+
WOLFSSL_ENTER("wolfSSL_check_ip_address");
7471+
7472+
if (ssl == NULL || ipaddr == NULL) {
7473+
WOLFSSL_MSG("Bad function argument: NULL");
7474+
return WOLFSSL_FAILURE;
7475+
}
7476+
7477+
if (ssl->buffers.ipasc.buffer != NULL) {
7478+
XFREE(ssl->buffers.ipasc.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
7479+
ssl->buffers.ipasc.buffer = NULL;
7480+
ssl->buffers.ipasc.length = 0;
7481+
}
7482+
7483+
ssl->buffers.ipasc.length = (word32)XSTRLEN(ipaddr);
7484+
ssl->buffers.ipasc.buffer = (byte*)XMALLOC(ssl->buffers.ipasc.length + 1,
7485+
ssl->heap, DYNAMIC_TYPE_DOMAIN);
7486+
if (ssl->buffers.ipasc.buffer == NULL) {
7487+
ssl->error = MEMORY_ERROR;
7488+
return WOLFSSL_FAILURE;
7489+
}
7490+
7491+
XMEMCPY(ssl->buffers.ipasc.buffer, ipaddr, ssl->buffers.ipasc.length);
7492+
ssl->buffers.ipasc.buffer[ssl->buffers.ipasc.length] = '\0';
7493+
7494+
#ifdef OPENSSL_EXTRA
7495+
if (ssl->param == NULL) {
7496+
return WOLFSSL_FAILURE;
7497+
}
7498+
if (wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(ssl->param, ipaddr) !=
7499+
WOLFSSL_SUCCESS) {
7500+
return WOLFSSL_FAILURE;
7501+
}
7502+
#endif
7503+
7504+
return WOLFSSL_SUCCESS;
7505+
}
7506+
74657507
#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
74667508
const char *wolfSSL_get0_peername(WOLFSSL *ssl) {
74677509
if (ssl == NULL) {

tests/api.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15288,6 +15288,8 @@ static int test_wolfSSL_check_domain_basic_client_ssl(WOLFSSL* ssl)
1528815288

1528915289
return EXPECT_RESULT();
1529015290
}
15291+
/* Verify wolfSSL_check_domain_name() controls DNS-name matching during
15292+
* handshake with expected fail/pass outcomes. */
1529115293
static int test_wolfSSL_check_domain_basic(void)
1529215294
{
1529315295
EXPECT_DECLS;
@@ -15320,6 +15322,102 @@ static int test_wolfSSL_check_domain_basic(void)
1532015322
}
1532115323
#endif /* HAVE_SSL_MEMIO_TESTS_DEPENDENCIES */
1532215324

15325+
#if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \
15326+
(defined(WOLFSSL_IP_ALT_NAME) || defined(OPENSSL_ALL)) && \
15327+
!defined(OPENSSL_COMPATIBLE_DEFAULTS) && !defined(NO_SHA256)
15328+
static const char* ipaddr = NULL;
15329+
static int test_wolfSSL_check_ip_param_client_ssl(WOLFSSL* ssl)
15330+
{
15331+
EXPECT_DECLS;
15332+
X509_VERIFY_PARAM* param = NULL;
15333+
15334+
ExpectNotNull(param = SSL_get0_param(ssl));
15335+
ExpectIntEQ(X509_VERIFY_PARAM_set1_ip_asc(param, ipaddr), WOLFSSL_SUCCESS);
15336+
15337+
return EXPECT_RESULT();
15338+
}
15339+
15340+
/* Verify the OpenSSL-compat verify-param path:
15341+
* SSL_get0_param() + X509_VERIFY_PARAM_set1_ip_asc() controls IP SAN matching
15342+
* during handshake. */
15343+
static int test_wolfSSL_check_ip_param_basic(void)
15344+
{
15345+
EXPECT_DECLS;
15346+
test_ssl_cbf func_cb_client;
15347+
test_ssl_cbf func_cb_server;
15348+
15349+
XMEMSET(&func_cb_client, 0, sizeof(func_cb_client));
15350+
XMEMSET(&func_cb_server, 0, sizeof(func_cb_server));
15351+
15352+
func_cb_client.ssl_ready = &test_wolfSSL_check_ip_param_client_ssl;
15353+
15354+
ipaddr = "127.0.0.2";
15355+
/* Expect to fail: cert SAN IP is 127.0.0.1 */
15356+
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client,
15357+
&func_cb_server, NULL), -1001);
15358+
15359+
ipaddr = "127.0.0.1";
15360+
/* Expect to succeed */
15361+
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client,
15362+
&func_cb_server, NULL), TEST_SUCCESS);
15363+
15364+
return EXPECT_RESULT();
15365+
}
15366+
#else
15367+
static int test_wolfSSL_check_ip_param_basic(void)
15368+
{
15369+
EXPECT_DECLS;
15370+
return EXPECT_RESULT();
15371+
}
15372+
#endif
15373+
15374+
#if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \
15375+
!defined(OPENSSL_COMPATIBLE_DEFAULTS) && !defined(NO_SHA256) && \
15376+
defined(WOLFSSL_IP_ALT_NAME)
15377+
static const char* ipaddr_api = NULL;
15378+
static int test_wolfSSL_check_ip_address_basic_client_ssl(WOLFSSL* ssl)
15379+
{
15380+
EXPECT_DECLS;
15381+
15382+
ExpectIntEQ(wolfSSL_check_ip_address(ssl, ipaddr_api), WOLFSSL_SUCCESS);
15383+
15384+
return EXPECT_RESULT();
15385+
}
15386+
15387+
/* Verify wolfSSL convenience API path:
15388+
* wolfSSL_check_ip_address() enables IP SAN matching during handshake,
15389+
* including the non-OPENSSL_EXTRA storage/verification flow. */
15390+
static int test_wolfSSL_check_ip_address_basic(void)
15391+
{
15392+
EXPECT_DECLS;
15393+
test_ssl_cbf func_cb_client;
15394+
test_ssl_cbf func_cb_server;
15395+
15396+
XMEMSET(&func_cb_client, 0, sizeof(func_cb_client));
15397+
XMEMSET(&func_cb_server, 0, sizeof(func_cb_server));
15398+
15399+
func_cb_client.ssl_ready = &test_wolfSSL_check_ip_address_basic_client_ssl;
15400+
15401+
ipaddr_api = "127.0.0.2";
15402+
/* Expect to fail: cert SAN IP is 127.0.0.1 */
15403+
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client,
15404+
&func_cb_server, NULL), -1001);
15405+
15406+
ipaddr_api = "127.0.0.1";
15407+
/* Expect to succeed */
15408+
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client,
15409+
&func_cb_server, NULL), TEST_SUCCESS);
15410+
15411+
return EXPECT_RESULT();
15412+
}
15413+
#else
15414+
static int test_wolfSSL_check_ip_address_basic(void)
15415+
{
15416+
EXPECT_DECLS;
15417+
return EXPECT_RESULT();
15418+
}
15419+
#endif
15420+
1532315421
static int test_wolfSSL_BUF(void)
1532415422
{
1532515423
EXPECT_DECLS;
@@ -33192,6 +33290,8 @@ TEST_CASE testCases[] = {
3319233290

3319333291
TEST_DECL(test_wolfSSL_check_domain),
3319433292
TEST_DECL(test_wolfSSL_check_domain_basic),
33293+
TEST_DECL(test_wolfSSL_check_ip_param_basic),
33294+
TEST_DECL(test_wolfSSL_check_ip_address_basic),
3319533295
TEST_DECL(test_wolfSSL_cert_cb),
3319633296
TEST_DECL(test_wolfSSL_cert_cb_dyn_ciphers),
3319733297
TEST_DECL(test_wolfSSL_ciphersuite_auth),

wolfssl/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4876,6 +4876,7 @@ typedef struct Buffers {
48764876
ThreadCrypt encrypt[WOLFSSL_THREADED_CRYPT_CNT];
48774877
#endif
48784878
buffer domainName; /* for client check */
4879+
buffer ipasc; /* for client IP SAN check */
48794880
buffer clearOutputBuffer;
48804881
buffer sig; /* signature data */
48814882
buffer digest; /* digest data */

wolfssl/ssl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3356,6 +3356,9 @@ WOLFSSL_API int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx,
33563356
/* call before SSL_connect, if verifying will add name check to
33573357
date check and signature check */
33583358
WOLFSSL_ABI WOLFSSL_API int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn);
3359+
/* call before SSL_connect, if verifying will add IP address check to
3360+
date check and signature check */
3361+
WOLFSSL_ABI WOLFSSL_API int wolfSSL_check_ip_address(WOLFSSL* ssl, const char* ipaddr);
33593362

33603363

33613364
/* need to call once to load library (session cache) */

0 commit comments

Comments
 (0)