From 99f590f48728aa15a8d7f5e1eb51b2410e138159 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 23 Feb 2026 19:23:41 +0100 Subject: [PATCH 1/7] Add Python CI workflow and Blake2 EVP support - Add a GitHub Actions workflow to automate testing of Python integration - Implement Blake2b and Blake2s hash functions into the EVP API. - Improve OpenSSL compatibility by standardizing ASN.1 encoding for serial numbers and registered IDs, streamlining cipher stack management, and optimizing stack node copying. - Enforce maximum fragment size during data transmission to ensure proper TLS/DTLS record fragmentation. --- .github/workflows/python.yml | 156 +++++++++++++++++++++++++++++++++++ src/internal.c | 5 ++ src/ocsp.c | 17 ++-- src/ssl.c | 69 +++++++--------- src/ssl_sk.c | 40 +++------ src/x509.c | 64 ++++++++------ tests/api.c | 5 +- wolfcrypt/src/evp.c | 84 +++++++++++++++++++ wolfssl/internal.h | 2 + wolfssl/openssl/evp.h | 12 +++ wolfssl/openssl/opensslv.h | 6 +- 11 files changed, 349 insertions(+), 111 deletions(-) create mode 100644 .github/workflows/python.yml diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml new file mode 100644 index 0000000000..6cbcc8f8ce --- /dev/null +++ b/.github/workflows/python.yml @@ -0,0 +1,156 @@ +name: Python Tests + +# START OF COMMON SECTION +on: + push: + branches: [ 'master', 'main', 'release/**' ] + pull_request: + branches: [ '*' ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +# END OF COMMON SECTION + +jobs: + build_wolfssl: + name: Build wolfSSL + if: github.repository_owner == 'wolfssl' + runs-on: ubuntu-24.04 + timeout-minutes: 10 + steps: + - name: Build wolfSSL + uses: wolfSSL/actions-build-autotools-project@v1 + with: + path: wolfssl + configure: >- + --enable-all --enable-tlsv10 + 'CPPFLAGS=-DHAVE_SECRET_CALLBACK -DWOLFSSL_PYTHON' + check: false + install: true + + - name: tar build-dir + run: tar -zcf build-dir.tgz build-dir + + - name: Upload built lib + uses: actions/upload-artifact@v4 + with: + name: wolf-install-python + path: build-dir.tgz + retention-days: 5 + + python_check: + strategy: + fail-fast: false + matrix: + include: + - python_ver: 3.12.11 + tests: >- + test_ssl + test.test_asyncio.test_ssl + test.test_asyncio.test_sslproto + test_hashlib + test_hmac + test_secrets + test_ftplib + test_imaplib + test_poplib + test_smtplib + test_httplib + test_urllib2_localnet + test_xmlrpc + test_docxmlrpc + - python_ver: 3.13.4 + tests: >- + test_ssl + test.test_asyncio.test_ssl + test.test_asyncio.test_sslproto + test_hashlib + test_hmac + test_secrets + test_ftplib + test_imaplib + test_poplib + test_smtplib + test_httplib + test_urllib2_localnet + test_xmlrpc + test_docxmlrpc + - python_ver: 3.13.7 + tests: >- + test_ssl + test.test_asyncio.test_ssl + test.test_asyncio.test_sslproto + test_hashlib + test_hmac + test_secrets + test_ftplib + test_imaplib + test_poplib + test_smtplib + test_httplib + test_urllib2_localnet + test_xmlrpc + test_docxmlrpc + name: Python ${{ matrix.python_ver }} + if: github.repository_owner == 'wolfssl' + runs-on: ubuntu-24.04 + timeout-minutes: 60 + needs: build_wolfssl + steps: + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + build-essential autoconf automake autoconf-archive pkgconf \ + libffi-dev libbz2-dev libreadline-dev libsqlite3-dev \ + zlib1g-dev libncursesw5-dev libgdbm-dev libnss3-dev \ + liblzma-dev uuid-dev pkg-config + + - name: Download wolfSSL + uses: actions/download-artifact@v4 + with: + name: wolf-install-python + + - name: Untar wolfSSL build + run: tar -xf build-dir.tgz + + - name: Checkout OSP + uses: actions/checkout@v4 + with: + repository: wolfssl/osp + path: osp + + - name: Checkout CPython + uses: actions/checkout@v4 + with: + repository: python/cpython + ref: v${{ matrix.python_ver }} + path: cpython + + - name: Apply wolfSSL patch + working-directory: cpython + run: patch -p1 < $GITHUB_WORKSPACE/osp/Python/wolfssl-python-${{ matrix.python_ver }}.patch + + - name: Build CPython and run SSL and crypto tests + working-directory: cpython + run: | + export LD_LIBRARY_PATH=$GITHUB_WORKSPACE/build-dir/lib:$LD_LIBRARY_PATH + rm aclocal.m4 + autoreconf -if + ./configure --with-wolfssl=$GITHUB_WORKSPACE/build-dir + make -j test TESTOPTS="-v \ + test_ssl \ + test.test_asyncio.test_ssl \ + test.test_asyncio.test_sslproto \ + test_hashlib \ + test_hmac \ + test_secrets \ + test_ftplib \ + test_imaplib \ + test_poplib \ + test_smtplib \ + test_httplib \ + test_urllib2_localnet \ + test_xmlrpc \ + test_docxmlrpc" diff --git a/src/internal.c b/src/internal.c index f7f0b26d64..5435f4b849 100644 --- a/src/internal.c +++ b/src/internal.c @@ -26282,6 +26282,11 @@ int SendData(WOLFSSL* ssl, const void* data, size_t sz) if (sent == (word32)sz) break; buffSz = (word32)sz - sent; + { + int maxFrag = wolfSSL_GetMaxFragSize(ssl); + if (maxFrag > 0 && (int)buffSz > maxFrag) + buffSz = (word32)maxFrag; + } outputSz = wolfssl_local_GetRecordSize(ssl, (word32)buffSz, 1); #if defined(WOLFSSL_DTLS) if (ssl->options.dtls) { diff --git a/src/ocsp.c b/src/ocsp.c index ce42b4d65a..0f1e2ec4cd 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -1995,18 +1995,11 @@ int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING **name, ser->dataMax = WOLFSSL_ASN1_INTEGER_MAX; } - #if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY) - /* Serial number starts at 0 index of ser->data */ - XMEMCPY(&ser->data[i], cid->status->serial, - (size_t)cid->status->serialSz); - ser->length = cid->status->serialSz; - #else - ser->data[i++] = ASN_INTEGER; - i += SetLength(cid->status->serialSz, ser->data + i); - XMEMCPY(&ser->data[i], cid->status->serial, - (size_t)cid->status->serialSz); - ser->length = i + cid->status->serialSz; - #endif + ser->data[i++] = ASN_INTEGER; + i += SetLength(cid->status->serialSz, ser->data + i); + XMEMCPY(&ser->data[i], cid->status->serial, + (size_t)cid->status->serialSz); + ser->length = i + cid->status->serialSz; cid->status->serialInt = ser; *serial = ser; diff --git a/src/ssl.c b/src/ssl.c index 8f693bba1b..eb8881818c 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -10457,8 +10457,7 @@ const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher) return NULL; } - #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) && \ - !defined(WOLFSSL_QT) + #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) return GetCipherNameIana(cipher->cipherSuite0, cipher->cipherSuite); #else return wolfSSL_get_cipher_name_from_suite(cipher->cipherSuite0, @@ -14028,12 +14027,7 @@ void* wolfSSL_GetHKDFExtractCtx(WOLFSSL* ssl) } if (i == (int)WOLFSSL_OBJECT_INFO_SZ) { WOLFSSL_MSG("NID not in table"); - #ifdef WOLFSSL_QT - sName = NULL; - type = (word32)id; - #else return NULL; - #endif } #ifdef HAVE_ECC @@ -16022,9 +16016,8 @@ static WC_INLINE int sslCipherMinMaxCheck(const WOLFSSL *ssl, byte suite0, */ WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl) { - WOLF_STACK_OF(WOLFSSL_CIPHER)* ret = NULL; const Suites* suites; -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) +#if defined(OPENSSL_ALL) const CipherSuiteInfo* cipher_names = GetCipherNames(); int cipherSz = GetCipherNamesSize(); #endif @@ -16040,15 +16033,20 @@ WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl) /* check if stack needs populated */ if (ssl->suitesStack == NULL) { int i; -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) - int j; + + ((WOLFSSL*)ssl)->suitesStack = + wolfssl_sk_new_type_ex(STACK_TYPE_CIPHER, ssl->heap); + if (ssl->suitesStack == NULL) + return NULL; /* higher priority of cipher suite will be on top of stack */ - for (i = suites->suiteSz - 2; i >=0; i-=2) { +#if defined(OPENSSL_ALL) + for (i = suites->suiteSz - 2; i >=0; i-=2) #else - for (i = 0; i < suites->suiteSz; i+=2) { + for (i = 0; i < suites->suiteSz; i+=2) #endif - WOLFSSL_STACK* add; + { + struct WOLFSSL_CIPHER cipher; /* A couple of suites are placeholders for special options, * skip those. */ @@ -16058,39 +16056,30 @@ WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl) continue; } - add = wolfSSL_sk_new_node(ssl->heap); - if (add != NULL) { - add->type = STACK_TYPE_CIPHER; - add->data.cipher.cipherSuite0 = suites->suites[i]; - add->data.cipher.cipherSuite = suites->suites[i+1]; - add->data.cipher.ssl = ssl; -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + XMEMSET(&cipher, 0, sizeof(cipher)); + cipher.cipherSuite0 = suites->suites[i]; + cipher.cipherSuite = suites->suites[i+1]; + cipher.ssl = ssl; +#if defined(OPENSSL_ALL) + cipher.in_stack = 1; + { + int j; for (j = 0; j < cipherSz; j++) { - if (cipher_names[j].cipherSuite0 == - add->data.cipher.cipherSuite0 && - cipher_names[j].cipherSuite == - add->data.cipher.cipherSuite) { - add->data.cipher.offset = (unsigned long)j; + if (cipher_names[j].cipherSuite0 == cipher.cipherSuite0 && + cipher_names[j].cipherSuite == cipher.cipherSuite) { + cipher.offset = (unsigned long)j; break; } } + } #endif - #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) - /* in_stack is checked in wolfSSL_CIPHER_description */ - add->data.cipher.in_stack = 1; - #endif - - add->next = ret; - if (ret != NULL) { - add->num = ret->num + 1; - } - else { - add->num = 1; - } - ret = add; + if (wolfSSL_sk_insert(ssl->suitesStack, &cipher, 0) <= 0) { + WOLFSSL_MSG("Error inserting cipher onto stack"); + wolfSSL_sk_CIPHER_free(ssl->suitesStack); + ((WOLFSSL*)ssl)->suitesStack = NULL; + break; } } - ((WOLFSSL*)ssl)->suitesStack = ret; } return ssl->suitesStack; } diff --git a/src/ssl_sk.c b/src/ssl_sk.c index a8cf68d52e..31fa966e2d 100644 --- a/src/ssl_sk.c +++ b/src/ssl_sk.c @@ -113,24 +113,6 @@ WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* stack, int idx) #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. @@ -188,13 +170,12 @@ static void wolfssl_sk_node_set_data(WOLFSSL_STACK* node, WOLF_STACK_TYPE type, { switch (type) { case STACK_TYPE_CIPHER: -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) node->data.cipher = *(WOLFSSL_CIPHER*)data; - if (node->hash_fn != NULL) { +#ifdef OPENSSL_ALL + if (node->hash_fn != NULL) node->hash = node->hash_fn(&node->data.cipher); - } - break; #endif + break; case STACK_TYPE_X509: case STACK_TYPE_GEN_NAME: case STACK_TYPE_BIO: @@ -331,7 +312,7 @@ void* wolfSSL_sk_pop_node(WOLFSSL_STACK* stack, int idx) if (stack->next) { /* Keep the first node as it is the pointer passed in. */ tmp = stack->next; - wolfssl_sk_node_copy(stack, stack->next); + XMEMCPY(stack, stack->next, sizeof(WOLFSSL_STACK)); wolfSSL_sk_free_node(tmp); } } @@ -374,7 +355,12 @@ void* wolfSSL_sk_pop_node(WOLFSSL_STACK* stack, int idx) */ WOLFSSL_STACK* wolfssl_sk_new_type(WOLF_STACK_TYPE type) { - WOLFSSL_STACK* stack = wolfSSL_sk_new_node(NULL); + return wolfssl_sk_new_type_ex(type, NULL); +} + +WOLFSSL_STACK* wolfssl_sk_new_type_ex(WOLF_STACK_TYPE type, void* heap) +{ + WOLFSSL_STACK* stack = wolfSSL_sk_new_node(heap); if (stack != NULL) { stack->type = type; } @@ -546,7 +532,7 @@ WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* stack) /* Update last node in linked list. */ last = cur; - wolfssl_sk_node_copy(cur, stack); + XMEMCPY(cur, stack, sizeof(WOLFSSL_STACK)); /* We will allocate new memory for this */ XMEMSET(&cur->data, 0, sizeof(cur->data)); cur->next = NULL; @@ -588,7 +574,7 @@ WOLFSSL_STACK* wolfSSL_shallow_sk_dup(WOLFSSL_STACK* stack) break; } - wolfssl_sk_node_copy(cur, stack); + XMEMCPY(cur, stack, sizeof(WOLFSSL_STACK)); cur->next = NULL; *prev = cur; @@ -756,7 +742,7 @@ int wolfSSL_sk_insert(WOLFSSL_STACK *stack, const void *data, int idx) 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); + XMEMCPY(node, stack, sizeof(WOLFSSL_STACK)); wolfssl_sk_node_set_data(stack, stack->type, data); stack->num++; stack->next = node; diff --git a/src/x509.c b/src/x509.c index c147d28fee..c45d9fba55 100644 --- a/src/x509.c +++ b/src/x509.c @@ -661,17 +661,25 @@ static int DNS_to_GENERAL_NAME(WOLFSSL_GENERAL_NAME* gn, DNS_entry* dns) if (gn->d.registeredID == NULL) { return WOLFSSL_FAILURE; } - gn->d.registeredID->obj = (const unsigned char*)XMALLOC(dns->len, - gn->d.registeredID->heap, DYNAMIC_TYPE_ASN1); - if (gn->d.registeredID->obj == NULL) { - /* registeredID gets free'd up by caller after failure */ - return WOLFSSL_FAILURE; + { + /* Store DER-encoded OID (tag + length + content) in obj */ + word32 derSz = 1 + SetLength(dns->len, NULL) + dns->len; + byte* der = (byte*)XMALLOC(derSz, + gn->d.registeredID->heap, DYNAMIC_TYPE_ASN1); + if (der == NULL) { + return WOLFSSL_FAILURE; + } + { + word32 idx = 0; + der[idx++] = ASN_OBJECT_ID; + idx += SetLength(dns->len, der + idx); + XMEMCPY(der + idx, dns->name, dns->len); + } + gn->d.registeredID->obj = der; + gn->d.registeredID->objSz = derSz; } gn->d.registeredID->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA; - XMEMCPY((byte*)gn->d.registeredID->obj, dns->ridString, dns->len); - gn->d.registeredID->objSz = dns->len; gn->d.registeredID->grp = oidCertExtType; - gn->d.registeredID->nid = WC_NID_registeredAddress; break; #endif @@ -2533,19 +2541,28 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c, if (gn->d.registeredID == NULL) { goto err; } - gn->d.registeredID->obj = - (const unsigned char*)XMALLOC(dns->len, - gn->d.registeredID->heap, DYNAMIC_TYPE_ASN1); - if (gn->d.registeredID->obj == NULL) { - goto err; + { + /* Store DER-encoded OID (tag+length+content) */ + word32 derSz = 1 + SetLength(dns->len, NULL) + + dns->len; + byte* der = (byte*)XMALLOC(derSz, + gn->d.registeredID->heap, + DYNAMIC_TYPE_ASN1); + if (der == NULL) { + goto err; + } + { + word32 derIdx = 0; + der[derIdx++] = ASN_OBJECT_ID; + derIdx += SetLength(dns->len, der + derIdx); + XMEMCPY(der + derIdx, dns->name, dns->len); + } + gn->d.registeredID->obj = der; + gn->d.registeredID->objSz = derSz; } gn->d.registeredID->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA; - XMEMCPY((byte*)gn->d.registeredID->obj, - dns->ridString, dns->len); - gn->d.registeredID->objSz = dns->len; gn->d.registeredID->grp = oidCertExtType; - gn->d.registeredID->nid = WC_NID_registeredAddress; break; #endif /* WOLFSSL_RID_ALT_NAME */ @@ -10830,15 +10847,10 @@ WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509) a->dataMax = WOLFSSL_ASN1_INTEGER_MAX; } - #if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY) - XMEMCPY(&a->data[i], x509->serial, x509->serialSz); - a->length = x509->serialSz; - #else - a->data[i++] = ASN_INTEGER; - i += SetLength(x509->serialSz, a->data + i); - XMEMCPY(&a->data[i], x509->serial, x509->serialSz); - a->length = x509->serialSz + 2; - #endif + a->data[i++] = ASN_INTEGER; + i += SetLength(x509->serialSz, a->data + i); + XMEMCPY(&a->data[i], x509->serial, x509->serialSz); + a->length = x509->serialSz + 2; x509->serialNumber = a; diff --git a/tests/api.c b/tests/api.c index 0cda4e114a..8ab7009ca7 100644 --- a/tests/api.c +++ b/tests/api.c @@ -13582,8 +13582,7 @@ static int test_wolfSSL_get_client_ciphers_on_result(WOLFSSL* ssl) { ExpectIntEQ(sk_SSL_CIPHER_num(ciphers), 1); current = sk_SSL_CIPHER_value(ciphers, 0); ExpectNotNull(current); - #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) && \ - !defined(WOLFSSL_QT) + #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) ExpectStrEQ("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", SSL_CIPHER_get_name(current)); #else @@ -25561,7 +25560,7 @@ static int test_wolfSSL_crypto_policy_ciphers(void) /* We return a different cipher string depending on build settings. */ #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && \ - !defined(NO_ERROR_STRINGS) && !defined(WOLFSSL_QT) + !defined(NO_ERROR_STRINGS) found = crypto_policy_cipher_found(ssl, "AES_128", 0); ExpectIntEQ(found, !is_future); diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index cf197ef15b..76e4f5a877 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -5820,9 +5820,15 @@ void wolfSSL_EVP_init(void) case WC_HASH_TYPE_BLAKE2S: #if defined(WOLFSSL_SHA3) && defined(WOLFSSL_SHAKE128) case WC_HASH_TYPE_SHAKE128: + ret = wc_Shake128_Copy((wc_Shake*)&src->hash.digest.shake, + (wc_Sha3*)&des->hash.digest.shake); + break; #endif #if defined(WOLFSSL_SHA3) && defined(WOLFSSL_SHAKE256) case WC_HASH_TYPE_SHAKE256: + ret = wc_Shake256_Copy((wc_Shake*)&src->hash.digest.shake, + (wc_Sha3*)&des->hash.digest.shake); + break; #endif default: ret = BAD_FUNC_ARG; @@ -10864,6 +10870,22 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type) ret = WOLFSSL_FAILURE; } } else + #endif + #ifdef HAVE_BLAKE2 + if (XSTRCMP(md, WC_SN_blake2b512) == 0) { + if (wc_InitBlake2b(&ctx->hash.digest.blake2b, + WC_BLAKE2B_DIGEST_SIZE) != 0) { + ret = WOLFSSL_FAILURE; + } + } else + #endif + #ifdef HAVE_BLAKE2S + if (XSTRCMP(md, WC_SN_blake2s256) == 0) { + if (wc_InitBlake2s(&ctx->hash.digest.blake2s, + WC_BLAKE2S_DIGEST_SIZE) != 0) { + ret = WOLFSSL_FAILURE; + } + } else #endif { ctx->macType = WC_HASH_TYPE_NONE; @@ -10999,12 +11021,32 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type) ret = WOLFSSL_SUCCESS; } break; + #endif + #ifdef HAVE_BLAKE2 + case WC_HASH_TYPE_BLAKE2B: + if (wc_Blake2bUpdate(&ctx->hash.digest.blake2b, + (const byte*)data, (word32)sz) == 0) { + ret = WOLFSSL_SUCCESS; + } + break; + #endif + #ifdef HAVE_BLAKE2S + case WC_HASH_TYPE_BLAKE2S: + if (wc_Blake2sUpdate(&ctx->hash.digest.blake2s, + (const byte*)data, (word32)sz) == 0) { + ret = WOLFSSL_SUCCESS; + } + break; #endif case WC_HASH_TYPE_NONE: case WC_HASH_TYPE_MD2: case WC_HASH_TYPE_MD5_SHA: + #ifndef HAVE_BLAKE2 case WC_HASH_TYPE_BLAKE2B: + #endif + #ifndef HAVE_BLAKE2S case WC_HASH_TYPE_BLAKE2S: + #endif default: return WOLFSSL_FAILURE; } @@ -11129,12 +11171,34 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type) ret = WOLFSSL_SUCCESS; } break; + #endif + #ifdef HAVE_BLAKE2 + case WC_HASH_TYPE_BLAKE2B: + if (wc_Blake2bFinal(&ctx->hash.digest.blake2b, md, + WC_BLAKE2B_DIGEST_SIZE) == 0) { + if (s) *s = WC_BLAKE2B_DIGEST_SIZE; + ret = WOLFSSL_SUCCESS; + } + break; + #endif + #ifdef HAVE_BLAKE2S + case WC_HASH_TYPE_BLAKE2S: + if (wc_Blake2sFinal(&ctx->hash.digest.blake2s, md, + WC_BLAKE2S_DIGEST_SIZE) == 0) { + if (s) *s = WC_BLAKE2S_DIGEST_SIZE; + ret = WOLFSSL_SUCCESS; + } + break; #endif case WC_HASH_TYPE_NONE: case WC_HASH_TYPE_MD2: case WC_HASH_TYPE_MD5_SHA: + #ifndef HAVE_BLAKE2 case WC_HASH_TYPE_BLAKE2B: + #endif + #ifndef HAVE_BLAKE2S case WC_HASH_TYPE_BLAKE2S: + #endif default: return WOLFSSL_FAILURE; } @@ -11169,12 +11233,22 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type) case WC_HASH_TYPE_SHA3_512: #ifdef WOLFSSL_SM3 case WC_HASH_TYPE_SM3: + #endif + #ifdef HAVE_BLAKE2 + case WC_HASH_TYPE_BLAKE2B: + #endif + #ifdef HAVE_BLAKE2S + case WC_HASH_TYPE_BLAKE2S: #endif case WC_HASH_TYPE_NONE: case WC_HASH_TYPE_MD2: case WC_HASH_TYPE_MD5_SHA: + #ifndef HAVE_BLAKE2 case WC_HASH_TYPE_BLAKE2B: + #endif + #ifndef HAVE_BLAKE2S case WC_HASH_TYPE_BLAKE2S: + #endif break; #if defined(WOLFSSL_SHA3) && defined(WOLFSSL_SHAKE128) @@ -11364,6 +11438,16 @@ int wolfSSL_EVP_MD_block_size(const WOLFSSL_EVP_MD* type) return WC_SHA3_512_BLOCK_SIZE; } else #endif +#if defined(WOLFSSL_SHA3) && defined(WOLFSSL_SHAKE128) + if (XSTRCMP(type, WC_SN_shake128) == 0) { + return WC_SHA3_128_BLOCK_SIZE; + } else +#endif +#if defined(WOLFSSL_SHA3) && defined(WOLFSSL_SHAKE256) + if (XSTRCMP(type, WC_SN_shake256) == 0) { + return WC_SHA3_256_BLOCK_SIZE; + } else +#endif #endif /* WOLFSSL_SHA3 */ #ifdef WOLFSSL_SM3 if (XSTRCMP(type, WC_SN_sm3) == 0) { diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 18d7d10213..f39be10e2f 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -7340,6 +7340,8 @@ WOLFSSL_LOCAL void* wolfssl_sk_pop_type(WOLFSSL_STACK* sk, WOLF_STACK_TYPE type); WOLFSSL_LOCAL void* wolfSSL_sk_pop_node(WOLFSSL_STACK* sk, int idx); WOLFSSL_LOCAL WOLFSSL_STACK* wolfssl_sk_new_type(WOLF_STACK_TYPE type); +WOLFSSL_LOCAL WOLFSSL_STACK* wolfssl_sk_new_type_ex(WOLF_STACK_TYPE type, + void* heap); WOLFSSL_LOCAL int wolfssl_asn1_obj_set(WOLFSSL_ASN1_OBJECT* obj, const byte* der, word32 len, int addHdr); diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index dc6394cdff..caf2b70f21 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -61,6 +61,12 @@ #ifdef WOLFSSL_SM3 #include #endif +#ifdef HAVE_BLAKE2 + #include +#endif +#ifdef HAVE_BLAKE2S + #include +#endif #ifdef WOLFSSL_SM4 #include #endif @@ -224,6 +230,12 @@ typedef union { #if defined(WOLFSSL_SHAKE128) || defined(WOLFSSL_SHAKE256) wc_Shake shake; #endif + #ifdef HAVE_BLAKE2 + Blake2b blake2b; + #endif + #ifdef HAVE_BLAKE2S + Blake2s blake2s; + #endif } WOLFSSL_Hasher; diff --git a/wolfssl/openssl/opensslv.h b/wolfssl/openssl/opensslv.h index bb3f7a828f..df75d9e0d4 100644 --- a/wolfssl/openssl/opensslv.h +++ b/wolfssl/openssl/opensslv.h @@ -40,6 +40,9 @@ #elif defined(OPENSSL_VERSION_NUMBER) /* unrecognized version, but continue. */ #define WOLFSSL_OPENSSL_VERSION_NUMBER_UNRECOGNIZED +#elif defined(WOLFSSL_QT) || defined(WOLFSSL_PYTHON) + /* For Qt and Python 3.8.5 compatibility */ + #define OPENSSL_VERSION_NUMBER 0x10101000L #elif defined(HAVE_MOSQUITTO) #define OPENSSL_VERSION_NUMBER 0x10100000L #elif defined(WOLFSSL_APACHE_HTTPD) || defined(HAVE_LIBEST) || \ @@ -48,9 +51,6 @@ defined(WOLFSSL_OPENSSH) /* For Apache httpd, Use 1.1.0 compatibility */ #define OPENSSL_VERSION_NUMBER 0x10100003L -#elif defined(WOLFSSL_QT) || defined(WOLFSSL_PYTHON) - /* For Qt and Python 3.8.5 compatibility */ - #define OPENSSL_VERSION_NUMBER 0x10101000L #elif defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_FFMPEG) #define OPENSSL_VERSION_NUMBER 0x1010000fL #elif defined(OPENSSL_ALL) || defined(HAVE_LIGHTY) || \ From 0ed58ee6fdd506d66d503223cd339bf7d29df708 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 26 Feb 2026 21:35:29 +0100 Subject: [PATCH 2/7] Revert version change --- wolfssl/openssl/opensslv.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wolfssl/openssl/opensslv.h b/wolfssl/openssl/opensslv.h index df75d9e0d4..bb3f7a828f 100644 --- a/wolfssl/openssl/opensslv.h +++ b/wolfssl/openssl/opensslv.h @@ -40,9 +40,6 @@ #elif defined(OPENSSL_VERSION_NUMBER) /* unrecognized version, but continue. */ #define WOLFSSL_OPENSSL_VERSION_NUMBER_UNRECOGNIZED -#elif defined(WOLFSSL_QT) || defined(WOLFSSL_PYTHON) - /* For Qt and Python 3.8.5 compatibility */ - #define OPENSSL_VERSION_NUMBER 0x10101000L #elif defined(HAVE_MOSQUITTO) #define OPENSSL_VERSION_NUMBER 0x10100000L #elif defined(WOLFSSL_APACHE_HTTPD) || defined(HAVE_LIBEST) || \ @@ -51,6 +48,9 @@ defined(WOLFSSL_OPENSSH) /* For Apache httpd, Use 1.1.0 compatibility */ #define OPENSSL_VERSION_NUMBER 0x10100003L +#elif defined(WOLFSSL_QT) || defined(WOLFSSL_PYTHON) + /* For Qt and Python 3.8.5 compatibility */ + #define OPENSSL_VERSION_NUMBER 0x10101000L #elif defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_FFMPEG) #define OPENSSL_VERSION_NUMBER 0x1010000fL #elif defined(OPENSSL_ALL) || defined(HAVE_LIGHTY) || \ From f9da5fae56a59a962ad3e11ec4e00d867eb0d26c Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Fri, 27 Feb 2026 14:13:58 +0100 Subject: [PATCH 3/7] Remove qt from enable-all as its defines are disruptive for most OSP's --- configure.ac | 3 --- src/ocsp.c | 18 ++++++++++++------ src/x509.c | 13 +++++++++---- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/configure.ac b/configure.ac index c3cbbb5be6..41be187d7d 100644 --- a/configure.ac +++ b/configure.ac @@ -1300,9 +1300,6 @@ then test "$enable_openvpn" = "" && enable_openvpn=yes test "$enable_asio" = "" && enable_asio=yes test "$enable_libwebsockets" = "" && enable_libwebsockets=yes - if test "$ENABLED_FIPS" = "no" || test "$HAVE_FIPS_VERSION" -le 5; then - test "$enable_qt" = "" && enable_qt=yes - fi fi fi diff --git a/src/ocsp.c b/src/ocsp.c index 0f1e2ec4cd..bf37e3c012 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -1995,12 +1995,18 @@ int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING **name, ser->dataMax = WOLFSSL_ASN1_INTEGER_MAX; } - ser->data[i++] = ASN_INTEGER; - i += SetLength(cid->status->serialSz, ser->data + i); - XMEMCPY(&ser->data[i], cid->status->serial, - (size_t)cid->status->serialSz); - ser->length = i + cid->status->serialSz; - + #if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY) + /* Serial number starts at 0 index of ser->data */ + XMEMCPY(&ser->data[i], cid->status->serial, + (size_t)cid->status->serialSz); + ser->length = cid->status->serialSz; + #else + ser->data[i++] = ASN_INTEGER; + i += SetLength(cid->status->serialSz, ser->data + i); + XMEMCPY(&ser->data[i], cid->status->serial, + (size_t)cid->status->serialSz); + ser->length = i + cid->status->serialSz; + #endif cid->status->serialInt = ser; *serial = ser; } diff --git a/src/x509.c b/src/x509.c index c45d9fba55..45289b016c 100644 --- a/src/x509.c +++ b/src/x509.c @@ -10847,10 +10847,15 @@ WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509) a->dataMax = WOLFSSL_ASN1_INTEGER_MAX; } - a->data[i++] = ASN_INTEGER; - i += SetLength(x509->serialSz, a->data + i); - XMEMCPY(&a->data[i], x509->serial, x509->serialSz); - a->length = x509->serialSz + 2; + #if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY) + XMEMCPY(&a->data[i], x509->serial, x509->serialSz); + a->length = x509->serialSz; + #else + a->data[i++] = ASN_INTEGER; + i += SetLength(x509->serialSz, a->data + i); + XMEMCPY(&a->data[i], x509->serial, x509->serialSz); + a->length = x509->serialSz + 2; + #endif x509->serialNumber = a; From c9a2b67713418045c5b09b27bf64cd7008eec114 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Fri, 27 Feb 2026 15:20:40 +0100 Subject: [PATCH 4/7] Configure wolfSSL to disable old names for softhsm --- .github/workflows/softhsm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/softhsm.yml b/.github/workflows/softhsm.yml index 593cd69135..ea9b3e5aa4 100644 --- a/.github/workflows/softhsm.yml +++ b/.github/workflows/softhsm.yml @@ -25,7 +25,7 @@ jobs: uses: wolfSSL/actions-build-autotools-project@v1 with: path: wolfssl - configure: --enable-all CFLAGS=-DRSA_MIN_SIZE=1024 + configure: --enable-all --disable-oldnames CFLAGS=-DRSA_MIN_SIZE=1024 install: true check: false From 996b14cd8219659e235d1d391ebca5c057c4362f Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Fri, 27 Feb 2026 16:46:11 +0100 Subject: [PATCH 5/7] Apply copilot suggestions --- .github/workflows/python.yml | 18 ++---------------- src/ssl.c | 5 +++++ wolfcrypt/src/evp.c | 6 ++++-- wolfssl/openssl/evp.h | 5 +---- 4 files changed, 12 insertions(+), 22 deletions(-) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 6cbcc8f8ce..4080b1528c 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -136,21 +136,7 @@ jobs: working-directory: cpython run: | export LD_LIBRARY_PATH=$GITHUB_WORKSPACE/build-dir/lib:$LD_LIBRARY_PATH - rm aclocal.m4 + rm -f aclocal.m4 autoreconf -if ./configure --with-wolfssl=$GITHUB_WORKSPACE/build-dir - make -j test TESTOPTS="-v \ - test_ssl \ - test.test_asyncio.test_ssl \ - test.test_asyncio.test_sslproto \ - test_hashlib \ - test_hmac \ - test_secrets \ - test_ftplib \ - test_imaplib \ - test_poplib \ - test_smtplib \ - test_httplib \ - test_urllib2_localnet \ - test_xmlrpc \ - test_docxmlrpc" + make -j test TESTOPTS="-v ${{ matrix.tests }}" diff --git a/src/ssl.c b/src/ssl.c index eb8881818c..2979f321a0 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -14027,7 +14027,12 @@ void* wolfSSL_GetHKDFExtractCtx(WOLFSSL* ssl) } if (i == (int)WOLFSSL_OBJECT_INFO_SZ) { WOLFSSL_MSG("NID not in table"); + #ifdef WOLFSSL_QT + sName = NULL; + type = (word32)id; + #else return NULL; + #endif } #ifdef HAVE_ECC diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 76e4f5a877..f2277bb31b 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -5818,16 +5818,18 @@ void wolfSSL_EVP_init(void) case WC_HASH_TYPE_MD5_SHA: case WC_HASH_TYPE_BLAKE2B: case WC_HASH_TYPE_BLAKE2S: + ret = BAD_FUNC_ARG; + break; #if defined(WOLFSSL_SHA3) && defined(WOLFSSL_SHAKE128) case WC_HASH_TYPE_SHAKE128: ret = wc_Shake128_Copy((wc_Shake*)&src->hash.digest.shake, - (wc_Sha3*)&des->hash.digest.shake); + (wc_Shake*)&des->hash.digest.shake); break; #endif #if defined(WOLFSSL_SHA3) && defined(WOLFSSL_SHAKE256) case WC_HASH_TYPE_SHAKE256: ret = wc_Shake256_Copy((wc_Shake*)&src->hash.digest.shake, - (wc_Sha3*)&des->hash.digest.shake); + (wc_Shake*)&des->hash.digest.shake); break; #endif default: diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index caf2b70f21..f4ee44cd00 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -61,10 +61,7 @@ #ifdef WOLFSSL_SM3 #include #endif -#ifdef HAVE_BLAKE2 - #include -#endif -#ifdef HAVE_BLAKE2S +#if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S) #include #endif #ifdef WOLFSSL_SM4 From 6f83d75a195768f0e73bb9e7146efd80a8b2ce78 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 2 Mar 2026 17:56:42 +0100 Subject: [PATCH 6/7] CI fixes --- src/internal.c | 19 +++++++++++++------ src/ocsp.c | 1 + wolfssl/openssl/opensslv.h | 6 +++--- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/internal.c b/src/internal.c index 5435f4b849..a9c21ac863 100644 --- a/src/internal.c +++ b/src/internal.c @@ -26281,13 +26281,12 @@ int SendData(WOLFSSL* ssl, const void* data, size_t sz) if (sent == (word32)sz) break; - buffSz = (word32)sz - sent; - { - int maxFrag = wolfSSL_GetMaxFragSize(ssl); - if (maxFrag > 0 && (int)buffSz > maxFrag) - buffSz = (word32)maxFrag; + buffSz = (int)((word32)sz - sent); + if (buffSz <= 0) { + WOLFSSL_MSG("error: sent size exceeds input size"); + ssl->error = BAD_FUNC_ARG; + return WOLFSSL_FATAL_ERROR; } - outputSz = wolfssl_local_GetRecordSize(ssl, (word32)buffSz, 1); #if defined(WOLFSSL_DTLS) if (ssl->options.dtls) { #if defined(WOLFSSL_DTLS_MTU) @@ -26295,6 +26294,7 @@ int SendData(WOLFSSL* ssl, const void* data, size_t sz) #else int mtu = MAX_MTU; #endif + outputSz = wolfssl_local_GetRecordSize(ssl, (word32)buffSz, 1); if (outputSz > mtu) { #if defined(WOLFSSL_NO_DTLS_SIZE_CHECK) /* split instead of error out */ @@ -26308,7 +26308,14 @@ int SendData(WOLFSSL* ssl, const void* data, size_t sz) #endif /* WOLFSSL_NO_DTLS_SIZE_CHECK */ } } + else #endif /* WOLFSSL_DTLS */ + { + int maxFrag = wolfSSL_GetMaxFragSize(ssl); + if (maxFrag > 0) + buffSz = min((word32)buffSz, (word32)maxFrag); + outputSz = wolfssl_local_GetRecordSize(ssl, (word32)buffSz, 1); + } /* check for available size, it does also DTLS MTU checks */ if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) diff --git a/src/ocsp.c b/src/ocsp.c index bf37e3c012..ce42b4d65a 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -2007,6 +2007,7 @@ int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING **name, (size_t)cid->status->serialSz); ser->length = i + cid->status->serialSz; #endif + cid->status->serialInt = ser; *serial = ser; } diff --git a/wolfssl/openssl/opensslv.h b/wolfssl/openssl/opensslv.h index bb3f7a828f..df75d9e0d4 100644 --- a/wolfssl/openssl/opensslv.h +++ b/wolfssl/openssl/opensslv.h @@ -40,6 +40,9 @@ #elif defined(OPENSSL_VERSION_NUMBER) /* unrecognized version, but continue. */ #define WOLFSSL_OPENSSL_VERSION_NUMBER_UNRECOGNIZED +#elif defined(WOLFSSL_QT) || defined(WOLFSSL_PYTHON) + /* For Qt and Python 3.8.5 compatibility */ + #define OPENSSL_VERSION_NUMBER 0x10101000L #elif defined(HAVE_MOSQUITTO) #define OPENSSL_VERSION_NUMBER 0x10100000L #elif defined(WOLFSSL_APACHE_HTTPD) || defined(HAVE_LIBEST) || \ @@ -48,9 +51,6 @@ defined(WOLFSSL_OPENSSH) /* For Apache httpd, Use 1.1.0 compatibility */ #define OPENSSL_VERSION_NUMBER 0x10100003L -#elif defined(WOLFSSL_QT) || defined(WOLFSSL_PYTHON) - /* For Qt and Python 3.8.5 compatibility */ - #define OPENSSL_VERSION_NUMBER 0x10101000L #elif defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_FFMPEG) #define OPENSSL_VERSION_NUMBER 0x1010000fL #elif defined(OPENSSL_ALL) || defined(HAVE_LIGHTY) || \ From 5f53479040d514378ac0ad7517efdebdb6745803 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 2 Mar 2026 21:20:34 +0100 Subject: [PATCH 7/7] Adjust SendClientKeyExchange to use exact cipher overhead for DTLS MTU checks --- src/internal.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index a9c21ac863..8153d01f02 100644 --- a/src/internal.c +++ b/src/internal.c @@ -34095,7 +34095,15 @@ int SendClientKeyExchange(WOLFSSL* ssl) #endif if (IsEncryptionOn(ssl, 1)) { - args->sendSz += MAX_MSG_EXTRA; + #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_MTU) + /* Use exact cipher overhead for the MTU pre-flight check. + * MAX_MSG_EXTRA is an upper bound that can exceed a small MTU, + * while the actual message fits within it. */ + if (ssl->options.dtls) + args->sendSz += cipherExtraData(ssl); + else + #endif + args->sendSz += MAX_MSG_EXTRA; } /* check for available size */