Skip to content
Open
36 changes: 36 additions & 0 deletions src/bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -2119,6 +2119,42 @@ long wolfSSL_BIO_set_nbio(WOLFSSL_BIO* bio, long on)
return WOLFSSL_SUCCESS;
}

int wolfSSL_BIO_get_new_index(void)
{
#if defined(WOLFSSL_ATOMIC_OPS) && !defined(SINGLE_THREADED)
/* Zero-initialized count (no initializer needed); atomically claim the next
* offset so concurrent callers get distinct indices without a lock. The
* first index returned is WOLFSSL_BIO_TYPE_START. */
static wolfSSL_Atomic_Int bio_type_count;
int idx;

WOLFSSL_ENTER("wolfSSL_BIO_get_new_index");

idx = WOLFSSL_BIO_TYPE_START +
(int)wolfSSL_Atomic_Int_FetchAdd(&bio_type_count, 1);
if (idx > WOLFSSL_BIO_TYPE_MAX) {
WOLFSSL_MSG("BIO type index space exhausted");
return WOLFSSL_FATAL_ERROR;
}

return idx;
#else
static int bio_type_idx = WOLFSSL_BIO_TYPE_START;
int idx;

WOLFSSL_ENTER("wolfSSL_BIO_get_new_index");

idx = bio_type_idx;
if (idx > WOLFSSL_BIO_TYPE_MAX) {
WOLFSSL_MSG("BIO type index space exhausted");
return WOLFSSL_FATAL_ERROR;
}
bio_type_idx++;

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.

This is not thread safe. Should it use the atomic?


return idx;
#endif
}

/* creates a new custom WOLFSSL_BIO_METHOD */
WOLFSSL_BIO_METHOD *wolfSSL_BIO_meth_new(int type, const char *name)
{
Expand Down
47 changes: 31 additions & 16 deletions src/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -5562,12 +5562,7 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out,

const char* wolfSSLeay_version(int type)
{
(void)type;
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
return wolfSSL_OpenSSL_version(type);
#else
return wolfSSL_OpenSSL_version();
#endif
}
#endif /* OPENSSL_EXTRA */

Expand Down Expand Up @@ -5899,19 +5894,39 @@ const char* wolfSSL_lib_version(void)
}

#ifdef OPENSSL_EXTRA
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
const char* wolfSSL_OpenSSL_version(int a)
{
(void)a;
return "wolfSSL " LIBWOLFSSL_VERSION_STRING;
}
/* Signature deliberately does not depend on OPENSSL_VERSION_NUMBER. That macro
* can evaluate differently in the library and in the application (e.g. under
* OPENSSL_COEXIST the library also sees the real OpenSSL headers), which would
* make the caller and the definition disagree on the argument list. */
const char* wolfSSL_OpenSSL_version(int type)
{
WOLFSSL_ENTER("wolfSSL_OpenSSL_version");
switch (type) {
case OPENSSL_VERSION:
return "wolfSSL " LIBWOLFSSL_VERSION_STRING;
case OPENSSL_CFLAGS:
return "compiler: information not available";
case OPENSSL_BUILT_ON:
/* Kernel module builds compile with -Werror=date-time. Define
* WOLFSSL_OPENSSL_NO_BUILD_DATE to drop the date without needing the
* full reproducible-build option. */
#if defined(HAVE_REPRODUCIBLE_BUILD) || defined(WOLFSSL_LINUXKM) || \
defined(WOLFSSL_OPENSSL_NO_BUILD_DATE)
return "built on: date not available";
#else
const char* wolfSSL_OpenSSL_version(void)
{
return "wolfSSL " LIBWOLFSSL_VERSION_STRING;
return "built on: " __DATE__ " " __TIME__;
#endif
case OPENSSL_PLATFORM:
return "platform: information not available";
case OPENSSL_DIR:
return "OPENSSLDIR: N/A";
case OPENSSL_ENGINES_DIR:
return "ENGINESDIR: N/A";
default:
return "not available";
}
}
#endif /* WOLFSSL_QT */
#endif
#endif /* OPENSSL_EXTRA */


/* current library version in hex */
Expand Down
105 changes: 99 additions & 6 deletions tests/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -20119,6 +20119,73 @@ defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA)
return EXPECT_RESULT();
}

static int test_wolfSSL_i2d_PUBKEY_bio(void)
{
EXPECT_DECLS;
/* Guards must match wolfSSL_i2d_PUBKEY_bio() in wolfcrypt/src/evp_pk.c. */
#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) && \
!defined(NO_CERTS) && !defined(NO_BIO) && !defined(NO_ASN) && \
!defined(NO_PWDBASED)
BIO* bio = NULL;
EVP_PKEY* pkey = NULL;
EVP_PKEY* pkey2 = NULL;

/* NULL parameter tests */
ExpectIntEQ(wolfSSL_i2d_PUBKEY_bio(NULL, NULL), WOLFSSL_FAILURE);

#if defined(USE_CERT_BUFFERS_2048) && !defined(NO_RSA)
{
const unsigned char* p = client_keypub_der_2048;
/* Load an RSA public key from DER buffer */
ExpectNotNull(pkey = d2i_PUBKEY(NULL, &p,
sizeof_client_keypub_der_2048));

/* Write it to BIO */
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntEQ(i2d_PUBKEY_bio(bio, pkey), WOLFSSL_SUCCESS);

/* Read it back and verify round-trip */
ExpectNotNull(pkey2 = d2i_PUBKEY_bio(bio, NULL));

EVP_PKEY_free(pkey2);
pkey2 = NULL;
EVP_PKEY_free(pkey);
pkey = NULL;
BIO_free(bio);
bio = NULL;
}
#endif

#if defined(USE_CERT_BUFFERS_256) && defined(HAVE_ECC)
{
const unsigned char* p = ecc_clikeypub_der_256;
/* Load an ECC public key from DER buffer */
ExpectNotNull(pkey = d2i_PUBKEY(NULL, &p,
sizeof_ecc_clikeypub_der_256));

/* Write it to BIO */
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
ExpectIntEQ(i2d_PUBKEY_bio(bio, pkey), WOLFSSL_SUCCESS);

/* Read it back and verify round-trip */
ExpectNotNull(pkey2 = d2i_PUBKEY_bio(bio, NULL));

EVP_PKEY_free(pkey2);
pkey2 = NULL;
EVP_PKEY_free(pkey);
pkey = NULL;
BIO_free(bio);
bio = NULL;
}
#endif

(void)pkey;
(void)pkey2;
(void)bio;
#endif
return EXPECT_RESULT();
}

#if (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO)) && !defined(NO_RSA) && \
!defined(NO_TLS)
static int test_wolfSSL_d2i_PrivateKeys_bio(void)
Expand Down Expand Up @@ -30232,16 +30299,41 @@ static int test_wolfSSL_CTX_set_timeout(void)
static int test_wolfSSL_OpenSSL_version(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA)
#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
const char* ver;

#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
ExpectNotNull(ver = OpenSSL_version(0));
ExpectNotNull(ver = OpenSSL_version(OPENSSL_VERSION));
ExpectStrEQ(ver, "wolfSSL " LIBWOLFSSL_VERSION_STRING);

/* Test OPENSSL_CFLAGS type */
ExpectNotNull(ver = OpenSSL_version(OPENSSL_CFLAGS));
ExpectStrEQ(ver, "compiler: information not available");

/* Test OPENSSL_BUILT_ON type */
ExpectNotNull(ver = OpenSSL_version(OPENSSL_BUILT_ON));
#ifdef HAVE_REPRODUCIBLE_BUILD
ExpectStrEQ(ver, "built on: date not available");
#else
ExpectNotNull(ver = OpenSSL_version());
/* __DATE__/__TIME__ differ between translation units, so just check
* the prefix is present. */
ExpectNotNull(XSTRSTR(ver, "built on: "));
#endif
ExpectIntEQ(XMEMCMP(ver, "wolfSSL " LIBWOLFSSL_VERSION_STRING,
XSTRLEN("wolfSSL " LIBWOLFSSL_VERSION_STRING)), 0);

/* Test OPENSSL_PLATFORM type */
ExpectNotNull(ver = OpenSSL_version(OPENSSL_PLATFORM));
ExpectStrEQ(ver, "platform: information not available");

/* Test OPENSSL_DIR type */
ExpectNotNull(ver = OpenSSL_version(OPENSSL_DIR));
ExpectStrEQ(ver, "OPENSSLDIR: N/A");

/* Test OPENSSL_ENGINES_DIR type */
ExpectNotNull(ver = OpenSSL_version(OPENSSL_ENGINES_DIR));
ExpectStrEQ(ver, "ENGINESDIR: N/A");

/* Unknown selector returns the OpenSSL fallback string. */
ExpectNotNull(ver = OpenSSL_version(99));
ExpectStrEQ(ver, "not available");
#endif
return EXPECT_RESULT();
}
Expand Down Expand Up @@ -38210,6 +38302,7 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wolfSSL_d2i_and_i2d_PublicKey_ecc),
#ifndef NO_BIO
TEST_DECL(test_wolfSSL_d2i_PUBKEY),
TEST_DECL(test_wolfSSL_i2d_PUBKEY_bio),
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_HAVE_MLDSA) && \
defined(WOLFSSL_MLDSA_NO_ASN1) && !defined(WOLFSSL_NO_ML_DSA_44) && \
!defined(WOLFSSL_NO_ML_DSA_65) && !defined(WOLFSSL_MLDSA_NO_VERIFY)
Expand Down
40 changes: 40 additions & 0 deletions tests/api/test_ossl_bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1899,5 +1899,45 @@ int test_wolfSSL_BIO_get_init(void)
return EXPECT_RESULT();
}

int test_wolfSSL_BIO_get_new_index(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA)
int idx1, idx2, idx3;
BIO_METHOD* meth = NULL;
BIO* bio = NULL;

/* Get three consecutive indices - should be unique and in valid range */
idx1 = BIO_get_new_index();
idx2 = BIO_get_new_index();
idx3 = BIO_get_new_index();

ExpectIntGE(idx1, BIO_TYPE_START);
ExpectIntLE(idx1, BIO_TYPE_MASK);
ExpectIntGE(idx2, BIO_TYPE_START);
ExpectIntLE(idx2, BIO_TYPE_MASK);
ExpectIntGE(idx3, BIO_TYPE_START);
ExpectIntLE(idx3, BIO_TYPE_MASK);

/* Each index must be unique */
ExpectIntNE(idx1, idx2);
ExpectIntNE(idx2, idx3);
ExpectIntNE(idx1, idx3);

/* Each consecutive call must return a strictly increasing value */
ExpectIntGT(idx2, idx1);
ExpectIntGT(idx3, idx2);

/* Use returned index with BIO_meth_new */
ExpectNotNull(meth = BIO_meth_new(idx1, "custom_test"));
ExpectNotNull(bio = BIO_new(meth));
ExpectIntEQ(BIO_method_type(bio), idx1);

BIO_free(bio);
BIO_meth_free(meth);
#endif
return EXPECT_RESULT();
}

#endif /* !NO_BIO */

4 changes: 3 additions & 1 deletion tests/api/test_ossl_bio.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ int test_wolfSSL_BIO_set_conn_hostname(void);
int test_wolfSSL_BIO_ctrl_pending_chain(void);
int test_wolfSSL_BIO_meth_type_large(void);
int test_wolfSSL_BIO_get_init(void);
int test_wolfSSL_BIO_get_new_index(void);

#define TEST_OSSL_BIO_DECLS \
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_gets), \
Expand All @@ -70,7 +71,8 @@ int test_wolfSSL_BIO_get_init(void);
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_set_conn_hostname), \
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_ctrl_pending_chain), \
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_meth_type_large), \
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_get_init)
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_get_init), \
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_get_new_index)

#define TEST_OSSL_BIO_TLS_DECLS \
TEST_DECL_GROUP("ossl_bio_tls", test_wolfSSL_BIO_connect), \
Expand Down
53 changes: 53 additions & 0 deletions wolfcrypt/src/evp_pk.c
Original file line number Diff line number Diff line change
Expand Up @@ -2452,6 +2452,59 @@ int wolfSSL_i2d_PUBKEY(const WOLFSSL_EVP_PKEY *key, unsigned char **der)
{
return wolfSSL_i2d_PublicKey(key, der);
}

#ifndef NO_BIO
/* Encode public key as DER data and write to BIO.
*
* @param [in] bio BIO to write data to.
* @param [in] key Public key to encode.
* @return WOLFSSL_SUCCESS on success.
* @return WOLFSSL_FAILURE on failure.
*/
int wolfSSL_i2d_PUBKEY_bio(WOLFSSL_BIO* bio, const WOLFSSL_EVP_PKEY* key)
{
int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
int derSz = 0;
byte* der = NULL;
byte* derPtr = NULL;

WOLFSSL_ENTER("wolfSSL_i2d_PUBKEY_bio");

if (bio == NULL || key == NULL) {
return WOLFSSL_FAILURE;
}

derSz = wolfSSL_i2d_PUBKEY(key, NULL);
if (derSz <= 0) {
WOLFSSL_MSG("wolfSSL_i2d_PUBKEY size query failed");
return WOLFSSL_FAILURE;
}

der = (byte*)XMALLOC((size_t)derSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (der == NULL) {
WOLFSSL_MSG("XMALLOC failed");
return WOLFSSL_FAILURE;
}

derPtr = der;
derSz = wolfSSL_i2d_PUBKEY(key, &derPtr);
if (derSz <= 0) {
WOLFSSL_MSG("wolfSSL_i2d_PUBKEY failed");
goto cleanup;
}

if (wolfSSL_BIO_write(bio, der, derSz) != derSz) {
goto cleanup;
}

ret = WOLFSSL_SUCCESS;

cleanup:
XFREE(der, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
#endif /* !NO_BIO */

#endif /* !NO_ASN && !NO_PWDBASED */

#endif /* OPENSSL_EXTRA */
Expand Down
3 changes: 3 additions & 0 deletions wolfssl/openssl/bio.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@
#define BIO_TYPE_BIO WOLFSSL_BIO_BIO
#define BIO_TYPE_MEM WOLFSSL_BIO_MEMORY
#define BIO_TYPE_BASE64 WOLFSSL_BIO_BASE64
#define BIO_TYPE_START WOLFSSL_BIO_TYPE_START
#define BIO_TYPE_MASK WOLFSSL_BIO_TYPE_MASK
#define BIO_get_new_index wolfSSL_BIO_get_new_index

#define BIO_vprintf wolfSSL_BIO_vprintf
#define BIO_printf wolfSSL_BIO_printf
Expand Down
15 changes: 15 additions & 0 deletions wolfssl/openssl/opensslv.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,21 @@
#ifndef OPENSSL_VERSION
#define OPENSSL_VERSION 0
#endif
#ifndef OPENSSL_CFLAGS
#define OPENSSL_CFLAGS 1
#endif
#ifndef OPENSSL_BUILT_ON
#define OPENSSL_BUILT_ON 2
#endif
#ifndef OPENSSL_PLATFORM
#define OPENSSL_PLATFORM 3
#endif
#ifndef OPENSSL_DIR
#define OPENSSL_DIR 4
#endif
#ifndef OPENSSL_ENGINES_DIR
#define OPENSSL_ENGINES_DIR 5
#endif

#ifndef OPENSSL_IS_WOLFSSL
#define OPENSSL_IS_WOLFSSL
Expand Down
Loading
Loading