diff --git a/CMakeLists.txt b/CMakeLists.txt
index 410518e4a..d5c3d3d97 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2682,16 +2682,17 @@ if(WOLFSSL_EXAMPLES)
tests/api/test_pkcs7.c
tests/api/test_pkcs12.c
tests/api/test_ossl_asn1.c
- tests/api/test_ossl_bn.c
tests/api/test_ossl_bio.c
- tests/api/test_ossl_dgst.c
- tests/api/test_ossl_mac.c
+ tests/api/test_ossl_bn.c
tests/api/test_ossl_cipher.c
- tests/api/test_ossl_rsa.c
tests/api/test_ossl_dh.c
+ tests/api/test_ossl_dgst.c
+ tests/api/test_ossl_dsa.c
tests/api/test_ossl_ec.c
tests/api/test_ossl_ecx.c
- tests/api/test_ossl_dsa.c
+ tests/api/test_ossl_mac.c
+ tests/api/test_ossl_rsa.c
+ tests/api/test_ossl_sk.c
tests/api/test_tls13.c
tests/srp.c
tests/suites.c
diff --git a/IDE/Espressif/ESP-IDF/UPDATE.md b/IDE/Espressif/ESP-IDF/UPDATE.md
index 010054e9e..7ccc655e3 100644
--- a/IDE/Espressif/ESP-IDF/UPDATE.md
+++ b/IDE/Espressif/ESP-IDF/UPDATE.md
@@ -22,3 +22,4 @@ Updates to Espressif ESP-IDF wolfssl_benchmark and wolfssl_test examples:
- Added optional `time_helper` for wolfssl_test
- Exclude `ssl_misc.c` in component cmake to fix warning: #warning ssl_misc.c does not need to be compiled separately from ssl.c
- Exclude `ssl_crypto.c` in component cmake to fix warning: #warning ssl_crypto.c does not need to be compiled separately from ssl.c
+- Exclude `ssl_sk.c` in component cmake to fix warning: #warning ssl_sk.c does not need to be compiled separately from ssl.c
diff --git a/IDE/Espressif/ESP-IDF/examples/template/components/wolfssl/CMakeLists.txt b/IDE/Espressif/ESP-IDF/examples/template/components/wolfssl/CMakeLists.txt
index a266a9c1c..66eb43909 100644
--- a/IDE/Espressif/ESP-IDF/examples/template/components/wolfssl/CMakeLists.txt
+++ b/IDE/Espressif/ESP-IDF/examples/template/components/wolfssl/CMakeLists.txt
@@ -845,6 +845,7 @@ else()
"\"${WOLFSSL_ROOT}/src/ssl_misc.c\"" # included by ssl.c
"\"${WOLFSSL_ROOT}/src/ssl_p7p12.c\"" # included by ssl.c
"\"${WOLFSSL_ROOT}/src/ssl_sess.c\"" # included by ssl.c
+ "\"${WOLFSSL_ROOT}/src/ssl_sk.c\"" # included by ssl.c
"\"${WOLFSSL_ROOT}/src/x509.c\""
"\"${WOLFSSL_ROOT}/src/x509_str.c\""
"\"${WOLFSSL_ROOT}/wolfcrypt/src/ext_kyber.c\"" # external non-wolfssl Kyber disabled by default
diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/components/wolfssl/CMakeLists.txt b/IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/components/wolfssl/CMakeLists.txt
index a266a9c1c..66eb43909 100644
--- a/IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/components/wolfssl/CMakeLists.txt
+++ b/IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/components/wolfssl/CMakeLists.txt
@@ -845,6 +845,7 @@ else()
"\"${WOLFSSL_ROOT}/src/ssl_misc.c\"" # included by ssl.c
"\"${WOLFSSL_ROOT}/src/ssl_p7p12.c\"" # included by ssl.c
"\"${WOLFSSL_ROOT}/src/ssl_sess.c\"" # included by ssl.c
+ "\"${WOLFSSL_ROOT}/src/ssl_sk.c\"" # included by ssl.c
"\"${WOLFSSL_ROOT}/src/x509.c\""
"\"${WOLFSSL_ROOT}/src/x509_str.c\""
"\"${WOLFSSL_ROOT}/wolfcrypt/src/ext_kyber.c\"" # external non-wolfssl Kyber disabled by default
diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_client/components/wolfssl/CMakeLists.txt b/IDE/Espressif/ESP-IDF/examples/wolfssl_client/components/wolfssl/CMakeLists.txt
index a266a9c1c..66eb43909 100644
--- a/IDE/Espressif/ESP-IDF/examples/wolfssl_client/components/wolfssl/CMakeLists.txt
+++ b/IDE/Espressif/ESP-IDF/examples/wolfssl_client/components/wolfssl/CMakeLists.txt
@@ -845,6 +845,7 @@ else()
"\"${WOLFSSL_ROOT}/src/ssl_misc.c\"" # included by ssl.c
"\"${WOLFSSL_ROOT}/src/ssl_p7p12.c\"" # included by ssl.c
"\"${WOLFSSL_ROOT}/src/ssl_sess.c\"" # included by ssl.c
+ "\"${WOLFSSL_ROOT}/src/ssl_sk.c\"" # included by ssl.c
"\"${WOLFSSL_ROOT}/src/x509.c\""
"\"${WOLFSSL_ROOT}/src/x509_str.c\""
"\"${WOLFSSL_ROOT}/wolfcrypt/src/ext_kyber.c\"" # external non-wolfssl Kyber disabled by default
diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_server/components/wolfssl/CMakeLists.txt b/IDE/Espressif/ESP-IDF/examples/wolfssl_server/components/wolfssl/CMakeLists.txt
index a266a9c1c..66eb43909 100644
--- a/IDE/Espressif/ESP-IDF/examples/wolfssl_server/components/wolfssl/CMakeLists.txt
+++ b/IDE/Espressif/ESP-IDF/examples/wolfssl_server/components/wolfssl/CMakeLists.txt
@@ -845,6 +845,7 @@ else()
"\"${WOLFSSL_ROOT}/src/ssl_misc.c\"" # included by ssl.c
"\"${WOLFSSL_ROOT}/src/ssl_p7p12.c\"" # included by ssl.c
"\"${WOLFSSL_ROOT}/src/ssl_sess.c\"" # included by ssl.c
+ "\"${WOLFSSL_ROOT}/src/ssl_sk.c\"" # included by ssl.c
"\"${WOLFSSL_ROOT}/src/x509.c\""
"\"${WOLFSSL_ROOT}/src/x509_str.c\""
"\"${WOLFSSL_ROOT}/wolfcrypt/src/ext_kyber.c\"" # external non-wolfssl Kyber disabled by default
diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_test/components/wolfssl/CMakeLists.txt b/IDE/Espressif/ESP-IDF/examples/wolfssl_test/components/wolfssl/CMakeLists.txt
index a266a9c1c..66eb43909 100644
--- a/IDE/Espressif/ESP-IDF/examples/wolfssl_test/components/wolfssl/CMakeLists.txt
+++ b/IDE/Espressif/ESP-IDF/examples/wolfssl_test/components/wolfssl/CMakeLists.txt
@@ -845,6 +845,7 @@ else()
"\"${WOLFSSL_ROOT}/src/ssl_misc.c\"" # included by ssl.c
"\"${WOLFSSL_ROOT}/src/ssl_p7p12.c\"" # included by ssl.c
"\"${WOLFSSL_ROOT}/src/ssl_sess.c\"" # included by ssl.c
+ "\"${WOLFSSL_ROOT}/src/ssl_sk.c\"" # included by ssl.c
"\"${WOLFSSL_ROOT}/src/x509.c\""
"\"${WOLFSSL_ROOT}/src/x509_str.c\""
"\"${WOLFSSL_ROOT}/wolfcrypt/src/ext_kyber.c\"" # external non-wolfssl Kyber disabled by default
diff --git a/IDE/Espressif/ESP-IDF/libs/CMakeLists.txt b/IDE/Espressif/ESP-IDF/libs/CMakeLists.txt
index b25311e38..5d8bad01d 100644
--- a/IDE/Espressif/ESP-IDF/libs/CMakeLists.txt
+++ b/IDE/Espressif/ESP-IDF/libs/CMakeLists.txt
@@ -79,6 +79,7 @@ set(COMPONENT_SRCEXCLUDE
"./src/ssl_misc.c" # included by ssl.c
"./src/ssl_p7p12.c" # included by ssl.c
"./src/ssl_sess.c" # included by ssl.c
+ "./src/ssl_sk.c" # included by ssl.c
"./src/x509.c"
"./src/x509_str.c"
"./wolfcrypt/src/evp.c"
diff --git a/IDE/INTIME-RTOS/wolfssl-lib.vcxproj b/IDE/INTIME-RTOS/wolfssl-lib.vcxproj
index c00ecf0c7..3c5bd1d8d 100644
--- a/IDE/INTIME-RTOS/wolfssl-lib.vcxproj
+++ b/IDE/INTIME-RTOS/wolfssl-lib.vcxproj
@@ -61,6 +61,10 @@
true
true
+
+ true
+ true
+
true
@@ -360,4 +364,4 @@
-
\ No newline at end of file
+
diff --git a/IDE/MSVS-2019-AZSPHERE/wolfssl_new_azsphere/CMakeLists.txt b/IDE/MSVS-2019-AZSPHERE/wolfssl_new_azsphere/CMakeLists.txt
index 18c3633b0..9cecc1a8c 100644
--- a/IDE/MSVS-2019-AZSPHERE/wolfssl_new_azsphere/CMakeLists.txt
+++ b/IDE/MSVS-2019-AZSPHERE/wolfssl_new_azsphere/CMakeLists.txt
@@ -45,6 +45,7 @@ list( REMOVE_ITEM SSL_SOURCES ../../../src/ssl_load.c )
list( REMOVE_ITEM SSL_SOURCES ../../../src/ssl_misc.c )
list( REMOVE_ITEM SSL_SOURCES ../../../src/ssl_p7p12.c )
list( REMOVE_ITEM SSL_SOURCES ../../../src/ssl_sess.c )
+list( REMOVE_ITEM SSL_SOURCES ../../../src/ssl_sk.c )
aux_source_directory( ${CRYPTO_SRC_DIR} CRYPTO_SOURCES )
list( REMOVE_ITEM CRYPTO_SOURCES ../../../wolfcrypt/src/evp.c )
list( REMOVE_ITEM CRYPTO_SOURCES ../../../wolfcrypt/src/misc.c )
diff --git a/src/include.am b/src/include.am
index d7642d67d..f1dd851b0 100644
--- a/src/include.am
+++ b/src/include.am
@@ -25,6 +25,7 @@ EXTRA_DIST += src/ssl_load.c
EXTRA_DIST += src/ssl_misc.c
EXTRA_DIST += src/ssl_p7p12.c
EXTRA_DIST += src/ssl_sess.c
+EXTRA_DIST += src/ssl_sk.c
EXTRA_DIST += src/x509.c
EXTRA_DIST += src/x509_str.c
diff --git a/src/ssl.c b/src/ssl.c
index daa9b6dc7..966c94065 100644
--- a/src/ssl.c
+++ b/src/ssl.c
@@ -359,6 +359,49 @@ WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local)
#define WOLFSSL_PK_INCLUDED
#include "src/pk.c"
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+/* copies over data of "in" to "out" */
+static void wolfSSL_CIPHER_copy(WOLFSSL_CIPHER* in, WOLFSSL_CIPHER* out)
+{
+ if (in == NULL || out == NULL)
+ return;
+
+ *out = *in;
+}
+
+
+#if defined(OPENSSL_ALL)
+static WOLFSSL_X509_OBJECT* wolfSSL_X509_OBJECT_dup(WOLFSSL_X509_OBJECT* obj)
+{
+ WOLFSSL_X509_OBJECT* ret = NULL;
+ if (obj) {
+ ret = wolfSSL_X509_OBJECT_new();
+ if (ret) {
+ ret->type = obj->type;
+ switch (ret->type) {
+ case WOLFSSL_X509_LU_NONE:
+ break;
+ case WOLFSSL_X509_LU_X509:
+ ret->data.x509 = wolfSSL_X509_dup(obj->data.x509);
+ break;
+ case WOLFSSL_X509_LU_CRL:
+ #if defined(HAVE_CRL)
+ ret->data.crl = wolfSSL_X509_CRL_dup(obj->data.crl);
+ #endif
+ break;
+ }
+ }
+ }
+ return ret;
+}
+#endif /* OPENSSL_ALL */
+
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+
+#define WOLFSSL_SSL_SK_INCLUDED
+#include "src/ssl_sk.c"
+
+
#include
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
@@ -14844,468 +14887,6 @@ WOLF_STACK_OF(WOLFSSL_X509) *wolfSSL_get0_verified_chain(const WOLFSSL *ssl)
#endif /* SESSION_CERTS && OPENSSL_EXTRA */
#ifndef NO_CERTS
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
-
-/* create a generic wolfSSL stack node
- * returns a new WOLFSSL_STACK structure on success */
-WOLFSSL_STACK* wolfSSL_sk_new_node(void* heap)
-{
- WOLFSSL_STACK* sk;
- WOLFSSL_ENTER("wolfSSL_sk_new_node");
-
- sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), heap,
- DYNAMIC_TYPE_OPENSSL);
- if (sk != NULL) {
- XMEMSET(sk, 0, sizeof(*sk));
- sk->heap = heap;
- }
-
- return sk;
-}
-
-/* free's node but does not free internal data such as in->data.x509 */
-void wolfSSL_sk_free_node(WOLFSSL_STACK* in)
-{
- if (in != NULL) {
- XFREE(in, in->heap, DYNAMIC_TYPE_OPENSSL);
- }
-}
-
-/* pushes node "in" onto "stack" and returns pointer to the new stack on success
- * also handles internal "num" for number of nodes on stack
- * return WOLFSSL_SUCCESS on success
- */
-int wolfSSL_sk_push_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* in)
-{
- if (stack == NULL || in == NULL) {
- return WOLFSSL_FAILURE;
- }
-
- if (*stack == NULL) {
- in->num = 1;
- *stack = in;
- return WOLFSSL_SUCCESS;
- }
-
- in->num = (*stack)->num + 1;
- in->next = *stack;
- *stack = in;
- return WOLFSSL_SUCCESS;
-}
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
-static WC_INLINE int compare_WOLFSSL_CIPHER(
- WOLFSSL_CIPHER *a,
- WOLFSSL_CIPHER *b)
-{
- if ((a->cipherSuite0 == b->cipherSuite0) &&
- (a->cipherSuite == b->cipherSuite) &&
- (a->ssl == b->ssl) &&
- (XMEMCMP(a->description, b->description, sizeof a->description) == 0) &&
- (a->offset == b->offset) &&
- (a->in_stack == b->in_stack) &&
- (a->bits == b->bits))
- return 0;
- else
- return WOLFSSL_FATAL_ERROR;
-}
-#endif /* OPENSSL_ALL || WOLFSSL_QT */
-
-
-/* return number of elements on success 0 on fail */
-int wolfSSL_sk_push(WOLFSSL_STACK* sk, const void *data)
-{
- WOLFSSL_ENTER("wolfSSL_sk_push");
-
- return wolfSSL_sk_insert(sk, data, -1);
-}
-
-void* wolfSSL_sk_pop(WOLFSSL_STACK* sk)
-{
- WOLFSSL_ENTER("wolfSSL_sk_pop");
-
- return wolfSSL_sk_pop_node(sk, -1);
-}
-
-/* return number of elements on success 0 on fail */
-int wolfSSL_sk_insert(WOLFSSL_STACK *sk, const void *data, int idx)
-{
- WOLFSSL_STACK* node;
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- WOLFSSL_CIPHER ciph;
-#endif
- WOLFSSL_ENTER("wolfSSL_sk_insert");
-
- if (!sk)
- return WOLFSSL_FATAL_ERROR;
- if (!data)
- return WOLFSSL_FAILURE;
-
- if (idx == 0 || sk->num == 0) {
- /* Check if empty data */
- switch (sk->type) {
- case STACK_TYPE_CIPHER:
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- /* check if entire struct is zero */
- XMEMSET(&ciph, 0, sizeof(WOLFSSL_CIPHER));
- if (compare_WOLFSSL_CIPHER(&sk->data.cipher, &ciph) == 0) {
- sk->data.cipher = *(WOLFSSL_CIPHER*)data;
- sk->num = 1;
- if (sk->hash_fn) {
- sk->hash = sk->hash_fn(&sk->data.cipher);
- }
- return (int)sk->num;
- }
- if (sk->num == 0)
- sk->num = 1; /* confirmed at least one element */
- break;
-#endif
- case STACK_TYPE_X509:
- case STACK_TYPE_GEN_NAME:
- case STACK_TYPE_BIO:
- case STACK_TYPE_OBJ:
- case STACK_TYPE_STRING:
- case STACK_TYPE_ACCESS_DESCRIPTION:
- case STACK_TYPE_X509_EXT:
- case STACK_TYPE_X509_REQ_ATTR:
- case STACK_TYPE_NULL:
- case STACK_TYPE_X509_NAME:
- case STACK_TYPE_X509_NAME_ENTRY:
- case STACK_TYPE_CONF_VALUE:
- case STACK_TYPE_X509_INFO:
- case STACK_TYPE_BY_DIR_entry:
- case STACK_TYPE_BY_DIR_hash:
- case STACK_TYPE_X509_OBJ:
- case STACK_TYPE_DIST_POINT:
- case STACK_TYPE_X509_CRL:
- default:
- /* All other types are pointers */
- if (!sk->data.generic) {
- sk->data.generic = (void*)data;
- sk->num = 1;
-#ifdef OPENSSL_ALL
- if (sk->hash_fn)
- sk->hash = sk->hash_fn(sk->data.generic);
-#endif
- return (int)sk->num;
- }
- if (sk->num == 0)
- sk->num = 1; /* confirmed at least one element */
- break;
- }
- }
-
- /* stack already has value(s) create a new node and add more */
- node = wolfSSL_sk_new_node(sk->heap);
- if (!node) {
- WOLFSSL_MSG("Memory error");
- return WOLFSSL_FAILURE;
- }
- node->type = sk->type;
- sk->num += 1;
-#ifdef OPENSSL_ALL
- node->hash_fn = sk->hash_fn;
-#endif
-
- if (idx == 0) {
- /* Special case where we need to change the values in the head element
- * to avoid changing the initial pointer. */
- /* push new item onto head of stack */
- node->next = sk->next;
- sk->next = node;
-#ifdef OPENSSL_ALL
- node->hash = sk->hash;
- sk->hash = 0;
-#endif
- switch (sk->type) {
- case STACK_TYPE_CIPHER:
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- node->data.cipher = sk->data.cipher;
- sk->data.cipher = *(WOLFSSL_CIPHER*)data;
- if (sk->hash_fn) {
- sk->hash = sk->hash_fn(&sk->data.cipher);
- }
- break;
-#endif
- case STACK_TYPE_X509:
- case STACK_TYPE_GEN_NAME:
- case STACK_TYPE_BIO:
- case STACK_TYPE_OBJ:
- case STACK_TYPE_STRING:
- case STACK_TYPE_ACCESS_DESCRIPTION:
- case STACK_TYPE_X509_EXT:
- case STACK_TYPE_X509_REQ_ATTR:
- case STACK_TYPE_NULL:
- case STACK_TYPE_X509_NAME:
- case STACK_TYPE_X509_NAME_ENTRY:
- case STACK_TYPE_CONF_VALUE:
- case STACK_TYPE_X509_INFO:
- case STACK_TYPE_BY_DIR_entry:
- case STACK_TYPE_BY_DIR_hash:
- case STACK_TYPE_X509_OBJ:
- case STACK_TYPE_DIST_POINT:
- case STACK_TYPE_X509_CRL:
- default:
- /* All other types are pointers */
- node->data.generic = sk->data.generic;
- sk->data.generic = (void*)data;
-#ifdef OPENSSL_ALL
- if (sk->hash_fn)
- sk->hash = sk->hash_fn(sk->data.generic);
-#endif
- break;
- }
-
- return (int)sk->num;
- }
-
- /* populate node */
- switch (sk->type) {
- case STACK_TYPE_CIPHER:
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- node->data.cipher = *(WOLFSSL_CIPHER*)data;
- if (node->hash_fn)
- node->hash = node->hash_fn(&node->data.cipher);
- break;
-#endif
- case STACK_TYPE_X509:
- case STACK_TYPE_GEN_NAME:
- case STACK_TYPE_BIO:
- case STACK_TYPE_OBJ:
- case STACK_TYPE_STRING:
- case STACK_TYPE_ACCESS_DESCRIPTION:
- case STACK_TYPE_X509_EXT:
- case STACK_TYPE_X509_REQ_ATTR:
- case STACK_TYPE_NULL:
- case STACK_TYPE_X509_NAME:
- case STACK_TYPE_X509_NAME_ENTRY:
- case STACK_TYPE_CONF_VALUE:
- case STACK_TYPE_X509_INFO:
- case STACK_TYPE_BY_DIR_entry:
- case STACK_TYPE_BY_DIR_hash:
- case STACK_TYPE_X509_OBJ:
- case STACK_TYPE_DIST_POINT:
- case STACK_TYPE_X509_CRL:
- default:
- /* All other types are pointers */
- node->data.generic = (void*)data;
-#ifdef OPENSSL_ALL
- if (node->hash_fn)
- node->hash = node->hash_fn(node->data.generic);
-#endif
- break;
- }
- {
- /* insert node into stack. not using sk since we return sk->num after */
- WOLFSSL_STACK* prev_node = sk;
- while (--idx != 0 && prev_node->next != NULL)
- prev_node = prev_node->next;
- node->next = prev_node->next;
- prev_node->next = node;
- }
-
- return (int)sk->num;
-}
-
-void* wolfSSL_sk_pop_node(WOLFSSL_STACK* sk, int idx)
-{
- void* ret = NULL;
- WOLFSSL_STACK* tmp = NULL;
-
- if (!sk)
- return NULL;
- if (sk->num == 0)
- return NULL;
-
- sk->num--;
- if (idx == 0 || sk->next == NULL) {
- switch (sk->type) {
- case STACK_TYPE_CIPHER:
- /* Can't return cipher type */
- break;
- case STACK_TYPE_X509:
- case STACK_TYPE_GEN_NAME:
- case STACK_TYPE_BIO:
- case STACK_TYPE_OBJ:
- case STACK_TYPE_STRING:
- case STACK_TYPE_ACCESS_DESCRIPTION:
- case STACK_TYPE_X509_EXT:
- case STACK_TYPE_X509_REQ_ATTR:
- case STACK_TYPE_NULL:
- case STACK_TYPE_X509_NAME:
- case STACK_TYPE_X509_NAME_ENTRY:
- case STACK_TYPE_CONF_VALUE:
- case STACK_TYPE_X509_INFO:
- case STACK_TYPE_BY_DIR_entry:
- case STACK_TYPE_BY_DIR_hash:
- case STACK_TYPE_X509_OBJ:
- case STACK_TYPE_DIST_POINT:
- case STACK_TYPE_X509_CRL:
- default:
- ret = sk->data.generic;
- sk->data.generic = NULL;
- break;
- }
- if (sk->next) {
- tmp = sk->next;
- sk->next = tmp->next;
- XMEMCPY(&sk->data, &tmp->data, sizeof(sk->data));
- wolfSSL_sk_free_node(tmp);
- }
- return ret;
- }
-
- {
- WOLFSSL_STACK* prev_node = sk;
- tmp = sk->next;
- while (--idx != 0 && tmp->next != NULL) {
- prev_node = tmp;
- tmp = tmp->next;
- }
- prev_node->next = tmp->next;
- switch (sk->type) {
- case STACK_TYPE_CIPHER:
- /* Can't return cipher type */
- break;
- case STACK_TYPE_X509:
- case STACK_TYPE_GEN_NAME:
- case STACK_TYPE_BIO:
- case STACK_TYPE_OBJ:
- case STACK_TYPE_STRING:
- case STACK_TYPE_ACCESS_DESCRIPTION:
- case STACK_TYPE_X509_EXT:
- case STACK_TYPE_X509_REQ_ATTR:
- case STACK_TYPE_NULL:
- case STACK_TYPE_X509_NAME:
- case STACK_TYPE_X509_NAME_ENTRY:
- case STACK_TYPE_CONF_VALUE:
- case STACK_TYPE_X509_INFO:
- case STACK_TYPE_BY_DIR_entry:
- case STACK_TYPE_BY_DIR_hash:
- case STACK_TYPE_X509_OBJ:
- case STACK_TYPE_DIST_POINT:
- case STACK_TYPE_X509_CRL:
- default:
- ret = tmp->data.generic;
- break;
- }
- wolfSSL_sk_free_node(tmp);
- }
- return ret;
-}
-
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
-
-#ifdef OPENSSL_EXTRA
-
-/* returns the node at index "idx", NULL if not found */
-WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* sk, int idx)
-{
- int i;
- WOLFSSL_STACK* ret = NULL;
- WOLFSSL_STACK* current;
-
- current = sk;
- for (i = 0; i <= idx && current != NULL; i++) {
- if (i == idx) {
- ret = current;
- break;
- }
- current = current->next;
- }
- return ret;
-}
-
-
-#endif /* OPENSSL_EXTRA */
-
-#ifdef OPENSSL_EXTRA
-
-#if defined(OPENSSL_ALL)
-
-void *wolfSSL_lh_retrieve(WOLFSSL_STACK *sk, void *data)
-{
- unsigned long hash;
-
- WOLFSSL_ENTER("wolfSSL_lh_retrieve");
-
- if (!sk || !data) {
- WOLFSSL_MSG("Bad parameters");
- return NULL;
- }
-
- if (!sk->hash_fn) {
- WOLFSSL_MSG("No hash function defined");
- return NULL;
- }
-
- hash = sk->hash_fn(data);
-
- while (sk) {
- /* Calc hash if not done so yet */
- if (!sk->hash) {
- switch (sk->type) {
- case STACK_TYPE_CIPHER:
- sk->hash = sk->hash_fn(&sk->data.cipher);
- break;
- case STACK_TYPE_X509:
- case STACK_TYPE_GEN_NAME:
- case STACK_TYPE_BIO:
- case STACK_TYPE_OBJ:
- case STACK_TYPE_STRING:
- case STACK_TYPE_ACCESS_DESCRIPTION:
- case STACK_TYPE_X509_EXT:
- case STACK_TYPE_X509_REQ_ATTR:
- case STACK_TYPE_NULL:
- case STACK_TYPE_X509_NAME:
- case STACK_TYPE_X509_NAME_ENTRY:
- case STACK_TYPE_CONF_VALUE:
- case STACK_TYPE_X509_INFO:
- case STACK_TYPE_BY_DIR_entry:
- case STACK_TYPE_BY_DIR_hash:
- case STACK_TYPE_X509_OBJ:
- case STACK_TYPE_DIST_POINT:
- case STACK_TYPE_X509_CRL:
- default:
- sk->hash = sk->hash_fn(sk->data.generic);
- break;
- }
- }
- if (sk->hash == hash) {
- switch (sk->type) {
- case STACK_TYPE_CIPHER:
- return &sk->data.cipher;
- case STACK_TYPE_X509:
- case STACK_TYPE_GEN_NAME:
- case STACK_TYPE_BIO:
- case STACK_TYPE_OBJ:
- case STACK_TYPE_STRING:
- case STACK_TYPE_ACCESS_DESCRIPTION:
- case STACK_TYPE_X509_EXT:
- case STACK_TYPE_X509_REQ_ATTR:
- case STACK_TYPE_NULL:
- case STACK_TYPE_X509_NAME:
- case STACK_TYPE_X509_NAME_ENTRY:
- case STACK_TYPE_CONF_VALUE:
- case STACK_TYPE_X509_INFO:
- case STACK_TYPE_BY_DIR_entry:
- case STACK_TYPE_BY_DIR_hash:
- case STACK_TYPE_X509_OBJ:
- case STACK_TYPE_DIST_POINT:
- case STACK_TYPE_X509_CRL:
- default:
- return sk->data.generic;
- }
- }
- sk = sk->next;
- }
-
- return NULL;
-}
-
-#endif /* OPENSSL_ALL */
-
-#endif /* OPENSSL_EXTRA */
/* OPENSSL_EXTRA is needed for wolfSSL_X509_d21 function
KEEP_OUR_CERT is to insure ability for returning ssl certificate */
@@ -15626,38 +15207,6 @@ int wolfSSL_get_cipher_suite_from_name(const char* name, byte* cipherSuite0,
}
-#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
-/* Creates and returns a new WOLFSSL_CIPHER stack. */
-WOLFSSL_STACK* wolfSSL_sk_new_cipher(void)
-{
- WOLFSSL_STACK* sk;
- WOLFSSL_ENTER("wolfSSL_sk_new_cipher");
-
- sk = wolfSSL_sk_new_null();
- if (sk == NULL)
- return NULL;
- sk->type = STACK_TYPE_CIPHER;
-
- return sk;
-}
-
-/* returns the number of elements in stack on success, 0 on fail */
-int wolfSSL_sk_CIPHER_push(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk,
- WOLFSSL_CIPHER* cipher)
-{
- return wolfSSL_sk_push(sk, cipher);
-}
-
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_CIPHER* wolfSSL_sk_CIPHER_pop(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk)
-{
- WOLFSSL_STUB("wolfSSL_sk_CIPHER_pop");
- (void)sk;
- return NULL;
-}
-#endif /* NO_WOLFSSL_STUB */
-#endif /* WOLFSSL_QT || OPENSSL_ALL */
-
word32 wolfSSL_CIPHER_get_id(const WOLFSSL_CIPHER* cipher)
{
word16 cipher_id = 0;
@@ -15690,19 +15239,6 @@ const WOLFSSL_CIPHER* wolfSSL_get_cipher_by_value(word16 value)
}
-#if defined(OPENSSL_EXTRA)
-/* Free the structure for WOLFSSL_CIPHER stack
- *
- * sk stack to free nodes in
- */
-void wolfSSL_sk_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk)
-{
- WOLFSSL_ENTER("wolfSSL_sk_CIPHER_free");
-
- wolfSSL_sk_free(sk);
-}
-#endif /* OPENSSL_ALL */
-
#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) || \
!defined(NO_DH)
#ifdef HAVE_FFDHE
@@ -17702,17 +17238,6 @@ long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg)
}
#endif /* HAVE_PK_CALLBACKS */
-/*** TBD ***/
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st)
-{
- (void)st;
- WOLFSSL_STUB("wolfSSL_sk_SSL_COMP_zero");
- /* wolfSSL_set_options(ssl, SSL_OP_NO_COMPRESSION); */
- return WOLFSSL_FAILURE;
-}
-#endif
-
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type)
{
@@ -17819,21 +17344,6 @@ WOLF_STACK_OF(WOLFSSL_COMP) *WOLFSSL_COMP_get_compression_methods(void)
#endif
-int wolfSSL_sk_SSL_CIPHER_num(const WOLF_STACK_OF(WOLFSSL_CIPHER)* p)
-{
- WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_num");
- if (p == NULL) {
- return WOLFSSL_FATAL_ERROR;
- }
- return (int)p->num;
-}
-
-WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(WOLFSSL_STACK* sk, int i)
-{
- WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_value");
- return (WOLFSSL_CIPHER*)wolfSSL_sk_value(sk, i);
-}
-
#if !defined(NETOS)
void wolfSSL_ERR_load_SSL_strings(void)
{
@@ -18106,461 +17616,6 @@ long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx,
#endif /* OPENSSL_EXTRA */
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
-int wolfSSL_sk_num(const WOLFSSL_STACK* sk)
-{
- WOLFSSL_ENTER("wolfSSL_sk_num");
- if (sk == NULL)
- return 0;
- return (int)sk->num;
-}
-
-void* wolfSSL_sk_value(const WOLFSSL_STACK* sk, int i)
-{
- WOLFSSL_ENTER("wolfSSL_sk_value");
-
- for (; sk != NULL && i > 0; i--)
- sk = sk->next;
- if (sk == NULL)
- return NULL;
-
- switch (sk->type) {
- case STACK_TYPE_X509:
- return (void*)sk->data.x509;
- case STACK_TYPE_GEN_NAME:
- return (void*)sk->data.gn;
- case STACK_TYPE_BIO:
- return (void*)sk->data.bio;
- case STACK_TYPE_OBJ:
- return (void*)sk->data.obj;
- case STACK_TYPE_STRING:
- return (void*)sk->data.string;
- case STACK_TYPE_CIPHER:
- return (void*)&sk->data.cipher;
- case STACK_TYPE_ACCESS_DESCRIPTION:
- return (void*)sk->data.access;
- case STACK_TYPE_X509_EXT:
- return (void*)sk->data.ext;
- case STACK_TYPE_X509_REQ_ATTR:
- return (void*)sk->data.generic;
- case STACK_TYPE_NULL:
- return (void*)sk->data.generic;
- case STACK_TYPE_X509_NAME:
- return (void*)sk->data.name;
- case STACK_TYPE_X509_NAME_ENTRY:
- return (void*)sk->data.name_entry;
- case STACK_TYPE_CONF_VALUE:
- #ifdef OPENSSL_EXTRA
- return (void*)sk->data.conf;
- #else
- return NULL;
- #endif
- case STACK_TYPE_X509_INFO:
- return (void*)sk->data.info;
- case STACK_TYPE_BY_DIR_entry:
- return (void*)sk->data.dir_entry;
- case STACK_TYPE_BY_DIR_hash:
- return (void*)sk->data.dir_hash;
- case STACK_TYPE_X509_OBJ:
- return (void*)sk->data.x509_obj;
- case STACK_TYPE_DIST_POINT:
- return (void*)sk->data.dp;
- case STACK_TYPE_X509_CRL:
- return (void*)sk->data.crl;
- default:
- return (void*)sk->data.generic;
- }
-}
-
-/* copies over data of "in" to "out" */
-static void wolfSSL_CIPHER_copy(WOLFSSL_CIPHER* in, WOLFSSL_CIPHER* out)
-{
- if (in == NULL || out == NULL)
- return;
-
- *out = *in;
-}
-
-
-#if defined(OPENSSL_ALL)
-static WOLFSSL_X509_OBJECT* wolfSSL_X509_OBJECT_dup(WOLFSSL_X509_OBJECT* obj)
-{
- WOLFSSL_X509_OBJECT* ret = NULL;
- if (obj) {
- ret = wolfSSL_X509_OBJECT_new();
- if (ret) {
- ret->type = obj->type;
- switch (ret->type) {
- case WOLFSSL_X509_LU_NONE:
- break;
- case WOLFSSL_X509_LU_X509:
- ret->data.x509 = wolfSSL_X509_dup(obj->data.x509);
- break;
- case WOLFSSL_X509_LU_CRL:
- #if defined(HAVE_CRL)
- ret->data.crl = wolfSSL_X509_CRL_dup(obj->data.crl);
- #endif
- break;
- }
- }
- }
- return ret;
-}
-#endif /* OPENSSL_ALL */
-
-WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* sk)
-{
-
- WOLFSSL_STACK* ret = NULL;
- WOLFSSL_STACK* last = NULL;
-
- WOLFSSL_ENTER("wolfSSL_sk_dup");
-
- while (sk) {
- WOLFSSL_STACK* cur = wolfSSL_sk_new_node(sk->heap);
-
- if (!cur) {
- WOLFSSL_MSG("wolfSSL_sk_new_node error");
- goto error;
- }
-
- if (!ret) {
- /* Set first node */
- ret = cur;
- }
-
- if (last) {
- last->next = cur;
- }
-
- XMEMCPY(cur, sk, sizeof(WOLFSSL_STACK));
-
- /* We will allocate new memory for this */
- XMEMSET(&cur->data, 0, sizeof(cur->data));
- cur->next = NULL;
-
- switch (sk->type) {
- case STACK_TYPE_X509:
- if (!sk->data.x509)
- break;
- cur->data.x509 = wolfSSL_X509_dup(sk->data.x509);
- if (!cur->data.x509) {
- WOLFSSL_MSG("wolfSSL_X509_dup error");
- goto error;
- }
- break;
- case STACK_TYPE_CIPHER:
- wolfSSL_CIPHER_copy(&sk->data.cipher, &cur->data.cipher);
- break;
- case STACK_TYPE_GEN_NAME:
- if (!sk->data.gn)
- break;
- cur->data.gn = wolfSSL_GENERAL_NAME_dup(sk->data.gn);
- if (!cur->data.gn) {
- WOLFSSL_MSG("wolfSSL_GENERAL_NAME_new error");
- goto error;
- }
- break;
- case STACK_TYPE_OBJ:
- if (!sk->data.obj)
- break;
- cur->data.obj = wolfSSL_ASN1_OBJECT_dup(sk->data.obj);
- if (!cur->data.obj) {
- WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_dup error");
- goto error;
- }
- break;
- case STACK_TYPE_X509_OBJ:
- #if defined(OPENSSL_ALL)
- if (!sk->data.x509_obj)
- break;
- cur->data.x509_obj = wolfSSL_X509_OBJECT_dup(sk->data.x509_obj);
- if (!cur->data.x509_obj) {
- WOLFSSL_MSG("wolfSSL_X509_OBJECT_dup error");
- goto error;
- }
- break;
- #endif
- case STACK_TYPE_BIO:
- case STACK_TYPE_STRING:
- case STACK_TYPE_ACCESS_DESCRIPTION:
- case STACK_TYPE_X509_EXT:
- case STACK_TYPE_X509_REQ_ATTR:
- case STACK_TYPE_NULL:
- case STACK_TYPE_X509_NAME:
- case STACK_TYPE_X509_NAME_ENTRY:
- case STACK_TYPE_CONF_VALUE:
- case STACK_TYPE_X509_INFO:
- case STACK_TYPE_BY_DIR_entry:
- case STACK_TYPE_BY_DIR_hash:
- case STACK_TYPE_DIST_POINT:
- case STACK_TYPE_X509_CRL:
- default:
- WOLFSSL_MSG("Unsupported stack type");
- goto error;
- }
-
- sk = sk->next;
- last = cur;
- }
- return ret;
-
-error:
- if (ret) {
- wolfSSL_sk_GENERAL_NAME_free(ret);
- }
- return NULL;
-}
-
-
-WOLFSSL_STACK* wolfSSL_shallow_sk_dup(WOLFSSL_STACK* sk)
-{
-
- WOLFSSL_STACK* ret = NULL;
- WOLFSSL_STACK** prev = &ret;
-
- WOLFSSL_ENTER("wolfSSL_shallow_sk_dup");
-
- for (; sk != NULL; sk = sk->next) {
- WOLFSSL_STACK* cur = wolfSSL_sk_new_node(sk->heap);
-
- if (!cur) {
- WOLFSSL_MSG("wolfSSL_sk_new_node error");
- goto error;
- }
-
- XMEMCPY(cur, sk, sizeof(WOLFSSL_STACK));
- cur->next = NULL;
-
- *prev = cur;
- prev = &cur->next;
- }
- return ret;
-
-error:
- if (ret) {
- wolfSSL_sk_free(ret);
- }
- return NULL;
-}
-
-/* Free the just the stack structure */
-void wolfSSL_sk_free(WOLFSSL_STACK* sk)
-{
- WOLFSSL_ENTER("wolfSSL_sk_free");
-
- while (sk != NULL) {
- WOLFSSL_STACK* next = sk->next;
- wolfSSL_sk_free_node(sk);
- sk = next;
- }
-}
-
-/* Frees each node in the stack and frees the stack.
- */
-void wolfSSL_sk_GENERIC_pop_free(WOLFSSL_STACK* sk,
- void (*f) (void*))
-{
- WOLFSSL_ENTER("wolfSSL_sk_GENERIC_pop_free");
- wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f);
-}
-
-/* returns the number of elements in stack on success, 0 on fail */
-int wolfSSL_sk_GENERIC_push(WOLFSSL_STACK* sk, void* generic)
-{
- WOLFSSL_ENTER("wolfSSL_sk_GENERIC_push");
-
- return wolfSSL_sk_push(sk, generic);
-}
-void wolfSSL_sk_GENERIC_free(WOLFSSL_STACK* sk)
-{
- wolfSSL_sk_free(sk);
-}
-
-/* Pop off data from the stack. Checks that the type matches the stack type.
- *
- * @param [in, out] sk Stack of objects.
- * @param [in] type Type of stack.
- * @return Object on success.
- * @return NULL when stack is NULL or no nodes left in stack.
- */
-void* wolfssl_sk_pop_type(WOLFSSL_STACK* sk, WOLF_STACK_TYPE type)
-{
- void* data = NULL;
-
- /* Check we have a stack passed in of the right type. */
- if ((sk != NULL) && (sk->type == type))
- data = wolfSSL_sk_pop(sk);
-
- return data;
-}
-
-/* Free all nodes in a stack including the pushed objects */
-void wolfSSL_sk_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk,
- wolfSSL_sk_freefunc func)
-{
- WOLFSSL_ENTER("wolfSSL_sk_pop_free");
-
- if (sk == NULL) {
- /* pop_free can be called with NULL, do not print bad argument */
- return;
- }
- #if defined(WOLFSSL_QT)
- /* In Qt v15.5, it calls OPENSSL_sk_free(xxx, OPENSSL_sk_free).
- * By using OPENSSL_sk_free for free causes access violation.
- * Therefore, switching free func to wolfSSL_ACCESS_DESCRIPTION_free
- * is needed even the func isn't NULL.
- */
- if (sk->type == STACK_TYPE_ACCESS_DESCRIPTION) {
- func = (wolfSSL_sk_freefunc)wolfSSL_ACCESS_DESCRIPTION_free;
- }
- #endif
- if (func == NULL) {
- switch(sk->type) {
- case STACK_TYPE_ACCESS_DESCRIPTION:
- #if defined(OPENSSL_ALL)
- func = (wolfSSL_sk_freefunc)wolfSSL_ACCESS_DESCRIPTION_free;
- #endif
- break;
- case STACK_TYPE_X509:
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_free;
- break;
- case STACK_TYPE_X509_OBJ:
- #ifdef OPENSSL_ALL
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_OBJECT_free;
- #endif
- break;
- case STACK_TYPE_OBJ:
- func = (wolfSSL_sk_freefunc)wolfSSL_ASN1_OBJECT_free;
- break;
- case STACK_TYPE_DIST_POINT:
- #ifdef OPENSSL_EXTRA
- func = (wolfSSL_sk_freefunc)wolfSSL_DIST_POINT_free;
- #endif
- break;
- case STACK_TYPE_GEN_NAME:
- func = (wolfSSL_sk_freefunc)wolfSSL_GENERAL_NAME_free;
- break;
- case STACK_TYPE_STRING:
- #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
- defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
- func = (wolfSSL_sk_freefunc)wolfSSL_WOLFSSL_STRING_free;
- #endif
- break;
- case STACK_TYPE_X509_NAME:
- #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \
- && !defined(WOLFCRYPT_ONLY)
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_NAME_free;
- #endif
- break;
- case STACK_TYPE_X509_NAME_ENTRY:
- #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \
- && !defined(WOLFCRYPT_ONLY)
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_NAME_ENTRY_free;
- #endif
- break;
- case STACK_TYPE_X509_EXT:
- #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_EXTENSION_free;
- #endif
- break;
- case STACK_TYPE_X509_REQ_ATTR:
- #if defined(OPENSSL_ALL) && \
- (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_REQ))
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_ATTRIBUTE_free;
- #endif
- break;
- case STACK_TYPE_CONF_VALUE:
- #if defined(OPENSSL_ALL)
- func = (wolfSSL_sk_freefunc)wolfSSL_X509V3_conf_free;
- #endif
- break;
- case STACK_TYPE_X509_INFO:
- #if defined(OPENSSL_ALL)
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_INFO_free;
- #endif
- break;
- case STACK_TYPE_BIO:
-#if !defined(NO_BIO) && defined(OPENSSL_EXTRA)
- func = (wolfSSL_sk_freefunc)wolfSSL_BIO_vfree;
-#endif
- break;
- case STACK_TYPE_BY_DIR_entry:
-#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
- func = (wolfSSL_sk_freefunc)wolfSSL_BY_DIR_entry_free;
-#endif
- break;
- case STACK_TYPE_BY_DIR_hash:
-#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
- func = (wolfSSL_sk_freefunc)wolfSSL_BY_DIR_HASH_free;
-#endif
- break;
- case STACK_TYPE_X509_CRL:
-#if defined(HAVE_CRL) && (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL))
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_CRL_free;
-#endif
- break;
- case STACK_TYPE_CIPHER:
- case STACK_TYPE_NULL:
- default:
- break;
- }
- }
-
- while (sk != NULL) {
- WOLFSSL_STACK* next = sk->next;
-
- if (func != NULL) {
- if (sk->type != STACK_TYPE_CIPHER)
- func(sk->data.generic);
- }
- XFREE(sk, sk->heap, DYNAMIC_TYPE_OPENSSL);
- sk = next;
- }
-}
-
-/* Creates a new stack of the requested type.
- *
- * @param [in] type Type of stack.
- * @return Empty stack on success.
- * @return NULL when dynamic memory allocation fails.
- */
-WOLFSSL_STACK* wolfssl_sk_new_type(WOLF_STACK_TYPE type)
-{
- WOLFSSL_STACK* sk;
-
- /* Allocate a new stack - first node. */
- sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
- DYNAMIC_TYPE_OPENSSL);
- if (sk == NULL) {
- WOLFSSL_MSG("WOLFSSL_STACK memory error");
- }
- else {
- /* Clear node and set type. */
- XMEMSET(sk, 0, sizeof(WOLFSSL_STACK));
- sk->type = type;
- }
-
- return sk;
-}
-
-/* Creates and returns a new null stack. */
-WOLFSSL_STACK* wolfSSL_sk_new_null(void)
-{
- WOLFSSL_ENTER("wolfSSL_sk_new_null");
-
- return wolfssl_sk_new_type(STACK_TYPE_NULL);
-}
-
-int wolfSSL_sk_SSL_COMP_num(WOLF_STACK_OF(WOLFSSL_COMP)* sk)
-{
- if (sk == NULL)
- return 0;
- return (int)sk->num;
-}
-
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
-
#if defined(OPENSSL_EXTRA) && defined(KEEP_PEER_CERT) && \
defined(HAVE_EX_DATA) && !defined(NO_FILESYSTEM)
int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname)
@@ -21748,38 +20803,6 @@ int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits)
return ret;
}
-/* returns value less than 0 on fail to match
- * On a successful match the priority level found is returned
- */
-int wolfSSL_sk_SSL_CIPHER_find(
- WOLF_STACK_OF(WOLFSSL_CIPHER)* sk, const WOLFSSL_CIPHER* toFind)
-{
- WOLFSSL_STACK* next;
- int i, sz;
-
- if (sk == NULL || toFind == NULL) {
- return WOLFSSL_FATAL_ERROR;
- }
-
- sz = wolfSSL_sk_SSL_CIPHER_num(sk);
- next = sk;
- for (i = 0; i < sz && next != NULL; i++) {
- if (next->data.cipher.cipherSuite0 == toFind->cipherSuite0 &&
- next->data.cipher.cipherSuite == toFind->cipherSuite) {
- return sz - i; /* reverse because stack pushed highest on first */
- }
- next = next->next;
- }
- return WOLFSSL_FATAL_ERROR;
-}
-
-/* free's all nodes in the stack and there data */
-void wolfSSL_sk_SSL_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk)
-{
- WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_free");
- wolfSSL_sk_free(sk);
-}
-
#ifdef HAVE_SNI
int wolfSSL_set_tlsext_host_name(WOLFSSL* ssl, const char* host_name)
{
@@ -23187,17 +22210,6 @@ int wolfSSL_get0_chain_certs(WOLFSSL *ssl,
}
#endif
-WOLF_STACK_OF(WOLFSSL_STRING)* wolfSSL_sk_WOLFSSL_STRING_new(void)
-{
- WOLF_STACK_OF(WOLFSSL_STRING)* ret = wolfSSL_sk_new_node(NULL);
-
- if (ret) {
- ret->type = STACK_TYPE_STRING;
- }
-
- return ret;
-}
-
void wolfSSL_WOLFSSL_STRING_free(WOLFSSL_STRING s)
{
WOLFSSL_ENTER("wolfSSL_WOLFSSL_STRING_free");
@@ -23205,40 +22217,6 @@ void wolfSSL_WOLFSSL_STRING_free(WOLFSSL_STRING s)
XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL);
}
-void wolfSSL_sk_WOLFSSL_STRING_free(WOLF_STACK_OF(WOLFSSL_STRING)* sk)
-{
- WOLFSSL_STACK* tmp;
- WOLFSSL_ENTER("wolfSSL_sk_WOLFSSL_STRING_free");
-
- if (sk == NULL)
- return;
-
- /* parse through stack freeing each node */
- while (sk) {
- tmp = sk->next;
- XFREE(sk->data.string, NULL, DYNAMIC_TYPE_OPENSSL);
- XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL);
- sk = tmp;
- }
-}
-
-WOLFSSL_STRING wolfSSL_sk_WOLFSSL_STRING_value(
- WOLF_STACK_OF(WOLFSSL_STRING)* strings, int idx)
-{
- for (; idx > 0 && strings != NULL; idx--)
- strings = strings->next;
- if (strings == NULL)
- return NULL;
- return strings->data.string;
-}
-
-int wolfSSL_sk_WOLFSSL_STRING_num(WOLF_STACK_OF(WOLFSSL_STRING)* strings)
-{
- if (strings)
- return (int)strings->num;
- return 0;
-}
-
#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
diff --git a/src/ssl_sk.c b/src/ssl_sk.c
new file mode 100644
index 000000000..4b01b443f
--- /dev/null
+++ b/src/ssl_sk.c
@@ -0,0 +1,1251 @@
+/* ssl_sk.c
+ *
+ * Copyright (C) 2006-2025 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#include
+
+#if !defined(WOLFSSL_SSL_SK_INCLUDED)
+ #ifndef WOLFSSL_IGNORE_FILE_WARN
+ #warning ssl_sk.c does not need to be compiled separately from ssl.c
+ #endif
+#else
+
+/* In OpenSSL, OPENSSL_STACK is structure with an array of data pointers.
+ *
+ * In wolfSSL, WOLFSSL_STACK is a linked-list of nodes and therefore the first
+ * node has no data but the type is set.
+ * When the first data is set, the first node has the data stored against it and
+ * the number of nodes goes up to 1.
+ * If a new node is prepended then, to keep the pointer the same, the first
+ * node is copied into a new node and inserted after first node, and the new
+ * data is put into the first node.
+ */
+
+/*******************************************************************************
+ * SK node APIs
+ ******************************************************************************/
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
+ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
+ defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+/* Creates a generic wolfSSL stack node.
+ *
+ * @param [in] heap eap hint for dynamic memory allocation.
+ * @return WOLFSSL_STACK structure on success.
+ * @return NULL when dynamic memory allocation fails.
+ */
+WOLFSSL_STACK* wolfSSL_sk_new_node(void* heap)
+{
+ WOLFSSL_STACK* node;
+
+ WOLFSSL_ENTER("wolfSSL_sk_new_node");
+
+ node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), heap,
+ DYNAMIC_TYPE_OPENSSL);
+ if (node != NULL) {
+ XMEMSET(node, 0, sizeof(*node));
+ node->heap = heap;
+ }
+
+ return node;
+}
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
+ defined(OPENSSL_ALL)
+/* Disposes of WOLFSSL_STACK object.
+ *
+ * Cannot use node after this call.
+ *
+ * @param [in] node WOLFSSL_STACK object.
+ */
+void wolfSSL_sk_free_node(WOLFSSL_STACK* node)
+{
+ /* Don't dereference node for heap when NULL. */
+ if (node != NULL) {
+ XFREE(node, node->heap, DYNAMIC_TYPE_OPENSSL);
+ }
+}
+#endif
+
+#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA)
+/* Gets the node from stack at the index.
+ *
+ * @param [in] stack Stack of nodes.
+ * @param [in] idx Index of node to get.
+ * @return Node at index on success.
+ * @return NULL when no node at index.
+ */
+WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* stack, int idx)
+{
+ int i;
+ WOLFSSL_STACK* ret;
+
+ if ((idx < 0) || (idx > (int)stack->num)) {
+ ret = NULL;
+ }
+ else {
+ ret = stack;
+ for (i = 0; i < idx; i++) {
+ ret = ret->next;
+ }
+ }
+
+ return ret;
+}
+#endif /* !NO_CERT && OPENSSL_EXTRA*/
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+/* Copy all fields from src into dst.
+ *
+ * Shallow copy only.
+ *
+ * @param [in, out] dst Node to copy into.
+ * @param [in] src Node to copy.
+ */
+static void wolfssl_sk_node_copy(WOLFSSL_STACK* dst, WOLFSSL_STACK* src)
+{
+ dst->data.generic = src->data.generic;
+ dst->next = src->next;
+#ifdef OPENSSL_ALL
+ dst->hash_fn = src->hash_fn;
+ dst->hash = src->hash;
+#endif
+ dst->type = src->type;
+ dst->num = src->num;
+}
+
+#ifndef NO_CERTS
+/* Get data pointer from node.
+ *
+ * @param [in] node Node to get data from.
+ * @param [in] no_static Don't return static data.
+ * @return Data pointer of node on success.
+ * @return NULL when node type is STACK_TYPE_CIPHER.
+ */
+static void* wolfssl_sk_node_get_data(WOLFSSL_STACK* node, int no_static)
+{
+ void *ret = NULL;
+
+ switch (node->type) {
+ case STACK_TYPE_CIPHER:
+ if (!no_static) {
+ ret = &node->data.cipher;
+ }
+ break;
+ case STACK_TYPE_X509:
+ case STACK_TYPE_GEN_NAME:
+ case STACK_TYPE_BIO:
+ case STACK_TYPE_OBJ:
+ case STACK_TYPE_STRING:
+ case STACK_TYPE_ACCESS_DESCRIPTION:
+ case STACK_TYPE_X509_EXT:
+ case STACK_TYPE_X509_REQ_ATTR:
+ case STACK_TYPE_NULL:
+ case STACK_TYPE_X509_NAME:
+ case STACK_TYPE_X509_NAME_ENTRY:
+ case STACK_TYPE_CONF_VALUE:
+ case STACK_TYPE_X509_INFO:
+ case STACK_TYPE_BY_DIR_entry:
+ case STACK_TYPE_BY_DIR_hash:
+ case STACK_TYPE_X509_OBJ:
+ case STACK_TYPE_DIST_POINT:
+ case STACK_TYPE_X509_CRL:
+ default:
+ ret = node->data.generic;
+ break;
+ }
+
+ return ret;
+}
+
+/* Set data with type into node.
+ *
+ * @param [in, out] node Node to place data into.
+ * @param [in] type Type of data.
+ * @param [in] data Data to set.
+ */
+static void wolfssl_sk_node_set_data(WOLFSSL_STACK* node, WOLF_STACK_TYPE type,
+ const void* data)
+{
+ switch (type) {
+ case STACK_TYPE_CIPHER:
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ node->data.cipher = *(WOLFSSL_CIPHER*)data;
+ if (node->hash_fn != NULL) {
+ node->hash = node->hash_fn(&node->data.cipher);
+ }
+ break;
+#endif
+ case STACK_TYPE_X509:
+ case STACK_TYPE_GEN_NAME:
+ case STACK_TYPE_BIO:
+ case STACK_TYPE_OBJ:
+ case STACK_TYPE_STRING:
+ case STACK_TYPE_ACCESS_DESCRIPTION:
+ case STACK_TYPE_X509_EXT:
+ case STACK_TYPE_X509_REQ_ATTR:
+ case STACK_TYPE_NULL:
+ case STACK_TYPE_X509_NAME:
+ case STACK_TYPE_X509_NAME_ENTRY:
+ case STACK_TYPE_CONF_VALUE:
+ case STACK_TYPE_X509_INFO:
+ case STACK_TYPE_BY_DIR_entry:
+ case STACK_TYPE_BY_DIR_hash:
+ case STACK_TYPE_X509_OBJ:
+ case STACK_TYPE_DIST_POINT:
+ case STACK_TYPE_X509_CRL:
+ default:
+ node->data.generic = (void*)data;
+#ifdef OPENSSL_ALL
+ if (node->hash_fn != NULL)
+ node->hash = node->hash_fn(node->data.generic);
+#endif
+ break;
+ }
+}
+
+/* Pushes the node onto the stack.
+ *
+ * stack will point to node on success.
+ *
+ * @param [in, out] stack Stack of nodes.
+ * @param [in] node Node to push on.
+ *
+ * @return WOLFSSL_SUCCESS on success
+ * @return WOLFSSL_FAILURE when stack or node is NULL.
+ */
+int wolfSSL_sk_push_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* node)
+{
+ int ret = WOLFSSL_SUCCESS;
+
+ /* Validate parameters. */
+ if (stack == NULL || node == NULL) {
+ ret = WOLFSSL_FAILURE;
+ }
+ if (ret == WOLFSSL_SUCCESS) {
+ if (*stack == NULL) {
+ /* First node. */
+ node->num = 1;
+ }
+ else {
+ /* Place new node at start of the stack. */
+ node->num = (*stack)->num + 1;
+ node->next = *stack;
+ }
+ /* Return new start. */
+ *stack = node;
+ }
+
+ return ret;
+}
+
+/* Removes the node at the index from the stack and returns data.
+ *
+ * This is an internal API.
+ *
+ * @param [in, out] stack Stack of nodes.
+ * @param [in] idx Index of node to remove.
+ * @return Data in node on success.
+ * @return NULL when no node at index or no data.
+ */
+void* wolfSSL_sk_pop_node(WOLFSSL_STACK* stack, int idx)
+{
+ void* ret = NULL;
+ WOLFSSL_STACK* tmp = NULL;
+ WOLFSSL_STACK* prev;
+
+ /* Validate parameters. */
+ if ((stack != NULL) && (stack->num != 0)) {
+ stack->num--;
+ /* Popping first node handled differently. */
+ if (idx == 0 || stack->next == NULL) {
+ ret = wolfssl_sk_node_get_data(stack, 1);
+ /* Clear out data if we are returning it. */
+ if (ret != NULL) {
+ stack->data.generic = NULL;
+ }
+ if (stack->next) {
+ /* Keep the first node as it is the pointer passed in. */
+ tmp = stack->next;
+ wolfssl_sk_node_copy(stack, stack->next);
+ wolfSSL_sk_free_node(tmp);
+ }
+ }
+ else {
+ /* Find node at index and take out it. */
+ prev = stack;
+ tmp = stack->next;
+ while ((--idx != 0) && (tmp->next != NULL)) {
+ prev = tmp;
+ prev->num--;
+ tmp = tmp->next;
+ }
+ prev->next = tmp->next;
+
+ /* Get data to return and free node only. */
+ ret = wolfssl_sk_node_get_data(tmp, 1);
+ wolfSSL_sk_free_node(tmp);
+ }
+ }
+
+ return ret;
+}
+#endif /* NO_CERTS */
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+
+/*******************************************************************************
+ * SK APIs
+ ******************************************************************************/
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
+ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
+ defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+/* Creates a new stack of the requested type.
+ *
+ * This is an internal API.
+ *
+ * @param [in] type Type of stack.
+ * @return Empty stack on success.
+ * @return NULL when dynamic memory allocation fails.
+ */
+WOLFSSL_STACK* wolfssl_sk_new_type(WOLF_STACK_TYPE type)
+{
+ WOLFSSL_STACK* stack = wolfSSL_sk_new_node(NULL);
+ if (stack != NULL) {
+ stack->type = type;
+ }
+ return stack;
+}
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+/* Creates a new NULL type stack.
+ *
+ * This is an internal API.
+ *
+ * @return Empty stack on success.
+ * @return NULL when dynamic memory allocation fails.
+ */
+WOLFSSL_STACK* wolfSSL_sk_new_null(void)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_new_null");
+
+ return wolfssl_sk_new_type(STACK_TYPE_NULL);
+}
+
+/* Duplicate the data of a node into another.
+ *
+ * Limited too: STACK_TYPE_X509, STACK_TYPE_CIPHER, STACK_TYPE_GEN_NAME,
+ * STACK_TYPE_OBJ, STACK_TYPE_X509_OBJ.
+ *
+ * @param [in, out] dst Destination node.
+ * @param [in] src Source node.
+ * @return 0 on success.
+ * @return 1 when duplication failed or stack type is not supported.
+ */
+static int wolfssl_sk_dup_data(WOLFSSL_STACK* dst, WOLFSSL_STACK* src)
+{
+ int err = 0;
+
+ switch (src->type) {
+ case STACK_TYPE_X509:
+ if (src->data.x509 == NULL) {
+ break;
+ }
+ dst->data.x509 = wolfSSL_X509_dup(src->data.x509);
+ if (dst->data.x509 == NULL) {
+ WOLFSSL_MSG("wolfSSL_X509_dup error");
+ err = 1;
+ break;
+ }
+ break;
+ case STACK_TYPE_CIPHER:
+ wolfSSL_CIPHER_copy(&src->data.cipher, &dst->data.cipher);
+ break;
+ case STACK_TYPE_GEN_NAME:
+ if (src->data.gn == NULL) {
+ break;
+ }
+ dst->data.gn = wolfSSL_GENERAL_NAME_dup(src->data.gn);
+ if (dst->data.gn == NULL) {
+ WOLFSSL_MSG("wolfSSL_GENERAL_NAME_new error");
+ err = 1;
+ break;
+ }
+ break;
+ case STACK_TYPE_OBJ:
+ if (src->data.obj == NULL) {
+ break;
+ }
+ dst->data.obj = wolfSSL_ASN1_OBJECT_dup(src->data.obj);
+ if (dst->data.obj == NULL) {
+ WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_dup error");
+ err = 1;
+ break;
+ }
+ break;
+ case STACK_TYPE_X509_OBJ:
+ #if defined(OPENSSL_ALL)
+ if (src->data.x509_obj == NULL) {
+ break;
+ }
+ dst->data.x509_obj = wolfSSL_X509_OBJECT_dup(
+ src->data.x509_obj);
+ if (dst->data.x509_obj == NULL) {
+ WOLFSSL_MSG("wolfSSL_X509_OBJECT_dup error");
+ err = 1;
+ break;
+ }
+ break;
+ #endif
+ case STACK_TYPE_BIO:
+ case STACK_TYPE_STRING:
+ case STACK_TYPE_ACCESS_DESCRIPTION:
+ case STACK_TYPE_X509_EXT:
+ case STACK_TYPE_X509_REQ_ATTR:
+ case STACK_TYPE_NULL:
+ case STACK_TYPE_X509_NAME:
+ case STACK_TYPE_X509_NAME_ENTRY:
+ case STACK_TYPE_CONF_VALUE:
+ case STACK_TYPE_X509_INFO:
+ case STACK_TYPE_BY_DIR_entry:
+ case STACK_TYPE_BY_DIR_hash:
+ case STACK_TYPE_DIST_POINT:
+ case STACK_TYPE_X509_CRL:
+ default:
+ WOLFSSL_MSG("Unsupported stack type");
+ err = 1;
+ break;
+ }
+
+ return err;
+}
+
+/* Duplicate the stack of nodes.
+ *
+ * TODO: OpenSSL does a shallow copy but we have wolfSSL_shallow_sk_dup().
+ *
+ * Data is copied/duplicated - deep copy.
+ *
+ * Limited too: STACK_TYPE_X509, STACK_TYPE_CIPHER, STACK_TYPE_GEN_NAME,
+ * STACK_TYPE_OBJ, STACK_TYPE_X509_OBJ.
+ *
+ * @param [in, out] stack Stack of nodes.
+ * @return A new stack of nodes with data duplicated/copied on success.
+ * @return NULL on error.
+ */
+WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* stack)
+{
+ WOLFSSL_STACK* ret = NULL;
+ WOLFSSL_STACK* last = NULL;
+ int err = 0;
+
+ WOLFSSL_ENTER("wolfSSL_sk_dup");
+
+ for (; stack != NULL; stack = stack->next) {
+ /* New node for duplicate stack. */
+ WOLFSSL_STACK* cur = wolfSSL_sk_new_node(stack->heap);
+ if (cur == NULL) {
+ WOLFSSL_MSG("wolfSSL_sk_new_node error");
+ err = 1;
+ break;
+ }
+
+ if (ret == NULL) {
+ /* Keep the first node for returning. */
+ ret = cur;
+ }
+ if (last != NULL) {
+ /* Add new node to end of list. */
+ last->next = cur;
+ }
+ /* Update last node in linked list. */
+ last = cur;
+
+ wolfssl_sk_node_copy(cur, stack);
+ /* We will allocate new memory for this */
+ XMEMSET(&cur->data, 0, sizeof(cur->data));
+ cur->next = NULL;
+
+ err = wolfssl_sk_dup_data(cur, stack);
+ if (err) {
+ break;
+ }
+ }
+
+ if (err && (ret != NULL)) {
+ wolfSSL_sk_pop_free(ret, NULL);
+ ret = NULL;
+ }
+
+ return ret;
+}
+
+/* Shallow duplicate a stack of nodes.
+ *
+ * @param [in] stack Stack of nodes.
+ * @return A new stack of nodes with data duplicated/copied on success.
+ * @return NULL on error.
+ */
+WOLFSSL_STACK* wolfSSL_shallow_sk_dup(WOLFSSL_STACK* stack)
+{
+
+ WOLFSSL_STACK* ret = NULL;
+ WOLFSSL_STACK** prev = &ret;
+
+ WOLFSSL_ENTER("wolfSSL_shallow_sk_dup");
+
+ for (; stack != NULL; stack = stack->next) {
+ WOLFSSL_STACK* cur = wolfSSL_sk_new_node(stack->heap);
+ if (cur == NULL) {
+ WOLFSSL_MSG("wolfSSL_sk_new_node error");
+ wolfSSL_sk_free(ret);
+ ret = NULL;
+ break;
+ }
+
+ wolfssl_sk_node_copy(cur, stack);
+ cur->next = NULL;
+
+ *prev = cur;
+ prev = &cur->next;
+ }
+
+ return ret;
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
+ defined(OPENSSL_ALL)
+/* Free the nodes in the stack only.
+ *
+ * @param [in] stack Stack of nodes.
+ */
+void wolfSSL_sk_free(WOLFSSL_STACK* stack)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_free");
+
+ while (stack != NULL) {
+ WOLFSSL_STACK* next = stack->next;
+ wolfSSL_sk_free_node(stack);
+ stack = next;
+ }
+}
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
+ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_ALL)
+/* Get the number of nodes in the stack.
+ *
+ * @param [in] stack Stack of nodes.
+ * @return Number of nodes in stack on success.
+ * @return 0 when no nodes or stack is NULL.
+ */
+int wolfSSL_sk_num(const WOLFSSL_STACK* stack)
+{
+ int num = 0;
+
+ WOLFSSL_ENTER("wolfSSL_sk_num");
+
+ if (stack != NULL) {
+ num = (int)stack->num;
+ }
+
+ return num;
+}
+
+/* Get the value/data in a node from the stack at the index.
+ *
+ * If stack type is STACK_TYPE_CONF_VALUE and OPENSSL_EXTRA is not defined,
+ * the value will be NULL.
+ *
+ * @param [in] stack Stack of nodes.
+ * @param [in] i Index of node to get value/data.
+ * @return Data in node at index on success.
+ * @return NULL when no node at index.
+ */
+void* wolfSSL_sk_value(const WOLFSSL_STACK* sk, int i)
+{
+ void* val;
+
+ WOLFSSL_ENTER("wolfSSL_sk_value");
+
+ for (; (sk != NULL) && (i > 0); i--) {
+ sk = sk->next;
+ }
+
+ if (sk == NULL) {
+ val = NULL;
+ }
+ else {
+ switch (sk->type) {
+ case STACK_TYPE_CIPHER:
+ val = (void*)&sk->data.cipher;
+ break;
+ case STACK_TYPE_CONF_VALUE:
+ #ifndef OPENSSL_EXTRA
+ val = NULL;
+ break;
+ #endif
+ case STACK_TYPE_X509:
+ case STACK_TYPE_GEN_NAME:
+ case STACK_TYPE_BIO:
+ case STACK_TYPE_OBJ:
+ case STACK_TYPE_STRING:
+ case STACK_TYPE_ACCESS_DESCRIPTION:
+ case STACK_TYPE_X509_EXT:
+ case STACK_TYPE_X509_REQ_ATTR:
+ case STACK_TYPE_NULL:
+ case STACK_TYPE_X509_NAME:
+ case STACK_TYPE_X509_NAME_ENTRY:
+ case STACK_TYPE_X509_INFO:
+ case STACK_TYPE_BY_DIR_entry:
+ case STACK_TYPE_BY_DIR_hash:
+ case STACK_TYPE_X509_OBJ:
+ case STACK_TYPE_DIST_POINT:
+ case STACK_TYPE_X509_CRL:
+ default:
+ val = sk->data.generic;
+ break;
+ }
+ }
+
+ return val;
+}
+#endif
+
+#if (!defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || \
+ defined(WOLFSSL_WPAS_SMALL))) || defined(WOLFSSL_QT) || \
+ defined(OPENSSL_ALL)
+/* Put the data into a node at the top of the stack.
+ *
+ * @param [in, out] stack Stack of objects.
+ * @param [in] data Data to store in stack.
+ * @return Number of nodes in stack on success.
+ * @return WOLFSSL_FAILURE when data is NULL.
+ * @return WOLFSSL_FATAL_ERROR when stack is NULL.
+ */
+int wolfSSL_sk_push(WOLFSSL_STACK* stack, const void *data)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_push");
+
+ return wolfSSL_sk_insert(stack, data, -1);
+}
+
+/* Put the data into a node at an index in the stack.
+ *
+ * @param [in, out] stack Stack of objects.
+ * @param [in] data Data to store in stack.
+ * @return Number of nodes in stack on success.
+ * @return WOLFSSL_FAILURE when data is NULL.
+ * @return WOLFSSL_FATAL_ERROR when stack is NULL.
+ */
+int wolfSSL_sk_insert(WOLFSSL_STACK *stack, const void *data, int idx)
+{
+ int ret;
+ WOLFSSL_STACK* node;
+ WOLFSSL_ENTER("wolfSSL_sk_insert");
+
+ /* Validate parameters. */
+ if (stack == NULL) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ else if (data == NULL) {
+ ret = WOLFSSL_FAILURE;
+ }
+ else if (stack->num == 0) {
+ /* No data set in stack - set data into empty first node. */
+ wolfssl_sk_node_set_data(stack, stack->type, data);
+ stack->num = 1;
+ ret = 1;
+ }
+ else {
+ /* Create a new node. */
+ node = wolfSSL_sk_new_node(stack->heap);
+ if (node == NULL) {
+ WOLFSSL_MSG("Memory error");
+ ret = WOLFSSL_FAILURE;
+ }
+ else {
+ /* Place at front of linked-list. */
+ if (idx == 0) {
+ /* Special case where we need to change the values in the head
+ * element to avoid changing the initial pointer. */
+ wolfssl_sk_node_copy(node, stack);
+ wolfssl_sk_node_set_data(stack, stack->type, data);
+ stack->num++;
+ stack->next = node;
+ }
+ /* Place new node with data into list. */
+ else {
+ WOLFSSL_STACK* prev;
+ unsigned long num = stack->num;
+
+ node->type = stack->type;
+ #ifdef OPENSSL_ALL
+ node->hash_fn = stack->hash_fn;
+ #endif
+ /* Put data into new node. */
+ wolfssl_sk_node_set_data(node, stack->type, data);
+
+ /* Update count as new node being placed after first. */
+ stack->num++;
+ prev = stack;
+ while (((--idx) != 0) && (prev->next != NULL)) {
+ prev = prev->next;
+ /* Update count as new node being placed after this one. */
+ prev->num = num--;
+ }
+ /* Set count for new node. */
+ node->num = num;
+ /* Place node in linked list after prev. */
+ node->next = prev->next;
+ prev->next = node;
+ }
+
+ /* Returning new stack count. */
+ ret = (int)stack->num;
+ }
+ }
+
+ return ret;
+}
+#endif
+
+#if !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || \
+ defined(WOLFSSL_WPAS_SMALL))
+/* Remove the top node from the stack and return its data.
+ *
+ * @param [in, out] stack Stack of nodes with data.
+ * @return Data in top node on success.
+ * @return NULL when stack is NULL or stack is empty.
+ */
+void* wolfSSL_sk_pop(WOLFSSL_STACK* stack)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_pop");
+
+ return wolfSSL_sk_pop_node(stack, -1);
+}
+
+#endif /* !NO_CERTS && (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) */
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+/* Pop off data from the stack. Checks that the type matches the stack type.
+ *
+ * This is an internal API.
+ *
+ * @param [in, out] stack Stack of data.
+ * @param [in] type Type of stack.
+ * @return Data on success.
+ * @return NULL when stack is NULL or no nodes left in stack.
+ */
+void* wolfssl_sk_pop_type(WOLFSSL_STACK* stack, WOLF_STACK_TYPE type)
+{
+ void* data = NULL;
+
+ /* Check we have a stack passed in of the right type. */
+ if ((stack != NULL) && (stack->type == type))
+ data = wolfSSL_sk_pop(stack);
+
+ return data;
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
+ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_ALL)
+/* Get the free function for the stack type.
+ *
+ * @param [in] type Type of stack object.
+ * @return A free function on success.
+ * @return NULL when no free function to use.
+ */
+static wolfSSL_sk_freefunc wolfssl_sk_get_free_func(WOLF_STACK_TYPE type)
+{
+ wolfSSL_sk_freefunc func = NULL;
+
+ switch(type) {
+ case STACK_TYPE_ACCESS_DESCRIPTION:
+ #if defined(OPENSSL_ALL)
+ func = (wolfSSL_sk_freefunc)wolfSSL_ACCESS_DESCRIPTION_free;
+ #endif
+ break;
+ case STACK_TYPE_X509:
+ func = (wolfSSL_sk_freefunc)wolfSSL_X509_free;
+ break;
+ case STACK_TYPE_X509_OBJ:
+ #ifdef OPENSSL_ALL
+ func = (wolfSSL_sk_freefunc)wolfSSL_X509_OBJECT_free;
+ #endif
+ break;
+ case STACK_TYPE_OBJ:
+ func = (wolfSSL_sk_freefunc)wolfSSL_ASN1_OBJECT_free;
+ break;
+ case STACK_TYPE_DIST_POINT:
+ #ifdef OPENSSL_EXTRA
+ func = (wolfSSL_sk_freefunc)wolfSSL_DIST_POINT_free;
+ #endif
+ break;
+ case STACK_TYPE_GEN_NAME:
+ func = (wolfSSL_sk_freefunc)wolfSSL_GENERAL_NAME_free;
+ break;
+ case STACK_TYPE_STRING:
+ #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
+ defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+ func = (wolfSSL_sk_freefunc)wolfSSL_WOLFSSL_STRING_free;
+ #endif
+ break;
+ case STACK_TYPE_X509_NAME:
+ #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \
+ && !defined(WOLFCRYPT_ONLY)
+ func = (wolfSSL_sk_freefunc)wolfSSL_X509_NAME_free;
+ #endif
+ break;
+ case STACK_TYPE_X509_NAME_ENTRY:
+ #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \
+ && !defined(WOLFCRYPT_ONLY)
+ func = (wolfSSL_sk_freefunc)wolfSSL_X509_NAME_ENTRY_free;
+ #endif
+ break;
+ case STACK_TYPE_X509_EXT:
+ #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
+ func = (wolfSSL_sk_freefunc)wolfSSL_X509_EXTENSION_free;
+ #endif
+ break;
+ case STACK_TYPE_X509_REQ_ATTR:
+ #if defined(OPENSSL_ALL) && \
+ (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_REQ))
+ func = (wolfSSL_sk_freefunc)wolfSSL_X509_ATTRIBUTE_free;
+ #endif
+ break;
+ case STACK_TYPE_CONF_VALUE:
+ #if defined(OPENSSL_ALL)
+ func = (wolfSSL_sk_freefunc)wolfSSL_X509V3_conf_free;
+ #endif
+ break;
+ case STACK_TYPE_X509_INFO:
+ #if defined(OPENSSL_ALL)
+ func = (wolfSSL_sk_freefunc)wolfSSL_X509_INFO_free;
+ #endif
+ break;
+ case STACK_TYPE_BIO:
+ #if !defined(NO_BIO) && defined(OPENSSL_EXTRA)
+ func = (wolfSSL_sk_freefunc)wolfSSL_BIO_vfree;
+ #endif
+ break;
+ case STACK_TYPE_BY_DIR_entry:
+ #if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && \
+ !defined(NO_WOLFSSL_DIR)
+ func = (wolfSSL_sk_freefunc)wolfSSL_BY_DIR_entry_free;
+ #endif
+ break;
+ case STACK_TYPE_BY_DIR_hash:
+ #if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && \
+ !defined(NO_WOLFSSL_DIR)
+ func = (wolfSSL_sk_freefunc)wolfSSL_BY_DIR_HASH_free;
+ #endif
+ break;
+ case STACK_TYPE_X509_CRL:
+ #if defined(HAVE_CRL) && (defined(OPENSSL_EXTRA) || \
+ defined(WOLFSSL_WPAS_SMALL))
+ func = (wolfSSL_sk_freefunc)wolfSSL_X509_CRL_free;
+ #endif
+ break;
+ case STACK_TYPE_CIPHER:
+ /* Static copy kept in node. */
+ case STACK_TYPE_NULL:
+ default:
+ break;
+ }
+
+ return func;
+}
+
+/* Free all nodes and the dynamic data associated with them.
+ *
+ * This is an internal API.
+ *
+ * @param [in, out] sk Stack of objects.
+ * @param [in] func Function to use to free objects.
+ */
+void wolfSSL_sk_pop_free(WOLFSSL_STACK* stack, wolfSSL_sk_freefunc func)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_pop_free");
+
+ /* Validate parameters. */
+ if (stack == NULL) {
+ /* pop_free can be called with NULL, do not print bad argument */
+ return;
+ }
+#if defined(WOLFSSL_QT)
+ /* In Qt v15.5, it calls OPENSSL_sk_free(xxx, OPENSSL_sk_free).
+ * By using OPENSSL_sk_free for free causes access violation.
+ * Therefore, switching free func to wolfSSL_ACCESS_DESCRIPTION_free
+ * is needed even when func isn't NULL.
+ */
+ if (stack->type == STACK_TYPE_ACCESS_DESCRIPTION) {
+ func = (wolfSSL_sk_freefunc)wolfSSL_ACCESS_DESCRIPTION_free;
+ }
+#endif
+ /* Discover free function if none provided. */
+ if (func == NULL) {
+ func = wolfssl_sk_get_free_func(stack->type);
+ }
+
+ /* Free all nodes and data. */
+ while (stack != NULL) {
+ WOLFSSL_STACK* next = stack->next;
+
+ /* Free the data of the node. */
+ if ((func != NULL) && (stack->type != STACK_TYPE_CIPHER)) {
+ func(stack->data.generic);
+ }
+ /* Dispose of node. */
+ XFREE(stack, stack->heap, DYNAMIC_TYPE_OPENSSL);
+ stack = next;
+ }
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+
+/*******************************************************************************
+ * Stack - Generic
+ ******************************************************************************/
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+/* Free the nodes in the stack only.
+ *
+ * @param [in] stack Stack of nodes.
+ */
+void wolfSSL_sk_GENERIC_free(WOLFSSL_STACK* sk)
+{
+ wolfSSL_sk_free(sk);
+}
+
+/* Free all nodes and the dynamic data associated with them.
+ *
+ * This is an internal API.
+ *
+ * @param [in, out] sk Stack of objects.
+ * @param [in] func Function to use to free objects.
+ */
+void wolfSSL_sk_GENERIC_pop_free(WOLFSSL_STACK* sk, void (*f) (void*))
+{
+ WOLFSSL_ENTER("wolfSSL_sk_GENERIC_pop_free");
+ wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f);
+}
+
+/* Put the data into a node at the top of the stack.
+ *
+ * @param [in, out] stack Stack of objects.
+ * @param [in] data Data to store in stack.
+ * @return Number of nodes in stack on success.
+ * @return WOLFSSL_FAILURE when data is NULL.
+ * @return WOLFSSL_FATAL_ERROR when stack is NULL.
+ */
+int wolfSSL_sk_GENERIC_push(WOLFSSL_STACK* sk, void* generic)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_GENERIC_push");
+
+ return wolfSSL_sk_push(sk, generic);
+}
+#endif
+
+/*******************************************************************************
+ * Stack - Compression
+ ******************************************************************************/
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+/* Get the number of compression algorithms in stack.
+ *
+ * @param [in] stack Stack of compression algorithms.
+ * @return Number of compression algorithms in stack on success.
+ * @return 0 when no compression algorithms or stack is NULL.
+ */
+int wolfSSL_sk_SSL_COMP_num(WOLF_STACK_OF(WOLFSSL_COMP)* stack)
+{
+ return wolfSSL_sk_num(stack);
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_STUB)
+/* Remove all compression algorithms from stack.
+ *
+ * TBD
+ * Used when
+ * wolfSSL_set_options(ssl, SSL_OP_NO_COMPRESSION);
+ * is called.
+ *
+ * @param [in, out] stack Stack of compression algorithms.
+ * @return WOLFSSL_FAILURE always.
+ */
+int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* stack)
+{
+ (void)stack;
+ WOLFSSL_STUB("wolfSSL_sk_SSL_COMP_zero");
+ return WOLFSSL_FAILURE;
+}
+#endif
+
+/*******************************************************************************
+ * Stack - Cipher
+ ******************************************************************************/
+
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+/* Creates a new stack of ciphers.
+ *
+ * This is not an OpenSSL API.
+ *
+ * @return Empty stack on success.
+ * @return NULL when dynamic memory allocation fails.
+ */
+WOLFSSL_STACK* wolfSSL_sk_new_cipher(void)
+{
+ return wolfssl_sk_new_type(STACK_TYPE_CIPHER);
+}
+
+/* Put the cipher into a node at the top of the stack.
+ *
+ * This is an internal API.
+ *
+ * @param [in, out] stack Stack of ciphers.
+ * @param [in] cipher Cipher to store in stack.
+ * @return Number of ciphers in stack on success.
+ * @return WOLFSSL_FAILURE when data is NULL.
+ * @return WOLFSSL_FATAL_ERROR when stack is NULL.
+ */
+int wolfSSL_sk_CIPHER_push(WOLF_STACK_OF(WOLFSSL_CIPHER)* stack,
+ WOLFSSL_CIPHER* cipher)
+{
+ return wolfSSL_sk_push(stack, cipher);
+}
+
+#ifndef NO_WOLFSSL_STUB
+/* Does not do anythting at this time.
+ *
+ * @param [in, out] stack Stack of nodes with data.
+ * @return NULL always.
+ */
+WOLFSSL_CIPHER* wolfSSL_sk_CIPHER_pop(WOLF_STACK_OF(WOLFSSL_CIPHER)* stack)
+{
+ WOLFSSL_STUB("wolfSSL_sk_CIPHER_pop");
+ (void)stack;
+ return NULL;
+}
+#endif /* NO_WOLFSSL_STUB */
+#endif /* WOLFSSL_QT || OPENSSL_ALL */
+
+#if defined(OPENSSL_EXTRA)
+/* Free the nodes in the stack only.
+ *
+ * Ciphers are stored into a structure in a node and therefore don't need to be
+ * freed.
+ *
+ * @param [in] ciphers Stack of ciphers.
+ */
+void wolfSSL_sk_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* ciphers)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_CIPHER_free");
+
+ wolfSSL_sk_free(ciphers);
+}
+#endif /* OPENSSL_ALL */
+
+#ifdef OPENSSL_EXTRA
+/* Get the number of ciphers in the stack.
+ *
+ * @param [in] ciphers Stack of ciphers.
+ * @return Number of strings in stack on success.
+ * @return 0 when no strings or stack is NULL.
+ */
+int wolfSSL_sk_SSL_CIPHER_num(const WOLF_STACK_OF(WOLFSSL_CIPHER)* ciphers)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_num");
+ return wolfSSL_sk_num(ciphers);
+}
+
+/* Get the cipher from the stack at the index.
+ *
+ * @param [in] ciphers Stack of cihers
+ * @param [in] i Index of node to get cipher from.
+ * @return Cipher in node at index on success.
+ * @return NULL when no node at index.
+ */
+WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(WOLFSSL_STACK* ciphers, int i)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_value");
+ return (WOLFSSL_CIPHER*)wolfSSL_sk_value(ciphers, i);
+}
+#endif
+
+#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
+/* Get the priority level of the cipher if it is in the stack.
+ *
+ * Priority level is the number of ciphers minus the idex of the cipher.
+ *
+ * @param [in] ciphers Stack of ciphers.
+ * @param [in] cipher Cipher to find in stack.
+ * @return Priority level of cipher on success.
+ * @return WOLFSSL_FATAL_ERROR (-1) on failure to match.
+ */
+int wolfSSL_sk_SSL_CIPHER_find(WOLF_STACK_OF(WOLFSSL_CIPHER)* ciphers,
+ const WOLFSSL_CIPHER* cipher)
+{
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);
+
+ if (ciphers != NULL && cipher != NULL) {
+ int i;
+ int num = wolfSSL_sk_SSL_CIPHER_num(ciphers);
+ WOLFSSL_STACK* next = ciphers;
+
+ for (i = 0; (i < num) && (next != NULL); i++) {
+ /* Match on SSL/TLS cipher suite values. */
+ if ((next->data.cipher.cipherSuite0 == cipher->cipherSuite0) &&
+ (next->data.cipher.cipherSuite == cipher->cipherSuite)) {
+ /* reverse because stack pushed highest on first */
+ ret = num - i;
+ break;
+ }
+ next = next->next;
+ }
+ }
+
+ return ret;
+}
+
+/* Free the nodes in the stack only.
+ *
+ * @param [in] ciphers Stack of ciphers.
+ */
+void wolfSSL_sk_SSL_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_free");
+ wolfSSL_sk_free(sk);
+}
+#endif /* OPENSSL_ALL || OPENSSL_EXTRA */
+
+/*******************************************************************************
+ * Stack - String
+ ******************************************************************************/
+
+#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
+ defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+/* Creates a new stack of strings.
+ *
+ * @return Empty stack on success.
+ * @return NULL when dynamic memory allocation fails.
+ */
+WOLF_STACK_OF(WOLFSSL_STRING)* wolfSSL_sk_WOLFSSL_STRING_new(void)
+{
+ return wolfssl_sk_new_type(STACK_TYPE_STRING);
+}
+
+/* Free the nodes and strings of the stack.
+ *
+ * OpenSSL equivalent does not free data.
+ *
+ * @param [in] strings Stack of strings.
+ */
+void wolfSSL_sk_WOLFSSL_STRING_free(WOLF_STACK_OF(WOLFSSL_STRING)* strings)
+{
+ WOLFSSL_ENTER("wolfSSL_sk_WOLFSSL_STRING_free");
+
+ wolfSSL_sk_pop_free(strings, NULL);
+}
+
+/* Get the string from the node at an index.
+ *
+ * @param [in] strings Stack of strings.
+ * @param [in] idx Index of node.
+ * @return String in node at index on success.
+ * @return NULL when no node at index.
+ */
+WOLFSSL_STRING wolfSSL_sk_WOLFSSL_STRING_value(
+ WOLF_STACK_OF(WOLFSSL_STRING)* strings, int idx)
+{
+ return (WOLFSSL_STRING)wolfSSL_sk_value(strings, idx);
+}
+
+/* Get the number of strings in the stack.
+ *
+ * @param [in] strings Stack of strings.
+ * @return Number of strings in stack on success.
+ * @return 0 when no strings or stack is NULL.
+ */
+int wolfSSL_sk_WOLFSSL_STRING_num(WOLF_STACK_OF(WOLFSSL_STRING)* strings)
+{
+ return wolfSSL_sk_num(strings);
+}
+#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */
+
+/*******************************************************************************
+ * Stack - Linear Hash
+ ******************************************************************************/
+
+#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA) && defined(OPENSSL_ALL)
+/* Retrieve data from the stack by comparing with hash.
+ *
+ * @param [in] stack Stack of data.
+ * @param [in] data Data to look-up.
+ * @return Data of node with the same hash as data passed in.
+ * @return NULL when no match found.
+ */
+void *wolfSSL_lh_retrieve(WOLFSSL_STACK *stack, void *data)
+{
+ unsigned long hash;
+ void* sk_data = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_lh_retrieve");
+
+ /* Validate parameters. */
+ if ((stack == NULL) || (data == NULL)) {
+ WOLFSSL_MSG("Bad parameters");
+ }
+ else if (stack->hash_fn == NULL) {
+ WOLFSSL_MSG("No hash function defined");
+ }
+ else {
+ /* Calculate hassh of data we are looking for. */
+ hash = stack->hash_fn(data);
+
+ while (stack != NULL) {
+ /* Calculate hash if not done so yet. */
+ if (!stack->hash) {
+ sk_data = wolfssl_sk_node_get_data(stack, 0);
+ stack->hash = stack->hash_fn(sk_data);
+ }
+ /* Return data if hash matches. */
+ if (stack->hash == hash) {
+ if (sk_data == NULL) {
+ sk_data = wolfssl_sk_node_get_data(stack, 0);
+ }
+ break;
+ }
+
+ /* Not data to return. */
+ sk_data = NULL;
+ stack = stack->next;
+ }
+ }
+
+ return sk_data;
+}
+#endif /* !NO_CERTS && OPENSSL_EXTRA && OPENSSL_ALL */
+
+#endif /* !WOLFSSL_SSL_SK_INCLUDED */
diff --git a/tests/api.c b/tests/api.c
index 30b9dcddb..1730db85e 100644
--- a/tests/api.c
+++ b/tests/api.c
@@ -227,6 +227,7 @@
#include
#include
#include
+#include
#include
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \
@@ -50870,6 +50871,8 @@ TEST_CASE testCases[] = {
TEST_OSSL_ASN1_TIME_DECLS,
TEST_OSSL_ASN1_TYPE_DECLS,
+ TEST_SSL_SK_DECLS,
+
TEST_DECL(test_wolfSSL_lhash),
TEST_DECL(test_wolfSSL_certs),
diff --git a/tests/api/include.am b/tests/api/include.am
index 21d7dd89e..d6274cbff 100644
--- a/tests/api/include.am
+++ b/tests/api/include.am
@@ -77,6 +77,7 @@ tests_unit_test_SOURCES += tests/api/test_ossl_dh.c
tests_unit_test_SOURCES += tests/api/test_ossl_ec.c
tests_unit_test_SOURCES += tests/api/test_ossl_ecx.c
tests_unit_test_SOURCES += tests/api/test_ossl_dsa.c
+tests_unit_test_SOURCES += tests/api/test_ossl_sk.c
# TLS 1.3 specific
tests_unit_test_SOURCES += tests/api/test_tls13.c
endif
@@ -145,5 +146,6 @@ EXTRA_DIST += tests/api/test_ossl_dh.h
EXTRA_DIST += tests/api/test_ossl_ec.h
EXTRA_DIST += tests/api/test_ossl_ecx.h
EXTRA_DIST += tests/api/test_ossl_dsa.h
+EXTRA_DIST += tests/api/test_ossl_sk.h
EXTRA_DIST += tests/api/test_tls13.h
diff --git a/tests/api/test_ossl_sk.c b/tests/api/test_ossl_sk.c
new file mode 100644
index 000000000..23d69b1c2
--- /dev/null
+++ b/tests/api/test_ossl_sk.c
@@ -0,0 +1,487 @@
+/* test_ossl_sk.c
+ *
+ * Copyright (C) 2006-2025 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#include
+
+#ifdef NO_INLINE
+ #include
+#else
+ #define WOLFSSL_MISC_INCLUDED
+ #include
+#endif
+
+#include
+#include
+#include
+#include
+
+
+int test_wolfSSL_sk_new_free_node(void)
+{
+ EXPECT_DECLS;
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+ WOLFSSL_STACK* node = NULL;
+
+ wolfSSL_sk_free_node(NULL);
+
+ ExpectNotNull(node = wolfSSL_sk_new_node(HEAP_HINT));
+ wolfSSL_sk_free_node(node);
+#endif
+ return EXPECT_RESULT();
+}
+
+int test_wolfSSL_sk_push_get_node(void)
+{
+ EXPECT_DECLS;
+#if (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) && \
+ !defined(NO_CERTS)
+ WOLFSSL_STACK* stack = NULL;
+ WOLFSSL_STACK* node1 = NULL;
+ WOLFSSL_STACK* node2 = NULL;
+ WOLFSSL_STACK* node;
+
+ ExpectNotNull(node1 = wolfSSL_sk_new_node(HEAP_HINT));
+ ExpectNotNull(node2 = wolfSSL_sk_new_node(HEAP_HINT));
+
+ ExpectNull(wolfSSL_sk_get_node(NULL, -1));
+ ExpectNull(wolfSSL_sk_get_node(stack, -1));
+
+ ExpectIntEQ(wolfSSL_sk_push_node(NULL, NULL), WOLFSSL_FAILURE);
+ ExpectIntEQ(wolfSSL_sk_push_node(&stack, NULL), WOLFSSL_FAILURE);
+ ExpectIntEQ(wolfSSL_sk_push_node(NULL, node1), WOLFSSL_FAILURE);
+
+ ExpectIntEQ(wolfSSL_sk_push_node(&stack, node1), WOLFSSL_SUCCESS);
+ ExpectPtrEq(stack, node1);
+ ExpectIntEQ(wolfSSL_sk_push_node(&stack, node2), WOLFSSL_SUCCESS);
+ ExpectPtrEq(stack, node2);
+
+ ExpectNull(wolfSSL_sk_get_node(stack, -1));
+ ExpectNull(wolfSSL_sk_get_node(stack, 2));
+
+ ExpectNotNull(node = wolfSSL_sk_get_node(stack, 1));
+ ExpectPtrEq(node, node1);
+ ExpectNotNull(node = wolfSSL_sk_get_node(stack, 0));
+ ExpectPtrEq(node, node2);
+
+ wolfSSL_sk_free_node(node2);
+ wolfSSL_sk_free_node(node1);
+#endif
+ return EXPECT_RESULT();
+}
+
+int test_wolfSSL_sk_free(void)
+{
+ EXPECT_DECLS;
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+ WOLFSSL_STACK* stack = NULL;
+
+ wolfSSL_sk_free(NULL);
+
+ /* If there is ever a public API that creates a stack with the same ifdef
+ * protection then use it here instead of wolfSSL_sk_new_node(). */
+ ExpectNotNull(stack = wolfSSL_sk_new_node(HEAP_HINT));
+ wolfSSL_sk_free(stack);
+#endif
+ return EXPECT_RESULT();
+}
+
+int test_wolfSSL_sk_push_pop(void)
+{
+ EXPECT_DECLS;
+#if (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) && \
+ !defined(NO_CERTS)
+ WOLFSSL_STACK* stack = NULL;
+ unsigned char data_1[1] = { 1 };
+ unsigned char data_2[1] = { 2 };
+ unsigned char data_3[1] = { 3 };
+
+ /* If there is ever a public API that creates a stack with the same ifdef
+ * protection then use it here instead of wolfSSL_sk_new_node(). */
+ ExpectNotNull(stack = wolfSSL_sk_new_node(HEAP_HINT));
+ /* First node created and now have something to put data onto. */
+
+ ExpectIntEQ(wolfSSL_sk_push(NULL , NULL ), WOLFSSL_FATAL_ERROR);
+ ExpectIntEQ(wolfSSL_sk_push(NULL , data_1), WOLFSSL_FATAL_ERROR);
+ ExpectIntEQ(wolfSSL_sk_push(stack, NULL ), WOLFSSL_FAILURE);
+
+ ExpectNull(wolfSSL_sk_pop(NULL));
+
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_1), 1);
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_2), 2);
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_3), 3);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_3);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_2);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_1);
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_3), 1);
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_2), 2);
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_1), 3);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_1);
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_1), 3);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_1);
+
+ wolfSSL_sk_free(stack);
+#endif
+ return EXPECT_RESULT();
+}
+
+int test_wolfSSL_sk_insert(void)
+{
+ EXPECT_DECLS;
+#if (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) && \
+ !defined(NO_CERTS)
+ WOLFSSL_STACK* stack = NULL;
+ unsigned char data_1[1] = { 1 };
+ unsigned char data_2[1] = { 2 };
+ unsigned char data_3[1] = { 3 };
+
+ /* If there is ever a public API that creates a stack with the same ifdef
+ * protection then use it here instead of wolfSSL_sk_new_node(). */
+ ExpectNotNull(stack = wolfSSL_sk_new_node(HEAP_HINT));
+ /* First node created and now have something to put data onto. */
+
+ ExpectIntEQ(wolfSSL_sk_insert(NULL , NULL , 0), WOLFSSL_FATAL_ERROR);
+ ExpectIntEQ(wolfSSL_sk_insert(NULL , data_1, 0), WOLFSSL_FATAL_ERROR);
+ ExpectIntEQ(wolfSSL_sk_insert(stack, NULL , 0), WOLFSSL_FAILURE);
+
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_1, 0), 1);
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_2, 0), 2);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_1);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_2);
+ /* Zero or negative creates a node at the bottom of the stack. */
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_1, -2), 1);
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_2, -2), 2);
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_3, -2), 3);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_3);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_2);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_1);
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_1, 0), 1);
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_2, 1), 2);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_2);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_1);
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_1, 1), 1);
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_2, 0), 2);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_1);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_2);
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_1, 1), 1);
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_2, 1), 2);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_2);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_1);
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_1, 2), 1);
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_2, 1), 2);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_2);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_1);
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_1, 1), 1);
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_2, 2), 2);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_2);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_1);
+
+ wolfSSL_sk_free(stack);
+#endif
+ return EXPECT_RESULT();
+}
+
+int test_wolfSSL_shallow_sk_dup(void)
+{
+ EXPECT_DECLS;
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+ WOLFSSL_STACK* stack = NULL;
+ WOLFSSL_STACK* stack_dup = NULL;
+ unsigned char data_1[1] = { 1 };
+ unsigned char data_2[1] = { 2 };
+ unsigned char data_3[1] = { 3 };
+
+ ExpectNull(wolfSSL_shallow_sk_dup(NULL));
+
+ /* If there is ever a public API that creates a stack with the same ifdef
+ * protection then use it here instead of wolfSSL_sk_new_node(). */
+ ExpectNotNull(stack = wolfSSL_sk_new_node(HEAP_HINT));
+ /* First node created and now have something to put data onto. */
+
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_1, 0), 1);
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_2, 0), 2);
+ ExpectIntEQ(wolfSSL_sk_insert(stack, data_3, 0), 3);
+ ExpectNotNull(stack_dup = wolfSSL_shallow_sk_dup(stack));
+ ExpectPtrEq(wolfSSL_sk_pop(stack_dup), data_1);
+ ExpectPtrEq(wolfSSL_sk_pop(stack_dup), data_2);
+ ExpectPtrEq(wolfSSL_sk_pop(stack_dup), data_3);
+
+ wolfSSL_sk_free(stack_dup);
+ wolfSSL_sk_free(stack);
+#endif
+ return EXPECT_RESULT();
+}
+
+int test_wolfSSL_sk_num(void)
+{
+ EXPECT_DECLS;
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+ WOLFSSL_STACK* stack = NULL;
+ unsigned char data_1[1] = { 1 };
+ unsigned char data_2[1] = { 2 };
+ unsigned char data_3[1] = { 3 };
+
+ ExpectIntEQ(wolfSSL_sk_num(NULL), 0);
+
+ /* If there is ever a public API that creates a stack with the same ifdef
+ * protection then use it here instead of wolfSSL_sk_new_node(). */
+ ExpectNotNull(stack = wolfSSL_sk_new_node(HEAP_HINT));
+ /* First node created and now have something to put data onto. */
+
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_1), 1);
+ ExpectIntEQ(wolfSSL_sk_num(stack), 1);
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_2), 2);
+ ExpectIntEQ(wolfSSL_sk_num(stack), 2);
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_3), 3);
+ ExpectIntEQ(wolfSSL_sk_num(stack), 3);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_3);
+ ExpectIntEQ(wolfSSL_sk_num(stack), 2);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_2);
+ ExpectIntEQ(wolfSSL_sk_num(stack), 1);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_1);
+ ExpectIntEQ(wolfSSL_sk_num(stack), 0);
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_3), 1);
+ ExpectIntEQ(wolfSSL_sk_num(stack), 1);
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_2), 2);
+ ExpectIntEQ(wolfSSL_sk_num(stack), 2);
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_1), 3);
+ ExpectIntEQ(wolfSSL_sk_num(stack), 3);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_1);
+ ExpectIntEQ(wolfSSL_sk_num(stack), 2);
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_1), 3);
+ ExpectIntEQ(wolfSSL_sk_num(stack), 3);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_1);
+ ExpectIntEQ(wolfSSL_sk_num(stack), 2);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_2);
+ ExpectIntEQ(wolfSSL_sk_num(stack), 1);
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_2), 2);
+ ExpectIntEQ(wolfSSL_sk_num(stack), 2);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_2);
+ ExpectIntEQ(wolfSSL_sk_num(stack), 1);
+ ExpectPtrEq(wolfSSL_sk_pop(stack), data_3);
+ ExpectIntEQ(wolfSSL_sk_num(stack), 0);
+
+ wolfSSL_sk_free(stack);
+#endif
+ return EXPECT_RESULT();
+}
+
+int test_wolfSSL_sk_value(void)
+{
+ EXPECT_DECLS;
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+ WOLFSSL_STACK* stack = NULL;
+ unsigned char data_1[1] = { 1 };
+ unsigned char data_2[1] = { 2 };
+ unsigned char data_3[1] = { 3 };
+
+ /* If there is ever a public API that creates a stack with the same ifdef
+ * protection then use it here instead of wolfSSL_sk_new_node(). */
+ ExpectNotNull(stack = wolfSSL_sk_new_node(HEAP_HINT));
+ /* First node created and now have something to put data onto. */
+
+ ExpectNull(wolfSSL_sk_value(NULL, -1));
+ ExpectNull(wolfSSL_sk_value(NULL, 1));
+ ExpectNull(wolfSSL_sk_value(stack, -1));
+ ExpectNull(wolfSSL_sk_value(stack, 0));
+
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_1), 1);
+ ExpectNull(wolfSSL_sk_value(stack, 1));
+ ExpectPtrEq(wolfSSL_sk_value(stack, 0), data_1);
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_2), 2);
+ ExpectNull(wolfSSL_sk_value(stack, 2));
+ ExpectPtrEq(wolfSSL_sk_value(stack, 1), data_2);
+ ExpectPtrEq(wolfSSL_sk_value(stack, 0), data_1);
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_3), 3);
+ ExpectNull(wolfSSL_sk_value(stack, 3));
+ ExpectPtrEq(wolfSSL_sk_value(stack, 2), data_3);
+ ExpectPtrEq(wolfSSL_sk_value(stack, 1), data_2);
+ ExpectPtrEq(wolfSSL_sk_value(stack, 0), data_1);
+
+ wolfSSL_sk_free(stack);
+#endif
+ return EXPECT_RESULT();
+}
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+static void test_sk_xfree(void* data)
+{
+ XFREE(data, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+#endif
+
+int test_wolfssl_sk_GENERIC(void)
+{
+ EXPECT_DECLS;
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+ WOLFSSL_STACK* stack = NULL;
+ unsigned char data_1[1] = { 1 };
+ unsigned char data_2[1] = { 2 };
+ unsigned char data_3[1] = { 3 };
+ char* str_1 = NULL;
+
+ /* If there is ever a public API that creates a stack with the same ifdef
+ * protection then use it here instead of wolfSSL_sk_new_node(). */
+ ExpectNotNull(stack = wolfSSL_sk_new_node(HEAP_HINT));
+
+ ExpectIntEQ(wolfSSL_sk_GENERIC_push(stack, data_1), 1);
+ ExpectNull(wolfSSL_sk_value(stack, 1));
+ ExpectPtrEq(wolfSSL_sk_value(stack, 0), data_1);
+ ExpectIntEQ(wolfSSL_sk_GENERIC_push(stack, data_2), 2);
+ ExpectNull(wolfSSL_sk_value(stack, 2));
+ ExpectPtrEq(wolfSSL_sk_value(stack, 1), data_2);
+ ExpectPtrEq(wolfSSL_sk_value(stack, 0), data_1);
+ ExpectIntEQ(wolfSSL_sk_GENERIC_push(stack, data_3), 3);
+ ExpectNull(wolfSSL_sk_value(stack, 3));
+ ExpectPtrEq(wolfSSL_sk_value(stack, 2), data_3);
+ ExpectPtrEq(wolfSSL_sk_value(stack, 1), data_2);
+ ExpectPtrEq(wolfSSL_sk_value(stack, 0), data_1);
+
+ wolfSSL_sk_GENERIC_free(stack);
+ stack = NULL;
+
+ /* If there is ever a public API that creates a stack with the same ifdef
+ * protection then use it here instead of wolfSSL_sk_new_node(). */
+ ExpectNotNull(stack = wolfSSL_sk_new_node(HEAP_HINT));
+ wolfSSL_sk_GENERIC_pop_free(stack, test_sk_xfree);
+
+ /* If there is ever a public API that creates a stack with the same ifdef
+ * protection then use it here instead of wolfSSL_sk_new_node(). */
+ ExpectNotNull(stack = wolfSSL_sk_new_node(HEAP_HINT));
+ ExpectNotNull(str_1 = (char*)XMALLOC(2, NULL, DYNAMIC_TYPE_OPENSSL));
+ if (EXPECT_SUCCESS()) {
+ XSTRNCPY(str_1, "1", 2);
+ }
+ ExpectIntEQ(wolfSSL_sk_GENERIC_push(stack, str_1), 1);
+ if (EXPECT_FAIL()) {
+ XFREE(str_1, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+
+ wolfSSL_sk_GENERIC_pop_free(NULL, NULL);
+ wolfSSL_sk_GENERIC_pop_free(NULL, test_sk_xfree);
+ wolfSSL_sk_GENERIC_pop_free(stack, test_sk_xfree);
+#endif
+ return EXPECT_RESULT();
+}
+
+int test_wolfssl_sk_SSL_COMP(void)
+{
+ EXPECT_DECLS;
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+ ExpectIntEQ(wolfSSL_sk_SSL_COMP_num(NULL), 0);
+#endif
+
+#if defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_STUB)
+ ExpectIntEQ(wolfSSL_sk_SSL_COMP_zero(NULL), WOLFSSL_FAILURE);
+#endif
+ return EXPECT_RESULT();
+}
+
+int test_wolfSSL_sk_CIPHER(void)
+{
+ EXPECT_DECLS;
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ /* TODO: figure out a way to get a WOLFSSL_CIPHER to test with. */
+ WOLFSSL_STACK* ciphers = NULL;
+
+ ExpectNotNull(ciphers = wolfSSL_sk_new_cipher());
+
+#ifndef NO_WOLFSSL_STUB
+ ExpectNull(wolfSSL_sk_CIPHER_pop(NULL));
+ ExpectNull(wolfSSL_sk_CIPHER_pop(ciphers));
+#endif
+
+ ExpectIntEQ(wolfSSL_sk_CIPHER_push(NULL, NULL), WOLFSSL_FATAL_ERROR);
+ ExpectIntEQ(wolfSSL_sk_CIPHER_push(ciphers, NULL), WOLFSSL_FAILURE);
+
+#ifdef OPENSSL_EXTRA
+ wolfSSL_sk_CIPHER_free(NULL);
+ wolfSSL_sk_CIPHER_free(ciphers);
+#else
+ wolfSSL_sk_free(ciphers);
+#endif
+#endif
+ return EXPECT_RESULT();
+}
+
+int test_wolfssl_sk_WOLFSSL_STRING(void)
+{
+ EXPECT_DECLS;
+#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
+ defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+ WOLF_STACK_OF(WOLFSSL_STRING)* strings = NULL;
+ char* str_1 = NULL;
+ char* str = NULL;
+
+ ExpectNotNull(str_1 = (char*)XMALLOC(2, NULL, DYNAMIC_TYPE_OPENSSL));
+ if (str_1 != NULL) {
+ XSTRNCPY(str_1, "1", 2);
+ }
+
+ ExpectNotNull(strings = wolfSSL_sk_WOLFSSL_STRING_new());
+ ExpectIntEQ(wolfSSL_sk_WOLFSSL_STRING_num(strings), 0);
+
+ ExpectNull(wolfSSL_sk_WOLFSSL_STRING_value(NULL, 0));
+ ExpectNull(wolfSSL_sk_WOLFSSL_STRING_value(NULL, 1));
+ ExpectNull(wolfSSL_sk_WOLFSSL_STRING_value(strings, -1));
+ ExpectNull(wolfSSL_sk_WOLFSSL_STRING_value(strings, 0));
+
+ ExpectIntEQ(wolfSSL_sk_push(strings, str_1), 1);
+ ExpectIntEQ(wolfSSL_sk_WOLFSSL_STRING_num(strings), 1);
+ ExpectNull(wolfSSL_sk_WOLFSSL_STRING_value(strings, 1));
+ ExpectPtrEq(str = wolfSSL_sk_WOLFSSL_STRING_value(strings, 0), str_1);
+ if (str != str_1) {
+ XFREE(str_1, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+
+ wolfSSL_sk_WOLFSSL_STRING_free(NULL);
+ wolfSSL_sk_WOLFSSL_STRING_free(strings);
+#endif
+ return EXPECT_RESULT();
+}
+
+int test_wolfssl_lh_retrieve(void)
+{
+ EXPECT_DECLS;
+#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA) && defined(OPENSSL_ALL)
+ WOLFSSL_STACK* stack = NULL;
+ unsigned char data_1[1] = { 1 };
+
+ /* If there is ever a public API that creates a stack with the same ifdef
+ * protection then use it here instead of wolfSSL_sk_new_node(). */
+ ExpectNotNull(stack = wolfSSL_sk_new_node(HEAP_HINT));
+
+ ExpectNull(wolfSSL_lh_retrieve(NULL, NULL));
+ ExpectNull(wolfSSL_lh_retrieve(stack, NULL));
+ ExpectNull(wolfSSL_lh_retrieve(NULL, data_1));
+ /* No hash function. */
+ ExpectNull(wolfSSL_lh_retrieve(stack, data_1));
+
+ ExpectIntEQ(wolfSSL_sk_push(stack, data_1), 1);
+ /* No hash function - data present. */
+ ExpectNull(wolfSSL_lh_retrieve(stack, data_1));
+
+ /* No public API to set hash function. */
+
+ wolfSSL_sk_free(stack);
+#endif
+ return EXPECT_RESULT();
+}
+
diff --git a/tests/api/test_ossl_sk.h b/tests/api/test_ossl_sk.h
new file mode 100644
index 000000000..0ab75398e
--- /dev/null
+++ b/tests/api/test_ossl_sk.h
@@ -0,0 +1,57 @@
+/* test_ossl_sk.h
+ *
+ * Copyright (C) 2006-2025 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#ifndef WOLFCRYPT_TEST_SSL_SK_H
+#define WOLFCRYPT_TEST_SSL_SK_H
+
+#include
+
+int test_wolfSSL_sk_new_free_node(void);
+int test_wolfSSL_sk_push_get_node(void);
+int test_wolfSSL_sk_free(void);
+int test_wolfSSL_sk_push_pop(void);
+int test_wolfSSL_sk_insert(void);
+int test_wolfSSL_shallow_sk_dup(void);
+int test_wolfSSL_sk_num(void);
+int test_wolfSSL_sk_value(void);
+int test_wolfssl_sk_GENERIC(void);
+int test_wolfssl_sk_SSL_COMP(void);
+int test_wolfSSL_sk_CIPHER(void);
+int test_wolfssl_sk_WOLFSSL_STRING(void);
+int test_wolfssl_lh_retrieve(void);
+
+#define TEST_SSL_SK_DECLS \
+ TEST_DECL_GROUP("ossl_sk", test_wolfSSL_sk_new_free_node), \
+ TEST_DECL_GROUP("ossl_sk", test_wolfSSL_sk_push_get_node), \
+ TEST_DECL_GROUP("ossl_sk", test_wolfSSL_sk_free), \
+ TEST_DECL_GROUP("ossl_sk", test_wolfSSL_sk_push_pop), \
+ TEST_DECL_GROUP("ossl_sk", test_wolfSSL_sk_insert), \
+ TEST_DECL_GROUP("ossl_sk", test_wolfSSL_shallow_sk_dup), \
+ TEST_DECL_GROUP("ossl_sk", test_wolfSSL_sk_num), \
+ TEST_DECL_GROUP("ossl_sk", test_wolfSSL_sk_value), \
+ TEST_DECL_GROUP("ossl_sk", test_wolfssl_sk_GENERIC), \
+ TEST_DECL_GROUP("ossl_sk", test_wolfssl_sk_SSL_COMP), \
+ TEST_DECL_GROUP("ossl_sk", test_wolfSSL_sk_CIPHER), \
+ TEST_DECL_GROUP("ossl_sk", test_wolfssl_sk_WOLFSSL_STRING), \
+ TEST_DECL_GROUP("ossl_sk", test_wolfssl_lh_retrieve)
+
+#endif /* WOLFCRYPT_TEST_SSL_SK_H */
+
diff --git a/wolfcrypt/src/memory.c b/wolfcrypt/src/memory.c
index b8570f3f6..779898989 100644
--- a/wolfcrypt/src/memory.c
+++ b/wolfcrypt/src/memory.c
@@ -135,7 +135,7 @@ int mem_fail_allocs = 0;
int mem_fail_frees = 0;
int mem_fail_cnt = 0;
-void wc_MemFailCount_Init()
+void wc_MemFailCount_Init(void)
{
char* cnt;
#ifndef WOLFSSL_MUTEX_INITIALIZER
@@ -168,7 +168,7 @@ static void wc_MemFailCount_FreeMem(void)
mem_fail_frees++;
wc_UnLockMutex(&memFailMutex);
}
-void wc_MemFailCount_Free()
+void wc_MemFailCount_Free(void)
{
#ifndef WOLFSSL_MUTEX_INITIALIZER
wc_FreeMutex(&memFailMutex);
diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h
index 064dedcdf..ca8f4f81d 100644
--- a/wolfssl/ssl.h
+++ b/wolfssl/ssl.h
@@ -1883,18 +1883,35 @@ WOLFSSL_LOCAL int CertSetupCbWrapper(WOLFSSL* ssl);
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
WOLFSSL_API void wolfSSL_ERR_print_errors(WOLFSSL_BIO *bio);
+#endif
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
+ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_ALL)
WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_new_node(void* heap);
-WOLFSSL_API void wolfSSL_sk_free(WOLFSSL_STACK* sk);
+#endif
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
WOLFSSL_API void wolfSSL_sk_free_node(WOLFSSL_STACK* in);
+#endif
+#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA)
+WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* sk, int idx);
+#endif
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+WOLFSSL_API int wolfSSL_sk_push_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* in);
+
+WOLFSSL_API void wolfSSL_sk_free(WOLFSSL_STACK* sk);
WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* sk);
WOLFSSL_API WOLFSSL_STACK* wolfSSL_shallow_sk_dup(WOLFSSL_STACK* sk);
-WOLFSSL_API int wolfSSL_sk_push_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* in);
-WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* sk, int idx);
WOLFSSL_API int wolfSSL_sk_push(WOLFSSL_STACK *st, const void *data);
WOLFSSL_API int wolfSSL_sk_insert(WOLFSSL_STACK *sk, const void *data, int idx);
WOLFSSL_API void* wolfSSL_sk_pop(WOLFSSL_STACK* sk);
+#endif
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
+ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_ALL)
+WOLFSSL_API int wolfSSL_sk_num(const WOLFSSL_STACK* sk);
+WOLFSSL_API void* wolfSSL_sk_value(const WOLFSSL_STACK* sk, int i);
+#endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(WOLFSSL_QT)
WOLFSSL_API int wolfSSL_sk_ACCESS_DESCRIPTION_push(
WOLF_STACK_OF(ACCESS_DESCRIPTION)* sk,
@@ -3237,11 +3254,6 @@ WOLFSSL_API int wolfSSL_ASN1_TIME_set_string_X509(WOLFSSL_ASN1_TIME *t,
#endif /* OPENSSL_EXTRA */
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
-WOLFSSL_API int wolfSSL_sk_num(const WOLFSSL_STACK* sk);
-WOLFSSL_API void* wolfSSL_sk_value(const WOLFSSL_STACK* sk, int i);
-#endif
-
/* stunnel 4.28 needs */
WOLFSSL_API void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx,