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
1 change: 1 addition & 0 deletions .wolfssl_known_macro_extras
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,7 @@ WOLFSSL_USE_FLASHMEM
WOLFSSL_USE_FORCE_ZERO
WOLFSSL_USE_OPTIONS_H
WOLFSSL_VALIDATE_DH_KEYGEN
WOLFSSL_VERIFY_NONE_DEFAULT
WOLFSSL_WC_SLHDSA_RECURSIVE
WOLFSSL_WC_XMSS_NO_SHA256
WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME
Expand Down
6 changes: 6 additions & 0 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -2642,6 +2642,12 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)

XMEMSET(ctx, 0, sizeof(WOLFSSL_CTX));

#ifdef WOLFSSL_VERIFY_NONE_DEFAULT
Comment thread
dgarske marked this conversation as resolved.
/* OpenSSL compat: default to SSL_VERIFY_NONE unless the app
* sets SSL_VERIFY_PEER. */
ctx->verifyNone = 1;
#endif

ctx->method = method;
if (heap == NULL) {
ctx->heap = ctx; /* defaults to self */
Expand Down
44 changes: 44 additions & 0 deletions tests/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1793,6 +1793,46 @@ static int test_wolfSSL_CTX_new(void)
}
#endif

#if defined(WOLFSSL_VERIFY_NONE_DEFAULT) && !defined(NO_WOLFSSL_CLIENT) && \
!defined(NO_TLS)
/* WOLFSSL_VERIFY_NONE_DEFAULT makes a fresh CTX default to SSL_VERIFY_NONE
* (OpenSSL compat). Assert the default is applied, inherited by a spawned
* SSL, and correctly overridden by wolfSSL_CTX_set_verify(). */
static int test_wolfSSL_CTX_verify_none_default(void)
{
EXPECT_DECLS;
WOLFSSL_CTX* ctx = NULL;
WOLFSSL* ssl = NULL;

ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));

/* Freshly created CTX defaults to no verification. */
ExpectIntEQ(ctx->verifyNone, 1);
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
ExpectIntEQ(wolfSSL_CTX_get_verify_mode(ctx), WOLFSSL_VERIFY_NONE);
#endif

/* A spawned SSL inherits the default. */
ExpectNotNull(ssl = wolfSSL_new(ctx));
ExpectIntEQ(ssl->options.verifyNone, 1);
wolfSSL_free(ssl);

/* SSL_VERIFY_PEER clears the default. */
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL);
ExpectIntEQ(ctx->verifyNone, 0);
ExpectIntEQ(ctx->verifyPeer, 1);

/* WOLFSSL_VERIFY_DEFAULT resets verifyNone back to 0 (does not restore
* the compat default). */
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_DEFAULT, NULL);
ExpectIntEQ(ctx->verifyNone, 0);

wolfSSL_CTX_free(ctx);

return EXPECT_RESULT();
}
#endif

#if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \
!defined(NO_TLS) && \
(!defined(NO_RSA) || defined(HAVE_ECC)) && !defined(NO_FILESYSTEM)
Expand Down Expand Up @@ -35250,6 +35290,10 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wolfSSL_Method_Allocators),
#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS)
TEST_DECL(test_wolfSSL_CTX_new),
#endif
#if defined(WOLFSSL_VERIFY_NONE_DEFAULT) && !defined(NO_WOLFSSL_CLIENT) && \
!defined(NO_TLS)
TEST_DECL(test_wolfSSL_CTX_verify_none_default),
#endif
TEST_DECL(test_server_wolfSSL_new),
TEST_DECL(test_client_wolfSSL_new),
Expand Down
31 changes: 31 additions & 0 deletions wolfssl/openssl/bio.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,37 @@
#define BIO_meth_set_create wolfSSL_BIO_meth_set_create
#define BIO_meth_set_destroy wolfSSL_BIO_meth_set_destroy

#define WOLFSSL_BIO_TYPE_DESCRIPTOR 0x0100
#define WOLFSSL_BIO_TYPE_SOURCE_SINK 0x0400

/* OpenSSL allocates a fresh BIO type index per call; wolfSSL

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 [Low] BIO compat stubs report success/fixed values with silent limitations

wolfSSL_BIO_get_new_index() returns a fixed 1000 for every call, so two distinct app-defined BIO types receive the same index and are indistinguishable if compared. wolfSSL_BIO_meth_set_callback_ctrl() is an always-success no-op that discards the callback and returns 1, which conflicts with the wolfSSL guideline of not shipping always-success stubs (a caller that relies on the callback later being invoked gets no indication it was dropped). The getters correctly return NULL. These mirror OpenSSL's return conventions and are documented in the comments, so this is a low-priority observation rather than a defect.

Fix: If uniqueness is ever needed, hand out a monotonically increasing index instead of a constant. Keep the comment explicit that callback_ctrl is unsupported so callers don't assume the callback fires.

* untracked, so return a fixed app-range index. */
static WC_INLINE int wolfSSL_BIO_get_new_index(void) { return 1000; }

/* wolfSSL does not store these BIO method callbacks; getters
* report none, set_callback_ctrl is a no-op. */
static WC_INLINE void *
wolfSSL_BIO_meth_get_gets(WOLFSSL_BIO_METHOD *m)
{ (void)m; return NULL; }
static WC_INLINE void *
wolfSSL_BIO_meth_get_puts(WOLFSSL_BIO_METHOD *m)
{ (void)m; return NULL; }
static WC_INLINE void *
wolfSSL_BIO_meth_get_ctrl(WOLFSSL_BIO_METHOD *m)
{ (void)m; return NULL; }
static WC_INLINE void *
wolfSSL_BIO_meth_get_create(WOLFSSL_BIO_METHOD *m)
{ (void)m; return NULL; }
static WC_INLINE void *
wolfSSL_BIO_meth_get_destroy(WOLFSSL_BIO_METHOD *m)
{ (void)m; return NULL; }
static WC_INLINE void *
wolfSSL_BIO_meth_get_callback_ctrl(WOLFSSL_BIO_METHOD *m)
{ (void)m; return NULL; }
static WC_INLINE int
wolfSSL_BIO_meth_set_callback_ctrl(WOLFSSL_BIO_METHOD *m, void *cb)
{ (void)m; (void)cb; return 1; }

#define BIO_snprintf XSNPRINTF

/* BIO CTRL */
Expand Down
12 changes: 12 additions & 0 deletions wolfssl/openssl/err.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,22 @@
#define WOLFSSL_SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 2
#define WOLFSSL_SSL_F_SSL_USE_PRIVATEKEY 3
#define WOLFSSL_EC_F_EC_GFP_SIMPLE_POINT2OCT 4
#define WOLFSSL_SSL_F_SSL_SET_FD 5

/* reasons */
#define WOLFSSL_ERR_R_SYS_LIB 1
#define WOLFSSL_PKCS12_R_MAC_VERIFY_FAILURE 2
/* Matches OpenSSL's ERR_R_BUF_LIB (= ERR_LIB_BUF, 7). */
#define WOLFSSL_ERR_R_BUF_LIB 7
#define WOLFSSL_SSL_R_UNKNOWN_PROTOCOL 252
#define WOLFSSL_SSL_R_WRONG_VERSION_NUMBER 267
#define WOLFSSL_SSL_R_UNSUPPORTED_PROTOCOL 258
#define WOLFSSL_SSL_R_NO_PROTOCOLS_AVAILABLE 194
#define WOLFSSL_SSL_R_BAD_PROTOCOL_VERSION_NUMBER 182
#define WOLFSSL_SSL_R_UNKNOWN_SSL_VERSION 254
#define WOLFSSL_SSL_R_UNSUPPORTED_SSL_VERSION 259
#define WOLFSSL_SSL_R_WRONG_SSL_VERSION 266
#define WOLFSSL_SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070

#ifndef OPENSSL_COEXIST

Expand Down
6 changes: 6 additions & 0 deletions wolfssl/openssl/hmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@

#include <wolfssl/openssl/compat_types.h>
#include <wolfssl/openssl/opensslv.h>
/* OpenSSL's hmac.h pulls in evp.h; mirror it, but only on standalone
* include (WOLFSSL_SSL_H unset) to avoid an include cycle during
* wolfssl/ssl.h's own parse. */
#ifndef WOLFSSL_SSL_H
#include <wolfssl/openssl/evp.h>
#endif

#ifdef __cplusplus
extern "C" {
Expand Down
47 changes: 47 additions & 0 deletions wolfssl/openssl/objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,53 @@
#define NID_ad_OCSP WC_NID_ad_OCSP
#define NID_ad_ca_issuers WC_NID_ad_ca_issuers

/* OBJ_find_sigid_algs(): map a certificate signature-algorithm NID to its
* digest and public-key NIDs; returns 0 for unsupported algorithms. */
#ifndef BUILDING_WOLFSSL

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 [Medium] No test coverage for new wolfSSL_OBJ_find_sigid_algs mapping logic

The PR adds a non-trivial mapping function (a switch over ~10 signature-algorithm NIDs producing digest+pkey NID pairs, returning 0 for unsupported), but adds no unit test for it. grep finds no reference to OBJ_find_sigid_algs in tests/, examples/, or testsuite/. Mapping tables are exactly the kind of code where a transposed NID pair would go unnoticed. The verifyNone default got a good targeted test (test_wolfSSL_CTX_verify_none_default); this helper deserves the same.

Fix: Add an api.c test that calls OBJ_find_sigid_algs for a couple of RSA and ECDSA sig NIDs, asserts the returned digest/pkey NIDs and return==1, verifies NULL out-params are tolerated, and asserts an unsupported NID returns 0 without touching the out-params.

static WC_INLINE int
Comment thread
dgarske marked this conversation as resolved.
wolfSSL_OBJ_find_sigid_algs(int sigid, int *pdig, int *ppkey)
{
int dig = 0;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 [Low] wolfSSL_OBJ_find_sigid_algs omits RSA-PSS, EdDSA, and MD5 signature NIDs

The mapping covers SHA1/224/256/384/512 with RSA and ECDSA but returns 0 (unsupported) for other algorithms wolfSSL/OpenSSL know, e.g. NID_rsassaPss (WC_NID_rsassaPss=912), Ed25519/Ed448, and md5WithRSAEncryption (WC_NID_md5WithRSAEncryption=99), all of which are already defined in evp.h. For EdDSA in particular, OpenSSL's OBJ_find_sigid_algs returns 1 with pkey set and digest = undef; returning 0 here diverges and may cause a compat consumer's certificate-algorithm introspection to treat those certs as unknown. This is acceptable as a documented limitation for the current use case but is a divergence from OpenSSL semantics.

Fix: Consider extending the switch (guarded by the relevant feature macros) to cover RSA-PSS and Ed25519/Ed448 to match OpenSSL, or note the intentional scope limitation in the function comment.

int pkey = 0;
int ret = 1;

switch (sigid) {
#ifndef NO_RSA
case WC_NID_sha1WithRSAEncryption:
dig = WC_NID_sha1; pkey = WC_NID_rsaEncryption; break;
case WC_NID_sha224WithRSAEncryption:
dig = WC_NID_sha224; pkey = WC_NID_rsaEncryption; break;
case WC_NID_sha256WithRSAEncryption:
dig = WC_NID_sha256; pkey = WC_NID_rsaEncryption; break;
case WC_NID_sha384WithRSAEncryption:
dig = WC_NID_sha384; pkey = WC_NID_rsaEncryption; break;
case WC_NID_sha512WithRSAEncryption:
dig = WC_NID_sha512; pkey = WC_NID_rsaEncryption; break;
#endif /* !NO_RSA */
#ifdef HAVE_ECC
case WC_NID_ecdsa_with_SHA1:
dig = WC_NID_sha1; pkey = WC_NID_X9_62_id_ecPublicKey; break;
case WC_NID_ecdsa_with_SHA224:
dig = WC_NID_sha224; pkey = WC_NID_X9_62_id_ecPublicKey; break;
case WC_NID_ecdsa_with_SHA256:
dig = WC_NID_sha256; pkey = WC_NID_X9_62_id_ecPublicKey; break;
case WC_NID_ecdsa_with_SHA384:
dig = WC_NID_sha384; pkey = WC_NID_X9_62_id_ecPublicKey; break;
case WC_NID_ecdsa_with_SHA512:
dig = WC_NID_sha512; pkey = WC_NID_X9_62_id_ecPublicKey; break;
#endif /* HAVE_ECC */
default:
ret = 0; break;
}

if (ret == 1) {
if (pdig != NULL) *pdig = dig;
if (ppkey != NULL) *ppkey = pkey;
}
return ret;
}
#endif

#endif /* !OPENSSL_COEXIST */

#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
Expand Down
42 changes: 39 additions & 3 deletions wolfssl/openssl/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <wolfssl/openssl/evp.h>
#endif
#include <wolfssl/openssl/bio.h>
#include <wolfssl/openssl/err.h>
#ifdef OPENSSL_EXTRA
#include <wolfssl/openssl/crypto.h>
#endif
Expand Down Expand Up @@ -1568,6 +1569,14 @@ typedef WOLFSSL_SRTP_PROTECTION_PROFILE SRTP_PROTECTION_PROFILE;
#define SSL_get_state wolfSSL_get_state
#define SSL_state_string_long wolfSSL_state_string_long

/* Must equal HANDSHAKE_DONE in the internal 'enum states'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 [Medium] WOLFSSL_TLS_ST_OK hardcoded to 16, duplicating internal HANDSHAKE_DONE with no compile-time check

WOLFSSL_TLS_ST_OK (and its aliases TLS_ST_OK/SSL_ST_OK) is hardcoded to 16 to match HANDSHAKE_DONE in the private enum states (wolfssl/internal.h). The value is correct today (HANDSHAKE_DONE is the 17th enumerator, index 16, and wolfSSL_get_state() returns ssl->options.handShakeState), but the coupling is a magic number with no static assertion. The comment even admits 16 today. Because internal.h isn't a public header, a static_assert can't live in the public header, so a silent drift is possible if a state is ever inserted before HANDSHAKE_DONE (the enum comment warns this also breaks session import).

Fix: Add a compile-time check in a .c file that includes internal.h, e.g. wc_static_assert(WOLFSSL_TLS_ST_OK == HANDSHAKE_DONE);, so any future enum drift fails the build instead of silently returning a wrong state constant.

* (wolfssl/internal.h), returned by wolfSSL_get_state(); 16 today. */
#define WOLFSSL_TLS_ST_OK 16
Comment thread
dgarske marked this conversation as resolved.
#define WOLFSSL_SSL_ST_OK WOLFSSL_TLS_ST_OK
#define TLS_ST_OK WOLFSSL_TLS_ST_OK
#define SSL_ST_OK WOLFSSL_SSL_ST_OK
#define SSL_F_SSL_SET_FD WOLFSSL_SSL_F_SSL_SET_FD

#define GENERAL_NAME_new wolfSSL_GENERAL_NAME_new
#define GENERAL_NAME_free wolfSSL_GENERAL_NAME_free
#define GENERAL_NAME_dup wolfSSL_GENERAL_NAME_dup
Expand Down Expand Up @@ -1738,16 +1747,43 @@ typedef WOLFSSL_SRTP_PROTECTION_PROFILE SRTP_PROTECTION_PROFILE;
#define SSL_R_DATA_LENGTH_TOO_LONG BUFFER_ERROR
#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG BUFFER_ERROR
#define SSL_R_BAD_LENGTH BUFFER_ERROR
#define SSL_R_UNKNOWN_PROTOCOL VERSION_ERROR
#define SSL_R_WRONG_VERSION_NUMBER VERSION_ERROR
#define SSL_R_UNKNOWN_PROTOCOL WOLFSSL_SSL_R_UNKNOWN_PROTOCOL
#define SSL_R_WRONG_VERSION_NUMBER WOLFSSL_SSL_R_WRONG_VERSION_NUMBER
#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC ENCRYPT_ERROR
#define SSL_R_HTTPS_PROXY_REQUEST PARSE_ERROR
#define SSL_R_HTTP_REQUEST PARSE_ERROR
#define SSL_R_UNSUPPORTED_PROTOCOL VERSION_ERROR
#define SSL_R_UNSUPPORTED_PROTOCOL WOLFSSL_SSL_R_UNSUPPORTED_PROTOCOL
#define SSL_R_NO_PROTOCOLS_AVAILABLE \
WOLFSSL_SSL_R_NO_PROTOCOLS_AVAILABLE
#define SSL_R_BAD_PROTOCOL_VERSION_NUMBER \
WOLFSSL_SSL_R_BAD_PROTOCOL_VERSION_NUMBER
#define SSL_R_UNKNOWN_SSL_VERSION WOLFSSL_SSL_R_UNKNOWN_SSL_VERSION
#define SSL_R_UNSUPPORTED_SSL_VERSION \
WOLFSSL_SSL_R_UNSUPPORTED_SSL_VERSION
#define SSL_R_WRONG_SSL_VERSION WOLFSSL_SSL_R_WRONG_SSL_VERSION
#define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION \
WOLFSSL_SSL_R_TLSV1_ALERT_PROTOCOL_VERSION
#define SSL_R_CERTIFICATE_VERIFY_FAILED VERIFY_CERT_ERROR
#define SSL_R_CERT_CB_ERROR CLIENT_CERT_CB_ERROR
#define SSL_R_NULL_SSL_METHOD_PASSED BAD_FUNC_ARG
#define SSL_R_CCS_RECEIVED_EARLY OUT_OF_ORDER_E
#define ERR_R_BUF_LIB WOLFSSL_ERR_R_BUF_LIB
#define BIO_TYPE_DESCRIPTOR WOLFSSL_BIO_TYPE_DESCRIPTOR
#define BIO_TYPE_SOURCE_SINK WOLFSSL_BIO_TYPE_SOURCE_SINK
#define BIO_get_app_data(bio) wolfSSL_BIO_get_data(bio)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 [Medium] BIO_get_app_data/BIO_set_app_data aliased to BIO_get_data/BIO_set_data (shared storage)

In OpenSSL, BIO_set_data/BIO_get_data access the method-implementation pointer, while BIO_set_app_data/BIO_get_app_data access separate application ex-data. This PR maps BIO_get_app_data/BIO_set_app_data onto the same wolfSSL_BIO_get_data/wolfSSL_BIO_set_data slot that BIO_get_data/BIO_set_data already use (bio.h:163-164). A custom source/sink BIO (the ODBC/FreeTDS transport this PR targets) that stores its connection state via BIO_set_data in its create/ctrl callbacks and also uses BIO_set_app_data for an application pointer will have the two collide - whichever is written last silently overwrites the other.

Fix: Back app_data with a distinct storage slot (e.g. BIO ex_data index) so it does not alias the method data pointer, or document the limitation prominently if the aliasing is acceptable for the intended consumers.

#define BIO_set_app_data(bio, data) \
wolfSSL_BIO_set_data((bio), (data))
#define BIO_get_new_index wolfSSL_BIO_get_new_index
#define BIO_meth_get_gets wolfSSL_BIO_meth_get_gets
#define BIO_meth_get_puts wolfSSL_BIO_meth_get_puts
#define BIO_meth_get_ctrl wolfSSL_BIO_meth_get_ctrl
#define BIO_meth_get_create wolfSSL_BIO_meth_get_create
#define BIO_meth_get_destroy wolfSSL_BIO_meth_get_destroy
#define BIO_meth_get_callback_ctrl wolfSSL_BIO_meth_get_callback_ctrl
#define BIO_meth_set_callback_ctrl wolfSSL_BIO_meth_set_callback_ctrl
#ifndef BUILDING_WOLFSSL
#define OBJ_find_sigid_algs wolfSSL_OBJ_find_sigid_algs

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 [Medium] OBJ_find_sigid_algs compat macro placed in ssl.h instead of objects.h with the other OBJ_ macros*

Every other OBJ_* -> wolfSSL_OBJ_* compat macro is defined in wolfssl/openssl/objects.h (lines 53-69), co-located with the function it aliases. This PR defines the function wolfSSL_OBJ_find_sigid_algs in objects.h but puts the #define OBJ_find_sigid_algs wolfSSL_OBJ_find_sigid_algs alias in ssl.h (broad OPENSSL_EXTRA block), decoupling the macro from its definition. ssl.h only #includes objects.h under WOLFSSL_QT || OPENSSL_ALL (line 52-55); it works for plain OPENSSL_EXTRA builds only because evp.h happens to include objects.h at its tail. This transitive dependency is fragile: any build path where evp.h is skipped (e.g. WOLFCRYPT_ONLY) would define the macro while leaving wolfSSL_OBJ_find_sigid_algs undeclared, yielding an implicit-declaration error at the call site.

Fix: Move the #define OBJ_find_sigid_algs wolfSSL_OBJ_find_sigid_algs into objects.h next to the function definition and the other OBJ_* aliases, so the macro and its target are always defined together.

#endif

#ifdef HAVE_SESSION_TICKET
#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72
Expand Down
Loading