Merge branch 'master' of https://github.com/wolfSSL/wolfssl into zd21204

This commit is contained in:
Kareem
2026-02-26 17:03:15 -07:00
77 changed files with 4900 additions and 628 deletions
-2
View File
@@ -94,11 +94,9 @@ jobs:
- arduino:avr:nano
- arduino:avr:uno
- arduino:avr:yun
- arduino:samd:mkrwifi1010
- arduino:samd:mkr1000
- arduino:samd:mkrfox1200
- arduino:mbed_edge:edge_control
- arduino:mbed_nano:nanorp2040connect
- arduino:mbed_portenta:envie_m7
- arduino:mbed_portenta:portenta_x8
- arduino:renesas_uno:unor4wifi
+2 -2
View File
@@ -44,7 +44,7 @@ jobs:
fail-fast: false
matrix:
# List of releases to test
ref: [ 9.18.0, 9.18.28, 9.18.33 ]
ref: [ 9.18.0, 9.18.28, 9.18.33, 9.20.11 ]
name: ${{ matrix.ref }}
if: github.repository_owner == 'wolfssl'
runs-on: ubuntu-24.04
@@ -66,7 +66,7 @@ jobs:
export DEBIAN_FRONTEND=noninteractive
sudo apt-get update
# hostap dependencies
sudo apt-get install -y libuv1-dev libnghttp2-dev libcap-dev libcmocka-dev
sudo apt-get install -y libuv1-dev libnghttp2-dev libcap-dev libcmocka-dev liburcu-dev
- name: Checkout OSP
uses: actions/checkout@v4
+108
View File
@@ -0,0 +1,108 @@
name: msmtp 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
# Just to keep it the same as the testing target
if: github.repository_owner == 'wolfssl'
runs-on: ubuntu-24.04
# This should be a safe limit for the tests to run.
timeout-minutes: 4
steps:
- name: Build wolfSSL
uses: wolfSSL/actions-build-autotools-project@v1
with:
path: wolfssl
configure: --enable-opensslextra --enable-opensslall
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-msmtp
path: build-dir.tgz
retention-days: 5
msmtp_check:
strategy:
fail-fast: false
matrix:
ref: [ 1.8.28 ]
name: ${{ matrix.ref }}
if: github.repository_owner == 'wolfssl'
runs-on: ubuntu-24.04
# This should be a safe limit for the tests to run.
timeout-minutes: 10
needs: build_wolfssl
steps:
- name: Download lib
uses: actions/download-artifact@v4
with:
name: wolf-install-msmtp
- name: untar build-dir
run: tar -xf build-dir.tgz
- name: Checkout OSP
uses: actions/checkout@v4
with:
repository: wolfssl/osp
path: osp
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
autoconf automake libtool pkg-config gettext \
libidn2-dev libsecret-1-dev autopoint
- name: Checkout msmtp
uses: actions/checkout@v4
with:
repository: marlam/msmtp
ref: msmtp-${{ matrix.ref }}
path: msmtp-${{ matrix.ref }}
- name: Apply wolfSSL patch
working-directory: msmtp-${{ matrix.ref }}
run: patch -p1 < $GITHUB_WORKSPACE/osp/msmtp/${{ matrix.ref }}/wolfssl-msmtp-${{ matrix.ref }}.patch
- name: Regenerate build system
working-directory: msmtp-${{ matrix.ref }}
run: autoreconf -ivf
- name: Configure msmtp with wolfSSL
working-directory: msmtp-${{ matrix.ref }}
run: |
PKG_CONFIG_PATH=$GITHUB_WORKSPACE/build-dir/lib/pkgconfig \
./configure --with-tls=wolfssl
- name: Build msmtp
working-directory: msmtp-${{ matrix.ref }}
run: make -j$(nproc)
- name: Run msmtp tests
working-directory: msmtp-${{ matrix.ref }}
run: LD_LIBRARY_PATH=$GITHUB_WORKSPACE/build-dir/lib make check
- name: Confirm msmtp built with wolfSSL
run: ldd msmtp-${{ matrix.ref }}/src/msmtp | grep wolfssl
- name: Print test logs on failure
if: ${{ failure() }}
run: tail -n +1 msmtp-${{ matrix.ref }}/tests/*.log
+52 -30
View File
@@ -12,6 +12,10 @@ concurrency:
cancel-in-progress: true
# END OF COMMON SECTION
# clang has better sanitizer support
env:
CC: clang
jobs:
build_wolfssl:
name: Build wolfSSL
@@ -31,7 +35,8 @@ jobs:
uses: wolfSSL/actions-build-autotools-project@v1
with:
path: wolfssl
configure: --enable-nginx ${{ env.wolf_debug_flags }}
configure: >-
--enable-nginx --enable-curve25519 --enable-ed25519 ${{ env.wolf_debug_flags }}
install: true
- name: tar build-dir
@@ -50,6 +55,41 @@ jobs:
matrix:
include:
# in general we want to pass all tests that match *ssl*
- ref: 1.28.1
test-ref: 0fccfcef1278263416043e0bbb3e0116b84026e4
# Following tests pass with sanitizer on
sanitize-ok: >-
h2_ssl_proxy_cache.t h2_ssl.t h2_ssl_variables.t
h2_ssl_verify_client.t mail_imap_ssl.t mail_ssl_session_reuse.t
mail_ssl.t proxy_ssl_certificate_cache.t
proxy_ssl_certificate_empty.t proxy_ssl_certificate.t
proxy_ssl_certificate_vars.t proxy_ssl_name.t ssl_cache_reload.t
ssl_certificate_aux.t ssl_certificate_cache.t
ssl_certificate_chain.t ssl_certificates.t ssl_certificate.t
ssl_client_escaped_cert.t ssl_crl.t ssl_curve.t ssl_ocsp.t
ssl_password_file.t ssl_proxy_upgrade.t ssl_reject_handshake.t
ssl_session_reuse.t ssl_session_ticket_key.t ssl_sni_protocols.t
ssl_sni_reneg.t ssl_sni_sessions.t ssl_sni.t ssl_stapling.t ssl.t
ssl_verify_client.t ssl_verify_client_trusted.t ssl_verify_depth.t
stream_proxy_ssl_certificate_cache.t stream_proxy_ssl_certificate.t
stream_proxy_ssl_certificate_vars.t
stream_proxy_ssl_name_complex.t stream_proxy_ssl_name.t
stream_ssl_alpn.t stream_ssl_certificate_cache.t
stream_ssl_certificate.t stream_ssl_ocsp.t stream_ssl_preread_alpn.t
stream_ssl_preread_protocol.t stream_ssl_preread.t
stream_ssl_reject_handshake.t stream_ssl_session_reuse.t
stream_ssl_sni_protocols.t stream_ssl_stapling.t stream_ssl.t
stream_ssl_variables.t stream_ssl_verify_client.t
stream_upstream_zone_ssl.t upstream_zone_ssl.t
uwsgi_ssl_certificate.t uwsgi_ssl_certificate_vars.t
# Following tests do not pass with sanitizer on (with OpenSSL too)
sanitize-not-ok: >-
grpc_ssl.t h2_proxy_request_buffering_ssl.t h2_proxy_ssl.t
proxy_request_buffering_ssl.t proxy_ssl_conf_command.t
proxy_ssl_keepalive.t proxy_ssl.t proxy_ssl_verify.t ssl_cache.t
stream_proxy_protocol_ssl.t stream_proxy_ssl_conf_command.t
stream_proxy_ssl.t stream_proxy_ssl_verify.t
- ref: 1.25.0
test-ref: 5b2894ea1afd01a26c589ce11f310df118e42592
# Following tests pass with sanitizer on
@@ -120,30 +160,19 @@ jobs:
- name: untar build-dir
run: tar -xf build-dir.tgz
- name: Install dependencies
run: |
sudo cpan -iT Proc::Find
- name: Openssl version
run: openssl version -a
# Locking in the version of SSLeay used with testing
- name: Download and install Net::SSLeay 1.94 manually
run: |
curl -LO https://www.cpan.org/modules/by-module/Net/CHRISN/Net-SSLeay-1.94.tar.gz
tar -xzf Net-SSLeay-1.94.tar.gz
cd Net-SSLeay-1.94
perl Makefile.PL
make
sudo make install
- name: Setup Perl environment
uses: shogo82148/actions-setup-perl@v1
with:
perl-version: '5.38.2'
# SSL version 2.091 changes '' return to undef causing test case to fail.
# Locking in the test version to use as 2.090
- name: Download and install IO::Socket::SSL 2.090 manually
- name: Install dependencies
run: |
curl -LO https://www.cpan.org/modules/by-module/IO/IO-Socket-SSL-2.090.tar.gz
tar -xzf IO-Socket-SSL-2.090.tar.gz
cd IO-Socket-SSL-2.090
perl Makefile.PL
make
sudo make install
cpanm --notest Proc::Find Net::SSLeay@1.94 IO::Socket::SSL@2.090
- name: Checkout wolfssl-nginx
uses: actions/checkout@v4
@@ -211,10 +240,6 @@ jobs:
run: |
echo "nginx_c_flags=-O0" >> $GITHUB_ENV
- name: workaround high-entropy ASLR
# not needed after either an update to llvm or runner is done
run: sudo sysctl vm.mmap_rnd_bits=28
- name: Build nginx with sanitizer
working-directory: nginx
run: |
@@ -229,19 +254,16 @@ jobs:
working-directory: nginx
run: ldd objs/nginx | grep wolfssl
- if: ${{ runner.debug }}
name: Run nginx-tests with sanitizer (debug)
- name: Create LSAN suppression file
working-directory: nginx-tests
run: |
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$GITHUB_WORKSPACE/build-dir/lib \
TMPDIR=$GITHUB_WORKSPACE TEST_NGINX_VERBOSE=y TEST_NGINX_CATLOG=y \
TEST_NGINX_BINARY=../nginx/objs/nginx prove -v ${{ matrix.sanitize-ok }}
echo "leak:ngx_worker_process_init" > lsan.supp
- if: ${{ !runner.debug }}
name: Run nginx-tests with sanitizer
working-directory: nginx-tests
run: |
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$GITHUB_WORKSPACE/build-dir/lib \
LSAN_OPTIONS=suppressions=$GITHUB_WORKSPACE/nginx-tests/lsan.supp \
TMPDIR=$GITHUB_WORKSPACE TEST_NGINX_BINARY=../nginx/objs/nginx \
prove ${{ matrix.sanitize-ok }}
+2
View File
@@ -19,6 +19,8 @@ jobs:
config: [
# Add new configs here
'--enable-rsa --enable-keygen --disable-dh CFLAGS="-DWOLFSSL_NO_MALLOC -DRSA_MIN_SIZE=1024 -pedantic -Wdeclaration-after-statement -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"',
'--enable-ecc --enable-rsa --enable-keygen --enable-ed25519 --enable-curve25519 --enable-ed448 --enable-curve448 --enable-mlkem CFLAGS="-DWOLFSSL_NO_MALLOC -pedantic -Wdeclaration-after-statement -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"',
'--enable-ecc --enable-rsa --enable-keygen --enable-ed25519 --enable-curve25519 --enable-ed448 --enable-curve448 --enable-mlkem --enable-staticmemory CFLAGS="-DWOLFSSL_NO_MALLOC -pedantic -Wdeclaration-after-statement -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"',
]
name: make check
if: github.repository_owner == 'wolfssl'
+2
View File
@@ -53,6 +53,8 @@ jobs:
'--enable-opensslall --enable-opensslextra CPPFLAGS=-DWC_RNG_SEED_CB',
'--enable-opensslall --enable-opensslextra
CPPFLAGS=''-DWC_RNG_SEED_CB -DWOLFSSL_NO_GETPID'' ',
# PKCS#7 with RSA-PSS (CMS RSASSA-PSS signers)
'--enable-pkcs7 CPPFLAGS=-DWC_RSA_PSS',
'--enable-opensslextra CPPFLAGS=''-DWOLFSSL_NO_CA_NAMES'' ',
'--enable-opensslextra=x509small',
'CPPFLAGS=''-DWOLFSSL_EXTRA'' ',
+1
View File
@@ -38,6 +38,7 @@ jobs:
# Add new configs here
'',
'--enable-all',
'--enable-all --enable-dilithium',
'--enable-cryptonly --disable-examples',
'--enable-cryptonly --disable-examples --disable-aes --disable-aesgcm',
'--enable-cryptonly --disable-examples --disable-aescbc',
+14 -6
View File
@@ -23,7 +23,7 @@ jobs:
uses: wolfSSL/actions-build-autotools-project@v1
with:
path: wolfssl
configure: --enable-maxfragment --enable-opensslall --enable-opensslextra --enable-dtls --enable-oldtls --enable-tlsv10 --enable-ipv6 'CPPFLAGS=-DWOLFSSL_NO_DTLS_SIZE_CHECK -DOPENSSL_COMPATIBLE_DEFAULTS'
configure: --enable-all --enable-oldtls --enable-tlsv10 --enable-ipv6 'CPPFLAGS=-DWOLFSSL_NO_DTLS_SIZE_CHECK -DOPENSSL_COMPATIBLE_DEFAULTS'
install: true
- name: tar build-dir
@@ -43,6 +43,14 @@ jobs:
# This should be a safe limit for the tests to run.
timeout-minutes: 30
needs: build_wolfssl
strategy:
fail-fast: false
matrix:
include:
- socat_version: "1.8.0.0"
expect_fail: "36,64,146,216,309,310,386,399,402,403,459,460,467,468,475,478,491,492,528"
- socat_version: "1.8.0.3"
expect_fail: "146,386,399,402,459,460,467,468,475,478,491,492,495,528"
steps:
- name: Install prereqs
run:
@@ -57,7 +65,7 @@ jobs:
run: tar -xf build-dir.tgz
- name: Download socat
run: curl -O http://www.dest-unreach.org/socat/download/socat-1.8.0.0.tar.gz && tar xvf socat-1.8.0.0.tar.gz
run: curl -O http://www.dest-unreach.org/socat/download/socat-${{ matrix.socat_version }}.tar.gz && tar xvf socat-${{ matrix.socat_version }}.tar.gz
- name: Checkout OSP
uses: actions/checkout@v4
@@ -66,16 +74,16 @@ jobs:
path: osp
- name: Build socat
working-directory: ./socat-1.8.0.0
working-directory: ./socat-${{ matrix.socat_version }}
run: |
patch -p1 < ../osp/socat/1.8.0.0/socat-1.8.0.0.patch
patch -p1 < ../osp/socat/${{ matrix.socat_version }}/socat-${{ matrix.socat_version }}.patch
autoreconf -vfi
./configure --with-wolfssl=$GITHUB_WORKSPACE/build-dir --enable-default-ipv=4
make
- name: Run socat tests
working-directory: ./socat-1.8.0.0
working-directory: ./socat-${{ matrix.socat_version }}
run: |
export LD_LIBRARY_PATH=$GITHUB_WORKSPACE/build-dir/lib:$LD_LIBRARY_PATH
export SHELL=/bin/bash
SOCAT=$GITHUB_WORKSPACE/socat-1.8.0.0/socat ./test.sh -t 0.5 --expect-fail 36,64,146,214,216,217,309,310,386,399,402,403,459,460,467,468,475,478,492,528,530
SOCAT=$GITHUB_WORKSPACE/socat-${{ matrix.socat_version }}/socat ./test.sh -t 0.5 --expect-fail ${{ matrix.expect_fail }}
+3 -2
View File
@@ -44,7 +44,7 @@ jobs:
fail-fast: false
matrix:
# List of releases to test
ref: [ 2.9.1 ]
ref: [ 2.9.1, 2.10.2 ]
name: ${{ matrix.ref }}
if: github.repository_owner == 'wolfssl'
runs-on: ubuntu-24.04
@@ -61,7 +61,8 @@ jobs:
# Don't prompt for anything
export DEBIAN_FRONTEND=noninteractive
sudo apt-get update
sudo apt-get install -y build-essential autoconf libldb-dev libldb2 python3-ldb bc
sudo apt-get install -y build-essential autoconf libldb-dev \
libldb2 python3-ldb bc libcap-dev
- name: Setup env
run: |
+3
View File
@@ -220,6 +220,7 @@ ENABLED_BSDKM_REGISTER
ENABLE_SECURE_SOCKETS_LOGS
ESP32
ESP8266
ESPIPE
ESP_ENABLE_WOLFSSH
ESP_IDF_VERSION
ESP_IDF_VERSION_MAJOR
@@ -367,6 +368,7 @@ NO_ASM
NO_ASN_OLD_TYPE_NAMES
NO_CAMELLIA_CBC
NO_CERT
NO_CERT_IN_TICKET
NO_CIPHER_SUITE_ALIASES
NO_CLIENT_CACHE
NO_CLOCK_SPEEDUP
@@ -1094,6 +1096,7 @@ __clang_major__
__cplusplus
__ghc__
__ghs__
__has_attribute
__hpux__
__i386
__i386__
+2 -1
View File
@@ -2743,7 +2743,8 @@ if test "$ENABLED_LIBWEBSOCKETS" = "yes" || test "$ENABLED_OPENVPN" = "yes" || \
test "$ENABLED_OPENRESTY" = "yes" || test "$ENABLED_RSYSLOG" = "yes" || \
test "$ENABLED_KRB" = "yes" || test "$ENABLED_CHRONY" = "yes" || \
test "$ENABLED_FFMPEG" = "yes" || test "$ENABLED_STRONGSWAN" = "yes" || \
test "$ENABLED_OPENLDAP" = "yes" || test "x$ENABLED_MOSQUITTO" = "xyes" || test "$ENABLED_HITCH" = "yes"
test "$ENABLED_OPENLDAP" = "yes" || test "x$ENABLED_MOSQUITTO" = "xyes" || \
test "$ENABLED_HITCH" = "yes" || test "$ENABLED_NGINX" = "yes"
then
ENABLED_OPENSSLALL="yes"
fi
+11
View File
@@ -52,6 +52,17 @@
}
}
#endif
#if defined(WC_RSA_PSS) && !defined(NO_RSA)
if (info->pk.type == WC_PK_TYPE_RSA_PSS) {
// RSA-PSS sign/verify
ret = wc_RsaPSS_Sign_ex(
info->pk.rsa.in, info->pk.rsa.inLen,
info->pk.rsa.out, *info->pk.rsa.outLen,
WC_HASH_TYPE_SHA256, WC_MGF1SHA256,
RSA_PSS_SALT_LEN_DEFAULT,
info->pk.rsa.key, info->pk.rsa.rng);
}
#endif
#ifdef HAVE_ECC
if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) {
// ECDSA
@@ -51,6 +51,7 @@
<li>\ref MD5</li>
<li>\ref Password</li>
<li>\ref PKCS7</li>
<li>\ref PKCS7_RSA_PSS</li>
<li>\ref PKCS11</li>
<li>\ref Poly1305</li>
<li>\ref RIPEMD</li>
@@ -97,4 +98,13 @@
\sa wc_CryptoCb_AesSetKey
\sa \ref Crypto Callbacks
*/
/*!
\page PKCS7_RSA_PSS PKCS#7 RSA-PSS (CMS)
PKCS#7 SignedData supports RSA-PSS signers (CMS RSASSA-PSS). When WC_RSA_PSS
is defined, use wc_PKCS7_InitWithCert with a signer certificate that has
RSA-PSS (id-RSASSA-PSS) and set hashOID and optional rng; encode produces
full RSASSA-PSS-params (hashAlgorithm, mgfAlgorithm, saltLength,
trailerField). Verify accepts NULL, empty, or absent parameters with
RFC defaults. See \ref PKCS7 for the main API.
*/
+1 -1
View File
@@ -147,7 +147,7 @@ int wc_PKCS7_EncodeData(wc_PKCS7* pkcs7, byte* output,
\brief This function builds the PKCS7 signed data content type, encoding
the PKCS7 structure into a buffer containing a parsable PKCS7
signed data packet.
signed data packet. For RSA-PSS signers (WC_RSA_PSS), see \ref PKCS7_RSA_PSS.
\return Success On successfully encoding the PKCS7 data into the buffer,
returns the index parsed up to in the PKCS7 structure. This index also
+1 -1
View File
@@ -23,7 +23,7 @@ Example wolfSSL configuration file templates for use when autoconf is not availa
* `user_settings_openssl_compat.h`: OpenSSL compatibility layer for drop-in replacement. Enables OPENSSL_ALL and related APIs.
* `user_settings_baremetal.h`: Bare metal configuration. No filesystem, static memory only, minimal footprint.
* `user_settings_rsa_only.h`: RSA-only configuration (no ECC). For legacy systems requiring RSA cipher suites.
* `user_settings_pkcs7.h`: PKCS#7/CMS configuration for signing and encryption. S/MIME, firmware signing.
* `user_settings_pkcs7.h`: PKCS#7/CMS configuration for signing and encryption. S/MIME, firmware signing. For RSA-PSS SignedData (CMS RSASSA-PSS), define `WC_RSA_PSS`; see doxygen \ref PKCS7_RSA_PSS.
* `user_settings_ca.h`: Certificate Authority / PKI operations. Certificate generation, signing, CRL, OCSP.
* `user_settings_wolfboot_keytools.h`: wolfBoot key generation and signing tool. Supports ECC, RSA, ED25519, ED448, and post-quantum (ML-DSA/Dilithium, LMS, XMSS).
* `user_settings_wolfssh.h`: Minimum options for building wolfSSH. See comment at top for ./configure used to generate.
+1
View File
@@ -115,6 +115,7 @@ extern "C" {
#undef NO_RSA
#define WOLFSSL_KEY_GEN
#define WC_RSA_NO_PADDING
#define WC_RSA_PSS /* RSA-PSS SignedData (id-RSASSA-PSS); see PKCS7_RSA_PSS */
#else
#define NO_RSA
#endif
+2
View File
@@ -1938,6 +1938,8 @@ int wolfSSL_BIO_get_len(WOLFSSL_BIO *bio)
len = BAD_FUNC_ARG;
if (len == 0) {
len = wolfssl_file_len(file, &memSz);
if (len == WC_NO_ERR_TRACE(WOLFSSL_BAD_FILETYPE))
len = 0;
}
if (len == 0) {
len = (int)memSz;
+98 -17
View File
@@ -98,6 +98,35 @@ int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm)
}
#ifdef CRL_STATIC_REVOKED_LIST
/* Compare two RevokedCert entries by (serialSz, serialNumber) for sorting.
* Returns < 0, 0, or > 0 like memcmp. */
static int CompareRevokedCert(const RevokedCert* a, const RevokedCert* b)
{
if (a->serialSz != b->serialSz)
return a->serialSz - b->serialSz;
return XMEMCMP(a->serialNumber, b->serialNumber, (size_t)a->serialSz);
}
/* Sort revoked cert array in-place using insertion sort. The array is bounded
* by CRL_MAX_REVOKED_CERTS so O(n^2) is fine. */
static void SortCRL_CertList(RevokedCert* certs, int totalCerts)
{
int i, j;
RevokedCert tmp;
for (i = 1; i < totalCerts; i++) {
XMEMCPY(&tmp, &certs[i], sizeof(RevokedCert));
j = i - 1;
while (j >= 0 && CompareRevokedCert(&certs[j], &tmp) > 0) {
XMEMCPY(&certs[j + 1], &certs[j], sizeof(RevokedCert));
j--;
}
XMEMCPY(&certs[j + 1], &tmp, sizeof(RevokedCert));
}
}
#endif /* CRL_STATIC_REVOKED_LIST */
/* Initialize CRL Entry */
static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff,
int verified, void* heap)
@@ -132,12 +161,15 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff,
#endif
#ifdef CRL_STATIC_REVOKED_LIST
/* ParseCRL_CertList() has already cached the Revoked certs into
the crle->certs array */
the crle->certs array. Sort it so binary search in
FindRevokedSerial works correctly. */
crle->totalCerts = dcrl->totalCerts;
SortCRL_CertList(crle->certs, crle->totalCerts);
#else
crle->certs = dcrl->certs; /* take ownership */
crle->totalCerts = dcrl->totalCerts;
#endif
dcrl->certs = NULL;
crle->totalCerts = dcrl->totalCerts;
crle->crlNumberSet = dcrl->crlNumberSet;
if (crle->crlNumberSet) {
XMEMCPY(crle->crlNumber, dcrl->crlNumber, sizeof(crle->crlNumber));
@@ -313,25 +345,52 @@ static int FindRevokedSerial(RevokedCert* rc, byte* serial, int serialSz,
int ret = 0;
byte hash[SIGNER_DIGEST_SIZE];
#ifdef CRL_STATIC_REVOKED_LIST
/* do binary search */
int low, high, mid;
if (serialHash == NULL) {
/* Binary search by (serialSz, serialNumber). The array was sorted in
* InitCRL_Entry by the same comparison key. */
int low = 0;
int high = totalCerts - 1;
low = 0;
high = totalCerts - 1;
while (low <= high) {
int mid = (low + high) / 2;
int cmp;
while (low <= high) {
mid = (low + high) / 2;
/* Compare by serial size first, then by serial content. Shorter
* serials sort before longer ones. */
if (rc[mid].serialSz != serialSz) {
cmp = rc[mid].serialSz - serialSz;
}
else {
cmp = XMEMCMP(rc[mid].serialNumber, serial,
(size_t)rc[mid].serialSz);
}
if (XMEMCMP(rc[mid].serialNumber, serial, rc->serialSz) < 0) {
low = mid + 1;
if (cmp < 0) {
low = mid + 1;
}
else if (cmp > 0) {
high = mid - 1;
}
else {
WOLFSSL_MSG("Cert revoked");
ret = CRL_CERT_REVOKED;
break;
}
}
else if (XMEMCMP(rc[mid].serialNumber, serial, rc->serialSz) > 0) {
high = mid - 1;
}
else {
WOLFSSL_MSG("Cert revoked");
ret = CRL_CERT_REVOKED;
break;
}
else {
/* Hash-based lookup -- linear scan required since the array is sorted
* by serial number, not by hash. */
int i;
for (i = 0; i < totalCerts; i++) {
ret = CalcHashId(rc[i].serialNumber, (word32)rc[i].serialSz, hash);
if (ret != 0)
break;
if (XMEMCMP(hash, serialHash, SIGNER_DIGEST_SIZE) == 0) {
WOLFSSL_MSG("Cert revoked");
ret = CRL_CERT_REVOKED;
break;
}
}
}
#else
@@ -1369,6 +1428,28 @@ WOLFSSL_X509_CRL* wolfSSL_X509_CRL_dup(const WOLFSSL_X509_CRL* crl)
return ret;
}
#ifdef OPENSSL_ALL
int wolfSSL_X509_CRL_up_ref(WOLFSSL_X509_CRL* crl)
{
int ret;
if (crl == NULL)
return WOLFSSL_FAILURE;
wolfSSL_RefInc(&crl->ref, &ret);
#ifdef WOLFSSL_REFCNT_ERROR_RETURN
if (ret != 0) {
WOLFSSL_MSG("Failed to lock x509 mutex");
return WOLFSSL_FAILURE;
}
#else
(void)ret;
#endif
return WOLFSSL_SUCCESS;
}
#endif
/* returns WOLFSSL_SUCCESS on success. Does not take ownership of newcrl */
int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newcrl)
{
+3 -2
View File
@@ -403,8 +403,9 @@ static int TlsTicketIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector exts,
if (!IsAtLeastTLSv1_3(it->pv))
*resume = TRUE;
}
if (it != NULL)
ForceZero(it, sizeof(InternalTicket));
/* `it` points into tempTicket on successful decryption so clearing it will
* also satisfy the WOLFSSL_CHECK_MEM_ZERO check. */
ForceZero(tempTicket, SESSION_TICKET_LEN);
return 0;
}
#endif /* HAVE_SESSION_TICKET */
+222 -115
View File
@@ -1123,8 +1123,8 @@ static int ImportKeyState(WOLFSSL* ssl, const byte* exp, word32 len, byte ver,
idx += OPAQUE16_LEN;
if (wordCount > WOLFSSL_DTLS_WINDOW_WORDS) {
wordAdj = (wordCount - WOLFSSL_DTLS_WINDOW_WORDS) * sizeof(word32);
wordCount = WOLFSSL_DTLS_WINDOW_WORDS;
wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32);
}
XMEMSET(keys->peerSeq[0].window, 0xFF, DTLS_SEQ_SZ);
@@ -1139,8 +1139,8 @@ static int ImportKeyState(WOLFSSL* ssl, const byte* exp, word32 len, byte ver,
idx += OPAQUE16_LEN;
if (wordCount > WOLFSSL_DTLS_WINDOW_WORDS) {
wordAdj = (wordCount - WOLFSSL_DTLS_WINDOW_WORDS) * sizeof(word32);
wordCount = WOLFSSL_DTLS_WINDOW_WORDS;
wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32);
}
XMEMSET(keys->peerSeq[0].prevWindow, 0xFF, DTLS_SEQ_SZ);
@@ -10756,7 +10756,9 @@ static void AddRecordHeader(byte* output, word32 length, byte type,
#if !defined(WOLFSSL_NO_TLS12) || (defined(HAVE_SESSION_TICKET) && \
!defined(NO_WOLFSSL_SERVER))
!defined(NO_WOLFSSL_SERVER)) || \
defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) || !defined(NO_CERTS)
/* add handshake header for message */
static void AddHandShakeHeader(byte* output, word32 length,
word32 fragOffset, word32 fragLength,
@@ -10791,7 +10793,7 @@ static void AddHandShakeHeader(byte* output, word32 length,
}
/* add both headers for handshake message */
static void AddHeaders(byte* output, word32 length, byte type, WOLFSSL* ssl)
WC_MAYBE_UNUSED static void AddHeaders(byte* output, word32 length, byte type, WOLFSSL* ssl)
{
word32 lengthAdj = HANDSHAKE_HEADER_SZ;
word32 outputAdj = RECORD_HEADER_SZ;
@@ -10806,17 +10808,14 @@ static void AddHeaders(byte* output, word32 length, byte type, WOLFSSL* ssl)
AddRecordHeader(output, length + lengthAdj, handshake, ssl, CUR_ORDER);
AddHandShakeHeader(output + outputAdj, length, 0, length, type, ssl);
}
#endif /* !WOLFSSL_NO_TLS12 || (HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER) */
#endif /* !WOLFSSL_NO_TLS12 || (HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER) ||
* HAVE_CERTIFICATE_STATUS_REQUEST ||
* HAVE_CERTIFICATE_STATUS_REQUEST_V2 || !NO_CERTS */
#ifndef WOLFSSL_NO_TLS12
#if (!defined(NO_CERTS) && (!defined(NO_WOLFSSL_SERVER) || \
!defined(WOLFSSL_NO_CLIENT_AUTH))) || \
((!defined(NO_WOLFSSL_SERVER) || \
(!defined(NO_WOLFSSL_CLIENT) && !defined(NO_CERTS) && \
!defined(WOLFSSL_NO_CLIENT_AUTH))) && defined(WOLFSSL_DTLS))
static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset,
word32 length, byte type, WOLFSSL* ssl)
#if !defined(WOLFSSL_NO_TLS12) || (defined(WOLFSSL_DTLS) && defined(WOLFSSL_TLS13))
WC_MAYBE_UNUSED static void AddFragHeaders(byte* output, word32 fragSz,
word32 fragOffset, word32 length, byte type, WOLFSSL* ssl)
{
word32 lengthAdj = HANDSHAKE_HEADER_SZ;
word32 outputAdj = RECORD_HEADER_SZ;
@@ -10832,11 +10831,8 @@ static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset,
AddRecordHeader(output, fragSz + lengthAdj, handshake, ssl, CUR_ORDER);
AddHandShakeHeader(output + outputAdj, length, fragOffset, fragSz, type, ssl);
}
#endif
#endif /* !WOLFSSL_NO_TLS12 || (WOLFSSL_DTLS && WOLFSSL_TLS13) */
#if !defined(NO_WOLFSSL_SERVER) || \
(!defined(NO_WOLFSSL_CLIENT) && !defined(NO_CERTS) && \
!defined(WOLFSSL_NO_CLIENT_AUTH))
/**
* Send the handshake message. This function handles fragmenting the message
* so that it will fit into the desired MTU or the max fragment size.
@@ -10850,8 +10846,8 @@ static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset,
* @param type Type of message being sent
* @return 0 on success and negative otherwise
*/
static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz,
enum HandShakeType type, const char* packetName)
WC_MAYBE_UNUSED static int SendHandshakeMsg(WOLFSSL* ssl, byte* input,
word32 inputSz, enum HandShakeType type, const char* packetName)
{
int maxFrag;
int ret = 0;
@@ -11012,10 +11008,6 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz,
ssl->options.buildingMsg = 0;
return ret;
}
#endif /* !NO_WOLFSSL_SERVER || (!NO_WOLFSSL_CLIENT && !NO_CERTS &&
* !WOLFSSL_NO_CLIENT_AUTH) */
#endif /* !WOLFSSL_NO_TLS12 */
/* return bytes received, WOLFSSL_FATAL_ERROR on error,
@@ -12232,12 +12224,16 @@ static int GetRecordHeader(WOLFSSL* ssl, word32* inOutIdx,
/* record layer length check */
#ifdef HAVE_MAX_FRAGMENT
if (*size > (ssl->max_fragment + MAX_COMP_EXTRA + MAX_MSG_EXTRA)) {
if (*size > (ssl->max_fragment + MAX_MSG_EXTRA +
(ssl->options.usingCompression ? MAX_COMP_EXTRA : 0))) {
WOLFSSL_MSG_EX("Record length %d exceeds max fragment size", *size);
WOLFSSL_ERROR_VERBOSE(LENGTH_ERROR);
return LENGTH_ERROR;
}
#else
if (*size > (MAX_RECORD_SIZE + MAX_COMP_EXTRA + MAX_MSG_EXTRA)) {
if (*size > (MAX_RECORD_SIZE + MAX_MSG_EXTRA +
(ssl->options.usingCompression ? MAX_COMP_EXTRA : 0))) {
WOLFSSL_MSG_EX("Record length %d exceeds max record size", *size);
WOLFSSL_ERROR_VERBOSE(LENGTH_ERROR);
return LENGTH_ERROR;
}
@@ -13393,9 +13389,7 @@ int CheckIPAddr(DecodedCert* dCert, const char* ipasc)
}
#if defined(SESSION_CERTS) && (!defined(NO_WOLFSSL_CLIENT) || \
!defined(WOLFSSL_NO_CLIENT_AUTH))
static void AddSessionCertToChain(WOLFSSL_X509_CHAIN* chain,
WC_MAYBE_UNUSED static void AddSessionCertToChain(WOLFSSL_X509_CHAIN* chain,
byte* certBuf, word32 certSz)
{
if (chain->count < MAX_CHAIN_DEPTH &&
@@ -13408,7 +13402,6 @@ static void AddSessionCertToChain(WOLFSSL_X509_CHAIN* chain,
WOLFSSL_MSG("Couldn't store chain cert for session");
}
}
#endif
#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \
defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
@@ -38900,9 +38893,15 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
int error;
word32 itHash = 0;
byte zeros[WOLFSSL_TICKET_MAC_SZ]; /* biggest cmp size */
int internalTicketSz;
byte* mac;
#if defined(OPENSSL_ALL) && defined(KEEP_PEER_CERT) && \
!defined(NO_CERT_IN_TICKET)
word16 peerCertSz = 0;
#endif
WOLFSSL_ASSERT_GE(sizeof(ssl->session->staticTicket), WOLFSSL_TICKET_ENC_SZ);
WOLFSSL_ASSERT_SIZEOF_GE(ssl->session->staticTicket, *et);
WOLFSSL_ASSERT_SIZEOF_GE(et->enc_ticket, *it);
if (ssl->session->ticket != ssl->session->staticTicket) {
/* Always use the static ticket buffer */
@@ -38918,7 +38917,7 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
if (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E))
#endif
{
XMEMSET(et, 0, sizeof(*et));
XMEMSET(ssl->session->ticket, 0, SESSION_TICKET_LEN);
}
/* build internal */
@@ -38982,6 +38981,55 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
XMEMCPY(it->sessionCtx, ssl->sessionCtx, ID_LEN);
#endif
#if defined(OPENSSL_ALL) && defined(KEEP_PEER_CERT) && \
!defined(NO_CERT_IN_TICKET)
/* Store peer certificate in ticket for session resumption.
* Try ssl->peerCert first, then ssl->session->chain as fallback.
* Skip for DTLS to keep ticket size small for MTU constraints. */
if (ssl->options.dtls) {
c16toa(0, it->peerCertLen);
peerCertSz = 0;
}
else {
const byte* certDer = NULL;
word32 certDerSz = 0;
if (ssl->peerCert.derCert != NULL &&
ssl->peerCert.derCert->length > 0) {
/* Use current peer certificate */
certDer = ssl->peerCert.derCert->buffer;
certDerSz = ssl->peerCert.derCert->length;
}
#ifdef SESSION_CERTS
else if (ssl->session->chain.count > 0) {
/* Use peer certificate from session chain */
certDer = ssl->session->chain.certs[0].buffer;
certDerSz = ssl->session->chain.certs[0].length;
}
#endif
if (certDer != NULL && certDerSz > 0 &&
certDerSz <= MAX_TICKET_PEER_CERT_SZ
#ifdef HAVE_MAX_FRAGMENT
/* We don't support fragmentation in
* SendTls13NewSessionTicket yet. */
&& (!IsAtLeastTLSv1_3(ssl->version) ||
ssl->max_fragment == MAX_RECORD_SIZE)
#endif
) {
c16toa((word16)certDerSz, it->peerCertLen);
XMEMCPY(it->peerCert, certDer, certDerSz);
peerCertSz = (word16)certDerSz;
}
else {
if (certDerSz > MAX_TICKET_PEER_CERT_SZ)
WOLFSSL_MSG("Peer cert too large for ticket, skipping");
c16toa(0, it->peerCertLen);
peerCertSz = 0;
}
}
#endif
#ifdef WOLFSSL_TICKET_HAVE_ID
{
const byte* id = NULL;
@@ -38994,6 +39042,14 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
}
#endif
internalTicketSz = (int)WOLFSSL_INTERNAL_TICKET_BASE_SZ;
#if defined(OPENSSL_ALL) && defined(KEEP_PEER_CERT) && \
!defined(NO_CERT_IN_TICKET)
internalTicketSz += peerCertSz;
#endif
/* MAC is placed after the encrypted data */
mac = et->enc_ticket + WOLFSSL_TICKET_ENC_SZ;
/* encrypt */
encLen = WOLFSSL_TICKET_ENC_SZ; /* max size user can use */
if (ssl->ctx->ticketEncCb == NULL
@@ -39010,10 +39066,10 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
ret = BAD_TICKET_ENCRYPT;
}
else {
itHash = HashObject((byte*)it, sizeof(*it), &error);
itHash = HashObject((byte*)it, (word32)internalTicketSz, &error);
if (error == 0) {
ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, et->mac,
1, et->enc_ticket, WOLFSSL_INTERNAL_TICKET_LEN, &encLen,
ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, mac,
1, et->enc_ticket, internalTicketSz, &encLen,
SSL_TICKET_CTX(ssl));
}
else {
@@ -39028,7 +39084,7 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
#endif
goto error;
}
if (encLen < (int)WOLFSSL_INTERNAL_TICKET_LEN ||
if (encLen < internalTicketSz ||
encLen > (int)WOLFSSL_TICKET_ENC_SZ) {
WOLFSSL_MSG("Bad user ticket encrypt size");
ret = BAD_TICKET_KEY_CB_SZ;
@@ -39037,7 +39093,8 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
/* sanity checks on encrypt callback */
/* internal ticket can't be the same if encrypted */
if (itHash == HashObject((byte*)it, sizeof(*it), &error) || error != 0)
if (itHash == HashObject((byte*)it, (word32)internalTicketSz, &error) ||
error != 0)
{
WOLFSSL_MSG("User ticket encrypt didn't encrypt or hash failed");
ret = BAD_TICKET_ENCRYPT;
@@ -39061,7 +39118,7 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
}
/* mac */
if (XMEMCMP(et->mac, zeros, WOLFSSL_TICKET_MAC_SZ) == 0) {
if (XMEMCMP(mac, zeros, WOLFSSL_TICKET_MAC_SZ) == 0) {
WOLFSSL_MSG("User ticket encrypt didn't set mac");
ret = BAD_TICKET_ENCRYPT;
goto error;
@@ -39071,7 +39128,7 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
c16toa((word16)encLen, et->enc_len);
if (encLen < (int)WOLFSSL_TICKET_ENC_SZ) {
/* move mac up since whole enc buffer not used */
XMEMMOVE(et->enc_ticket + encLen, et->mac,
XMEMMOVE(et->enc_ticket + encLen, mac,
WOLFSSL_TICKET_MAC_SZ);
}
ssl->session->ticketLen =
@@ -39081,11 +39138,12 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
error:
#ifdef WOLFSSL_CHECK_MEM_ZERO
/* Ticket has sensitive data in it now. */
wc_MemZero_Add("Create Ticket internal", it, sizeof(InternalTicket));
wc_MemZero_Add("Create Ticket internal", it,
WOLFSSL_INTERNAL_TICKET_MAX_SZ);
#endif
ForceZero(it, sizeof(*it));
ForceZero(it, WOLFSSL_INTERNAL_TICKET_MAX_SZ);
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Check(it, sizeof(InternalTicket));
wc_MemZero_Check(it, WOLFSSL_INTERNAL_TICKET_MAX_SZ);
#endif
WOLFSSL_ERROR_VERBOSE(ret);
return ret;
@@ -39136,7 +39194,7 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
}
else {
/* Callback uses ssl without const but for DTLS, it really shouldn't
* modify its state. */
* modify its state. MAC is located after encrypted data. */
ret = ssl->ctx->ticketEncCb((WOLFSSL*)ssl, et->key_name, et->iv,
et->enc_ticket + inLen, 0,
et->enc_ticket, inLen, &outLen,
@@ -39274,6 +39332,48 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
}
#endif /* WOLFSSL_SLT13 */
#if defined(OPENSSL_ALL) && defined(KEEP_PEER_CERT) && \
!defined(NO_CERT_IN_TICKET)
static void RestorePeerCertFromTicket(WOLFSSL* ssl, InternalTicket* it)
{
word16 peerCertLen = 0;
ato16(it->peerCertLen, &peerCertLen);
if (peerCertLen > 0 && peerCertLen <= MAX_TICKET_PEER_CERT_SZ) {
#ifdef SESSION_CERTS
/* Clear existing chain and add the peer certificate */
ssl->session->chain.count = 0;
AddSessionCertToChain(&ssl->session->chain,
it->peerCert, peerCertLen);
#endif
/* Also decode into ssl->peerCert for direct access */
{
int ret;
DecodedCert* dCert;
dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
DYNAMIC_TYPE_DCERT);
if (dCert != NULL) {
InitDecodedCert(dCert, it->peerCert, peerCertLen, ssl->heap);
ret = ParseCertRelative(dCert, CERT_TYPE, 0, NULL, NULL);
if (ret == 0) {
FreeX509(&ssl->peerCert);
InitX509(&ssl->peerCert, 0, ssl->heap);
ret = CopyDecodedToX509(&ssl->peerCert, dCert);
if (ret != 0) {
/* Failed to copy - clear peerCert */
FreeX509(&ssl->peerCert);
InitX509(&ssl->peerCert, 0, ssl->heap);
}
}
FreeDecodedCert(dCert);
XFREE(dCert, ssl->heap, DYNAMIC_TYPE_DCERT);
}
}
}
}
#endif /* OPENSSL_ALL && KEEP_PEER_CERT && !NO_CERT_IN_TICKET */
void DoClientTicketFinalize(WOLFSSL* ssl, InternalTicket* it,
const WOLFSSL_SESSION* sess)
{
@@ -39361,6 +39461,12 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
ato16(it->namedGroup, &ssl->session->namedGroup);
#endif
}
#if defined(OPENSSL_ALL) && defined(KEEP_PEER_CERT) && \
!defined(NO_CERT_IN_TICKET)
RestorePeerCertFromTicket(ssl, it);
#endif
ssl->version.minor = it->pv.minor;
}
@@ -39405,6 +39511,23 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
#ifdef OPENSSL_EXTRA
it->sessionCtxSz = sess->sessionCtxSz;
XMEMCPY(it->sessionCtx, sess->sessionCtx, sess->sessionCtxSz);
#endif
#if defined(OPENSSL_ALL) && defined(KEEP_PEER_CERT) && \
defined(SESSION_CERTS) && !defined(NO_CERT_IN_TICKET)
/* Store peer certificate from session chain */
if (sess->chain.count > 0) {
word32 certLen = sess->chain.certs[0].length;
if (certLen <= MAX_TICKET_PEER_CERT_SZ) {
c16toa((word16)certLen, it->peerCertLen);
XMEMCPY(it->peerCert, sess->chain.certs[0].buffer, certLen);
}
else {
c16toa(0, it->peerCertLen);
}
}
else {
c16toa(0, it->peerCertLen);
}
#endif
}
@@ -39475,9 +39598,10 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
byte* tmp;
WOLFSSL_MSG("Found session matching the session id"
" found in the ticket");
/* Allocate and populate an InternalTicket */
/* Allocate and populate an InternalTicket. Need max size
* because PopulateInternalTicketFromSession may write peer cert */
#ifdef WOLFSSL_NO_REALLOC
tmp = (byte*)XMALLOC(sizeof(InternalTicket), ssl->heap,
tmp = (byte*)XMALLOC(WOLFSSL_INTERNAL_TICKET_MAX_SZ, ssl->heap,
DYNAMIC_TYPE_TLSX);
if (tmp != NULL && psk->identity != NULL)
{
@@ -39486,13 +39610,13 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
psk->identity = NULL;
}
#else
tmp = (byte*)XREALLOC(psk->identity, sizeof(InternalTicket),
tmp = (byte*)XREALLOC(psk->identity, WOLFSSL_INTERNAL_TICKET_MAX_SZ,
ssl->heap, DYNAMIC_TYPE_TLSX);
#endif
if (tmp != NULL) {
XMEMSET(tmp, 0, sizeof(InternalTicket));
XMEMSET(tmp, 0, WOLFSSL_INTERNAL_TICKET_MAX_SZ);
psk->identity = tmp;
psk->identityLen = sizeof(InternalTicket);
psk->identityLen = WOLFSSL_INTERNAL_TICKET_MAX_SZ;
psk->it = (InternalTicket*)tmp;
PopulateInternalTicketFromSession(sess, psk->it);
decryptRet = WOLFSSL_TICKET_RET_OK;
@@ -39527,8 +39651,8 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
}
#ifdef WOLFSSL_CHECK_MEM_ZERO
/* Internal ticket successfully decrypted. */
wc_MemZero_Add("Do Client Ticket internal", psk->it,
sizeof(InternalTicket));
wc_MemZero_Add("Do Client Ticket internal", psk->identity,
psk->identityLen);
#endif
ret = DoClientTicketCheckVersion(ssl, psk->it);
@@ -39536,7 +39660,7 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
psk->decryptRet = PSK_DECRYPT_FAIL;
ForceZero(psk->identity, psk->identityLen);
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Check(psk->it, sizeof(InternalTicket));
wc_MemZero_Check(psk->it, psk->identityLen);
#endif
WOLFSSL_LEAVE("DoClientTicket_ex", ret);
return ret;
@@ -39553,7 +39677,13 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
int ret;
InternalTicket* it = NULL;
#ifdef WOLFSSL_TLS13
InternalTicket staticIt;
/* Static buffer for stateful tickets - need max size for peer cert */
#ifdef WOLFSSL_SMALL_STACK
byte* staticItBuf = NULL;
#else
byte staticItBuf[WOLFSSL_INTERNAL_TICKET_MAX_SZ];
#endif
InternalTicket* staticIt = NULL;
const WOLFSSL_SESSION* sess = NULL;
psk_sess_free_cb_ctx freeCtx;
@@ -39585,18 +39715,27 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
* stateless tickets are much longer. */
sess = GetSesionFromCacheOrExt(ssl, input, &freeCtx);
if (sess != NULL) {
it = &staticIt;
XMEMSET(it, 0, sizeof(InternalTicket));
#ifdef WOLFSSL_SMALL_STACK
staticItBuf = (byte*)XMALLOC(WOLFSSL_INTERNAL_TICKET_MAX_SZ,
ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (staticItBuf == NULL) {
decryptRet = WOLFSSL_TICKET_RET_FATAL;
goto cleanup;
}
#endif
staticIt = (InternalTicket*)staticItBuf;
it = staticIt;
XMEMSET(it, 0, WOLFSSL_INTERNAL_TICKET_MAX_SZ);
PopulateInternalTicketFromSession(sess, it);
decryptRet = WOLFSSL_TICKET_RET_OK;
}
}
else
#endif
if (len >= sizeof(*it))
if (len >= WOLFSSL_INTERNAL_TICKET_LEN + WOLFSSL_TICKET_FIXED_SZ)
decryptRet = DoDecryptTicket(ssl, input, len, &it);
else
WOLFSSL_MSG("Ticket is smaller than InternalTicket. Rejecting.");
WOLFSSL_MSG("Ticket is smaller than minimum size. Rejecting.");
if (decryptRet != WOLFSSL_TICKET_RET_OK &&
@@ -39605,8 +39744,10 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
goto cleanup;
}
#ifdef WOLFSSL_CHECK_MEM_ZERO
/* Internal ticket successfully decrypted. */
wc_MemZero_Add("Do Client Ticket internal", it, sizeof(InternalTicket));
/* Internal ticket successfully decrypted. Zero at least the minimum
* internal ticket size (contains master secret). */
wc_MemZero_Add("Do Client Ticket internal", it,
WOLFSSL_INTERNAL_TICKET_LEN);
#endif
ret = DoClientTicketCheckVersion(ssl, it);
@@ -39619,12 +39760,19 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
cleanup:
if (it != NULL) {
ForceZero(it, sizeof(*it));
/* Zero the minimum internal ticket size. The it pointer points into
* the input buffer which may be smaller than MAX_SZ. We use the
* minimum length (WOLFSSL_INTERNAL_TICKET_LEN) which is guaranteed
* to fit and contains the sensitive master secret. */
ForceZero(it, WOLFSSL_INTERNAL_TICKET_LEN);
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Check(it, sizeof(InternalTicket));
wc_MemZero_Check(it, WOLFSSL_INTERNAL_TICKET_LEN);
#endif
}
#ifdef WOLFSSL_TLS13
#ifdef WOLFSSL_SMALL_STACK
XFREE(staticItBuf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
if (sess != NULL)
FreeSessionFromCacheOrExt(ssl, sess, &freeCtx);
#endif
@@ -39640,10 +39788,7 @@ cleanup:
psk->decryptRet = PSK_DECRYPT_NONE;
ForceZero(psk->identity, psk->identityLen);
#ifdef WOLFSSL_CHECK_MEM_ZERO
/* We want to check the InternalTicket area since that is what
* we registered in DoClientTicket_ex */
wc_MemZero_Check((((ExternalTicket*)psk->identity)->enc_ticket),
sizeof(InternalTicket));
wc_MemZero_Check(psk->identity, psk->identityLen);
#endif
}
}
@@ -39659,11 +39804,15 @@ cleanup:
int sendSz;
word32 length = SESSION_HINT_SZ + LENGTH_SZ;
word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
word32 headerSz = 0;
WOLFSSL_START(WC_FUNC_TICKET_SEND);
WOLFSSL_ENTER("SendTicket");
if (ssl->options.createTicket) {
if (ssl->options.createTicket &&
/* This will be set when SendHandshakeMsg returns WANT_WRITE. Create
* a new ticket only once. */
!ssl->options.buildingMsg) {
ret = SetupTicket(ssl);
if (ret != 0)
return ret;
@@ -39685,20 +39834,13 @@ cleanup:
idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
#endif
}
headerSz = idx;
if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone)
sendSz += cipherExtraData(ssl);
/* Set this in case CheckAvailableSize returns a WANT_WRITE so that state
* is not advanced yet */
ssl->options.buildingMsg = 1;
/* check for available size */
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
return ret;
output = (byte*)XMALLOC(sendSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (output == NULL)
return MEMORY_E;
/* get output buffer */
output = GetOutputBuffer(ssl);
AddHeaders(output, length, session_ticket, ssl);
/* hint */
@@ -39713,45 +39855,9 @@ cleanup:
XMEMCPY(output + idx, ssl->session->ticket, ssl->session->ticketLen);
idx += ssl->session->ticketLen;
if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) {
byte* input;
int inputSz = (int)idx; /* build msg adds rec hdr */
int recordHeaderSz = RECORD_HEADER_SZ;
if (ssl->options.dtls)
recordHeaderSz += DTLS_RECORD_EXTRA;
inputSz -= recordHeaderSz;
input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
if (input == NULL)
return MEMORY_E;
XMEMCPY(input, output + recordHeaderSz, inputSz);
sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
handshake, 1, 0, 0, CUR_ORDER);
XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
if (sendSz < 0)
return sendSz;
}
else {
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
if ((ret = DtlsMsgPoolSave(ssl, output, (word32)sendSz, session_ticket)) != 0)
return ret;
DtlsSEQIncrement(ssl, CUR_ORDER);
}
#endif
ret = HashOutput(ssl, output, sendSz, 0);
if (ret != 0)
return ret;
}
ssl->buffers.outputBuffer.length += sendSz;
ssl->options.buildingMsg = 0;
if (!ssl->options.groupMessages)
ret = SendBuffered(ssl);
ret = SendHandshakeMsg(ssl, output, idx - headerSz, session_ticket,
"Session Ticket");
XFREE(output, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
WOLFSSL_LEAVE("SendTicket", ret);
WOLFSSL_END(WC_FUNC_TICKET_SEND);
@@ -40249,7 +40355,8 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
WOLFSSL_ENTER("DefTicketEncCb");
if ((!enc) && (inLen != WOLFSSL_INTERNAL_TICKET_LEN)) {
/* For decryption, check minimum internal ticket size */
if ((!enc) && (inLen < (int)WOLFSSL_INTERNAL_TICKET_LEN)) {
return BUFFER_E;
}
+31
View File
@@ -2824,6 +2824,37 @@ int wolfSSL_EC_POINT_copy(WOLFSSL_EC_POINT *dest, const WOLFSSL_EC_POINT *src)
return ret;
}
/* Duplicates an EC point.
*
* @param [in] src EC point to duplicate.
* @param [in] group EC group for the new point.
* @return New EC point on success.
* @return NULL on failure.
*/
WOLFSSL_EC_POINT *wolfSSL_EC_POINT_dup(const WOLFSSL_EC_POINT *src,
const WOLFSSL_EC_GROUP *group)
{
WOLFSSL_EC_POINT *dest;
WOLFSSL_ENTER("wolfSSL_EC_POINT_dup");
if ((src == NULL) || (group == NULL)) {
return NULL;
}
dest = wolfSSL_EC_POINT_new(group);
if (dest == NULL) {
return NULL;
}
if (wolfSSL_EC_POINT_copy(dest, src) != 1) {
wolfSSL_EC_POINT_free(dest);
return NULL;
}
return dest;
}
/* Checks whether point is at infinity.
*
* Return code compliant with OpenSSL.
+22 -6
View File
@@ -5726,6 +5726,13 @@ int wolfSSL_export_keying_material(WOLFSSL *ssl,
return WOLFSSL_FAILURE;
}
/* Sanity check contextLen to prevent integer overflow when cast to word32
* and to ensure it fits in the 2-byte length encoding (max 65535). */
if (use_context && contextLen > WOLFSSL_MAX_16BIT) {
WOLFSSL_MSG("contextLen too large");
return WOLFSSL_FAILURE;
}
/* clientRandom + serverRandom
* OR
* clientRandom + serverRandom + ctx len encoding + ctx */
@@ -15508,11 +15515,10 @@ WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
#endif
#ifndef WOLFSSL_BLIND_PRIVATE_KEY
#ifdef WOLFSSL_COPY_KEY
if (ssl->buffers.key != NULL && ssl->buffers.weOwnKey) {
FreeDer(&ssl->buffers.key);
}
if (ctx->privateKey != NULL) {
if (ssl->buffers.key != NULL) {
FreeDer(&ssl->buffers.key);
ssl->buffers.key = NULL;
}
ret = AllocCopyDer(&ssl->buffers.key, ctx->privateKey->buffer,
ctx->privateKey->length, ctx->privateKey->type,
ctx->privateKey->heap);
@@ -16668,8 +16674,12 @@ int wolfSSL_select_next_proto(unsigned char **out, unsigned char *outLen,
for (i = 0; i < inLen; i += lenIn) {
lenIn = in[i++];
if (lenIn == 0 || i + lenIn > inLen)
break;
for (j = 0; j < clientLen; j += lenClient) {
lenClient = clientNames[j++];
if (lenClient == 0 || j + lenClient > clientLen)
break;
if (lenIn != lenClient)
continue;
@@ -16682,8 +16692,14 @@ int wolfSSL_select_next_proto(unsigned char **out, unsigned char *outLen,
}
}
*out = (unsigned char *)clientNames + 1;
*outLen = clientNames[0];
if (clientLen > 0 && (unsigned int)clientNames[0] + 1 <= clientLen) {
*out = (unsigned char *)clientNames + 1;
*outLen = clientNames[0];
}
else {
*out = (unsigned char *)clientNames;
*outLen = 0;
}
return WOLFSSL_NPN_NO_OVERLAP;
}
+23 -2
View File
@@ -869,7 +869,8 @@ int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl)
if (ssl->buffers.weOwnKey) {
WOLFSSL_MSG("Unloading key");
ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length);
if (ssl->buffers.key != NULL && ssl->buffers.key->buffer != NULL)
ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length);
FreeDer(&ssl->buffers.key);
#ifdef WOLFSSL_BLIND_PRIVATE_KEY
FreeDer(&ssl->buffers.keyMask);
@@ -880,7 +881,11 @@ int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl)
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (ssl->buffers.weOwnAltKey) {
WOLFSSL_MSG("Unloading alt key");
ForceZero(ssl->buffers.altKey->buffer, ssl->buffers.altKey->length);
if (ssl->buffers.altKey != NULL &&
ssl->buffers.altKey->buffer != NULL) {
ForceZero(ssl->buffers.altKey->buffer,
ssl->buffers.altKey->length);
}
FreeDer(&ssl->buffers.altKey);
#ifdef WOLFSSL_BLIND_PRIVATE_KEY
FreeDer(&ssl->buffers.altKeyMask);
@@ -1710,6 +1715,22 @@ WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl)
else if (ssl->buffers.weOwnCert) {
/* Check if we already have a certificate allocated. */
if (ssl->ourCert == NULL) {
/* Check if ctx has ourCert set - if so, use it instead of creating
* a new X509. This maintains pointer compatibility with
* applications (like nginx OCSP stapling) that use the X509 pointer
* from SSL_CTX_use_certificate as a lookup key. */
if (ssl->ctx != NULL && ssl->ctx->ourCert != NULL) {
/* Compare cert buffers to make sure they are the same */
if (ssl->buffers.certificate == NULL ||
ssl->buffers.certificate->buffer == NULL ||
(ssl->buffers.certificate->length ==
ssl->ctx->certificate->length &&
XMEMCMP(ssl->buffers.certificate->buffer,
ssl->ctx->certificate->buffer,
ssl->buffers.certificate->length) == 0)) {
return ssl->ctx->ourCert;
}
}
/* We own certificate so this should never happen. */
if (ssl->buffers.certificate == NULL) {
WOLFSSL_MSG("Certificate buffer not set!");
+13 -4
View File
@@ -4831,12 +4831,21 @@ static int wolfssl_add_to_chain(DerBuffer** chain, int weOwn, const byte* cert,
/* Get length of previous chain. */
len = oldChain->length;
}
/* Allocate DER buffer bug enough to hold old and new certificates. */
ret = AllocDer(&newChain, len + CERT_HEADER_SZ + certSz, CERT_TYPE, heap);
if (ret != 0) {
WOLFSSL_MSG("AllocDer error");
/* Check for integer overflow in size calculation. */
if ((len > WOLFSSL_MAX_32BIT - CERT_HEADER_SZ) ||
(certSz > WOLFSSL_MAX_32BIT - CERT_HEADER_SZ - len)) {
WOLFSSL_MSG("wolfssl_add_to_chain overflow");
res = 0;
}
if (res == 1) {
/* Allocate DER buffer big enough to hold old and new certificates. */
ret = AllocDer(&newChain, len + CERT_HEADER_SZ + certSz, CERT_TYPE,
heap);
if (ret != 0) {
WOLFSSL_MSG("AllocDer error");
res = 0;
}
}
if (res == 1) {
if (oldChain != NULL) {
+9 -1
View File
@@ -230,7 +230,15 @@ static int wolfssl_file_len(XFILE fp, long* fileSz)
/* Get file offset at end of file. */
curr = (long)XFTELL(fp);
if (curr < 0) {
ret = WOLFSSL_BAD_FILE;
#ifdef ESPIPE
if (errno == ESPIPE) {
WOLFSSL_ERROR_MSG("wolfssl_file_len: file is a pipe");
*fileSz = 0;
ret = WOLFSSL_BAD_FILETYPE;
}
else
#endif
ret = WOLFSSL_BAD_FILE;
}
}
/* Move to end of file. */
+25 -6
View File
@@ -448,8 +448,24 @@ static int wolfssl_sk_dup_data(WOLFSSL_STACK* dst, WOLFSSL_STACK* src)
break;
}
break;
case STACK_TYPE_X509_CRL:
#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL)
if (src->data.crl == NULL) {
break;
}
dst->data.crl = wolfSSL_X509_CRL_dup(src->data.crl);
if (dst->data.crl == NULL) {
WOLFSSL_MSG("wolfSSL_X509_CRL_dup error");
err = 1;
break;
}
#else
WOLFSSL_MSG("CRL support not enabled");
err = 1;
#endif
break;
case STACK_TYPE_X509_OBJ:
#if defined(OPENSSL_ALL)
#if defined(OPENSSL_ALL)
if (src->data.x509_obj == NULL) {
break;
}
@@ -460,8 +476,11 @@ static int wolfssl_sk_dup_data(WOLFSSL_STACK* dst, WOLFSSL_STACK* src)
err = 1;
break;
}
#else
WOLFSSL_MSG("OPENSSL_ALL support not enabled");
err = 1;
#endif
break;
#endif
case STACK_TYPE_BIO:
case STACK_TYPE_STRING:
case STACK_TYPE_ACCESS_DESCRIPTION:
@@ -475,7 +494,6 @@ static int wolfssl_sk_dup_data(WOLFSSL_STACK* dst, WOLFSSL_STACK* src)
case STACK_TYPE_BY_DIR_entry:
case STACK_TYPE_BY_DIR_hash:
case STACK_TYPE_DIST_POINT:
case STACK_TYPE_X509_CRL:
case STACK_TYPE_GENERAL_SUBTREE:
default:
WOLFSSL_MSG("Unsupported stack type");
@@ -488,7 +506,8 @@ static int wolfssl_sk_dup_data(WOLFSSL_STACK* dst, WOLFSSL_STACK* src)
/* Duplicate the stack of nodes.
*
* TODO: OpenSSL does a shallow copy but we have wolfSSL_shallow_sk_dup().
* OpenSSL does a shallow copy but we map to wolfSSL_shallow_sk_dup()
* when we want a shallow copy.
*
* Data is copied/duplicated - deep copy.
*
@@ -683,7 +702,7 @@ void* wolfSSL_sk_value(const WOLFSSL_STACK* sk, int i)
#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.
/* Put the data into a node at the end of the list.
*
* @param [in, out] stack Stack of objects.
* @param [in] data Data to store in stack.
@@ -698,7 +717,7 @@ int wolfSSL_sk_push(WOLFSSL_STACK* stack, const void *data)
return wolfSSL_sk_insert(stack, data, -1);
}
/* Put the data into a node at an index in the stack.
/* Put the data into a node at an index in the list.
*
* @param [in, out] stack Stack of objects.
* @param [in] data Data to store in stack.
+32 -11
View File
@@ -2135,10 +2135,10 @@ static void TLSX_SNI_FreeAll(SNI* list, void* heap)
}
/** Tells the buffered size of the SNI objects in a list. */
static word16 TLSX_SNI_GetSize(SNI* list)
WOLFSSL_TEST_VIS word16 TLSX_SNI_GetSize(SNI* list)
{
SNI* sni;
word16 length = OPAQUE16_LEN; /* list length */
word32 length = OPAQUE16_LEN; /* list length */
while ((sni = list)) {
list = sni->next;
@@ -2147,12 +2147,16 @@ static word16 TLSX_SNI_GetSize(SNI* list)
switch (sni->type) {
case WOLFSSL_SNI_HOST_NAME:
length += (word16)XSTRLEN((char*)sni->data.host_name);
length += (word32)XSTRLEN((char*)sni->data.host_name);
break;
}
if (length > WOLFSSL_MAX_16BIT) {
return 0;
}
}
return length;
return (word16)length;
}
/** Writes the SNI objects of a list in a buffer. */
@@ -3216,7 +3220,7 @@ static void TLSX_CSR_Free(CertificateStatusRequest* csr, void* heap)
word16 TLSX_CSR_GetSize_ex(CertificateStatusRequest* csr, byte isRequest,
int idx)
{
word16 size = 0;
word32 size = 0;
/* shut up compiler warnings */
(void) csr; (void) isRequest;
@@ -3237,15 +3241,25 @@ word16 TLSX_CSR_GetSize_ex(CertificateStatusRequest* csr, byte isRequest,
if (csr->ssl != NULL && SSL_CM(csr->ssl) != NULL &&
SSL_CM(csr->ssl)->ocsp_stapling != NULL &&
SSL_CM(csr->ssl)->ocsp_stapling->statusCb != NULL) {
return OPAQUE8_LEN + OPAQUE24_LEN + csr->ssl->ocspCsrResp[idx].length;
if (WOLFSSL_MAX_16BIT - OPAQUE8_LEN - OPAQUE24_LEN <
csr->ssl->ocspCsrResp[idx].length) {
return 0;
}
size = OPAQUE8_LEN + OPAQUE24_LEN +
csr->ssl->ocspCsrResp[idx].length;
return (word16)size;
}
return (word16)(OPAQUE8_LEN + OPAQUE24_LEN +
csr->responses[idx].length);
if (WOLFSSL_MAX_16BIT - OPAQUE8_LEN - OPAQUE24_LEN <
csr->responses[idx].length) {
return 0;
}
size = OPAQUE8_LEN + OPAQUE24_LEN + csr->responses[idx].length;
return (word16)size;
}
#else
(void)idx;
#endif
return size;
return (word16)size;
}
#if (defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER))
@@ -3855,7 +3869,7 @@ static void TLSX_CSR2_FreeAll(CertificateStatusRequestItemV2* csr2, void* heap)
static word16 TLSX_CSR2_GetSize(CertificateStatusRequestItemV2* csr2,
byte isRequest)
{
word16 size = 0;
word32 size = 0;
/* shut up compiler warnings */
(void) csr2; (void) isRequest;
@@ -3876,11 +3890,15 @@ static word16 TLSX_CSR2_GetSize(CertificateStatusRequestItemV2* csr2,
size += OCSP_NONCE_EXT_SZ;
break;
}
if (size > WOLFSSL_MAX_16BIT) {
return 0;
}
}
}
#endif
return size;
return (word16)size;
}
static int TLSX_CSR2_Write(CertificateStatusRequestItemV2* csr2,
@@ -13605,6 +13623,9 @@ static int TLSX_ECH_Parse(WOLFSSL* ssl, const byte* readBuf, word16 size,
}
/* read hello inner len */
ato16(readBuf_p, &ech->innerClientHelloLen);
if (ech->innerClientHelloLen < WC_AES_BLOCK_SIZE) {
return BUFFER_ERROR;
}
ech->innerClientHelloLen -= WC_AES_BLOCK_SIZE;
readBuf_p += 2;
ech->outerClientPayload = readBuf_p;
+8 -7
View File
@@ -1023,6 +1023,11 @@ int Tls13_Exporter(WOLFSSL* ssl, unsigned char *out, size_t outLen,
if (ret != 0)
return ret;
/* Sanity check contextLen to prevent truncation when cast to word32. */
if (contextLen > WOLFSSL_MAX_32BIT) {
return BAD_FUNC_ARG;
}
/* Hash(context_value) */
ret = wc_Hash(hashType, context, (word32)contextLen, hashOut, WC_MAX_DIGEST_SIZE);
if (ret != 0)
@@ -7791,7 +7796,6 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx,
int sendSz;
word32 i;
word32 reqSz;
word16 hashSigAlgoSz = 0;
SignatureAlgorithms* sa;
WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_SEND);
@@ -7802,14 +7806,11 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx,
if (ssl->options.side != WOLFSSL_SERVER_END)
return SIDE_ERROR;
/* Get the length of the hashSigAlgo buffer */
InitSuitesHashSigAlgo(NULL, SIG_ALL, 1, 1, ssl->buffers.keySz,
&hashSigAlgoSz);
sa = TLSX_SignatureAlgorithms_New(ssl, hashSigAlgoSz, ssl->heap);
/* Use ssl->suites->hashSigAlgo so wolfSSL_set1_sigalgs_list() is honored.
* hashSigAlgoSz=0 makes GetSize/Write fall back to WOLFSSL_SUITES(ssl). */
sa = TLSX_SignatureAlgorithms_New(ssl, 0, ssl->heap);
if (sa == NULL)
return MEMORY_ERROR;
InitSuitesHashSigAlgo(sa->hashSigAlgo, SIG_ALL, 1, 1, ssl->buffers.keySz,
&hashSigAlgoSz);
ret = TLSX_Push(&ssl->extensions, TLSX_SIGNATURE_ALGORITHMS, sa, ssl->heap);
if (ret != 0) {
TLSX_SignatureAlgorithms_FreeAll(sa, ssl->heap);
+218 -77
View File
@@ -38,6 +38,10 @@
#include <wolfssl/wolfio.h>
#endif
/* 16 times MAX_X509_SIZE should be more than enough to read any X509
* certificate file */
#define MAX_BIO_READ_BUFFER (MAX_X509_SIZE * 16)
#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
unsigned int wolfSSL_X509_get_extension_flags(WOLFSSL_X509* x509)
{
@@ -4672,6 +4676,14 @@ WOLFSSL_STACK* wolfSSL_sk_X509_CRL_new(void)
return s;
}
WOLFSSL_STACK* wolfSSL_sk_X509_CRL_new_null(void)
{
WOLFSSL_STACK* s = wolfSSL_sk_new_null();
if (s != NULL)
s->type = STACK_TYPE_X509_CRL;
return s;
}
void wolfSSL_sk_X509_CRL_pop_free(WOLF_STACK_OF(WOLFSSL_X509_CRL)* sk,
void (*f) (WOLFSSL_X509_CRL*))
{
@@ -6056,14 +6068,25 @@ static WOLFSSL_X509* loadX509orX509REQFromBuffer(
/* ready to be decoded. */
if (der != NULL && der->buffer != NULL) {
WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
/* For TRUSTED_CERT_TYPE, the DER buffer contains the certificate
* followed by auxiliary trust info. ParseCertRelative expects CERT_TYPE
* and will parse only the certificate portion, ignoring the rest. */
int parseType = (type == TRUSTED_CERT_TYPE) ? CERT_TYPE : type;
WC_ALLOC_VAR_EX(cert, DecodedCert, 1, NULL, DYNAMIC_TYPE_DCERT,
ret=MEMORY_ERROR);
if (WC_VAR_OK(cert))
{
InitDecodedCert(cert, der->buffer, der->length, NULL);
ret = ParseCertRelative(cert, type, 0, NULL, NULL);
ret = ParseCertRelative(cert, parseType, 0, NULL, NULL);
if (ret == 0) {
/* For TRUSTED_CERT_TYPE, truncate the DER buffer to exclude
* auxiliary trust data. ParseCertRelative sets srcIdx to the
* end of the certificate, so we adjust cert->maxIdx accordingly. */
if (type == TRUSTED_CERT_TYPE && cert->srcIdx < cert->maxIdx) {
cert->maxIdx = cert->srcIdx;
}
x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
DYNAMIC_TYPE_X509);
if (x509 != NULL) {
@@ -12922,22 +12945,23 @@ static WOLFSSL_X509 *loadX509orX509REQFromPemBio(WOLFSSL_BIO *bp,
int pemSz;
long i = 0, l, footerSz;
const char* footer = NULL;
int streaming = 0; /* Flag to indicate if source is streaming (FIFO) */
const char* altFooter = NULL;
long altFooterSz = 0;
WOLFSSL_ENTER("loadX509orX509REQFromPemBio");
if (bp == NULL || (type != CERT_TYPE && type != CERTREQ_TYPE)) {
if (bp == NULL || (type != CERT_TYPE && type != CERTREQ_TYPE &&
type != TRUSTED_CERT_TYPE)) {
WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_X509", BAD_FUNC_ARG);
return NULL;
}
if ((l = wolfSSL_BIO_get_len(bp)) <= 0) {
/* No certificate in buffer */
#if defined (WOLFSSL_HAPROXY)
WOLFSSL_ERROR(PEM_R_NO_START_LINE);
#else
WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
#endif
return NULL;
/* No certificate size available - could be FIFO or other streaming
* source. Use MAX_X509_SIZE as initial buffer, will resize if needed. */
l = MAX_X509_SIZE;
streaming = 1;
}
pemSz = (int)l;
@@ -12953,27 +12977,79 @@ static WOLFSSL_X509 *loadX509orX509REQFromPemBio(WOLFSSL_BIO *bp,
}
footerSz = (long)XSTRLEN(footer);
/* For TRUSTED_CERT_TYPE, also prepare to check for regular CERT footer
* as the file might contain regular certificates instead of TRUSTED
* format */
if (type == TRUSTED_CERT_TYPE) {
wc_PemGetHeaderFooter(CERT_TYPE, NULL, &altFooter);
if (altFooter != NULL) {
altFooterSz = (long)XSTRLEN(altFooter);
}
}
/* TODO: Inefficient
* reading in one byte at a time until see the footer
*/
while ((l = wolfSSL_BIO_read(bp, (char *)&pem[i], 1)) == 1) {
int foundFooter = 0;
i++;
if (i > footerSz && XMEMCMP((char *)&pem[i-footerSz], footer,
footerSz) == 0) {
if (wolfSSL_BIO_read(bp, (char *)&pem[i], 1) == 1) {
/* Check if buffer is full and we're reading from streaming source */
if (i >= pemSz && streaming) {
/* Double the buffer size for streaming sources */
int newSz = pemSz * 2;
unsigned char* newPem;
/* Sanity check: don't grow beyond reasonable limit */
if (newSz > MAX_BIO_READ_BUFFER) {
WOLFSSL_MSG("PEM data too large for streaming source");
XFREE(pem, 0, DYNAMIC_TYPE_PEM);
return NULL;
}
newPem = (unsigned char*)XREALLOC(pem, newSz, 0, DYNAMIC_TYPE_PEM);
if (newPem == NULL) {
WOLFSSL_MSG("Failed to resize PEM buffer");
XFREE(pem, 0, DYNAMIC_TYPE_PEM);
return NULL;
}
pem = newPem;
pemSz = newSz;
}
else if (i > pemSz) {
/* Buffer full for non-streaming source - this shouldn't happen */
break;
}
/* Check for the expected footer OR alternate footer (for
* TRUSTED_CERT_TYPE) */
if (i > footerSz &&
XMEMCMP((char *)&pem[i-footerSz], footer, footerSz) == 0) {
foundFooter = 1;
}
else if (i > altFooterSz && altFooter != NULL &&
XMEMCMP((char *)&pem[i-altFooterSz], altFooter, altFooterSz) == 0) {
foundFooter = 1;
}
if (foundFooter) {
if (i < pemSz && wolfSSL_BIO_read(bp, (char *)&pem[i], 1) == 1) {
/* attempt to read newline following footer */
i++;
if (pem[i-1] == '\r') {
if (i < pemSz && pem[i-1] == '\r') {
/* found \r , Windows line ending is \r\n so try to read one
* more byte for \n, ignoring return value */
(void)wolfSSL_BIO_read(bp, (char *)&pem[i++], 1);
if (i < pemSz) {
(void)wolfSSL_BIO_read(bp, (char *)&pem[i++], 1);
}
}
}
break;
}
}
if (l == 0)
if (l == 0 && i == 0) {
WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
}
if (i > pemSz) {
WOLFSSL_MSG("Error parsing PEM");
}
@@ -12985,6 +13061,12 @@ static WOLFSSL_X509 *loadX509orX509REQFromPemBio(WOLFSSL_BIO *bp,
CERTREQ_TYPE, cb, u);
else
#endif
/* Use TRUSTED_CERT_TYPE if input was TRUSTED CERTIFICATE format,
* otherwise use CERT_TYPE for regular certificates */
if (type == TRUSTED_CERT_TYPE)
x509 = loadX509orX509REQFromBuffer(pem, pemSz, WOLFSSL_FILETYPE_PEM,
TRUSTED_CERT_TYPE, cb, u);
else
x509 = loadX509orX509REQFromBuffer(pem, pemSz, WOLFSSL_FILETYPE_PEM,
CERT_TYPE, cb, u);
}
@@ -13005,6 +13087,86 @@ static WOLFSSL_X509 *loadX509orX509REQFromPemBio(WOLFSSL_BIO *bp,
}
WC_MAYBE_UNUSED
static unsigned char* ReadPemFromBioToBuffer(WOLFSSL_BIO *bp, int *pemSz)
{
unsigned char* pem = NULL;
WOLFSSL_ENTER("ReadPemFromBioToBuffer");
if (bp == NULL || pemSz == NULL) {
WOLFSSL_LEAVE("ReadPemFromBioToBuffer", BAD_FUNC_ARG);
return NULL;
}
if ((*pemSz = wolfSSL_BIO_get_len(bp)) <= 0) {
/* No certificate size available - could be FIFO or other streaming
* source. Use MAX_X509_SIZE as initial buffer, read in loop. */
int totalRead = 0;
int readSz;
*pemSz = MAX_X509_SIZE;
pem = (unsigned char*)XMALLOC(*pemSz, 0, DYNAMIC_TYPE_PEM);
if (pem == NULL) {
return NULL;
}
/* Read from streaming source until EOF or buffer full */
while ((readSz = wolfSSL_BIO_read(bp, pem + totalRead,
*pemSz - totalRead)) > 0) {
totalRead += readSz;
/* If buffer is full, try to grow it */
if (totalRead >= *pemSz) {
int newSz = *pemSz * 2;
unsigned char* newPem;
/* Sanity check */
if (newSz > MAX_BIO_READ_BUFFER) {
WOLFSSL_MSG("PEM data too large for streaming source");
XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
return NULL;
}
newPem = (unsigned char*)XREALLOC(pem, newSz, 0,
DYNAMIC_TYPE_PEM);
if (newPem == NULL) {
XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
return NULL;
}
pem = newPem;
*pemSz = newSz;
}
}
*pemSz = totalRead;
if (*pemSz <= 0) {
XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
return NULL;
}
}
else {
/* Known size - allocate and read */
pem = (unsigned char*)XMALLOC(*pemSz, 0, DYNAMIC_TYPE_PEM);
if (pem == NULL) {
return NULL;
}
XMEMSET(pem, 0, *pemSz);
*pemSz = wolfSSL_BIO_read(bp, pem, *pemSz);
if (*pemSz <= 0) {
XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
return NULL;
}
}
WOLFSSL_LEAVE("ReadPemFromBioToBuffer", 0);
return pem;
}
#if defined(WOLFSSL_ACERT)
WOLFSSL_X509_ACERT *wolfSSL_PEM_read_bio_X509_ACERT(WOLFSSL_BIO *bp,
WOLFSSL_X509_ACERT **x,
@@ -13019,29 +13181,14 @@ static WOLFSSL_X509 *loadX509orX509REQFromPemBio(WOLFSSL_BIO *bp,
WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509_ACERT");
if (bp == NULL) {
WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_X509_ACERT", BAD_FUNC_ARG);
return NULL;
}
if ((pemSz = wolfSSL_BIO_get_len(bp)) <= 0) {
/* No certificate in buffer */
WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
return NULL;
}
pem = (unsigned char*)XMALLOC(pemSz, 0, DYNAMIC_TYPE_PEM);
pem = ReadPemFromBioToBuffer(bp, &pemSz);
if (pem == NULL) {
return NULL;
}
XMEMSET(pem, 0, pemSz);
if (wolfSSL_BIO_read(bp, pem, pemSz) != pemSz) {
XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
return NULL;
}
x509 = wolfSSL_X509_ACERT_load_certificate_buffer(pem, pemSz,
WOLFSSL_FILETYPE_PEM);
@@ -13079,14 +13226,15 @@ static WOLFSSL_X509 *loadX509orX509REQFromPemBio(WOLFSSL_BIO *bp,
WOLFSSL_X509 **x, wc_pem_password_cb *cb,
void *u)
{
WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509");
WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509_AUX");
/* AUX info is; trusted/rejected uses, friendly name, private key id,
* and potentially a stack of "other" info. wolfSSL does not store
* friendly name or private key id yet in WOLFSSL_X509 for human
* readability and does not support extra trusted/rejected uses for
* root CA. */
return wolfSSL_PEM_read_bio_X509(bp, x, cb, u);
* root CA. Use TRUSTED_CERT_TYPE to properly parse TRUSTED CERTIFICATE
* format and strip auxiliary data. */
return loadX509orX509REQFromPemBio(bp, x, cb, u, TRUSTED_CERT_TYPE);
}
#ifdef WOLFSSL_CERT_REQ
@@ -13139,21 +13287,14 @@ WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_REQ(WOLFSSL_BIO *bp, WOLFSSL_X509 **x,
{
#if defined(WOLFSSL_PEM_TO_DER) && defined(HAVE_CRL)
unsigned char* pem = NULL;
int pemSz;
int derSz;
int pemSz = 0;
int derSz = 0;
DerBuffer* der = NULL;
WOLFSSL_X509_CRL* crl = NULL;
if ((pemSz = wolfSSL_BIO_get_len(bp)) <= 0) {
goto err;
}
WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509_CRL");
pem = (unsigned char*)XMALLOC(pemSz, 0, DYNAMIC_TYPE_PEM);
if (pem == NULL) {
goto err;
}
if (wolfSSL_BIO_read(bp, pem, pemSz) != pemSz) {
if ((pem = ReadPemFromBioToBuffer(bp, &pemSz)) == NULL) {
goto err;
}
@@ -13166,6 +13307,9 @@ WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_REQ(WOLFSSL_BIO *bp, WOLFSSL_X509 **x,
}
err:
if (pemSz == 0) {
WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
}
XFREE(pem, 0, DYNAMIC_TYPE_PEM);
if (der != NULL) {
FreeDer(&der);
@@ -15393,48 +15537,39 @@ void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk)
wolfSSL_sk_pop_free(sk, NULL);
}
static int x509_aia_append_string(WOLFSSL_STACK** head,
const byte* uri, word32 uriSz)
static int x509_aia_append_string(WOLFSSL_STACK* list, const byte* uri,
word32 uriSz)
{
WOLFSSL_STACK* node;
char* url;
url = (char*)XMALLOC(uriSz + 1, NULL, DYNAMIC_TYPE_OPENSSL);
WOLFSSL_STRING url = (WOLFSSL_STRING)XMALLOC(uriSz + 1, NULL,
DYNAMIC_TYPE_OPENSSL);
if (url == NULL)
return WOLFSSL_FAILURE;
return -1;
XMEMCPY(url, uri, uriSz);
url[uriSz] = '\0';
node = wolfSSL_sk_new_node(*head != NULL ? (*head)->heap : NULL);
if (node == NULL) {
if (wolfSSL_sk_push(list, url) <= 0) {
XFREE(url, NULL, DYNAMIC_TYPE_OPENSSL);
return WOLFSSL_FAILURE;
return -1;
}
node->type = STACK_TYPE_STRING;
node->data.string = url;
if (wolfSSL_sk_push_back_node(head, node) != WOLFSSL_SUCCESS) {
XFREE(url, NULL, DYNAMIC_TYPE_OPENSSL);
wolfSSL_sk_free_node(node);
return WOLFSSL_FAILURE;
}
return WOLFSSL_SUCCESS;
return 0;
}
static WOLFSSL_STACK* x509_get1_aia_by_method(WOLFSSL_X509* x, word32 method,
const byte* fallback, int fallbackSz)
{
WOLFSSL_STACK* head = NULL;
WOLFSSL_STACK* ret = NULL;
int i;
if (x == NULL)
return NULL;
/* Collect matching URIs from the multi-entry list into a new stack;
* fall back to the legacy single-entry field for compatibility. */
ret = wolfSSL_sk_WOLFSSL_STRING_new();
if (ret == NULL)
return NULL;
/* Build from multi-entry list when available; otherwise fall back to the
* legacy single-entry fields to preserve previous behavior. */
if (x->authInfoListSz > 0) {
for (i = 0; i < x->authInfoListSz; i++) {
if (x->authInfoList[i].method != method ||
@@ -15443,22 +15578,28 @@ static WOLFSSL_STACK* x509_get1_aia_by_method(WOLFSSL_X509* x, word32 method,
continue;
}
if (x509_aia_append_string(&head, x->authInfoList[i].uri,
x->authInfoList[i].uriSz) != WOLFSSL_SUCCESS) {
wolfSSL_sk_pop_free(head, NULL);
if (x509_aia_append_string(ret, x->authInfoList[i].uri,
x->authInfoList[i].uriSz) != 0) {
wolfSSL_X509_email_free(ret);
return NULL;
}
}
}
if (head == NULL && fallback != NULL && fallbackSz > 0) {
if (x509_aia_append_string(&head, fallback, (word32)fallbackSz)
!= WOLFSSL_SUCCESS) {
wolfSSL_sk_pop_free(head, NULL);
/* Only use fallback when nothing was found in the list */
if (wolfSSL_sk_num(ret) == 0 && fallback != NULL && fallbackSz > 0) {
if (x509_aia_append_string(ret, fallback, (word32)fallbackSz) != 0) {
wolfSSL_X509_email_free(ret);
return NULL;
}
}
return head;
/* Return NULL when empty */
if (wolfSSL_sk_num(ret) == 0) {
wolfSSL_X509_email_free(ret);
ret = NULL;
}
return ret;
}
WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x)
+292
View File
@@ -3515,6 +3515,60 @@ static int test_wolfSSL_CTX_add1_chain_cert(void)
return EXPECT_RESULT();
}
/* Test that wolfssl_add_to_chain rejects sizes that would overflow word32.
* ZD #21241 */
static int test_wolfSSL_add_to_chain_overflow(void)
{
EXPECT_DECLS;
#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA) && \
defined(KEEP_OUR_CERT) && !defined(NO_RSA) && !defined(NO_TLS) && \
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_FILESYSTEM)
WOLFSSL_CTX* ctx = NULL;
WOLFSSL_X509* x509 = NULL;
DerBuffer* fakeChain = NULL;
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
/* Load a real cert so ctx->certificate is set (first add goes there). */
ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(
"./certs/intermediate/client-int-cert.pem", WOLFSSL_FILETYPE_PEM));
ExpectIntEQ(SSL_CTX_add1_chain_cert(ctx, x509), 1);
wolfSSL_X509_free(x509);
x509 = NULL;
/* Now ctx->certificate is set, next add goes to certChain via
* wolfssl_add_to_chain. Fake a chain whose length is near UINT32_MAX
* so the size calculation (len + CERT_HEADER_SZ + certSz) overflows. */
fakeChain = (DerBuffer*)XMALLOC(sizeof(DerBuffer) + 16, ctx->heap,
DYNAMIC_TYPE_CERT);
ExpectNotNull(fakeChain);
if (EXPECT_SUCCESS()) {
XMEMSET(fakeChain, 0, sizeof(DerBuffer) + 16);
fakeChain->buffer = (byte*)(fakeChain + 1);
fakeChain->length = WOLFSSL_MAX_32BIT - 2; /* will overflow with any cert */
fakeChain->type = CERT_TYPE;
fakeChain->dynType = DYNAMIC_TYPE_CERT;
/* Replace the real chain with our fake one. */
if (ctx->certChain != NULL) {
XFREE(ctx->certChain, ctx->heap, DYNAMIC_TYPE_CERT);
}
ctx->certChain = fakeChain;
}
else {
XFREE(fakeChain, ctx ? ctx->heap : NULL, DYNAMIC_TYPE_CERT);
}
/* Try to add another cert - this MUST fail due to overflow guard. */
ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(
"./certs/intermediate/ca-int2-cert.pem", WOLFSSL_FILETYPE_PEM));
ExpectIntEQ(SSL_CTX_add1_chain_cert(ctx, x509), 0);
wolfSSL_X509_free(x509);
wolfSSL_CTX_free(ctx);
#endif
return EXPECT_RESULT();
}
static int test_wolfSSL_CTX_use_certificate_chain_buffer_format(void)
{
EXPECT_DECLS;
@@ -9172,6 +9226,117 @@ static int test_wolfSSL_dtls_export_peers(void)
return EXPECT_RESULT();
}
/* Test that ImportKeyState correctly skips extra window words when importing
* state from a peer compiled with a larger WOLFSSL_DTLS_WINDOW_WORDS. */
static int test_wolfSSL_dtls_import_state_extra_window_words(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT)
WOLFSSL_CTX* ctx = NULL;
WOLFSSL* ssl = NULL;
unsigned int stateSz = 0;
byte* state = NULL;
byte* modified = NULL;
unsigned int modifiedSz;
word16 origKeyLen;
word16 origTotalLen;
/* Offset from start of key state data to the first wordCount field.
* Layout: 4 sequence numbers (16 bytes) + DTLS-specific fields (42 bytes) +
* encryptSz(4) + padSz(4) + encryptionOn(1) + decryptedCur(1) = 68 */
const int keyStateWindowOffset = 68;
/* Buffer header: 2 proto + 2 total_len + 2 key_len = 6 */
const int headerSz = 6;
int idx, modIdx;
int extraPerWindow = 2 * (int)sizeof(word32); /* 8 bytes extra per window */
int totalExtra = extraPerWindow * 2; /* 16 bytes extra total */
/* Create DTLS context and SSL object */
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method()));
ExpectNotNull(ssl = wolfSSL_new(ctx));
/* Get required buffer size and export state-only */
ExpectIntEQ(wolfSSL_dtls_export_state_only(ssl, NULL, &stateSz), 0);
ExpectIntGT((int)stateSz, 0);
state = (byte*)XMALLOC(stateSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(state);
ExpectIntGT(wolfSSL_dtls_export_state_only(ssl, state, &stateSz), 0);
/* Build a modified buffer that simulates a peer with
* WOLFSSL_DTLS_WINDOW_WORDS = WOLFSSL_DTLS_WINDOW_WORDS + 2.
* Each window section gets 2 extra word32 values (8 bytes).
* Two windows => 16 extra bytes total. */
modifiedSz = stateSz + totalExtra;
modified = (byte*)XMALLOC(modifiedSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(modified);
if (EXPECT_SUCCESS()) {
int windowWords = WOLFSSL_DTLS_WINDOW_WORDS;
int windowDataSz = windowWords * (int)sizeof(word32);
XMEMSET(modified, 0, modifiedSz);
/* Copy protocol/version bytes (first 2 bytes) */
XMEMCPY(modified, state, 2);
/* Read original total length and key state length */
ato16(state + 2, &origTotalLen);
ato16(state + 4, &origKeyLen);
/* Write updated total length and key state length */
c16toa((word16)(origTotalLen + totalExtra), modified + 2);
c16toa((word16)(origKeyLen + totalExtra), modified + 4);
/* Copy key state data up to first window section */
idx = headerSz;
modIdx = headerSz;
XMEMCPY(modified + modIdx, state + idx, keyStateWindowOffset);
idx += keyStateWindowOffset;
modIdx += keyStateWindowOffset;
/* First window: write increased wordCount */
c16toa((word16)(windowWords + 2), modified + modIdx);
idx += OPAQUE16_LEN;
modIdx += OPAQUE16_LEN;
/* Copy original window data */
XMEMCPY(modified + modIdx, state + idx, windowDataSz);
idx += windowDataSz;
modIdx += windowDataSz;
/* Insert 2 extra word32 padding values */
XMEMSET(modified + modIdx, 0, extraPerWindow);
modIdx += extraPerWindow;
/* Second window (prevWindow): same transformation */
c16toa((word16)(windowWords + 2), modified + modIdx);
idx += OPAQUE16_LEN;
modIdx += OPAQUE16_LEN;
XMEMCPY(modified + modIdx, state + idx, windowDataSz);
idx += windowDataSz;
modIdx += windowDataSz;
XMEMSET(modified + modIdx, 0, extraPerWindow);
modIdx += extraPerWindow;
/* Copy remainder of key state (after both windows) */
XMEMCPY(modified + modIdx, state + idx, stateSz - idx);
}
/* Import the modified state - should succeed with the fix */
wolfSSL_free(ssl);
ssl = NULL;
ExpectNotNull(ssl = wolfSSL_new(ctx));
ExpectIntGT(wolfSSL_dtls_import(ssl, modified, modifiedSz), 0);
XFREE(state, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(modified, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);
#endif
return EXPECT_RESULT();
}
static int test_wolfSSL_UseTrustedCA(void)
{
EXPECT_DECLS;
@@ -9865,6 +10030,124 @@ static int test_wolfSSL_set_alpn_protos(void)
return res;
}
static int test_wolfSSL_select_next_proto(void)
{
EXPECT_DECLS;
unsigned char *out = NULL;
unsigned char outLen = 0;
int ret;
/* Wire format: length-prefixed protocol names */
unsigned char serverList[] = {
8, 'h','t','t','p','/','1','.','1',
6, 's','p','d','y','/','2'
};
unsigned int serverLen = sizeof(serverList);
unsigned char clientList[] = {
6, 's','p','d','y','/','2'
};
unsigned int clientLen = sizeof(clientList);
unsigned char clientListHttp[] = {
8, 'h','t','t','p','/','1','.','1'
};
unsigned int clientListHttpLen = sizeof(clientListHttp);
unsigned char clientListNoMatch[] = {
6, 's','p','d','y','/','3'
};
unsigned int clientListNoMatchLen = sizeof(clientListNoMatch);
/* Test 1: NULL parameters return UNSUPPORTED */
ExpectIntEQ(wolfSSL_select_next_proto(NULL, &outLen, serverList,
serverLen, clientList, clientLen), WOLFSSL_NPN_UNSUPPORTED);
ExpectIntEQ(wolfSSL_select_next_proto(&out, NULL, serverList,
serverLen, clientList, clientLen), WOLFSSL_NPN_UNSUPPORTED);
ExpectIntEQ(wolfSSL_select_next_proto(&out, &outLen, NULL,
serverLen, clientList, clientLen), WOLFSSL_NPN_UNSUPPORTED);
ExpectIntEQ(wolfSSL_select_next_proto(&out, &outLen, serverList,
serverLen, NULL, clientLen), WOLFSSL_NPN_UNSUPPORTED);
/* Test 2: Normal match - client wants "spdy/2", server offers it */
out = NULL;
outLen = 0;
ret = wolfSSL_select_next_proto(&out, &outLen, serverList, serverLen,
clientList, clientLen);
ExpectIntEQ(ret, WOLFSSL_NPN_NEGOTIATED);
ExpectIntEQ(outLen, 6);
ExpectNotNull(out);
ExpectIntEQ(XMEMCMP(out, "spdy/2", 6), 0);
/* Test 3: No overlap - server offers "http/1.1,spdy/2", client wants
* "spdy/3". Falls back to first client protocol. */
out = NULL;
outLen = 0;
ret = wolfSSL_select_next_proto(&out, &outLen, serverList, serverLen,
clientListNoMatch, clientListNoMatchLen);
ExpectIntEQ(ret, WOLFSSL_NPN_NO_OVERLAP);
ExpectIntEQ(outLen, 6);
ExpectNotNull(out);
ExpectIntEQ(XMEMCMP(out, "spdy/3", 6), 0);
/* Test 4: Malformed server list - length byte overruns buffer.
* Must NOT crash (heap over-read). */
{
unsigned char malformedServer[] = { 200, 'h','t','t','p' };
out = NULL;
outLen = 0;
ret = wolfSSL_select_next_proto(&out, &outLen, malformedServer,
sizeof(malformedServer), clientList, clientLen);
ExpectIntEQ(ret, WOLFSSL_NPN_NO_OVERLAP);
}
/* Test 5: Malformed client list - length byte overruns buffer.
* Must NOT crash. */
{
unsigned char malformedClient[] = { 200, 's','p','d','y' };
out = NULL;
outLen = 0;
ret = wolfSSL_select_next_proto(&out, &outLen, serverList, serverLen,
malformedClient, sizeof(malformedClient));
ExpectIntEQ(ret, WOLFSSL_NPN_NO_OVERLAP);
}
/* Test 6: Zero-length entry in server list - must NOT infinite loop */
{
unsigned char zeroLenServer[] = { 0, 6, 's','p','d','y','/','2' };
out = NULL;
outLen = 0;
ret = wolfSSL_select_next_proto(&out, &outLen, zeroLenServer,
sizeof(zeroLenServer), clientList, clientLen);
/* Zero-length entry causes break, so no match found */
ExpectIntEQ(ret, WOLFSSL_NPN_NO_OVERLAP);
}
/* Test 7: Empty client list (clientLen == 0) - must NOT dereference
* clientNames[0]. */
{
unsigned char emptyClient[] = { 0 };
out = NULL;
outLen = 0;
ret = wolfSSL_select_next_proto(&out, &outLen, serverList, serverLen,
emptyClient, 0);
ExpectIntEQ(ret, WOLFSSL_NPN_NO_OVERLAP);
ExpectIntEQ(outLen, 0);
}
/* Test 8: First protocol match - both start with "http/1.1" */
out = NULL;
outLen = 0;
ret = wolfSSL_select_next_proto(&out, &outLen, serverList, serverLen,
clientListHttp, clientListHttpLen);
ExpectIntEQ(ret, WOLFSSL_NPN_NEGOTIATED);
ExpectIntEQ(outLen, 8);
ExpectNotNull(out);
ExpectIntEQ(XMEMCMP(out, "http/1.1", 8), 0);
return EXPECT_RESULT();
}
#endif /* HAVE_ALPN_PROTOS_SUPPORT */
static int test_wolfSSL_wolfSSL_UseSecureRenegotiation(void)
@@ -24070,6 +24353,11 @@ static int test_export_keying_material_cb(WOLFSSL_CTX *ctx, WOLFSSL *ssl)
NULL, 0, 0), 0);
ExpectIntEQ(wolfSSL_export_keying_material(ssl, ekm, sizeof(ekm),
"key expansion", XSTR_SIZEOF("key expansion"), NULL, 0, 0), 0);
/* contextLen overflow: values exceeding UINT16_MAX must be rejected to
* prevent integer overflow in seedLen calculation (ZD #21242). */
ExpectIntEQ(wolfSSL_export_keying_material(ssl, ekm, sizeof(ekm),
"Test label", XSTR_SIZEOF("Test label"), ekm,
(size_t)0xFFFF + 1, 1), 0);
return EXPECT_RESULT();
}
@@ -32759,6 +33047,7 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wolfSSL_CTX_load_verify_buffer_ex),
TEST_DECL(test_wolfSSL_CTX_load_verify_chain_buffer_format),
TEST_DECL(test_wolfSSL_CTX_add1_chain_cert),
TEST_DECL(test_wolfSSL_add_to_chain_overflow),
TEST_DECL(test_wolfSSL_CTX_use_certificate_chain_buffer_format),
TEST_DECL(test_wolfSSL_CTX_use_certificate_chain_file_format),
TEST_DECL(test_wolfSSL_use_certificate_chain_file),
@@ -32801,6 +33090,7 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wolfSSL_tls_export),
#endif
TEST_DECL(test_wolfSSL_dtls_export_peers),
TEST_DECL(test_wolfSSL_dtls_import_state_extra_window_words),
TEST_DECL(test_wolfSSL_SetMinVersion),
TEST_DECL(test_wolfSSL_CTX_SetMinVersion),
@@ -32848,12 +33138,14 @@ TEST_CASE testCases[] = {
#ifdef HAVE_ALPN_PROTOS_SUPPORT
/* Uses Assert in handshake callback. */
TEST_DECL(test_wolfSSL_set_alpn_protos),
TEST_DECL(test_wolfSSL_select_next_proto),
#endif
TEST_DECL(test_tls_ems_downgrade),
TEST_DECL(test_wolfSSL_DisableExtendedMasterSecret),
TEST_DECL(test_certificate_authorities_certificate_request),
TEST_DECL(test_certificate_authorities_client_hello),
TEST_DECL(test_TLSX_TCA_Find),
TEST_DECL(test_TLSX_SNI_GetSize_overflow),
TEST_DECL(test_wolfSSL_wolfSSL_UseSecureRenegotiation),
TEST_DECL(test_wolfSSL_SCR_Reconnect),
TEST_DECL(test_wolfSSL_SCR_check_enabled),
+133
View File
@@ -24,6 +24,7 @@
#include <tests/api/test_asn.h>
#include <wolfssl/wolfcrypt/asn.h>
#include <wolfssl/wolfcrypt/rsa.h>
#if defined(WC_ENABLE_ASYM_KEY_EXPORT) && defined(HAVE_ED25519)
static int test_SetAsymKeyDer_once(byte* privKey, word32 privKeySz, byte* pubKey,
@@ -787,3 +788,135 @@ int test_wolfssl_local_MatchBaseName(void)
return EXPECT_RESULT();
}
/*
* Testing wc_DecodeRsaPssParams with known DER byte arrays.
* Exercises both WOLFSSL_ASN_TEMPLATE and non-template paths.
*/
int test_wc_DecodeRsaPssParams(void)
{
EXPECT_DECLS;
#if defined(WC_RSA_PSS) && !defined(NO_RSA) && !defined(NO_ASN)
enum wc_HashType hash;
int mgf;
int saltLen;
/* SHA-256 / MGF1-SHA-256 / saltLen=32 */
static const byte pssParamsSha256[] = {
0x30, 0x34,
0xA0, 0x0F,
0x30, 0x0D,
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
0x04, 0x02, 0x01,
0x05, 0x00,
0xA1, 0x1C,
0x30, 0x1A,
0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
0x01, 0x01, 0x08,
0x30, 0x0D,
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
0x04, 0x02, 0x01,
0x05, 0x00,
0xA2, 0x03,
0x02, 0x01, 0x20,
};
/* Hash-only: SHA-256 hash, defaults for MGF and salt */
static const byte pssParamsHashOnly[] = {
0x30, 0x11,
0xA0, 0x0F,
0x30, 0x0D,
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
0x04, 0x02, 0x01,
0x05, 0x00,
};
/* Salt-only: default hash/mgf, saltLen=48 */
static const byte pssParamsSaltOnly[] = {
0x30, 0x05,
0xA2, 0x03,
0x02, 0x01, 0x30,
};
/* NULL tag (05 00) means all defaults */
static const byte pssParamsNull[] = { 0x05, 0x00 };
/* Empty SEQUENCE means all non-default fields omitted => defaults */
static const byte pssParamsEmptySeq[] = { 0x30, 0x00 };
/* --- Test 1: sz=0 => all defaults --- */
hash = WC_HASH_TYPE_NONE;
mgf = 0;
saltLen = 0;
ExpectIntEQ(wc_DecodeRsaPssParams((const byte*)"", 0,
&hash, &mgf, &saltLen), 0);
ExpectIntEQ((int)hash, (int)WC_HASH_TYPE_SHA);
ExpectIntEQ(mgf, WC_MGF1SHA1);
ExpectIntEQ(saltLen, 20);
/* --- Test 2: NULL tag => all defaults --- */
hash = WC_HASH_TYPE_NONE;
mgf = 0;
saltLen = 0;
ExpectIntEQ(wc_DecodeRsaPssParams(pssParamsNull,
(word32)sizeof(pssParamsNull), &hash, &mgf, &saltLen), 0);
ExpectIntEQ((int)hash, (int)WC_HASH_TYPE_SHA);
ExpectIntEQ(mgf, WC_MGF1SHA1);
ExpectIntEQ(saltLen, 20);
/* --- Test 3: Empty SEQUENCE => all defaults --- */
hash = WC_HASH_TYPE_NONE;
mgf = 0;
saltLen = 0;
ExpectIntEQ(wc_DecodeRsaPssParams(pssParamsEmptySeq,
(word32)sizeof(pssParamsEmptySeq), &hash, &mgf, &saltLen), 0);
ExpectIntEQ((int)hash, (int)WC_HASH_TYPE_SHA);
ExpectIntEQ(mgf, WC_MGF1SHA1);
ExpectIntEQ(saltLen, 20);
#ifndef NO_SHA256
/* --- Test 4: SHA-256 / MGF1-SHA-256 / salt=32 --- */
hash = WC_HASH_TYPE_NONE;
mgf = 0;
saltLen = 0;
ExpectIntEQ(wc_DecodeRsaPssParams(pssParamsSha256,
(word32)sizeof(pssParamsSha256), &hash, &mgf, &saltLen), 0);
ExpectIntEQ((int)hash, (int)WC_HASH_TYPE_SHA256);
ExpectIntEQ(mgf, WC_MGF1SHA256);
ExpectIntEQ(saltLen, 32);
/* --- Test 5: Hash only => SHA-256, default MGF/salt --- */
hash = WC_HASH_TYPE_NONE;
mgf = 0;
saltLen = 0;
ExpectIntEQ(wc_DecodeRsaPssParams(pssParamsHashOnly,
(word32)sizeof(pssParamsHashOnly), &hash, &mgf, &saltLen), 0);
ExpectIntEQ((int)hash, (int)WC_HASH_TYPE_SHA256);
ExpectIntEQ(mgf, WC_MGF1SHA1);
ExpectIntEQ(saltLen, 20);
#endif
/* --- Test 6: Salt only => default hash/MGF, salt=48 --- */
hash = WC_HASH_TYPE_NONE;
mgf = 0;
saltLen = 0;
ExpectIntEQ(wc_DecodeRsaPssParams(pssParamsSaltOnly,
(word32)sizeof(pssParamsSaltOnly), &hash, &mgf, &saltLen), 0);
ExpectIntEQ((int)hash, (int)WC_HASH_TYPE_SHA);
ExpectIntEQ(mgf, WC_MGF1SHA1);
ExpectIntEQ(saltLen, 48);
/* --- Test 7: NULL pointer -> BAD_FUNC_ARG --- */
ExpectIntEQ(wc_DecodeRsaPssParams(NULL, 10, &hash, &mgf, &saltLen),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
/* --- Test 8: Bad leading tag => ASN_PARSE_E --- */
{
static const byte badTag[] = { 0x01, 0x00 };
ExpectIntEQ(wc_DecodeRsaPssParams(badTag, (word32)sizeof(badTag),
&hash, &mgf, &saltLen), WC_NO_ERR_TRACE(ASN_PARSE_E));
}
#endif /* WC_RSA_PSS && !NO_RSA && !NO_ASN */
return EXPECT_RESULT();
}
+3 -1
View File
@@ -28,11 +28,13 @@ int test_SetAsymKeyDer(void);
int test_GetSetShortInt(void);
int test_wc_IndexSequenceOf(void);
int test_wolfssl_local_MatchBaseName(void);
int test_wc_DecodeRsaPssParams(void);
#define TEST_ASN_DECLS \
TEST_DECL_GROUP("asn", test_SetAsymKeyDer), \
TEST_DECL_GROUP("asn", test_GetSetShortInt), \
TEST_DECL_GROUP("asn", test_wc_IndexSequenceOf), \
TEST_DECL_GROUP("asn", test_wolfssl_local_MatchBaseName)
TEST_DECL_GROUP("asn", test_wolfssl_local_MatchBaseName), \
TEST_DECL_GROUP("asn", test_wc_DecodeRsaPssParams)
#endif /* WOLFCRYPT_TEST_ASN_H */
+112
View File
@@ -1781,6 +1781,118 @@ int test_wolfSSL_CertManagerCRL(void)
return EXPECT_RESULT();
}
int test_wolfSSL_CRL_static_revoked_list(void)
{
EXPECT_DECLS;
#if defined(CRL_STATIC_REVOKED_LIST) && defined(HAVE_CRL) && \
!defined(NO_RSA) && !defined(NO_CERTS)
/* CRL signed by certs/ca-cert.pem that revokes serials 05, 02, 01 in that
* (unsorted) wire order. The unsorted order exposes a binary search bug in
* FindRevokedSerial when CRL_STATIC_REVOKED_LIST is enabled: the revoked
* cert array is never sorted after parsing, so binary search misses entries
* that are out of order.
*
* Generated with Python cryptography library:
* builder.add_revoked_certificate(serial=5)
* builder.add_revoked_certificate(serial=2)
* builder.add_revoked_certificate(serial=1)
* crl = builder.sign(ca_key, hashes.SHA256())
*/
static const unsigned char crl_multi_revoked[] = {
0x30, 0x82, 0x02, 0x1D, 0x30, 0x82, 0x01, 0x05,
0x02, 0x01, 0x01, 0x30, 0x0D, 0x06, 0x09, 0x2A,
0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
0x05, 0x00, 0x30, 0x81, 0x94, 0x31, 0x0B, 0x30,
0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03,
0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E,
0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E,
0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42,
0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x11,
0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C,
0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74,
0x68, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73,
0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x31, 0x18,
0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C,
0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D,
0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86,
0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16,
0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F,
0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F,
0x6D, 0x17, 0x0D, 0x32, 0x36, 0x30, 0x31, 0x30,
0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A,
0x17, 0x0D, 0x33, 0x36, 0x30, 0x31, 0x30, 0x31,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30,
0x3C, 0x30, 0x12, 0x02, 0x01, 0x05, 0x17, 0x0D,
0x32, 0x33, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x12, 0x02,
0x01, 0x02, 0x17, 0x0D, 0x32, 0x33, 0x30, 0x32,
0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x5A, 0x30, 0x12, 0x02, 0x01, 0x01, 0x17, 0x0D,
0x32, 0x33, 0x30, 0x33, 0x30, 0x31, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x0D, 0x06,
0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01,
0x00, 0x15, 0x9F, 0xC1, 0x9E, 0x17, 0xB3, 0x5A,
0xF1, 0x48, 0xA5, 0x87, 0x2A, 0x84, 0xD1, 0x93,
0x8D, 0x19, 0x24, 0xCB, 0xC5, 0x32, 0x56, 0x10,
0x6C, 0x4D, 0xF5, 0xD1, 0x9A, 0xC0, 0x1A, 0x8B,
0x1C, 0x84, 0x6B, 0x4B, 0x20, 0xA7, 0xA4, 0x2C,
0x11, 0x5C, 0x23, 0xBD, 0x0C, 0xB1, 0x33, 0xBE,
0x38, 0x1B, 0xCB, 0xDB, 0x8E, 0xD4, 0x0F, 0x62,
0x0D, 0xB5, 0x18, 0x21, 0x28, 0x0B, 0x77, 0xB9,
0xB4, 0xA8, 0xE9, 0xA0, 0x25, 0x00, 0x83, 0xED,
0x64, 0x49, 0x8E, 0x52, 0xD9, 0x8D, 0xAF, 0xC2,
0x16, 0x3E, 0xD3, 0x93, 0x09, 0xB9, 0x18, 0xBB,
0x6C, 0x41, 0xDF, 0x59, 0x59, 0x53, 0x8C, 0x64,
0x8B, 0xD1, 0x9D, 0xBB, 0x92, 0x8F, 0xB2, 0x26,
0x27, 0x78, 0x41, 0xFB, 0xF8, 0xB1, 0x2F, 0x8F,
0xA1, 0x85, 0xB6, 0xC7, 0x8E, 0x42, 0x72, 0xEF,
0xF4, 0x3F, 0xC4, 0xAF, 0x40, 0x95, 0xCA, 0x94,
0xE5, 0x88, 0x89, 0x18, 0x32, 0x54, 0xC3, 0xC4,
0xBE, 0x7E, 0x48, 0x1B, 0x3D, 0xB3, 0x6C, 0x11,
0x54, 0x6F, 0x9E, 0xFE, 0x09, 0x5B, 0x72, 0x3F,
0xD7, 0xA0, 0x02, 0xFF, 0x43, 0x01, 0xFE, 0x23,
0xF8, 0x72, 0xCD, 0xA9, 0x76, 0x36, 0x31, 0x78,
0x21, 0xCB, 0x0E, 0xC2, 0x25, 0x8D, 0x0B, 0x4C,
0x2C, 0xAA, 0x6A, 0x80, 0x6E, 0xE2, 0x1E, 0xAC,
0x70, 0x5D, 0x4A, 0xAA, 0x56, 0x17, 0xF0, 0x2D,
0xA2, 0x2A, 0x4E, 0x2B, 0xC8, 0xC9, 0x87, 0x8E,
0x07, 0xEB, 0xD8, 0x36, 0x42, 0x39, 0xA0, 0xA4,
0xF6, 0x34, 0xC2, 0x5F, 0xE1, 0x21, 0x07, 0x50,
0x4B, 0x37, 0x15, 0x7D, 0xF9, 0x18, 0x54, 0x13,
0xC0, 0x1D, 0x0A, 0x27, 0x3A, 0x63, 0xD2, 0xC3,
0xD5, 0x57, 0x5E, 0x67, 0x56, 0x65, 0x9E, 0x2E,
0x4D, 0xB4, 0x96, 0x54, 0x7A, 0x3D, 0xFD, 0xF9,
0xCF, 0xCD, 0x10, 0x65, 0x05, 0x97, 0x53, 0x72,
0x12
};
WOLFSSL_CERT_MANAGER* cm = NULL;
/* Set up CertManager with the CA and CRL checking enabled */
ExpectNotNull(cm = wolfSSL_CertManagerNew());
ExpectIntEQ(wolfSSL_CertManagerLoadCA(cm, "./certs/ca-cert.pem", NULL),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECKALL),
WOLFSSL_SUCCESS);
/* Load the CRL that revokes serials {05, 02, 01} in unsorted wire order */
ExpectIntEQ(wolfSSL_CertManagerLoadCRLBuffer(cm, crl_multi_revoked,
sizeof(crl_multi_revoked), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS);
/* server-cert.pem has serial 01, which is in the CRL but at the last
* position in the unsorted array. Binary search on unsorted data misses
* it, so this assertion fails before the bug fix. */
ExpectIntEQ(wolfSSL_CertManagerCheckCRL(cm, server_cert_der_2048,
sizeof_server_cert_der_2048), WC_NO_ERR_TRACE(CRL_CERT_REVOKED));
wolfSSL_CertManagerFree(cm);
#endif
return EXPECT_RESULT();
}
int test_wolfSSL_CRL_duplicate_extensions(void)
{
EXPECT_DECLS;
+2
View File
@@ -36,6 +36,7 @@ int test_wolfSSL_CertManagerNameConstraint3(void);
int test_wolfSSL_CertManagerNameConstraint4(void);
int test_wolfSSL_CertManagerNameConstraint5(void);
int test_wolfSSL_CertManagerCRL(void);
int test_wolfSSL_CRL_static_revoked_list(void);
int test_wolfSSL_CRL_duplicate_extensions(void);
int test_wolfSSL_CertManagerCheckOCSPResponse(void);
int test_various_pathlen_chains(void);
@@ -53,6 +54,7 @@ int test_various_pathlen_chains(void);
TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerNameConstraint4), \
TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerNameConstraint5), \
TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerCRL), \
TEST_DECL_GROUP("certman", test_wolfSSL_CRL_static_revoked_list), \
TEST_DECL_GROUP("certman", test_wolfSSL_CRL_duplicate_extensions), \
TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerCheckOCSPResponse), \
TEST_DECL_GROUP("certman", test_various_pathlen_chains)
+14
View File
@@ -314,6 +314,7 @@ int test_wolfSSL_EC_POINT(void)
EC_POINT* set_point = NULL;
EC_POINT* get_point = NULL;
EC_POINT* infinity = NULL;
EC_POINT* dup_point = NULL;
BIGNUM* k = NULL;
BIGNUM* Gx = NULL;
BIGNUM* Gy = NULL;
@@ -507,6 +508,12 @@ int test_wolfSSL_EC_POINT(void)
ExpectIntEQ(EC_POINT_copy(new_point, NULL), 0);
ExpectIntEQ(EC_POINT_copy(new_point, set_point), 1);
/* Test duplicating */
ExpectNull(EC_POINT_dup(NULL, group));
ExpectNull(EC_POINT_dup(set_point, NULL));
ExpectNotNull(dup_point = EC_POINT_dup(set_point, group));
ExpectIntEQ(EC_POINT_cmp(group, dup_point, set_point, ctx), 0);
/* Test inverting */
ExpectIntEQ(EC_POINT_invert(NULL, NULL, ctx), 0);
ExpectIntEQ(EC_POINT_invert(NULL, new_point, ctx), 0);
@@ -526,6 +533,12 @@ int test_wolfSSL_EC_POINT(void)
ExpectIntEQ(EC_POINT_add(group, orig_point, orig_point, new_point,
NULL), 1);
ExpectIntEQ(EC_POINT_cmp(group, orig_point, set_point, NULL), 0);
/* dup_point equals set_point so let's test with that too */
ExpectIntEQ(EC_POINT_add(group, orig_point, dup_point, dup_point, NULL),
1);
ExpectIntEQ(EC_POINT_add(group, orig_point, orig_point, new_point,
NULL), 1);
ExpectIntEQ(EC_POINT_cmp(group, orig_point, set_point, NULL), 0);
EC_POINT_free(orig_point);
}
#endif
@@ -769,6 +782,7 @@ int test_wolfSSL_EC_POINT(void)
BN_free(k);
BN_free(set_point_bn);
EC_POINT_free(infinity);
EC_POINT_free(dup_point);
EC_POINT_free(new_point);
EC_POINT_free(set_point);
EC_POINT_clear_free(Gxy);
+92
View File
@@ -947,6 +947,98 @@ int test_wc_PKCS7_EncodeSignedData(void)
} /* END test_wc_PKCS7_EncodeSignedData */
/*
* Testing wc_PKCS7_EncodeSignedData() with RSA-PSS signer certificate.
* Uses certs/rsapss/client-rsapss.der and client-rsapss-priv.der.
* Requires both encode and round-trip verify to succeed.
*/
#if defined(HAVE_PKCS7) && defined(WC_RSA_PSS) && !defined(NO_RSA) && \
!defined(NO_FILESYSTEM) && !defined(NO_SHA256)
int test_wc_PKCS7_EncodeSignedData_RSA_PSS(void)
{
EXPECT_DECLS;
PKCS7* pkcs7 = NULL;
WC_RNG rng;
byte output[FOURK_BUF];
byte cert[FOURK_BUF];
byte key[FOURK_BUF];
word32 outputSz = (word32)sizeof(output);
word32 certSz = 0;
word32 keySz = 0;
XFILE fp = XBADFILE;
byte data[] = "Test data for RSA-PSS SignedData.";
XMEMSET(&rng, 0, sizeof(WC_RNG));
XMEMSET(output, 0, outputSz);
XMEMSET(cert, 0, sizeof(cert));
XMEMSET(key, 0, sizeof(key));
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
ExpectTrue((fp = XFOPEN("./certs/rsapss/client-rsapss.der", "rb")) != XBADFILE);
if (fp != XBADFILE) {
ExpectIntGT(certSz = (word32)XFREAD(cert, 1, sizeof(cert), fp), 0);
XFCLOSE(fp);
fp = XBADFILE;
}
ExpectTrue((fp = XFOPEN("./certs/rsapss/client-rsapss-priv.der", "rb")) != XBADFILE);
if (fp != XBADFILE) {
ExpectIntGT(keySz = (word32)XFREAD(key, 1, sizeof(key), fp), 0);
XFCLOSE(fp);
fp = XBADFILE;
}
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0);
if (pkcs7 != NULL) {
/* Force RSA-PSS so SignerInfo uses id-RSASSA-PSS (cert may use RSA
* in subjectPublicKeyInfo). WC_RSA_PSS is guaranteed by outer guard. */
pkcs7->publicKeyOID = RSAPSSk;
pkcs7->content = data;
pkcs7->contentSz = (word32)sizeof(data);
pkcs7->contentOID = DATA;
pkcs7->hashOID = SHA256h;
pkcs7->encryptOID = RSAk;
pkcs7->privateKey = key;
pkcs7->privateKeySz = keySz;
pkcs7->rng = &rng;
pkcs7->signedAttribs = NULL;
pkcs7->signedAttribsSz = 0;
}
/* EncodeSignedData with RSA-PSS cert: require encode and verify success */
{
int outLen = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz);
ExpectIntGT(outLen, 0);
if (outLen > 0) {
int verifyRet = wc_PKCS7_VerifySignedData(pkcs7, output,
(word32)outLen);
ExpectIntEQ(verifyRet, 0);
if (pkcs7 != NULL) {
/* Verify decoded RSASSA-PSS parameters match what we
* encoded:
* hashAlgorithm = SHA-256
* maskGenAlgorithm = MGF1-SHA-256
* saltLength = 32 (== SHA-256 digest length) */
ExpectIntEQ(pkcs7->pssHashType, (int)WC_HASH_TYPE_SHA256);
ExpectIntEQ(pkcs7->pssMgf, WC_MGF1SHA256);
ExpectIntEQ(pkcs7->pssSaltLen, 32);
}
}
}
wc_PKCS7_Free(pkcs7);
DoExpectIntEQ(wc_FreeRng(&rng), 0);
return EXPECT_RESULT();
} /* END test_wc_PKCS7_EncodeSignedData_RSA_PSS */
#endif
/*
* Testing wc_PKCS7_EncodeSignedData_ex() and wc_PKCS7_VerifySignedData_ex()
*/
+13
View File
@@ -29,6 +29,10 @@ int test_wc_PKCS7_Init(void);
int test_wc_PKCS7_InitWithCert(void);
int test_wc_PKCS7_EncodeData(void);
int test_wc_PKCS7_EncodeSignedData(void);
#if defined(HAVE_PKCS7) && defined(WC_RSA_PSS) && !defined(NO_RSA) && \
!defined(NO_FILESYSTEM) && !defined(NO_SHA256)
int test_wc_PKCS7_EncodeSignedData_RSA_PSS(void);
#endif
int test_wc_PKCS7_EncodeSignedData_ex(void);
int test_wc_PKCS7_VerifySignedData_RSA(void);
int test_wc_PKCS7_VerifySignedData_ECC(void);
@@ -55,10 +59,19 @@ int test_wc_PKCS7_VerifySignedData_PKCS7ContentSeq(void);
TEST_DECL_GROUP("pkcs7", test_wc_PKCS7_New), \
TEST_DECL_GROUP("pkcs7", test_wc_PKCS7_Init)
#if defined(HAVE_PKCS7) && defined(WC_RSA_PSS) && !defined(NO_RSA) && \
!defined(NO_FILESYSTEM) && !defined(NO_SHA256)
#define TEST_PKCS7_RSA_PSS_SD_DECL \
TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_EncodeSignedData_RSA_PSS),
#else
#define TEST_PKCS7_RSA_PSS_SD_DECL
#endif
#define TEST_PKCS7_SIGNED_DATA_DECLS \
TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_InitWithCert), \
TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_EncodeData), \
TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_EncodeSignedData), \
TEST_PKCS7_RSA_PSS_SD_DECL \
TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_EncodeSignedData_ex), \
TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_VerifySignedData_RSA), \
TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_VerifySignedData_ECC), \
+86
View File
@@ -3100,3 +3100,89 @@ int test_tls13_plaintext_alert(void)
return EXPECT_RESULT();
}
/* Test that wolfSSL_set1_sigalgs_list() is honored in TLS 1.3
*/
int test_tls13_cert_req_sigalgs(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_TLS13) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
!defined(NO_CERTS) && !defined(NO_RSA) && defined(WC_RSA_PSS) && \
defined(HAVE_ECC) && !defined(NO_WOLFSSL_CLIENT) && \
!defined(NO_WOLFSSL_SERVER) && defined(OPENSSL_EXTRA) && \
!defined(NO_FILESYSTEM)
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
/* Server: require client cert and load ECC client cert for verification */
if (EXPECT_SUCCESS()) {
wolfSSL_set_verify(ssl_s,
WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_s,
cliEccCertFile, 0), WOLFSSL_SUCCESS);
}
/* Server: restrict CertificateRequest to RSA-PSS+SHA256 only */
if (EXPECT_SUCCESS()) {
ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl_s, "RSA-PSS+SHA256"),
WOLFSSL_SUCCESS);
}
/* Client: load ECC cert/key */
if (EXPECT_SUCCESS()) {
ExpectIntEQ(wolfSSL_use_certificate_file(ssl_c, cliEccCertFile,
CERT_FILETYPE), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_use_PrivateKey_file(ssl_c, cliEccKeyFile,
CERT_FILETYPE), WOLFSSL_SUCCESS);
}
/* Handshake must fail: ECC client cannot match RSA-PSS+SHA256 */
ExpectIntNE(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
wolfSSL_free(ssl_c); ssl_c = NULL;
wolfSSL_free(ssl_s); ssl_s = NULL;
wolfSSL_CTX_free(ctx_c); ctx_c = NULL;
wolfSSL_CTX_free(ctx_s); ctx_s = NULL;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
/* Server: require client cert and load RSA client cert for verification */
if (EXPECT_SUCCESS()) {
wolfSSL_set_verify(ssl_s,
WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_s,
cliCertFile, 0), WOLFSSL_SUCCESS);
}
/* Server: restrict CertificateRequest to RSA-PSS+SHA256 only */
if (EXPECT_SUCCESS()) {
ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl_s, "RSA-PSS+SHA256"),
WOLFSSL_SUCCESS);
}
/* Client: load RSA cert/key */
if (EXPECT_SUCCESS()) {
ExpectIntEQ(wolfSSL_use_certificate_file(ssl_c, cliCertFile,
CERT_FILETYPE), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_use_PrivateKey_file(ssl_c, cliKeyFile,
CERT_FILETYPE), WOLFSSL_SUCCESS);
}
/* Handshake must succeed: RSA client satisfies RSA-PSS+SHA256 */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
wolfSSL_free(ssl_c); ssl_c = NULL;
wolfSSL_free(ssl_s); ssl_s = NULL;
wolfSSL_CTX_free(ctx_c); ctx_c = NULL;
wolfSSL_CTX_free(ctx_s); ctx_s = NULL;
#endif
return EXPECT_RESULT();
}
+3 -1
View File
@@ -38,6 +38,7 @@ int test_tls13_duplicate_extension(void);
int test_key_share_mismatch(void);
int test_tls13_middlebox_compat_empty_session_id(void);
int test_tls13_plaintext_alert(void);
int test_tls13_cert_req_sigalgs(void);
#define TEST_TLS13_DECLS \
TEST_DECL_GROUP("tls13", test_tls13_apis), \
@@ -53,6 +54,7 @@ int test_tls13_plaintext_alert(void);
TEST_DECL_GROUP("tls13", test_tls13_duplicate_extension), \
TEST_DECL_GROUP("tls13", test_key_share_mismatch), \
TEST_DECL_GROUP("tls13", test_tls13_middlebox_compat_empty_session_id), \
TEST_DECL_GROUP("tls13", test_tls13_plaintext_alert)
TEST_DECL_GROUP("tls13", test_tls13_plaintext_alert), \
TEST_DECL_GROUP("tls13", test_tls13_cert_req_sigalgs)
#endif /* WOLFCRYPT_TEST_TLS13_H */
+64
View File
@@ -545,3 +545,67 @@ int test_certificate_authorities_client_hello(void) {
#endif
return EXPECT_RESULT();
}
/* Test that the SNI size calculation returns 0 on overflow instead of
* wrapping around to a small value (integer overflow vulnerability). */
int test_TLSX_SNI_GetSize_overflow(void)
{
EXPECT_DECLS;
#if defined(HAVE_SNI) && !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS)
WOLFSSL_CTX* ctx = NULL;
WOLFSSL* ssl = NULL;
TLSX* sni_ext = NULL;
SNI* head = NULL;
SNI* sni = NULL;
int i;
/* Each SNI adds ENUM_LEN(1) + OPAQUE16_LEN(2) + hostname_len to the size.
* With a 1-byte hostname, each entry adds 4 bytes. Starting from
* OPAQUE16_LEN(2) base, we need enough entries to exceed UINT16_MAX. */
const int num_sni = (0xFFFF / 4) + 2;
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
ExpectNotNull(ssl = wolfSSL_new(ctx));
/* Add initial SNI via public API */
ExpectIntEQ(WOLFSSL_SUCCESS,
wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, "a", 1));
/* Find the SNI extension and manually build a long chain */
if (EXPECT_SUCCESS()) {
sni_ext = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME);
ExpectNotNull(sni_ext);
}
if (EXPECT_SUCCESS()) {
head = (SNI*)sni_ext->data;
ExpectNotNull(head);
}
/* Append many SNI nodes to force overflow in the size calculation */
for (i = 1; EXPECT_SUCCESS() && i < num_sni; i++) {
sni = (SNI*)XMALLOC(sizeof(SNI), NULL, DYNAMIC_TYPE_TLSX);
ExpectNotNull(sni);
if (sni != NULL) {
XMEMSET(sni, 0, sizeof(SNI));
sni->type = WOLFSSL_SNI_HOST_NAME;
sni->data.host_name = (char*)XMALLOC(2, NULL, DYNAMIC_TYPE_TLSX);
ExpectNotNull(sni->data.host_name);
if (sni->data.host_name != NULL) {
sni->data.host_name[0] = 'a';
sni->data.host_name[1] = '\0';
}
sni->next = head->next;
head->next = sni;
}
}
if (EXPECT_SUCCESS()) {
/* The fixed calculation should return 0 (overflow detected) */
ExpectIntEQ(TLSX_SNI_GetSize((SNI*)sni_ext->data), 0);
}
wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);
#endif
return EXPECT_RESULT();
}
+1
View File
@@ -27,5 +27,6 @@ int test_wolfSSL_DisableExtendedMasterSecret(void);
int test_certificate_authorities_certificate_request(void);
int test_certificate_authorities_client_hello(void);
int test_TLSX_TCA_Find(void);
int test_TLSX_SNI_GetSize_overflow(void);
#endif /* TESTS_API_TEST_TLS_EMS_H */
+4 -4
View File
@@ -909,6 +909,10 @@ int SuiteTest(int argc, char** argv)
char argv0[3][80];
char* myArgv[3];
#ifdef WOLFSSL_STATIC_MEMORY
byte memory[200000];
#endif
printf(" Begin Cipher Suite Tests\n");
/* setup */
@@ -918,10 +922,6 @@ int SuiteTest(int argc, char** argv)
args.argv = myArgv;
XSTRLCPY(argv0[0], "SuiteTest", sizeof(argv0[0]));
#ifdef WOLFSSL_STATIC_MEMORY
byte memory[200000];
#endif
cipherSuiteCtx = wolfSSL_CTX_new(wolfSSLv23_client_method());
if (cipherSuiteCtx == NULL) {
printf("can't get cipher suite ctx\n");
-11
View File
@@ -202,14 +202,3 @@
-v 3
-l ECDHE-RSA-AES256-GCM-SHA384
-F 6
# server DTLSv1.2 DHE-RSA-AES256-GCM-SHA384
-u
-v 3
-l DHE-RSA-AES256-GCM-SHA384
# client DTLSv1.2 DHE-RSA-AES256-GCM-SHA384
-u
-v 3
-l DHE-RSA-AES256-GCM-SHA384
-F 6
-9
View File
@@ -169,15 +169,6 @@
-l ECDHE-RSA-AES256-GCM-SHA384
-F 6
# server TLSv1.2 DHE-RSA-AES256-GCM-SHA384
-v 3
-l DHE-RSA-AES256-GCM-SHA384
# client TLSv1.2 DHE-RSA-AES256-GCM-SHA384
-v 3
-l DHE-RSA-AES256-GCM-SHA384
-F 6
# server TLSv1.2 DHE-RSA-AES256-GCM-SHA384
-v 3
-l DHE-RSA-AES256-GCM-SHA384
+267 -51
View File
@@ -70,9 +70,9 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits
#include <wolfssl/wolfcrypt/port/nxp/se050_port.h>
#endif
#if defined(WOLFSSL_AES_SIV)
#ifdef WOLFSSL_CMAC
#include <wolfssl/wolfcrypt/cmac.h>
#endif /* WOLFSSL_AES_SIV */
#endif
#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES)
#include <wolfssl/wolfcrypt/port/psa/psa.h>
@@ -91,6 +91,11 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits
#if defined(WOLFSSL_TI_CRYPT)
#include <wolfcrypt/src/port/ti/ti-aes.c>
#define AesEncrypt_preFetchOpt(aes, inBlock, outBlock, do_preFetch) \
wc_AesEncryptDirect(aes, outBlock, inBlock)
#define AesDecrypt_preFetchOpt(aes, inBlock, outBlock, do_preFetch) \
wc_AesDecryptDirect(aes, outBlock, inBlock)
#else
@@ -2142,8 +2147,12 @@ static word32 GetTable8_4(const byte* t, byte o0, byte o1, byte o2, byte o3)
* @param [out] outBlock Encrypted block.
* @param [in] r Rounds divided by 2.
*/
#define WC_AES_HAVE_PREFETCH_ARG
static int always_prefetch = 0;
WC_MAYBE_UNUSED static int never_prefetch = 1;
WC_ARGS_NOT_NULL((1, 2, 3, 5))
static void AesEncrypt_C(Aes* aes, const byte* inBlock, byte* outBlock,
word32 r)
word32 r, int *prefetch_ptr)
{
word32 s0 = 0, s1 = 0, s2 = 0, s3 = 0;
word32 t0 = 0, t1 = 0, t2 = 0, t3 = 0;
@@ -2178,8 +2187,15 @@ static void AesEncrypt_C(Aes* aes, const byte* inBlock, byte* outBlock,
s3 ^= rk[3];
#ifndef WOLFSSL_AES_SMALL_TABLES
#ifndef WC_NO_CACHE_RESISTANT
s0 |= PreFetchTe();
if (*prefetch_ptr == 0) {
s0 |= PreFetchTe();
if (prefetch_ptr != &always_prefetch)
*prefetch_ptr = 1;
}
#else
(void)prefetch_ptr;
#endif
#ifndef WOLFSSL_AES_TOUCH_LINES
@@ -2320,9 +2336,17 @@ static void AesEncrypt_C(Aes* aes, const byte* inBlock, byte* outBlock,
s2 ^= u2 & 0x000000ff; s3 ^= u3 & 0x000000ff;
}
#endif
#else
#else /* WOLFSSL_AES_SMALL_TABLES */
#ifndef WC_NO_CACHE_RESISTANT
s0 |= PreFetchSBox();
if (*prefetch_ptr == 0) {
s0 |= PreFetchSBox();
if (prefetch_ptr != &always_prefetch)
*prefetch_ptr = 1;
}
#else
(void)prefetch_ptr;
#endif
r *= 2;
@@ -2399,7 +2423,8 @@ static void AesEncrypt_C(Aes* aes, const byte* inBlock, byte* outBlock,
s1 = t1 ^ rk[1];
s2 = t2 ^ rk[2];
s3 = t3 ^ rk[3];
#endif
#endif /* WOLFSSL_AES_SMALL_TABLES */
/* write out */
#ifdef LITTLE_ENDIAN_ORDER
@@ -2429,9 +2454,10 @@ static void AesEncrypt_C(Aes* aes, const byte* inBlock, byte* outBlock,
static void AesEncryptBlocks_C(Aes* aes, const byte* in, byte* out, word32 sz)
{
word32 i;
int did_prefetches = 0;
for (i = 0; i < sz; i += WC_AES_BLOCK_SIZE) {
AesEncrypt_C(aes, in, out, aes->rounds >> 1);
AesEncrypt_C(aes, in, out, aes->rounds >> 1, &did_prefetches);
in += WC_AES_BLOCK_SIZE;
out += WC_AES_BLOCK_SIZE;
}
@@ -2998,10 +3024,18 @@ extern void AesEncryptBlocks_C(Aes* aes, const byte* in, byte* out, word32 sz);
#endif /* !WC_AES_BITSLICED */
/* this section disabled with NO_AES_192 */
/* calling this one when missing NO_AES_192 */
#ifdef WC_AES_HAVE_PREFETCH_ARG
#define wc_AesEncrypt(aes, inBlock, outBlock) \
AesEncrypt_preFetchOpt(aes, inBlock, outBlock, &always_prefetch)
WC_ALL_ARGS_NOT_NULL static WARN_UNUSED_RESULT int AesEncrypt_preFetchOpt(
Aes* aes, const byte* inBlock, byte* outBlock, int *prefetch_ptr)
#else
#define AesEncrypt_preFetchOpt(aes, inBlock, outBlock, prefetch_ptr) \
wc_AesEncrypt(aes, inBlock, outBlock)
static WARN_UNUSED_RESULT int wc_AesEncrypt(
Aes* aes, const byte* inBlock, byte* outBlock)
WC_ALL_ARGS_NOT_NULL
#endif
{
#if defined(MAX3266X_AES)
word32 keySize;
@@ -3153,7 +3187,11 @@ static WARN_UNUSED_RESULT int wc_AesEncrypt(
}
#endif
#ifdef WC_AES_HAVE_PREFETCH_ARG
AesEncrypt_C(aes, inBlock, outBlock, r, prefetch_ptr);
#else
AesEncrypt_C(aes, inBlock, outBlock, r);
#endif
return 0;
} /* wc_AesEncrypt */
@@ -3211,8 +3249,14 @@ static WARN_UNUSED_RESULT WC_INLINE word32 PreFetchTd4(void)
* @param [out] outBlock Encrypted block.
* @param [in] r Rounds divided by 2.
*/
#ifndef WC_AES_HAVE_PREFETCH_ARG
#define WC_AES_HAVE_PREFETCH_ARG
static int always_prefetch = 0;
WC_MAYBE_UNUSED static int never_prefetch = 1;
#endif
WC_ARGS_NOT_NULL((1, 2, 3, 5))
static void AesDecrypt_C(Aes* aes, const byte* inBlock, byte* outBlock,
word32 r)
word32 r, int *prefetch_ptr)
{
word32 s0 = 0, s1 = 0, s2 = 0, s3 = 0;
word32 t0 = 0, t1 = 0, t2 = 0, t3 = 0;
@@ -3246,8 +3290,16 @@ static void AesDecrypt_C(Aes* aes, const byte* inBlock, byte* outBlock,
s3 ^= rk[3];
#ifndef WOLFSSL_AES_SMALL_TABLES
#ifndef WC_NO_CACHE_RESISTANT
s0 |= PreFetchTd();
if (*prefetch_ptr == 0) {
s0 |= PreFetchTd();
/* don't set the prefetched flag here -- PreFetchTd4() is called
* below.
*/
}
#else
(void)prefetch_ptr;
#endif
#ifndef WOLFSSL_AES_TOUCH_LINES
@@ -3330,7 +3382,13 @@ static void AesDecrypt_C(Aes* aes, const byte* inBlock, byte* outBlock,
*/
#ifndef WC_NO_CACHE_RESISTANT
t0 |= PreFetchTd4();
if (*prefetch_ptr == 0) {
t0 |= PreFetchTd4();
if (prefetch_ptr != &always_prefetch)
*prefetch_ptr = 1;
}
#else
(void)prefetch_ptr;
#endif
s0 = GetTable8_4(Td4, GETBYTE(t0, 3), GETBYTE(t3, 2),
@@ -3341,9 +3399,17 @@ static void AesDecrypt_C(Aes* aes, const byte* inBlock, byte* outBlock,
GETBYTE(t0, 1), GETBYTE(t3, 0)) ^ rk[2];
s3 = GetTable8_4(Td4, GETBYTE(t3, 3), GETBYTE(t2, 2),
GETBYTE(t1, 1), GETBYTE(t0, 0)) ^ rk[3];
#else
#else /* WOLFSSL_AES_SMALL_TABLES */
#ifndef WC_NO_CACHE_RESISTANT
s0 |= PreFetchTd4();
if (*prefetch_ptr == 0) {
s0 |= PreFetchTd4();
if (prefetch_ptr != &always_prefetch)
*prefetch_ptr = 1;
}
#else
(void)prefetch_ptr;
#endif
r *= 2;
@@ -3419,7 +3485,8 @@ static void AesDecrypt_C(Aes* aes, const byte* inBlock, byte* outBlock,
s1 = t1 ^ rk[1];
s2 = t2 ^ rk[2];
s3 = t3 ^ rk[3];
#endif
#endif /* WOLFSSL_AES_SMALL_TABLES */
/* write out */
#ifdef LITTLE_ENDIAN_ORDER
@@ -3450,9 +3517,10 @@ static void AesDecrypt_C(Aes* aes, const byte* inBlock, byte* outBlock,
static void AesDecryptBlocks_C(Aes* aes, const byte* in, byte* out, word32 sz)
{
word32 i;
int did_prefetches = 0;
for (i = 0; i < sz; i += WC_AES_BLOCK_SIZE) {
AesDecrypt_C(aes, in, out, aes->rounds >> 1);
AesDecrypt_C(aes, in, out, aes->rounds >> 1, &did_prefetches);
in += WC_AES_BLOCK_SIZE;
out += WC_AES_BLOCK_SIZE;
}
@@ -3808,8 +3876,18 @@ static void AesDecryptBlocks_C(Aes* aes, const byte* in, byte* out, word32 sz)
#if defined(__aarch64__) || !defined(WOLFSSL_ARMASM)
#if !defined(WC_AES_BITSLICED) || defined(WOLFSSL_AES_DIRECT)
/* Software AES - ECB Decrypt */
static WARN_UNUSED_RESULT int wc_AesDecrypt(
#ifdef WC_AES_HAVE_PREFETCH_ARG
#define wc_AesDecrypt(aes, inBlock, outBlock) \
AesDecrypt_preFetchOpt(aes, inBlock, outBlock, &always_prefetch)
WC_ALL_ARGS_NOT_NULL static WARN_UNUSED_RESULT int AesDecrypt_preFetchOpt(
Aes* aes, const byte* inBlock, byte* outBlock, int *prefetch_ptr)
#else
#define AesDecrypt_preFetchOpt(aes, inBlock, outBlock, prefetch_ptr) \
wc_AesDecrypt(aes, inBlock, outBlock)
WC_ALL_ARGS_NOT_NULL static WARN_UNUSED_RESULT int wc_AesDecrypt(
Aes* aes, const byte* inBlock, byte* outBlock)
#endif
{
#if defined(MAX3266X_AES)
word32 keySize;
@@ -3935,7 +4013,11 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(
}
#endif
#ifdef WC_AES_HAVE_PREFETCH_ARG
AesDecrypt_C(aes, inBlock, outBlock, r, prefetch_ptr);
#else
AesDecrypt_C(aes, inBlock, outBlock, r);
#endif
return 0;
} /* wc_AesDecrypt[_SW]() */
@@ -3946,7 +4028,16 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(
#endif /* NEED_AES_TABLES */
#ifndef WC_AES_HAVE_PREFETCH_ARG
#ifndef AesEncrypt_preFetchOpt
#define AesEncrypt_preFetchOpt(aes, inBlock, outBlock, do_preFetch) \
wc_AesEncrypt(aes, inBlock, outBlock)
#endif
#ifndef AesDecrypt_preFetchOpt
#define AesDecrypt_preFetchOpt(aes, inBlock, outBlock, do_preFetch) \
wc_AesDecrypt(aes, inBlock, outBlock)
#endif
#endif
/* wc_AesSetKey */
#if defined(STM32_CRYPTO)
@@ -5335,6 +5426,7 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
#else
/* Allow direct access to one block encrypt */
/* Note, the in and out args are swapped compared to wc_AesEncrypt(). */
int wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
{
int ret;
@@ -5355,6 +5447,7 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
#ifdef HAVE_AES_DECRYPT
/* Allow direct access to one block decrypt */
/* Note, the in and out args are swapped compared to wc_AesDecrypt(). */
int wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
{
int ret;
@@ -6097,7 +6190,6 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
offset += WC_AES_BLOCK_SIZE;
}
return 0;
}
#endif /* HAVE_AES_DECRYPT */
@@ -6471,10 +6563,15 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
else
#endif
{
#ifdef WC_AES_HAVE_PREFETCH_ARG
int did_prefetches = 0;
#endif
ret = 0;
while (blocks--) {
xorbuf((byte*)aes->reg, in, WC_AES_BLOCK_SIZE);
ret = wc_AesEncrypt(aes, (byte*)aes->reg, (byte*)aes->reg);
ret = AesEncrypt_preFetchOpt(aes, (byte*)aes->reg,
(byte*)aes->reg,
&did_prefetches);
if (ret != 0)
break;
XMEMCPY(out, aes->reg, WC_AES_BLOCK_SIZE);
@@ -6713,9 +6810,13 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
}
}
#else
#ifdef WC_AES_HAVE_PREFETCH_ARG
{
int did_prefetches = 0;
#endif
while (blocks--) {
XMEMCPY(aes->tmp, in, WC_AES_BLOCK_SIZE);
ret = wc_AesDecrypt(aes, in, out);
ret = AesDecrypt_preFetchOpt(aes, in, out, &did_prefetches);
if (ret != 0)
return ret;
xorbuf(out, (byte*)aes->reg, WC_AES_BLOCK_SIZE);
@@ -6725,6 +6826,9 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
out += WC_AES_BLOCK_SIZE;
in += WC_AES_BLOCK_SIZE;
}
#ifdef WC_AES_HAVE_PREFETCH_ARG
}
#endif
#endif
}
@@ -6967,6 +7071,9 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
int ret = 0;
#endif
word32 processed;
#ifdef WC_AES_HAVE_PREFETCH_ARG
int did_prefetches = 0;
#endif
#if !(!defined(__aarch64__) && defined(WOLFSSL_ARMASM) && \
!defined(WOLFSSL_ARMASM_NO_HW_CRYPTO))
@@ -7118,7 +7225,9 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
#ifdef XTRANSFORM_AESCTRBLOCK
XTRANSFORM_AESCTRBLOCK(aes, out, in);
#else
ret = wc_AesEncrypt(aes, (byte*)aes->reg, scratch);
ret = AesEncrypt_preFetchOpt(aes, (byte*)aes->reg,
scratch,
&did_prefetches);
if (ret != 0)
break;
xorbuf(scratch, in, WC_AES_BLOCK_SIZE);
@@ -7136,7 +7245,9 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
/* handle non block size remaining and store unused byte count in left */
if ((ret == 0) && sz) {
ret = wc_AesEncrypt(aes, (byte*)aes->reg, (byte*)aes->tmp);
ret = AesEncrypt_preFetchOpt(aes, (byte*)aes->reg,
(byte*)aes->tmp,
&did_prefetches);
if (ret == 0) {
IncrementAesCounter((byte*)aes->reg);
aes->left = WC_AES_BLOCK_SIZE - sz;
@@ -7173,8 +7284,26 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
#endif /* NEED_AES_CTR_SOFT */
#endif /* WOLFSSL_AES_COUNTER */
#endif /* !WOLFSSL_RISCV_ASM */
#ifndef WC_AES_HAVE_PREFETCH_ARG
#ifndef AesEncrypt_preFetchOpt
#define AesEncrypt_preFetchOpt(aes, inBlock, outBlock, do_preFetch) \
wc_AesEncrypt(aes, inBlock, outBlock)
#endif
#ifndef AesDecrypt_preFetchOpt
#define AesDecrypt_preFetchOpt(aes, inBlock, outBlock, do_preFetch) \
wc_AesDecrypt(aes, inBlock, outBlock)
#endif
#endif
#else /* WOLFSSL_RISCV_ASM */
#define AesEncrypt_preFetchOpt(aes, inBlock, outBlock, do_preFetch) \
wc_AesEncryptDirect(aes, outBlock, inBlock)
#define AesDecrypt_preFetchOpt(aes, inBlock, outBlock, do_preFetch) \
wc_AesDecryptDirect(aes, outBlock, inBlock)
#endif /* WOLFSSL_RISCV_ASM */
/*
* The IV for AES GCM and CCM, stored in struct Aes's member reg, is comprised
@@ -9616,6 +9745,9 @@ WARN_UNUSED_RESULT int AES_GCM_encrypt_C(
ALIGN16 byte counter[WC_AES_BLOCK_SIZE];
ALIGN16 byte initialCounter[WC_AES_BLOCK_SIZE];
ALIGN16 byte scratch[WC_AES_BLOCK_SIZE];
#ifdef WC_AES_HAVE_PREFETCH_ARG
int did_prefetches = 0;
#endif
if (ivSz == GCM_NONCE_MID_SZ) {
/* Counter is IV with bottom 4 bytes set to: 0x00,0x00,0x00,0x01. */
@@ -9674,7 +9806,8 @@ WARN_UNUSED_RESULT int AES_GCM_encrypt_C(
while (blocks--) {
IncrementGcmCounter(counter);
#if !defined(WOLFSSL_PIC32MZ_CRYPT)
ret = wc_AesEncrypt(aes, counter, scratch);
ret = AesEncrypt_preFetchOpt(aes, counter, scratch,
&did_prefetches);
if (ret != 0)
return ret;
xorbufout(c, scratch, p, WC_AES_BLOCK_SIZE);
@@ -9686,14 +9819,15 @@ WARN_UNUSED_RESULT int AES_GCM_encrypt_C(
if (partial != 0) {
IncrementGcmCounter(counter);
ret = wc_AesEncrypt(aes, counter, scratch);
ret = AesEncrypt_preFetchOpt(aes, counter, scratch, &did_prefetches);
if (ret != 0)
return ret;
xorbufout(c, scratch, p, partial);
}
if (authTag) {
GHASH(&aes->gcm, authIn, authInSz, out, sz, authTag, authTagSz);
ret = wc_AesEncrypt(aes, initialCounter, scratch);
ret = AesEncrypt_preFetchOpt(aes, initialCounter, scratch,
&did_prefetches);
if (ret != 0)
return ret;
xorbuf(authTag, scratch, authTagSz);
@@ -12814,7 +12948,11 @@ static WARN_UNUSED_RESULT int roll_x(
in += WC_AES_BLOCK_SIZE;
inSz -= WC_AES_BLOCK_SIZE;
ret = wc_AesEncrypt(aes, out, out);
/* wc_AesCcmEncrypt(), wc_AesCcmDecrypt(), and roll_auth() only call
* roll_x() after the AES cache lines are already hot -- no need to
* absorb additional prefetch overhead here.
*/
ret = AesEncrypt_preFetchOpt(aes, out, out, &never_prefetch);
if (ret != 0)
return ret;
}
@@ -12822,7 +12960,11 @@ static WARN_UNUSED_RESULT int roll_x(
/* process remainder of the data */
if (inSz > 0) {
xorbuf(out, in, inSz);
ret = wc_AesEncrypt(aes, out, out);
/* wc_AesCcmEncrypt(), wc_AesCcmDecrypt(), and roll_auth() only call
* roll_x() after the AES cache lines are already hot -- no need to
* absorb additional prefetch overhead here.
*/
ret = AesEncrypt_preFetchOpt(aes, out, out, &never_prefetch);
if (ret != 0)
return ret;
}
@@ -12870,7 +13012,11 @@ static WARN_UNUSED_RESULT int roll_auth(
xorbuf(out + authLenSz, in, inSz);
inSz = 0;
}
ret = wc_AesEncrypt(aes, out, out);
/* wc_AesCcmEncrypt() and wc_AesCcmDecrypt() only call roll_auth() after the
* AES cache lines are already hot -- no need to absorb additional prefetch
* overhead here.
*/
ret = AesEncrypt_preFetchOpt(aes, out, out, &never_prefetch);
if ((ret == 0) && (inSz > 0)) {
ret = roll_x(aes, in, inSz, out);
@@ -12996,6 +13142,9 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
#endif
VECTOR_REGISTERS_PUSH;
/* note this wc_AesEncrypt() will perform cache prefetches if needed, so
* that the later encrypt ops don't need to.
*/
ret = wc_AesEncrypt(aes, B, A);
#ifdef WOLFSSL_CHECK_MEM_ZERO
if (ret == 0)
@@ -13014,7 +13163,7 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
B[0] = (byte)(lenSz - 1U);
for (i = 0; i < lenSz; i++)
B[WC_AES_BLOCK_SIZE - 1 - i] = 0;
ret = wc_AesEncrypt(aes, B, A);
ret = AesEncrypt_preFetchOpt(aes, B, A, &never_prefetch);
}
if (ret == 0) {
@@ -13042,7 +13191,7 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
#endif
if (ret == 0) {
while (inSz >= WC_AES_BLOCK_SIZE) {
ret = wc_AesEncrypt(aes, B, A);
ret = AesEncrypt_preFetchOpt(aes, B, A, &never_prefetch);
if (ret != 0)
break;
xorbuf(A, in, WC_AES_BLOCK_SIZE);
@@ -13055,7 +13204,7 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
}
}
if ((ret == 0) && (inSz > 0)) {
ret = wc_AesEncrypt(aes, B, A);
ret = AesEncrypt_preFetchOpt(aes, B, A, &never_prefetch);
}
if ((ret == 0) && (inSz > 0)) {
xorbuf(A, in, inSz);
@@ -13095,6 +13244,9 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
byte mask = 0xFF;
const word32 wordSz = (word32)sizeof(word32);
int ret = 0;
#ifdef WC_AES_HAVE_PREFETCH_ARG
int did_prefetches = 0;
#endif
/* sanity check on arguments */
if (aes == NULL || (inSz != 0 && (in == NULL || out == NULL)) ||
@@ -13165,7 +13317,7 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
#endif
while (oSz >= WC_AES_BLOCK_SIZE) {
ret = wc_AesEncrypt(aes, B, A);
ret = AesEncrypt_preFetchOpt(aes, B, A, &did_prefetches);
if (ret != 0)
break;
xorbuf(A, in, WC_AES_BLOCK_SIZE);
@@ -13177,14 +13329,14 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
}
if ((ret == 0) && (inSz > 0))
ret = wc_AesEncrypt(aes, B, A);
ret = AesEncrypt_preFetchOpt(aes, B, A, &did_prefetches);
if ((ret == 0) && (inSz > 0)) {
xorbuf(A, in, oSz);
XMEMCPY(o, A, oSz);
for (i = 0; i < lenSz; i++)
B[WC_AES_BLOCK_SIZE - 1 - i] = 0;
ret = wc_AesEncrypt(aes, B, A);
ret = AesEncrypt_preFetchOpt(aes, B, A, &did_prefetches);
}
if (ret == 0) {
@@ -13200,7 +13352,7 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
B[WC_AES_BLOCK_SIZE - 1 - i] = (byte)((inSz >> ((8 * i) & mask)) & mask);
}
ret = wc_AesEncrypt(aes, B, A);
ret = AesEncrypt_preFetchOpt(aes, B, A, &did_prefetches);
}
if (ret == 0) {
@@ -13214,7 +13366,7 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
B[0] = (byte)(lenSz - 1U);
for (i = 0; i < lenSz; i++)
B[WC_AES_BLOCK_SIZE - 1 - i] = 0;
ret = wc_AesEncrypt(aes, B, B);
ret = AesEncrypt_preFetchOpt(aes, B, B, &did_prefetches);
}
if (ret == 0)
@@ -13772,9 +13924,12 @@ static WARN_UNUSED_RESULT int _AesEcbEncrypt(
AesEncryptBlocks_C(aes, in, out, sz);
#else
word32 i;
#ifdef WC_AES_HAVE_PREFETCH_ARG
int did_prefetches = 0;
#endif
for (i = 0; i < sz; i += WC_AES_BLOCK_SIZE) {
ret = wc_AesEncryptDirect(aes, out, in);
ret = AesEncrypt_preFetchOpt(aes, in, out, &did_prefetches);
if (ret != 0)
break;
in += WC_AES_BLOCK_SIZE;
@@ -13936,6 +14091,9 @@ static WARN_UNUSED_RESULT int AesCfbEncrypt_C(Aes* aes, byte* out,
{
int ret = 0;
word32 processed;
#ifdef WC_AES_HAVE_PREFETCH_ARG
int did_prefetches = 0;
#endif
if ((aes == NULL) || (out == NULL) || (in == NULL)) {
return BAD_FUNC_ARG;
@@ -13960,7 +14118,8 @@ static WARN_UNUSED_RESULT int AesCfbEncrypt_C(Aes* aes, byte* out,
VECTOR_REGISTERS_PUSH;
while (sz >= WC_AES_BLOCK_SIZE) {
ret = wc_AesEncryptDirect(aes, (byte*)aes->reg, (byte*)aes->reg);
ret = AesEncrypt_preFetchOpt(aes, (byte*)aes->reg, (byte*)aes->reg,
&did_prefetches);
if (ret != 0) {
break;
}
@@ -13973,7 +14132,8 @@ static WARN_UNUSED_RESULT int AesCfbEncrypt_C(Aes* aes, byte* out,
/* encrypt left over data */
if ((ret == 0) && sz) {
ret = wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg);
ret = AesEncrypt_preFetchOpt(aes, (byte*)aes->reg, (byte*)aes->tmp,
&did_prefetches);
if (ret == 0) {
xorbufout(out, in, aes->tmp, sz);
XMEMCPY(aes->reg, out, sz);
@@ -14004,6 +14164,9 @@ static WARN_UNUSED_RESULT int AesCfbDecrypt_C(Aes* aes, byte* out,
{
int ret = 0;
word32 processed;
#ifdef WC_AES_HAVE_PREFETCH_ARG
int did_prefetches = 0;
#endif
(void)mode;
@@ -14050,7 +14213,8 @@ static WARN_UNUSED_RESULT int AesCfbDecrypt_C(Aes* aes, byte* out,
}
#endif
while (sz >= WC_AES_BLOCK_SIZE) {
ret = wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg);
ret = AesEncrypt_preFetchOpt(aes, (byte*)aes->reg, (byte*)aes->tmp,
&did_prefetches);
if (ret != 0) {
break;
}
@@ -14063,7 +14227,8 @@ static WARN_UNUSED_RESULT int AesCfbDecrypt_C(Aes* aes, byte* out,
/* decrypt left over data */
if ((ret == 0) && sz) {
ret = wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg);
ret = AesEncrypt_preFetchOpt(aes, (byte*)aes->reg, (byte*)aes->tmp,
&did_prefetches);
if (ret == 0) {
XMEMCPY(aes->reg, in, sz);
xorbufout(out, in, aes->tmp, sz);
@@ -14144,6 +14309,9 @@ static WARN_UNUSED_RESULT int wc_AesFeedbackCFB8(
{
byte *pt;
int ret = 0;
#ifdef WC_AES_HAVE_PREFETCH_ARG
int did_prefetches = 0;
#endif
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
@@ -14156,7 +14324,8 @@ static WARN_UNUSED_RESULT int wc_AesFeedbackCFB8(
VECTOR_REGISTERS_PUSH;
while (sz > 0) {
ret = wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg);
ret = AesEncrypt_preFetchOpt(aes, (byte*)aes->reg, (byte*)aes->tmp,
&did_prefetches);
if (ret != 0)
break;
if (dir == AES_DECRYPTION) {
@@ -14200,6 +14369,9 @@ static WARN_UNUSED_RESULT int wc_AesFeedbackCFB1(
byte* pt;
int bit = 7;
int ret = 0;
#ifdef WC_AES_HAVE_PREFETCH_ARG
int did_prefetches = 0;
#endif
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
@@ -14212,7 +14384,8 @@ static WARN_UNUSED_RESULT int wc_AesFeedbackCFB1(
VECTOR_REGISTERS_PUSH;
while (sz > 0) {
ret = wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg);
ret = AesEncrypt_preFetchOpt(aes, (byte*)aes->reg, (byte*)aes->tmp,
&did_prefetches);
if (ret != 0)
break;
if (dir == AES_DECRYPTION) {
@@ -14351,6 +14524,9 @@ static WARN_UNUSED_RESULT int AesOfbCrypt_C(Aes* aes, byte* out, const byte* in,
{
int ret = 0;
word32 processed;
#ifdef WC_AES_HAVE_PREFETCH_ARG
int did_prefetches = 0;
#endif
if ((aes == NULL) || (out == NULL) || (in == NULL)) {
return BAD_FUNC_ARG;
@@ -14373,7 +14549,8 @@ static WARN_UNUSED_RESULT int AesOfbCrypt_C(Aes* aes, byte* out, const byte* in,
VECTOR_REGISTERS_PUSH;
while (sz >= WC_AES_BLOCK_SIZE) {
ret = wc_AesEncryptDirect(aes, (byte*)aes->reg, (byte*)aes->reg);
ret = AesEncrypt_preFetchOpt(aes, (byte*)aes->reg, (byte*)aes->reg,
&did_prefetches);
if (ret != 0) {
break;
}
@@ -14385,7 +14562,8 @@ static WARN_UNUSED_RESULT int AesOfbCrypt_C(Aes* aes, byte* out, const byte* in,
/* encrypt left over data */
if ((ret == 0) && sz) {
ret = wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg);
ret = AesEncrypt_preFetchOpt(aes, (byte*)aes->reg, (byte*)aes->tmp,
&did_prefetches);
if (ret == 0) {
XMEMCPY(aes->reg, aes->tmp, WC_AES_BLOCK_SIZE);
xorbufout(out, in, aes->tmp, sz);
@@ -14643,7 +14821,7 @@ int wc_AesKeyUnWrap_ex(Aes *aes, const byte* in, word32 inSz, byte* out,
return ret;
/* verify IV */
if (XMEMCMP(tmp, expIv, KEYWRAP_BLOCK_SIZE) != 0)
if (ConstantCompare(tmp, expIv, KEYWRAP_BLOCK_SIZE) != 0)
return BAD_KEYWRAP_IV_E;
return (int)(inSz - KEYWRAP_BLOCK_SIZE);
@@ -16096,6 +16274,45 @@ int wc_AesXtsDecryptConsecutiveSectors(XtsAes* aes, byte* out, const byte* in,
#endif /* HAVE_AES_DECRYPT */
#endif /* WOLFSSL_AES_XTS */
#ifdef WOLFSSL_CMAC
int wc_local_CmacUpdateAes(struct Cmac *cmac, const byte* in, word32 inSz) {
int ret = 0;
Aes *aes = &cmac->aes;
#ifdef WC_AES_HAVE_PREFETCH_ARG
int did_prefetches = 0;
#endif
VECTOR_REGISTERS_PUSH;
while ((ret == 0) && (inSz != 0)) {
word32 add = min(inSz, WC_AES_BLOCK_SIZE - cmac->bufferSz);
XMEMCPY(&cmac->buffer[cmac->bufferSz], in, add);
cmac->bufferSz += add;
inSz -= add;
in += add;
if (cmac->bufferSz == WC_AES_BLOCK_SIZE && inSz != 0) {
if (cmac->totalSz != 0) {
xorbuf(cmac->buffer, cmac->digest, WC_AES_BLOCK_SIZE);
}
ret = AesEncrypt_preFetchOpt(aes, cmac->buffer,
cmac->digest, &did_prefetches);
if (ret == 0) {
cmac->totalSz += WC_AES_BLOCK_SIZE;
cmac->bufferSz = 0;
}
}
}
VECTOR_REGISTERS_POP;
return ret;
}
#endif /* WOLFSSL_CMAC */
#ifdef WOLFSSL_AES_SIV
/*
@@ -16303,7 +16520,7 @@ static WARN_UNUSED_RESULT int AesSivCipher(
WOLFSSL_MSG("S2V failed.");
}
if (XMEMCMP(siv, sivTmp, WC_AES_BLOCK_SIZE) != 0) {
if (ConstantCompare(siv, sivTmp, WC_AES_BLOCK_SIZE) != 0) {
WOLFSSL_MSG("Computed SIV doesn't match received SIV.");
ret = AES_SIV_AUTH_E;
}
@@ -17147,5 +17364,4 @@ int wc_AesCtsDecryptFinal(Aes* aes, byte* out, word32* outSz)
#endif /* WOLFSSL_AES_CTS */
#endif /* !NO_AES */
+396 -115
View File
@@ -487,7 +487,7 @@ static word32 SizeASNLength(word32 length)
#define ALLOC_ASNSETDATA(name, cnt, err, heap) \
do { \
if ((err) == 0) { \
(name) = (ASNSetData*)XMALLOC(sizeof(ASNGetData) * (cnt), (heap), \
(name) = (ASNSetData*)XMALLOC(sizeof(ASNSetData) * (cnt), (heap), \
DYNAMIC_TYPE_TMP_BUFFER); \
if ((name) == NULL) { \
(err) = MEMORY_E; \
@@ -2539,7 +2539,7 @@ int GetASNHeader(const byte* input, byte tag, word32* inOutIdx, int* len,
return GetASNHeader_ex(input, tag, inOutIdx, len, maxIdx, 1);
}
#ifndef WOLFSSL_ASN_TEMPLATE
#if !defined(WOLFSSL_ASN_TEMPLATE)
static int GetHeader(const byte* input, byte* tag, word32* inOutIdx, int* len,
word32 maxIdx, int check)
{
@@ -2894,7 +2894,9 @@ static int GetInteger7Bit(const byte* input, word32* inOutIdx, word32 maxIdx)
return b;
}
#endif /* !NO_CERTS */
#endif /* !WOLFSSL_ASN_TEMPLATE */
#if !defined(WOLFSSL_ASN_TEMPLATE)
#if ((defined(WC_RSA_PSS) && !defined(NO_RSA)) || !defined(NO_CERTS))
/* Get the DER/BER encoding of an ASN.1 INTEGER that has a value of no more than
* 16 bits.
@@ -2932,7 +2934,7 @@ static int GetInteger16Bit(const byte* input, word32* inOutIdx, word32 maxIdx)
return ASN_PARSE_E;
}
n = input[idx++];
n = (n << 8) | input[idx++];
n = (word16)((n << 8) | input[idx++]);
}
else
return ASN_PARSE_E;
@@ -2940,7 +2942,7 @@ static int GetInteger16Bit(const byte* input, word32* inOutIdx, word32 maxIdx)
*inOutIdx = idx;
return n;
}
#endif /* WC_RSA_PSS && !NO_RSA */
#endif /* WC_RSA_PSS || !NO_CERTS */
#endif /* !WOLFSSL_ASN_TEMPLATE */
#if !defined(NO_DSA) && !defined(NO_SHA)
@@ -3132,10 +3134,12 @@ const char* GetSigName(int oid) {
#if !defined(WOLFSSL_ASN_TEMPLATE) || defined(HAVE_PKCS7) || \
defined(OPENSSL_EXTRA) || defined(WOLFSSL_CERT_GEN)
defined(OPENSSL_EXTRA) || defined(WOLFSSL_CERT_GEN) || defined(WC_RSA_PSS)
#if !defined(NO_DSA) || defined(HAVE_ECC) || !defined(NO_CERTS) || \
defined(WOLFSSL_CERT_GEN) || \
(!defined(NO_RSA) && (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)))
(!defined(NO_RSA) && \
(defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA))) || \
(defined(WC_RSA_PSS) && !defined(NO_RSA))
/* Set the DER/BER encoding of the ASN.1 INTEGER header.
*
* When output is NULL, calculate the header length only.
@@ -3146,7 +3150,7 @@ const char* GetSigName(int oid) {
* @param [out] output Buffer to write into.
* @return Number of bytes added to the buffer.
*/
int SetASNInt(int len, byte firstByte, byte* output)
WOLFSSL_LOCAL int SetASNInt(int len, byte firstByte, byte* output)
{
int idx = 0;
@@ -7452,6 +7456,9 @@ static int RsaPssHashOidToSigOid(word32 oid, word32* sigOid)
}
#endif
/* RSASSA-PSS-params context-specific tags.
* RFC 4055, 3.1
*/
#ifdef WOLFSSL_ASN_TEMPLATE
/* ASN tag for hashAlgorithm. */
#define ASN_TAG_RSA_PSS_HASH (ASN_CONTEXT_SPECIFIC | 0)
@@ -7498,7 +7505,7 @@ enum {
RSAPSSPARAMSASN_IDX_TRAILERINT
};
/* Number of items in ASN.1 template for an algorithm identifier. */
/* Number of items in ASN.1 template for RSA PSS parameters. */
#define rsaPssParamsASN_Length (sizeof(rsaPssParamsASN) / sizeof(ASNItem))
#else
/* ASN tag for hashAlgorithm. */
@@ -7525,122 +7532,44 @@ enum {
static int DecodeRsaPssParams(const byte* params, word32 sz,
enum wc_HashType* hash, int* mgf, int* saltLen)
{
#ifndef WOLFSSL_ASN_TEMPLATE
int ret = 0;
word32 idx = 0;
int len = 0;
word32 oid = 0;
byte tag;
int length;
if (params == NULL)
return BAD_FUNC_ARG;
if (params == NULL) {
ret = BAD_FUNC_ARG;
/* Empty or NULL-tag parameters mean all defaults per RFC 4055 */
if (sz == 0) {
*hash = WC_HASH_TYPE_SHA;
*mgf = WC_MGF1SHA1;
*saltLen = 20;
return 0;
}
if ((ret == 0) && (GetSequence_ex(params, &idx, &len, sz, 1) < 0)) {
ret = ASN_PARSE_E;
}
if (ret == 0) {
if ((idx < sz) && (params[idx] == ASN_TAG_RSA_PSS_HASH)) {
/* Hash algorithm to use on message. */
if (GetHeader(params, &tag, &idx, &length, sz, 0) < 0) {
ret = ASN_PARSE_E;
}
if (ret == 0) {
if (GetAlgoId(params, &idx, &oid, oidHashType, sz) < 0) {
ret = ASN_PARSE_E;
}
}
if (ret == 0) {
ret = RsaPssHashOidToType(oid, hash);
}
}
else {
/* Default hash algorithm. */
if (params[0] == ASN_TAG_NULL) {
if (sz >= 2 && params[1] == 0) {
*hash = WC_HASH_TYPE_SHA;
}
}
if (ret == 0) {
if ((idx < sz) && (params[idx] == ASN_TAG_RSA_PSS_MGF)) {
/* MGF and hash algorithm to use with padding. */
if (GetHeader(params, &tag, &idx, &length, sz, 0) < 0) {
ret = ASN_PARSE_E;
}
if (ret == 0) {
if (GetAlgoId(params, &idx, &oid, oidIgnoreType, sz) < 0) {
ret = ASN_PARSE_E;
}
}
if ((ret == 0) && (oid != MGF1_OID)) {
ret = ASN_PARSE_E;
}
if (ret == 0) {
ret = GetAlgoId(params, &idx, &oid, oidHashType, sz);
if (ret == 0) {
ret = RsaPssHashOidToMgf1(oid, mgf);
}
}
}
else {
/* Default MGF/Hash algorithm. */
*mgf = WC_MGF1SHA1;
}
}
if (ret == 0) {
if ((idx < sz) && (params[idx] == ASN_TAG_RSA_PSS_SALTLEN)) {
/* Salt length to use with padding. */
if (GetHeader(params, &tag, &idx, &length, sz, 0) < 0) {
ret = ASN_PARSE_E;
}
if (ret == 0) {
ret = GetInteger16Bit(params, &idx, sz);
if (ret >= 0) {
*saltLen = ret;
ret = 0;
}
}
}
else {
/* Default salt length. */
*saltLen = 20;
return 0;
}
return ASN_PARSE_E;
}
if (ret == 0) {
if ((idx < sz) && (params[idx] == ASN_TAG_RSA_PSS_TRAILER)) {
/* Unused - trialerField. */
if (GetHeader(params, &tag, &idx, &length, sz, 0) < 0) {
ret = ASN_PARSE_E;
}
if (ret == 0) {
ret = GetInteger16Bit(params, &idx, sz);
if (ret > 0) {
ret = 0;
}
}
}
}
if ((ret == 0) && (idx != sz)) {
ret = ASN_PARSE_E;
}
if (params[0] != (ASN_SEQUENCE | ASN_CONSTRUCTED))
return ASN_PARSE_E;
return ret;
#else
#ifdef WOLFSSL_ASN_TEMPLATE
{
DECL_ASNGETDATA(dataASN, rsaPssParamsASN_Length);
int ret = 0;
word16 sLen = 20;
if (params == NULL) {
ret = BAD_FUNC_ARG;
}
/* Default values. */
*hash = WC_HASH_TYPE_SHA;
*mgf = WC_MGF1SHA1;
CALLOC_ASNGETDATA(dataASN, rsaPssParamsASN_Length, ret, NULL);
if (ret == 0) {
word32 inOutIdx = 0;
/* Default values. */
*hash = WC_HASH_TYPE_SHA;
*mgf = WC_MGF1SHA1;
/* Set OID type expected. */
GetASN_OID(&dataASN[RSAPSSPARAMSASN_IDX_HASHOID], oidHashType);
GetASN_OID(&dataASN[RSAPSSPARAMSASN_IDX_MGFOID], oidIgnoreType);
GetASN_OID(&dataASN[RSAPSSPARAMSASN_IDX_MGFHOID], oidHashType);
/* Place the salt length into 16-bit var sLen. */
GetASN_Int16Bit(&dataASN[RSAPSSPARAMSASN_IDX_SALTLENINT], &sLen);
@@ -7652,6 +7581,10 @@ static int DecodeRsaPssParams(const byte* params, word32 sz,
word32 oid = dataASN[RSAPSSPARAMSASN_IDX_HASHOID].data.oid.sum;
ret = RsaPssHashOidToType(oid, hash);
}
if ((ret == 0) && (dataASN[RSAPSSPARAMSASN_IDX_MGFOID].tag != 0)) {
if (dataASN[RSAPSSPARAMSASN_IDX_MGFOID].data.oid.sum != MGF1_OID)
ret = ASN_PARSE_E;
}
if ((ret == 0) && (dataASN[RSAPSSPARAMSASN_IDX_MGFHOID].tag != 0)) {
word32 oid = dataASN[RSAPSSPARAMSASN_IDX_MGFHOID].data.oid.sum;
ret = RsaPssHashOidToMgf1(oid, mgf);
@@ -7662,8 +7595,317 @@ static int DecodeRsaPssParams(const byte* params, word32 sz,
FREE_ASNGETDATA(dataASN, NULL);
return ret;
}
#else /* !WOLFSSL_ASN_TEMPLATE */
{
int ret = 0;
word32 idx = 0;
int len = 0;
word32 oid = 0;
byte tag;
int length;
/* Decode RSASSA-PSS-params SEQUENCE content. */
if (GetSequence_ex(params, &idx, &len, sz, 1) < 0) {
WOLFSSL_MSG("DecodeRsaPssParams: fail at sequence");
return ASN_PARSE_E;
}
/* [0] hashAlgorithm */
if (ret == 0) {
if ((idx < sz) && (params[idx] == ASN_TAG_RSA_PSS_HASH)) {
/* Hash algorithm to use on message. */
if (GetHeader(params, &tag, &idx, &length, sz, 0) < 0) {
WOLFSSL_MSG("DecodeRsaPssParams: fail at hash_header");
ret = ASN_PARSE_E;
}
if (ret == 0) {
if (GetAlgoId(params, &idx, &oid, oidHashType, sz) < 0) {
WOLFSSL_MSG("DecodeRsaPssParams: fail at hash_algo");
ret = ASN_PARSE_E;
}
}
if (ret == 0) {
ret = RsaPssHashOidToType(oid, hash);
if (ret != 0) {
WOLFSSL_MSG("DecodeRsaPssParams: fail at hash_oid");
}
}
}
else {
/* Default hash algorithm. */
*hash = WC_HASH_TYPE_SHA;
}
}
/* [1] maskGenAlgorithm -- AlgorithmIdentifier { OID id-mgf1, hash AlgoId }
* Parse manually: read the MGF SEQUENCE + OID, then the hash AlgoId
* parameter, because GetAlgoId consumes the entire AlgorithmIdentifier
* including the hash parameter inside it. */
if (ret == 0) {
if ((idx < sz) && (params[idx] == ASN_TAG_RSA_PSS_MGF)) {
int mgfSeqLen = 0;
word32 mgfEnd;
if (GetHeader(params, &tag, &idx, &length, sz, 0) < 0) {
WOLFSSL_MSG("DecodeRsaPssParams: fail at mgf_header");
ret = ASN_PARSE_E;
}
/* Read MGF AlgorithmIdentifier SEQUENCE header */
if (ret == 0) {
if (GetSequence(params, &idx, &mgfSeqLen, sz) < 0) {
WOLFSSL_MSG("DecodeRsaPssParams: fail at mgf_seq");
ret = ASN_PARSE_E;
}
}
/* Bound subsequent reads to the MGF SEQUENCE content */
mgfEnd = idx + (word32)mgfSeqLen;
if (mgfEnd > sz) {
WOLFSSL_MSG("DecodeRsaPssParams: mgf_seq overflows buffer");
ret = ASN_PARSE_E;
}
/* Read MGF OID (id-mgf1) directly */
if (ret == 0) {
if (GetObjectId(params, &idx, &oid, oidIgnoreType,
mgfEnd) < 0) {
WOLFSSL_MSG("DecodeRsaPssParams: fail at mgf_oid");
ret = ASN_PARSE_E;
}
}
if ((ret == 0) && (oid != MGF1_OID)) {
WOLFSSL_MSG("DecodeRsaPssParams: fail at mgf_oid_value");
ret = ASN_PARSE_E;
}
/* Read hash AlgorithmIdentifier (parameter of MGF1) */
if (ret == 0) {
ret = GetAlgoId(params, &idx, &oid, oidHashType, mgfEnd);
if (ret == 0) {
ret = RsaPssHashOidToMgf1(oid, mgf);
if (ret != 0) {
WOLFSSL_MSG("DecodeRsaPssParams: fail at mgf_hash_oid");
}
}
else {
WOLFSSL_MSG("DecodeRsaPssParams: fail at mgf_hash_algo");
}
}
if ((ret == 0) && (idx != mgfEnd)) {
WOLFSSL_MSG("DecodeRsaPssParams: extra data in mgf_seq");
ret = ASN_PARSE_E;
}
}
else {
/* Default MGF/Hash algorithm. */
*mgf = WC_MGF1SHA1;
}
}
/* [2] saltLength */
if (ret == 0) {
if ((idx < sz) && (params[idx] == ASN_TAG_RSA_PSS_SALTLEN)) {
/* Salt length to use with padding. */
if (GetHeader(params, &tag, &idx, &length, sz, 0) < 0) {
WOLFSSL_MSG("DecodeRsaPssParams: fail at saltlen_header");
ret = ASN_PARSE_E;
}
if (ret == 0) {
ret = GetInteger16Bit(params, &idx, sz);
if (ret >= 0) {
*saltLen = ret;
ret = 0;
}
else {
WOLFSSL_MSG("DecodeRsaPssParams: fail at saltlen_value");
}
}
}
else {
/* Default salt length. */
*saltLen = 20;
}
}
/* [3] trailerField */
if (ret == 0) {
if ((idx < sz) && (params[idx] == ASN_TAG_RSA_PSS_TRAILER)) {
/* Unused - trailerField. */
if (GetHeader(params, &tag, &idx, &length, sz, 0) < 0) {
WOLFSSL_MSG("DecodeRsaPssParams: fail at trailer_header");
ret = ASN_PARSE_E;
}
if (ret == 0) {
ret = GetInteger16Bit(params, &idx, sz);
if (ret > 0) {
ret = 0;
}
else if (ret != 0) {
WOLFSSL_MSG("DecodeRsaPssParams: fail at trailer_value");
}
}
}
}
if ((ret == 0) && (idx != sz)) {
WOLFSSL_MSG("DecodeRsaPssParams: fail at extra_data");
ret = ASN_PARSE_E;
}
return ret;
}
#endif /* WOLFSSL_ASN_TEMPLATE */
}
WOLFSSL_TEST_VIS int wc_DecodeRsaPssParams(const byte* params, word32 sz,
enum wc_HashType* hash, int* mgf, int* saltLen)
{
return DecodeRsaPssParams(params, sz, hash, mgf, saltLen);
}
/* Encode AlgorithmIdentifier for id-RSASSA-PSS with full RSASSA-PSS-params.
* hashOID: e.g. SHA256h; saltLen: e.g. 32; trailerField is encoded as 1.
* When out is NULL returns required length only.
* Returns encoded length on success, 0 on error.
* Note: saltLength is encoded as a single-byte INTEGER; values >255 would
* require multi-byte encoding (not implemented; CMS profiles use hash-length
* salts, e.g. 20-64 bytes). */
/* Scratch buffer for building RSA-PSS AlgorithmIdentifier sub-encodings.
* Must hold the largest single sub-encoding (hash AlgoId, typically ~15 bytes)
* plus room for integer TLVs. 64 bytes is sufficient; 128 gives margin. */
#define RSA_PSS_ALGOID_TMPBUF_SZ 128
word32 wc_EncodeRsaPssAlgoId(int hashOID, int saltLen, byte* out, word32 outSz)
{
word32 idx = 0;
word32 hashAlgSz, mgf1ParamSz, tag0Sz, tag1Sz, tag2Sz, tag3Sz;
word32 paramsSz, outerSz;
const byte* rsapssOid = sigRsaSsaPssOid;
word32 rsapssOidSz = sizeof(sigRsaSsaPssOid);
/* MGF1 OID 1.2.840.113549.1.1.8 */
static const byte mgf1Oid[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08 };
int setIntRet;
#ifdef WOLFSSL_SMALL_STACK
byte* tmpBuf;
#else
byte tmpBuf[RSA_PSS_ALGOID_TMPBUF_SZ];
#endif
if (saltLen < 0 || saltLen > 255) {
WOLFSSL_MSG("Salt length must be 0-255 for single-byte encoding");
return 0;
}
#ifdef WOLFSSL_SMALL_STACK
tmpBuf = (byte*)XMALLOC(RSA_PSS_ALGOID_TMPBUF_SZ, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (tmpBuf == NULL)
return 0;
#endif
hashAlgSz = SetAlgoID(hashOID, out ? tmpBuf : NULL, oidHashType, 0);
if (hashAlgSz == 0) {
idx = 0; goto pss_algoid_done;
}
mgf1ParamSz = hashAlgSz;
tag0Sz = SetExplicit(0, hashAlgSz, NULL, 0) + hashAlgSz;
{
/* MGF AlgorithmIdentifier: SEQUENCE { OID id-mgf1, hash AlgoId }
* The hash AlgoId (from SetAlgoID) is the parameter of MGF1. */
word32 mgf1OidLen = (word32)SetObjectId((int)sizeof(mgf1Oid), NULL) + (word32)sizeof(mgf1Oid);
word32 mgf1SeqContent = mgf1OidLen + mgf1ParamSz;
word32 mgf1SeqSz = SetSequence(mgf1SeqContent, NULL) + mgf1SeqContent;
tag1Sz = SetExplicit(1, mgf1SeqSz, NULL, 0) + mgf1SeqSz;
}
/* SetASNInt writes only tag+length (+ optional leading 0); value byte(s) appended by caller. */
setIntRet = SetASNInt(1, (byte)(saltLen & 0xff), NULL);
if (setIntRet <= 0) {
idx = 0; goto pss_algoid_done;
}
{
word32 saltIntSz = (word32)setIntRet + 1; /* header + one value byte (two if high bit set) */
tag2Sz = SetExplicit(2, saltIntSz, NULL, 0) + saltIntSz;
}
setIntRet = SetASNInt(1, 0x01, NULL);
if (setIntRet <= 0) {
idx = 0; goto pss_algoid_done;
}
{
word32 trailerIntSz = (word32)setIntRet + 1;
tag3Sz = SetExplicit(3, trailerIntSz, NULL, 0) + trailerIntSz;
}
paramsSz = tag0Sz + tag1Sz + tag2Sz + tag3Sz;
{
word32 idPart = (word32)SetObjectId((int)rsapssOidSz, NULL) + rsapssOidSz;
word32 seqPart = SetSequence(paramsSz, NULL) + paramsSz;
outerSz = SetSequence(idPart + seqPart, NULL) + idPart + seqPart;
}
if (out == NULL) {
idx = outerSz; goto pss_algoid_done;
}
if (outSz < outerSz) {
idx = 0; goto pss_algoid_done;
}
{
word32 idPart = (word32)SetObjectId((int)rsapssOidSz, NULL) + rsapssOidSz;
word32 seqPart = SetSequence(paramsSz, NULL) + paramsSz;
idx += SetSequence(idPart + seqPart, out + idx);
}
idx += (word32)SetObjectId((int)rsapssOidSz, out + idx);
XMEMCPY(out + idx, rsapssOid, rsapssOidSz);
idx += rsapssOidSz;
idx += SetSequence(paramsSz, out + idx);
idx += SetExplicit(0, hashAlgSz, out + idx, 0);
XMEMCPY(out + idx, tmpBuf, hashAlgSz);
idx += hashAlgSz;
{
/* [1] EXPLICIT { SEQUENCE { OID id-mgf1, hash AlgoId } } */
word32 mgf1OidLen = (word32)SetObjectId((int)sizeof(mgf1Oid), NULL) + (word32)sizeof(mgf1Oid);
word32 mgf1SeqContent = mgf1OidLen + mgf1ParamSz;
word32 mgf1SeqSz = SetSequence(mgf1SeqContent, NULL) + mgf1SeqContent;
idx += SetExplicit(1, mgf1SeqSz, out + idx, 0);
idx += SetSequence(mgf1SeqContent, out + idx);
idx += (word32)SetObjectId((int)sizeof(mgf1Oid), out + idx);
XMEMCPY(out + idx, mgf1Oid, sizeof(mgf1Oid));
idx += (word32)sizeof(mgf1Oid);
XMEMCPY(out + idx, tmpBuf, hashAlgSz);
idx += hashAlgSz;
}
/* INTEGER saltLength (single byte; see function comment for >255 limitation). */
setIntRet = SetASNInt(1, (byte)(saltLen & 0xff), tmpBuf);
if (setIntRet > 0) {
tmpBuf[setIntRet] = (byte)(saltLen & 0xff);
}
{
word32 saltIntSz = (word32)setIntRet + 1;
idx += SetExplicit(2, saltIntSz, out + idx, 0);
XMEMCPY(out + idx, tmpBuf, saltIntSz);
idx += saltIntSz;
}
/* INTEGER trailerField (1): same pattern. */
setIntRet = SetASNInt(1, 0x01, tmpBuf);
if (setIntRet > 0) {
tmpBuf[setIntRet] = 0x01;
}
{
word32 trailerIntSz = (word32)setIntRet + 1;
idx += SetExplicit(3, trailerIntSz, out + idx, 0);
XMEMCPY(out + idx, tmpBuf, trailerIntSz);
idx += trailerIntSz;
}
pss_algoid_done:
#ifdef WOLFSSL_SMALL_STACK
XFREE(tmpBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return idx;
}
#endif /* WC_RSA_PSS */
#if defined(WOLFSSL_ASN_TEMPLATE) || (!defined(NO_CERTS) && \
@@ -11113,6 +11355,7 @@ int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, word32 inSz,
#else
DECL_ASNGETDATA(dataASN, rsaPublicKeyASN_Length);
int ret = 0;
word32 startIdx = (inOutIdx != NULL) ? *inOutIdx : 0;
#ifdef WC_RSA_PSS
word32 oid = RSAk;
#endif
@@ -11131,7 +11374,10 @@ int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, word32 inSz,
(int)(rsaPublicKeyASN_Length - RSAPUBLICKEYASN_IDX_PUBKEY_RSA_SEQ),
0, input, inOutIdx, inSz);
if (ret != 0) {
/* Didn't work - try whole SubjectKeyInfo instead. */
/* Didn't work - try whole SubjectKeyInfo instead. Reset index
* to caller's start since the previous attempt advanced it. */
if (inOutIdx != NULL)
*inOutIdx = startIdx;
#ifdef WC_RSA_PSS
/* Could be RSA or RSA PSS key. */
GetASN_OID(&dataASN[RSAPUBLICKEYASN_IDX_ALGOID_OID], oidKeyType);
@@ -17041,8 +17287,17 @@ static int GetSigAlg(DecodedCert* cert, word32* sigOid, word32 maxIdx)
if (cert->srcIdx != endSeqIdx) {
#ifdef WC_RSA_PSS
if (*sigOid == CTC_RSASSAPSS) {
cert->sigParamsIndex = cert->srcIdx;
cert->sigParamsLength = endSeqIdx - cert->srcIdx;
/* cert->srcIdx is at start of parameters TLV (NULL or SEQUENCE) */
word32 tmpIdx = cert->srcIdx;
byte tag;
int len;
WOLFSSL_MSG("Cert sigAlg is RSASSA-PSS; decoding params");
if (GetHeader(cert->source, &tag, &tmpIdx, &len, endSeqIdx, 0) < 0) {
return ASN_PARSE_E;
}
cert->sigParamsIndex = cert->srcIdx;
cert->sigParamsLength = (word32)((tmpIdx - cert->srcIdx) + len);
}
else
#endif
@@ -24082,10 +24337,17 @@ static int DecodeCertInternal(DecodedCert* cert, int verify, int* criticalExt,
}
}
if (ret == 0) {
/* Store parameters for use in signature verification. */
cert->sigParamsIndex =
dataASN[X509CERTASN_IDX_SIGALGO_PARAMS].offset;
cert->sigParamsLength = sigAlgParamsSz;
/* Store parameters for use in signature verification.
* Use full TLV length: tag (1) + length bytes + content.
* GetASNItem_Length can be content-only when buffer.data unset. */
word32 off = dataASN[X509CERTASN_IDX_SIGALGO_PARAMS].offset;
word32 contentLen =
(word32)dataASN[X509CERTASN_IDX_SIGALGO_PARAMS].length;
cert->sigParamsIndex = off;
cert->sigParamsLength = (contentLen <= 127)
? (2 + contentLen)
: GetASNItem_Length(
dataASN[X509CERTASN_IDX_SIGALGO_PARAMS], cert->source);
}
}
#endif
@@ -24119,8 +24381,6 @@ static int DecodeCertInternal(DecodedCert* cert, int verify, int* criticalExt,
cert->extensionsSz = (int)GetASNItem_Length(
dataASN[X509CERTASN_IDX_TBS_EXT], cert->source);
cert->extensionsIdx = dataASN[X509CERTASN_IDX_TBS_EXT].offset;
/* Advance past extensions. */
cert->srcIdx = dataASN[X509CERTASN_IDX_SIGALGO_SEQ].offset;
}
}
@@ -27452,6 +27712,27 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
footer = END_X509_CRL;
}
#endif
else if (type == CERT_TYPE
|| type == CA_TYPE
|| type == CHAIN_CERT_TYPE
|| type == TRUSTED_PEER_TYPE) {
if (header == BEGIN_CERT) {
header = BEGIN_TRUSTED_CERT;
footer = END_TRUSTED_CERT;
}
else {
break;
}
}
else if (type == TRUSTED_CERT_TYPE) {
if (header == BEGIN_TRUSTED_CERT) {
header = BEGIN_CERT;
footer = END_CERT;
}
else {
break;
}
}
else {
break;
}
+12 -5
View File
@@ -187,6 +187,8 @@ int wc_ChaCha20Poly1305_Init(ChaChaPoly_Aead* aead,
aead->state = CHACHA20_POLY1305_STATE_READY;
}
ForceZero(authKey, sizeof(authKey));
return ret;
}
@@ -332,25 +334,30 @@ int wc_XChaCha20Poly1305_Init(
/* Create the Poly1305 key */
if ((ret = wc_Chacha_Process(&aead->chacha, authKey, authKey,
(word32)sizeof authKey)) < 0)
return ret;
goto out;
/* advance to start of the next ChaCha block. */
wc_Chacha_purge_current_block(&aead->chacha);
/* Initialize Poly1305 context */
if ((ret = wc_Poly1305SetKey(&aead->poly, authKey,
(word32)sizeof authKey)) < 0)
return ret;
goto out;
if ((ret = wc_Poly1305Update(&aead->poly, ad, (word32)ad_len)) < 0)
return ret;
goto out;
if ((ret = wc_Poly1305_Pad(&aead->poly, (word32)ad_len)) < 0)
return ret;
goto out;
aead->isEncrypt = isEncrypt ? 1 : 0;
aead->state = CHACHA20_POLY1305_STATE_AAD;
return 0;
ret = 0;
out:
ForceZero(authKey, sizeof(authKey));
return ret;
}
static WC_INLINE int wc_XChaCha20Poly1305_crypt_oneshot(
+5 -9
View File
@@ -228,6 +228,7 @@ int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz)
#if !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
case WC_CMAC_AES:
{
#ifdef HAVE_SELFTEST
while ((ret == 0) && (inSz != 0)) {
word32 add = min(inSz, WC_AES_BLOCK_SIZE - cmac->bufferSz);
XMEMCPY(&cmac->buffer[cmac->bufferSz], in, add);
@@ -240,21 +241,16 @@ int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz)
if (cmac->totalSz != 0) {
xorbuf(cmac->buffer, cmac->digest, WC_AES_BLOCK_SIZE);
}
#ifndef HAVE_SELFTEST
ret = wc_AesEncryptDirect(&cmac->aes, cmac->digest,
cmac->buffer);
if (ret == 0) {
cmac->totalSz += WC_AES_BLOCK_SIZE;
cmac->bufferSz = 0;
}
#else
wc_AesEncryptDirect(&cmac->aes, cmac->digest,
cmac->buffer);
cmac->totalSz += WC_AES_BLOCK_SIZE;
cmac->bufferSz = 0;
#endif
}
}
#else
(void)ret;
ret = wc_local_CmacUpdateAes(cmac, in, inSz);
#endif
}; break;
#endif /* !NO_AES && WOLFSSL_AES_DIRECT */
default:
+6 -2
View File
@@ -14484,6 +14484,8 @@ int wc_ecc_encrypt_ex(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
RESTORE_VECTOR_REGISTERS();
ForceZero(sharedSecret, sharedSz);
ForceZero(keys, (word32)keysLen);
WC_FREE_VAR_EX(sharedSecret, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER);
WC_FREE_VAR_EX(keys, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER);
@@ -14778,8 +14780,8 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
if (ret == 0)
ret = wc_HmacFinal(hmac, verify);
if ((ret == 0) && (XMEMCMP(verify, msg + msgSz - digestSz,
digestSz) != 0)) {
if ((ret == 0) && (ConstantCompare(verify, msg + msgSz - digestSz,
(int)digestSz) != 0)) {
ret = HASH_TYPE_E;
WOLFSSL_MSG("ECC Decrypt HMAC Check failed!");
}
@@ -14882,6 +14884,8 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
if (pubKey == peerKey)
wc_ecc_free(peerKey);
#endif
ForceZero(sharedSecret, sharedSz);
ForceZero(keys, (word32)keysLen);
#ifdef WOLFSSL_SMALL_STACK
#ifndef WOLFSSL_ECIES_OLD
XFREE(peerKey, ctx->heap, DYNAMIC_TYPE_ECC_BUFFER);
+2 -2
View File
@@ -4952,7 +4952,7 @@ int wolfSSL_EVP_DigestVerifyFinal(WOLFSSL_EVP_MD_CTX *ctx,
hashLen = wolfssl_mac_len(ctx->hash.hmac.macType);
if (siglen > hashLen)
if (siglen > hashLen || siglen > INT_MAX)
return WOLFSSL_FAILURE;
/* May be a truncated signature. */
}
@@ -4962,7 +4962,7 @@ int wolfSSL_EVP_DigestVerifyFinal(WOLFSSL_EVP_MD_CTX *ctx,
if (ctx->isHMAC) {
/* Check HMAC result matches the signature. */
if (XMEMCMP(sig, digest, (size_t)siglen) == 0)
if (ConstantCompare(sig, digest, (int)siglen) == 0)
return WOLFSSL_SUCCESS;
return WOLFSSL_FAILURE;
}
+11
View File
@@ -796,6 +796,8 @@ static int wc_HpkeEncap(Hpke* hpke, void* ephemeralKey, void* receiverKey,
hpke->Npk * 2, sharedSecret);
}
ForceZero(dh, hpke->Ndh);
ForceZero(kemContext, hpke->Npk * 2);
WC_FREE_VAR_EX(dh, hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
WC_FREE_VAR_EX(kemContext, hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
@@ -816,6 +818,9 @@ static int wc_HpkeSetupBaseSender(Hpke* hpke, HpkeBaseContext* context,
#ifdef WOLFSSL_SMALL_STACK
sharedSecret = (byte*)XMALLOC(hpke->Nsecret, hpke->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (sharedSecret == NULL) {
return MEMORY_E;
}
#endif
/* encap */
@@ -827,6 +832,7 @@ static int wc_HpkeSetupBaseSender(Hpke* hpke, HpkeBaseContext* context,
infoSz);
}
ForceZero(sharedSecret, hpke->Nsecret);
WC_FREE_VAR_EX(sharedSecret, hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
@@ -914,6 +920,7 @@ int wc_HpkeSealBase(Hpke* hpke, void* ephemeralKey, void* receiverKey,
PRIVATE_KEY_LOCK();
ForceZero(context, sizeof(HpkeBaseContext));
WC_FREE_VAR_EX(context, hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
@@ -1032,6 +1039,8 @@ static int wc_HpkeDecap(Hpke* hpke, void* receiverKey, const byte* pubKey,
hpke->Npk * 2, sharedSecret);
}
ForceZero(dh, hpke->Ndh);
ForceZero(kemContext, hpke->Npk * 2);
WC_FREE_VAR_EX(dh, hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
WC_FREE_VAR_EX(kemContext, hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
@@ -1058,6 +1067,7 @@ static int wc_HpkeSetupBaseReceiver(Hpke* hpke, HpkeBaseContext* context,
infoSz);
}
ForceZero(sharedSecret, hpke->Nsecret);
WC_FREE_VAR_EX(sharedSecret, hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
@@ -1144,6 +1154,7 @@ int wc_HpkeOpenBase(Hpke* hpke, void* receiverKey, const byte* pubKey,
PRIVATE_KEY_LOCK();
ForceZero(context, sizeof(HpkeBaseContext));
WC_FREE_VAR_EX(context, hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
+7 -1
View File
@@ -637,7 +637,13 @@ static int wc_PKCS12_verify(WC_PKCS12* pkcs12, byte* data, word32 dataSz,
}
#endif
return XMEMCMP(digest, mac->digest, mac->digestSz);
if (ConstantCompare(digest, mac->digest, (int)mac->digestSz) != 0) {
ForceZero(digest, sizeof(digest));
return MAC_CMP_FAILED_E;
}
ForceZero(digest, sizeof(digest));
return 0;
}
int wc_PKCS12_verify_ex(WC_PKCS12* pkcs12, const byte* psw, word32 pswSz)
+439 -18
View File
@@ -28,6 +28,26 @@
#ifndef NO_RSA
#include <wolfssl/wolfcrypt/rsa.h>
#endif
#ifndef RSA_PSS_SALT_LEN_DEFAULT
#define RSA_PSS_SALT_LEN_DEFAULT (-1)
#endif
#if defined(WC_RSA_PSS) && !defined(NO_RSA)
#if (defined(HAVE_FIPS) && \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) || \
(defined(HAVE_SELFTEST) && \
(!defined(HAVE_SELFTEST_VERSION) || (HAVE_SELFTEST_VERSION < 2)))
#ifndef WC_MGF1NONE
#define WC_MGF1NONE 0
#define WC_MGF1SHA1 26
#define WC_MGF1SHA224 4
#define WC_MGF1SHA256 1
#define WC_MGF1SHA384 2
#define WC_MGF1SHA512 3
#define WC_MGF1SHA512_224 5
#define WC_MGF1SHA512_256 6
#endif
#endif
#endif
#ifdef HAVE_ECC
#include <wolfssl/wolfcrypt/ecc.h>
#endif
@@ -1019,6 +1039,11 @@ static int wc_PKCS7_CheckPublicKeyDer(wc_PKCS7* pkcs7, int keyOID,
switch (keyOID) {
#ifndef NO_RSA
#ifdef WC_RSA_PSS
case RSAPSSk:
/* RSA-PSS cert: public key is same RSA format as RSAk */
FALL_THROUGH;
#endif
case RSAk:
ret = wc_InitRsaKey_ex(rsa, pkcs7->heap, pkcs7->devId);
if (ret != 0) {
@@ -1173,6 +1198,10 @@ int wc_PKCS7_InitWithCert(wc_PKCS7* pkcs7, byte* derCert, word32 derCertSz)
XMEMCPY(pkcs7->publicKey, dCert->publicKey, dCert->pubKeySize);
pkcs7->publicKeySz = dCert->pubKeySize;
pkcs7->publicKeyOID = dCert->keyOID;
/* Do not derive publicKeyOID from cert signatureOID: the cert's
* signature is how the cert was signed by its issuer; the signer
* chooses digestEncryptionAlgorithm (e.g. RSASSA-PSS vs PKCS#1 v1.5)
* via API / pkcs7->publicKeyOID set by the application. */
XMEMCPY(pkcs7->issuerHash, dCert->issuerHash, KEYID_SIZE);
pkcs7->issuer = dCert->issuerRaw;
pkcs7->issuerSz = (word32)dCert->issuerRawLen;
@@ -1533,7 +1562,11 @@ typedef struct ESD {
byte issuerSKIDSeq[MAX_SEQ_SZ];
byte issuerSKID[MAX_OCTET_STR_SZ];
byte signerDigAlgoId[MAX_ALGO_SZ];
#if defined(WC_RSA_PSS)
byte digEncAlgoId[128]; /* RSASSA-PSS needs full params */
#else
byte digEncAlgoId[MAX_ALGO_SZ];
#endif
byte signedAttribSet[MAX_SET_SZ];
EncodedAttrib signedAttribs[7];
byte signerDigest[MAX_OCTET_STR_SZ];
@@ -1945,6 +1978,131 @@ static int wc_PKCS7_EcdsaSign(wc_PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd)
#endif /* HAVE_ECC */
#if defined(WC_RSA_PSS) && !defined(NO_RSA)
/* Map hash type to MGF1 identifier; local copy so PKCS7 does not depend on
* rsa.c when RSA is in a separate FIPS module (e.g. CAVP build). */
static int pkcs7_hash2mgf(enum wc_HashType hType)
{
switch (hType) {
case WC_HASH_TYPE_NONE:
return WC_MGF1NONE;
case WC_HASH_TYPE_SHA:
#ifndef NO_SHA
return WC_MGF1SHA1;
#else
break;
#endif
case WC_HASH_TYPE_SHA224:
#ifdef WOLFSSL_SHA224
return WC_MGF1SHA224;
#else
break;
#endif
case WC_HASH_TYPE_SHA256:
#ifndef NO_SHA256
return WC_MGF1SHA256;
#else
break;
#endif
case WC_HASH_TYPE_SHA384:
#ifdef WOLFSSL_SHA384
return WC_MGF1SHA384;
#else
break;
#endif
case WC_HASH_TYPE_SHA512:
#ifdef WOLFSSL_SHA512
return WC_MGF1SHA512;
#else
break;
#endif
/* MGF1 only supports SHA-1 and SHA-2; other hashes fall through to WC_MGF1NONE */
case WC_HASH_TYPE_MD2:
case WC_HASH_TYPE_MD4:
case WC_HASH_TYPE_MD5:
case WC_HASH_TYPE_MD5_SHA:
case WC_HASH_TYPE_SHA3_224:
case WC_HASH_TYPE_SHA3_256:
case WC_HASH_TYPE_SHA3_384:
case WC_HASH_TYPE_SHA3_512:
case WC_HASH_TYPE_BLAKE2B:
case WC_HASH_TYPE_BLAKE2S:
#ifndef WOLFSSL_NOSHA512_224
case WC_HASH_TYPE_SHA512_224:
#endif
#ifndef WOLFSSL_NOSHA512_256
case WC_HASH_TYPE_SHA512_256:
#endif
#ifdef WOLFSSL_SHAKE128
case WC_HASH_TYPE_SHAKE128:
#endif
#ifdef WOLFSSL_SHAKE256
case WC_HASH_TYPE_SHAKE256:
#endif
#ifdef WOLFSSL_SM3
case WC_HASH_TYPE_SM3:
#endif
default:
break;
}
return WC_MGF1NONE;
}
/* returns size of signature put into esd->encContentDigest, negative on error.
* Signs the digest (contentAttribsDigest) with RSA-PSS padding, like ECDSA. */
static int wc_PKCS7_RsaPssSign(wc_PKCS7* pkcs7, byte* digest, word32 digestSz,
ESD* esd)
{
int ret;
word32 outSz;
WC_DECLARE_VAR(privKey, RsaKey, 1, 0);
if (pkcs7 == NULL || pkcs7->rng == NULL || digest == NULL || esd == NULL) {
return BAD_FUNC_ARG;
}
WC_ALLOC_VAR_EX(privKey, RsaKey, 1, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER,
return MEMORY_E);
ret = wc_PKCS7_ImportRSA(pkcs7, privKey);
if (ret == 0) {
outSz = sizeof(esd->encContentDigest);
#ifdef WOLFSSL_ASYNC_CRYPT
do {
ret = wc_AsyncWait(ret, &privKey->asyncDev,
WC_ASYNC_FLAG_CALL_AGAIN);
if (ret >= 0)
#endif
{
/* Salt length policy: use hash digest length (RFC 4055 typical).
* RFC 3447 allows arbitrary salt lengths, but hash-length is the
* most interoperable choice and matches OpenSSL's default.
* Must agree with the saltLen encoded in
* SignerInfo.signatureAlgorithm params above. */
int saltLen = wc_HashGetDigestSize(wc_OidGetHash(pkcs7->hashOID));
if (saltLen < 0) {
ret = saltLen;
}
else {
ret = wc_RsaPSS_Sign_ex(digest, digestSz,
esd->encContentDigest, outSz,
esd->hashType, pkcs7_hash2mgf(esd->hashType),
saltLen, privKey, pkcs7->rng);
}
}
#ifdef WOLFSSL_ASYNC_CRYPT
} while (ret == WC_NO_ERR_TRACE(WC_PENDING_E));
#endif
/* wc_RsaPSS_Sign_ex returns signature length on success */
}
wc_FreeRsaKey(privKey);
WC_FREE_VAR_EX(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
#endif /* WC_RSA_PSS && !NO_RSA */
/* returns encContentDigestSz based on the signature set to be used */
static int wc_PKCS7_GetSignSize(wc_PKCS7* pkcs7)
{
@@ -1954,6 +2112,9 @@ static int wc_PKCS7_GetSignSize(wc_PKCS7* pkcs7)
#ifndef NO_RSA
case RSAk:
#ifdef WC_RSA_PSS
case RSAPSSk:
#endif
{
#ifndef WOLFSSL_SMALL_STACK
RsaKey privKey[1];
@@ -2244,6 +2405,20 @@ static int wc_PKCS7_SignedDataGetEncAlgoId(wc_PKCS7* pkcs7, int* digEncAlgoId,
}
#endif /* HAVE_ECC */
#ifdef WC_RSA_PSS
else if (pkcs7->publicKeyOID == RSAPSSk) {
algoType = oidSigType;
algoId = CTC_RSASSAPSS;
/* Hash/MGF/salt conveyed via PSS params in AlgorithmIdentifier */
}
#endif
#ifndef WC_RSA_PSS
else if (pkcs7->publicKeyOID == RSAPSSk) {
WOLFSSL_MSG("RSA-PSS requested but WC_RSA_PSS not compiled in");
return NOT_COMPILED_IN;
}
#endif
if (algoId == 0) {
WOLFSSL_MSG("Invalid signature algorithm type");
return BAD_FUNC_ARG;
@@ -2359,7 +2534,8 @@ static int wc_PKCS7_SignedDataBuildSignature(wc_PKCS7* pkcs7,
{
int ret = 0;
#if defined(HAVE_ECC) || \
(defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA))
(defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA)) || \
(defined(WC_RSA_PSS) && !defined(NO_RSA))
int hashSz = 0;
#endif
#if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA)
@@ -2384,7 +2560,8 @@ static int wc_PKCS7_SignedDataBuildSignature(wc_PKCS7* pkcs7,
}
#if defined(HAVE_ECC) || \
(defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA))
(defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA)) || \
(defined(WC_RSA_PSS) && !defined(NO_RSA))
/* get digest size from hash type */
hashSz = wc_HashGetDigestSize(esd->hashType);
if (hashSz < 0) {
@@ -2447,6 +2624,14 @@ static int wc_PKCS7_SignedDataBuildSignature(wc_PKCS7* pkcs7,
break;
#endif
#if defined(WC_RSA_PSS) && !defined(NO_RSA)
case RSAPSSk:
/* RSA-PSS signs the digest directly (no DigestInfo), like ECDSA */
ret = wc_PKCS7_RsaPssSign(pkcs7, esd->contentAttribsDigest,
(word32)hashSz, esd);
break;
#endif
default:
WOLFSSL_MSG("Unsupported public key type");
ret = BAD_FUNC_ARG;
@@ -2801,14 +2986,19 @@ static int PKCS7_EncodeSigned(wc_PKCS7* pkcs7,
return BAD_FUNC_ARG;
}
/* signature size varies with ECDSA, with a varying sign size the content
* hash must be known in order to create the surrounding ASN1 syntax
* properly before writing out the content and generating the hash on the
* fly and then creating the signature */
if (hashBuf == NULL && pkcs7->publicKeyOID == ECDSAk) {
/* signature size varies with ECDSA; RSA-PSS signs digest directly like
* ECDSA. For both, content hash must be known to build ASN.1 before signing */
#if defined(HAVE_ECC) || defined(WC_RSA_PSS)
if (hashBuf == NULL &&
(pkcs7->publicKeyOID == ECDSAk
#ifdef WC_RSA_PSS
|| pkcs7->publicKeyOID == RSAPSSk
#endif
)) {
WOLFSSL_MSG("Pre-calculated content hash is needed in this case");
return BAD_FUNC_ARG;
}
#endif
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
keyIdSize = wc_HashGetDigestSize(wc_HashTypeConvert(HashIdAlg(
@@ -2965,8 +3155,31 @@ static int PKCS7_EncodeSigned(wc_PKCS7* pkcs7,
idx = ret;
goto out;
}
esd->digEncAlgoIdSz = SetAlgoIDEx(digEncAlgoId, esd->digEncAlgoId,
digEncAlgoType, 0, pkcs7->hashParamsAbsent);
#if defined(WC_RSA_PSS)
if (digEncAlgoId == CTC_RSASSAPSS) {
/* Salt length policy: always encode as hash digest length.
* This is the common CMS/RFC 4055 profile and matches OpenSSL
* defaults. The decoder (pssSaltLen) handles arbitrary values
* from external blobs. A future pkcs7->pssSaltLen override for
* encode could be added here if custom salt lengths are needed. */
int saltLen = wc_HashGetDigestSize(wc_OidGetHash(pkcs7->hashOID));
if (saltLen < 0) {
idx = saltLen;
goto out;
}
esd->digEncAlgoIdSz = wc_EncodeRsaPssAlgoId(pkcs7->hashOID,
(int)(word32)saltLen, esd->digEncAlgoId,
(word32)sizeof(esd->digEncAlgoId));
if (esd->digEncAlgoIdSz == 0) {
idx = ASN_PARSE_E;
goto out;
}
} else
#endif
{
esd->digEncAlgoIdSz = SetAlgoIDEx(digEncAlgoId, esd->digEncAlgoId,
digEncAlgoType, 0, pkcs7->hashParamsAbsent);
}
signerInfoSz += esd->digEncAlgoIdSz;
/* build up signed attributes, include contentType, signingTime, and
@@ -3567,8 +3780,12 @@ int wc_PKCS7_EncodeSignedData(wc_PKCS7* pkcs7, byte* output, word32 outputSz)
return BAD_FUNC_ARG;
}
/* pre-calculate hash for ECC signatures */
if (pkcs7->publicKeyOID == ECDSAk) {
/* pre-calculate content hash for ECDSA and RSA-PSS (both sign digest directly) */
if (pkcs7->publicKeyOID == ECDSAk
#ifdef WC_RSA_PSS
|| pkcs7->publicKeyOID == RSAPSSk
#endif
) {
int hashSz;
enum wc_HashType hashType;
byte hashBuf[WC_MAX_DIGEST_SIZE];
@@ -4071,8 +4288,7 @@ static int wc_PKCS7_RsaVerify(wc_PKCS7* pkcs7, byte* sig, int sigSz,
byte digest[MAX_PKCS7_DIGEST_SZ];
#endif
RsaKey key[1];
DecodedCert stack_dCert;
DecodedCert* dCert = &stack_dCert;
DecodedCert dCert[1];
#endif
if (pkcs7 == NULL || sig == NULL || hash == NULL) {
@@ -4175,6 +4391,144 @@ static int wc_PKCS7_RsaVerify(wc_PKCS7* pkcs7, byte* sig, int sigSz,
return ret;
}
#if defined(WC_RSA_PSS)
/* returns 0 when signature verifies, negative on error */
static int wc_PKCS7_RsaPssVerify(wc_PKCS7* pkcs7, byte* sig, int sigSz,
byte* hash, word32 hashSz)
{
int ret = 0, i;
word32 scratch = 0, verified = 0;
word32 pkSz;
int saltLen, verify;
enum wc_HashType hashType;
int hashDigSz, mgf;
/* wc_RsaPSS_Verify_ex output is PSS-encoded message (RSA_PSS_PAD_SZ +
* saltLen + 2*hLen bytes), which can exceed MAX_PKCS7_DIGEST_SZ.
* Use MAX_ENCRYPTED_KEY_SZ (512) to cover RSA keys up to 4096-bit. */
WC_DECLARE_VAR(digest, byte, MAX_ENCRYPTED_KEY_SZ, 0);
WC_DECLARE_VAR(key, RsaKey, 1, 0);
WC_DECLARE_VAR(dCert, DecodedCert, 1, 0);
if (pkcs7 == NULL || sig == NULL || hash == NULL)
return BAD_FUNC_ARG;
/* Use SignerInfo.signatureAlgorithm params when decoded; else digestAlgo */
if (pkcs7->pssParamsPresent)
hashType = (enum wc_HashType)pkcs7->pssHashType;
else
hashType = wc_OidGetHash(pkcs7->hashOID);
hashDigSz = wc_HashGetDigestSize(hashType);
if (hashDigSz < 0)
return ASN_PARSE_E;
if (hashSz != (word32)hashDigSz)
return ASN_PARSE_E;
mgf = pkcs7->pssParamsPresent
? pkcs7->pssMgf : pkcs7_hash2mgf(hashType);
if (mgf == WC_MGF1NONE)
return ASN_PARSE_E;
WC_ALLOC_VAR_EX(digest, byte, MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
WC_ALLOC_VAR_EX(key, RsaKey, 1, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER,
{ WC_FREE_VAR_EX(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E; });
WC_ALLOC_VAR_EX(dCert, DecodedCert, 1, pkcs7->heap, DYNAMIC_TYPE_DCERT,
{ WC_FREE_VAR_EX(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
WC_FREE_VAR_EX(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E; });
XMEMSET(digest, 0, MAX_ENCRYPTED_KEY_SZ);
for (i = 0; i < MAX_PKCS7_CERTS; i++) {
if (pkcs7->certSz[i] == 0)
continue;
scratch = 0;
ret = wc_InitRsaKey_ex(key, pkcs7->heap, pkcs7->devId);
if (ret != 0)
break;
InitDecodedCert(dCert, pkcs7->cert[i], pkcs7->certSz[i], pkcs7->heap);
ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0);
if (ret < 0) {
FreeDecodedCert(dCert);
wc_FreeRsaKey(key);
continue;
}
pkSz = dCert->pubKeySize;
if (pkSz > (MAX_RSA_INT_SZ + MAX_RSA_E_SZ))
pkSz = (MAX_RSA_INT_SZ + MAX_RSA_E_SZ);
if (wc_RsaPublicKeyDecode(dCert->publicKey, &scratch, key,
pkSz) < 0) {
FreeDecodedCert(dCert);
wc_FreeRsaKey(key);
continue;
}
saltLen = pkcs7->pssParamsPresent
? pkcs7->pssSaltLen : RSA_PSS_SALT_LEN_DEFAULT;
/* wc_RsaPSS_Verify_ex returns PSS encoded message length, not
* the recovered hash. Must then call wc_RsaPSS_CheckPadding_ex
* to verify the PSS padding against the expected hash. */
verify = wc_RsaPSS_Verify_ex(sig, (word32)sigSz, digest,
MAX_ENCRYPTED_KEY_SZ,
hashType, mgf, saltLen, key);
if (verify > 0) {
/* wc_RsaPSS_CheckPadding_ex signature varies across
* FIPS / selftest versions; match the pattern in asn.c */
#if (defined(HAVE_SELFTEST) && \
(!defined(HAVE_SELFTEST_VERSION) || \
(HAVE_SELFTEST_VERSION < 2))) || \
(defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && \
(HAVE_FIPS_VERSION < 2))
ret = wc_RsaPSS_CheckPadding_ex(hash, hashSz, digest,
(word32)verify, hashType,
saltLen);
#elif (defined(HAVE_SELFTEST) && \
(HAVE_SELFTEST_VERSION == 2)) || \
(defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && \
(HAVE_FIPS_VERSION == 2))
ret = wc_RsaPSS_CheckPadding_ex(hash, hashSz, digest,
(word32)verify, hashType,
saltLen, 0);
#else
ret = wc_RsaPSS_CheckPadding_ex2(hash, hashSz, digest,
(word32)verify, hashType,
saltLen,
mp_count_bits(&key->n),
pkcs7->heap);
#endif
}
else {
ret = verify;
}
FreeDecodedCert(dCert);
wc_FreeRsaKey(key);
if (ret == 0) {
verified = 1;
pkcs7->verifyCert = pkcs7->cert[i];
pkcs7->verifyCertSz = pkcs7->certSz[i];
break;
}
ret = 0;
}
if (verified == 0)
ret = SIG_VERIFY_E;
WC_FREE_VAR_EX(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
WC_FREE_VAR_EX(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
WC_FREE_VAR_EX(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
return ret;
}
#endif /* WC_RSA_PSS */
#endif /* NO_RSA */
@@ -4194,8 +4548,7 @@ static int wc_PKCS7_EcdsaVerify(wc_PKCS7* pkcs7, byte* sig, int sigSz,
#else
byte digest[MAX_PKCS7_DIGEST_SZ];
ecc_key key[1];
DecodedCert stack_dCert;
DecodedCert* dCert = &stack_dCert;
DecodedCert dCert[1];
#endif
word32 idx = 0;
@@ -4695,6 +5048,14 @@ static int wc_PKCS7_SignedDataVerifySignature(wc_PKCS7* pkcs7, byte* sig,
plainDigestSz);
}
break;
#ifdef WC_RSA_PSS
/* RSA-PSS signs the raw hash (plainDigest), not DigestInfo */
case RSAPSSk:
ret = wc_PKCS7_RsaPssVerify(pkcs7, sig, (int)sigSz, plainDigest,
plainDigestSz);
break;
#endif
#endif
#ifdef HAVE_ECC
@@ -4741,6 +5102,13 @@ static int wc_PKCS7_SetPublicKeyOID(wc_PKCS7* pkcs7, int sigOID)
pkcs7->publicKeyOID = RSAk;
break;
#ifdef WC_RSA_PSS
/* CTC_RSASSAPSS and RSAPSSk are the same OID value */
case CTC_RSASSAPSS:
pkcs7->publicKeyOID = RSAPSSk;
break;
#endif
/* if sigOID is already RSAk */
case RSAk:
pkcs7->publicKeyOID = (word32)sigOID;
@@ -5050,9 +5418,62 @@ static int wc_PKCS7_ParseSignerInfo(wc_PKCS7* pkcs7, byte* in, word32 inSz,
idx += (word32)length;
}
/* Get digestEncryptionAlgorithm - key type or signature type */
if (ret == 0 && GetAlgoId(in, &idx, &sigOID, oidIgnoreType, inSz) < 0) {
ret = ASN_PARSE_E;
/* Get digestEncryptionAlgorithm (signatureAlgorithm) - parse manually
* so we can decode id-RSASSA-PSS parameters in all builds. */
#if defined(WC_RSA_PSS) && !defined(NO_RSA)
pkcs7->pssParamsPresent = 0;
#endif
if (ret == 0) {
int algoSeqLen = 0;
word32 algoContentStart = 0;
if (GetSequence(in, &idx, &algoSeqLen, (word32)inSz) < 0) {
ret = ASN_PARSE_E;
}
else {
algoContentStart = idx; /* first byte of AlgorithmIdentifier content */
if (GetObjectId(in, &idx, &sigOID, oidSigType, inSz) < 0) {
ret = ASN_PARSE_E;
}
/* Only parse params when still inside the AlgorithmIdentifier;
* when optional params are absent, idx is already past the sequence. */
else if (algoContentStart + (word32)algoSeqLen > idx) {
word32 paramsStart = idx;
byte paramTag;
int paramLen = 0;
if (GetASNTag(in, &idx, &paramTag, inSz) != 0 ||
GetLength(in, &idx, &paramLen, inSz) < 0) {
ret = ASN_PARSE_E;
}
else {
#if defined(WC_RSA_PSS) && !defined(NO_RSA)
if ((word32)sigOID == (word32)CTC_RSASSAPSS &&
paramTag == (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
word32 tlvLen = (idx - paramsStart) +
(word32)paramLen;
enum wc_HashType pssHash = WC_HASH_TYPE_SHA;
int pssMgfVal = 0, pssSalt = 0;
if (paramsStart + tlvLen > (word32)inSz) {
return ASN_PARSE_E;
}
ret = wc_DecodeRsaPssParams(in + paramsStart, tlvLen,
&pssHash, &pssMgfVal,
&pssSalt);
if (ret == 0) {
pkcs7->pssSaltLen = pssSalt;
pkcs7->pssHashType = (int)pssHash;
pkcs7->pssMgf = pssMgfVal;
pkcs7->pssParamsPresent = 1;
}
else {
WOLFSSL_MSG("RSASSA-PSS parameters invalid - failing parse");
return ASN_PARSE_E;
}
}
#endif
idx += (word32)paramLen;
}
}
}
}
/* store public key type based on digestEncryptionAlgorithm */
+3
View File
@@ -152,6 +152,8 @@ int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen,
WC_FREE_VAR_EX(hash, heap, DYNAMIC_TYPE_HASHCTX);
ForceZero(digest, sizeof(digest));
if (err != 0)
return err;
@@ -294,6 +296,7 @@ int wc_PBKDF2_ex(byte* output, const byte* passwd, int pLen, const byte* salt,
wc_HmacFree(hmac);
}
ForceZero(buffer, (word32)hLen);
WC_FREE_VAR_EX(buffer, heap, DYNAMIC_TYPE_TMP_BUFFER);
WC_FREE_VAR_EX(hmac, heap, DYNAMIC_TYPE_HMAC);
+2 -1
View File
@@ -6941,7 +6941,8 @@ int wc_DeriveSakkeSSV(SakkeKey* key, enum wc_HashType hashType, byte* ssv,
err = sakke_compute_point_r(key, key->id, key->idSz, ri, n, test);
}
if ((err == 0) && (XMEMCMP(auth, test, (size_t)(2 * n + 1)) != 0)) {
/* n is word16, so 2*n+1 always fits in int */
if ((err == 0) && (ConstantCompare(auth, test, (int)(2 * n + 1)) != 0)) {
err = SAKKE_VERIFY_FAIL_E;
}
+4 -2
View File
@@ -982,7 +982,7 @@ int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size)
if (hashSize < 0)
return ALGO_ID_E;
if (size != (word32)hashSize)
if (size != (word32)hashSize || size > INT_MAX)
return BUFFER_E;
r = SrpHashFinal(srp->side == SRP_CLIENT_SIDE ? &srp->server_proof
@@ -994,9 +994,11 @@ int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size)
if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, srp->keySz);
}
if (!r && XMEMCMP(proof, digest, size) != 0)
if (!r && ConstantCompare(proof, digest, (int)size) != 0)
r = SRP_VERIFY_E;
ForceZero(digest, sizeof(digest));
return r;
}
+60 -37
View File
@@ -950,6 +950,55 @@ static int mlkemkey_encapsulate(MlKemKey* key, const byte* m, byte* r, byte* c)
}
#endif
#if !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) || \
!defined(WOLFSSL_MLKEM_NO_DECAPSULATE)
static int wc_mlkemkey_check_h(MlKemKey* key)
{
int ret = 0;
/* If public hash (h) is not stored against key, calculate it
* (fields set explicitly instead of using decode).
* Step 1: ... H(ek)...
*/
if ((key->flags & MLKEM_FLAG_H_SET) == 0) {
#ifndef WOLFSSL_NO_MALLOC
byte* pubKey = NULL;
word32 pubKeyLen;
#else
byte pubKey[WC_ML_KEM_MAX_PUBLIC_KEY_SIZE];
word32 pubKeyLen;
#endif
/* Determine how big an encoded public key will be. */
ret = wc_KyberKey_PublicKeySize(key, &pubKeyLen);
if (ret == 0) {
#ifndef WOLFSSL_NO_MALLOC
/* Allocate dynamic memory for encoded public key. */
pubKey = (byte*)XMALLOC(pubKeyLen, key->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (pubKey == NULL) {
ret = MEMORY_E;
}
}
if (ret == 0) {
#endif
/* Encode public key - h is hash of encoded public key. */
ret = wc_KyberKey_EncodePublicKey(key, pubKey, pubKeyLen);
}
#ifndef WOLFSSL_NO_MALLOC
/* Dispose of encoded public key. */
XFREE(pubKey, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
}
if ((ret == 0) && ((key->flags & MLKEM_FLAG_H_SET) == 0)) {
/* Implementation issue if h not cached and flag set. */
ret = BAD_STATE_E;
}
return ret;
}
#endif
#ifndef WOLFSSL_MLKEM_NO_ENCAPSULATE
/**
* Encapsulate with random number generator and derive secret.
@@ -1084,43 +1133,8 @@ int wc_MlKemKey_EncapsulateWithRandom(MlKemKey* key, unsigned char* c,
}
#endif
/* If public hash (h) is not stored against key, calculate it
* (fields set explicitly instead of using decode).
* Step 1: ... H(ek)...
*/
if ((ret == 0) && ((key->flags & MLKEM_FLAG_H_SET) == 0)) {
#ifndef WOLFSSL_NO_MALLOC
byte* pubKey = NULL;
word32 pubKeyLen;
#else
byte pubKey[WC_ML_KEM_MAX_PUBLIC_KEY_SIZE];
word32 pubKeyLen = WC_ML_KEM_MAX_PUBLIC_KEY_SIZE;
#endif
#ifndef WOLFSSL_NO_MALLOC
/* Determine how big an encoded public key will be. */
ret = wc_KyberKey_PublicKeySize(key, &pubKeyLen);
if (ret == 0) {
/* Allocate dynamic memory for encoded public key. */
pubKey = (byte*)XMALLOC(pubKeyLen, key->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (pubKey == NULL) {
ret = MEMORY_E;
}
}
if (ret == 0) {
#endif
/* Encode public key - h is hash of encoded public key. */
ret = wc_KyberKey_EncodePublicKey(key, pubKey, pubKeyLen);
#ifndef WOLFSSL_NO_MALLOC
}
/* Dispose of encoded public key. */
XFREE(pubKey, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
}
if ((ret == 0) && ((key->flags & MLKEM_FLAG_H_SET) == 0)) {
/* Implementation issue if h not cached and flag set. */
ret = BAD_STATE_E;
if (ret == 0) {
ret = wc_mlkemkey_check_h(key);
}
#ifdef WOLFSSL_MLKEM_KYBER
@@ -1205,6 +1219,8 @@ int wc_MlKemKey_EncapsulateWithRandom(MlKemKey* key, unsigned char* c,
}
#endif
ForceZero(kr, sizeof(kr));
return ret;
}
#endif /* !WOLFSSL_MLKEM_NO_ENCAPSULATE */
@@ -1487,6 +1503,10 @@ int wc_MlKemKey_Decapsulate(MlKemKey* key, unsigned char* ss,
/* Decapsulate the cipher text. */
ret = mlkemkey_decapsulate(key, msg, ct);
}
if (ret == 0) {
/* Check we have H, hash of public, set. */
ret = wc_mlkemkey_check_h(key);
}
if (ret == 0) {
/* Hash message into seed buffer. */
ret = MLKEM_HASH_G(&key->hash, msg, WC_ML_KEM_SYM_SZ, key->h,
@@ -1541,6 +1561,9 @@ int wc_MlKemKey_Decapsulate(MlKemKey* key, unsigned char* ss,
}
#endif
ForceZero(msg, sizeof(msg));
ForceZero(kr, sizeof(kr));
return ret;
}
#endif /* WOLFSSL_MLKEM_NO_DECAPSULATE */
+26 -2
View File
@@ -20574,7 +20574,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void)
#ifdef WC_DRBG_BANKREF
WC_ALLOC_VAR_EX(rng, WC_RNG, 1, HEAP_HINT,
DYNAMIC_TYPE_TMP_BUFFER,
return WC_TEST_RET_ENC_EC(MEMORY_E));
ERROR_OUT(WC_TEST_RET_ENC_EC(MEMORY_E), out));
XMEMSET(rng, 0, sizeof(*rng));
#endif
@@ -21039,7 +21039,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t memory_test(void)
{
wc_test_ret_t ret = 0;
word32 j = 0; /* used in embedded const pointer test */
WOLFSSL_ENTER("memory_test");
#if defined(COMPLEX_MEM_TEST) || defined(WOLFSSL_STATIC_MEMORY)
int i;
@@ -21053,6 +21052,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t memory_test(void)
* alignment when tests are ran */
#endif
WOLFSSL_ENTER("memory_test");
#ifdef WOLFSSL_STATIC_MEMORY
/* check macro settings */
if (sizeof(size)/sizeof(word32) != WOLFMEM_DEF_BUCKETS) {
@@ -42961,6 +42962,29 @@ static wc_test_ret_t mlkem512_kat(void)
if (XMEMCMP(ss_dec, ml_kem_512_ss, sizeof(ml_kem_512_ss)) != 0)
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
#ifndef WOLFSSL_MLKEM_NO_MAKE_KEY
wc_MlKemKey_Free(key);
XMEMSET(key, 0, sizeof(MlKemKey));
key_inited = 0;
ret = wc_MlKemKey_Init(key, WC_ML_KEM_512, HEAP_HINT, devId);
if (ret != 0)
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
else
key_inited = 1;
ret = wc_MlKemKey_MakeKeyWithRandom(key, kyber512_rand,
sizeof(kyber512_rand));
if (ret != 0)
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
ret = wc_MlKemKey_Decapsulate(key, ss_dec, ml_kem_512_ct,
sizeof(ml_kem_512_ct));
if (ret != 0)
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
if (XMEMCMP(ss_dec, ml_kem_512_ss, sizeof(ml_kem_512_ss)) != 0)
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
#endif
#else
(void)ml_kem_512_ct;
(void)ml_kem_512_ss;
+74 -26
View File
@@ -1279,16 +1279,6 @@ enum {
#endif
#endif /* NO_DH */
#ifndef MAX_PSK_ID_LEN
/* max psk identity/hint supported */
#if defined(WOLFSSL_TLS13)
/* OpenSSL has a 1472 byte session ticket */
#define MAX_PSK_ID_LEN 1536
#else
#define MAX_PSK_ID_LEN 128
#endif
#endif
#ifndef MAX_PSK_KEY_LEN
#define MAX_PSK_KEY_LEN 64
#endif
@@ -2046,6 +2036,7 @@ WOLFSSL_LOCAL int NamedGroupIsPqcHybrid(int group);
#define MAX_ENCRYPT_SZ ENCRYPT_LEN
#define WOLFSSL_ASSERT_EQ(x, y) wc_static_assert((x) == (y))
#define WOLFSSL_ASSERT_GE(x, y) wc_static_assert((x) >= (y))
#define WOLFSSL_ASSERT_SIZEOF_GE(x, y) wc_static_assert(sizeof(x) >= sizeof(y))
@@ -3169,7 +3160,10 @@ struct TLSX {
struct TLSX* next; /* List Behavior */
};
WOLFSSL_LOCAL TLSX* TLSX_Find(TLSX* list, TLSX_Type type);
#ifdef WOLFSSL_API_PREFIX_MAP
#define TLSX_Find wolfSSL_TLSX_Find
#endif
WOLFSSL_TEST_VIS TLSX* TLSX_Find(TLSX* list, TLSX_Type type);
WOLFSSL_LOCAL void TLSX_Remove(TLSX** list, TLSX_Type type, void* heap);
WOLFSSL_LOCAL void TLSX_FreeAll(TLSX* list, void* heap);
WOLFSSL_LOCAL int TLSX_SupportExtensions(WOLFSSL* ssl);
@@ -3237,6 +3231,10 @@ WOLFSSL_LOCAL int TLSX_UseSNI(TLSX** extensions, byte type, const void* data,
WOLFSSL_LOCAL byte TLSX_SNI_Status(TLSX* extensions, byte type);
WOLFSSL_LOCAL word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type,
void** data, byte ignoreStatus);
#ifdef WOLFSSL_API_PREFIX_MAP
#define TLSX_SNI_GetSize wolfSSL_TLSX_SNI_GetSize
#endif
WOLFSSL_TEST_VIS word16 TLSX_SNI_GetSize(SNI* list);
#ifndef NO_WOLFSSL_SERVER
WOLFSSL_LOCAL void TLSX_SNI_SetOptions(TLSX* extensions, byte type,
@@ -3463,6 +3461,11 @@ WOLFSSL_LOCAL int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap);
#endif /* HAVE_SECURE_RENEGOTIATION */
#ifdef HAVE_SESSION_TICKET
/* Max peer cert size for ticket: 2KB is reasonable for most RSA/ECC certs */
#ifndef MAX_TICKET_PEER_CERT_SZ
#define MAX_TICKET_PEER_CERT_SZ 2048
#endif
/* Our ticket format. All members need to be a byte or array of byte to
* avoid alignment issues */
typedef struct InternalTicket {
@@ -3488,21 +3491,40 @@ typedef struct InternalTicket {
byte sessionCtxSz; /* sessionCtx length */
byte sessionCtx[ID_LEN]; /* app specific context id */
#endif /* OPENSSL_EXTRA */
#if defined(OPENSSL_ALL) && defined(KEEP_PEER_CERT) && \
!defined(NO_CERT_IN_TICKET)
byte peerCertLen[OPAQUE16_LEN]; /* peer cert length */
byte peerCert[]; /* peer certificate DER - variable length */
#endif
} InternalTicket;
/* Base size of InternalTicket without the variable-length peerCert field */
#define WOLFSSL_INTERNAL_TICKET_BASE_SZ (sizeof(InternalTicket))
/* Minimum internal ticket length (no peer cert) */
#ifndef WOLFSSL_TICKET_ENC_CBC_HMAC
#define WOLFSSL_INTERNAL_TICKET_LEN sizeof(InternalTicket)
#define WOLFSSL_INTERNAL_TICKET_LEN WOLFSSL_INTERNAL_TICKET_BASE_SZ
#else
#define WOLFSSL_INTERNAL_TICKET_LEN \
(((sizeof(InternalTicket) + 15) / 16) * 16)
(((WOLFSSL_INTERNAL_TICKET_BASE_SZ + 15) / 16) * 16)
#endif
/* Maximum internal ticket length (with max peer cert) */
#if defined(OPENSSL_ALL) && defined(KEEP_PEER_CERT) && \
!defined(NO_CERT_IN_TICKET)
#define WOLFSSL_INTERNAL_TICKET_MAX_SZ \
(WOLFSSL_INTERNAL_TICKET_BASE_SZ + MAX_TICKET_PEER_CERT_SZ)
#else
#define WOLFSSL_INTERNAL_TICKET_MAX_SZ WOLFSSL_INTERNAL_TICKET_BASE_SZ
#endif
#ifndef WOLFSSL_TICKET_EXTRA_PADDING_SZ
#define WOLFSSL_TICKET_EXTRA_PADDING_SZ 32
#endif
/* Maximum encrypted ticket size */
#define WOLFSSL_TICKET_ENC_SZ \
(sizeof(InternalTicket) + WOLFSSL_TICKET_EXTRA_PADDING_SZ)
(WOLFSSL_INTERNAL_TICKET_MAX_SZ + WOLFSSL_TICKET_EXTRA_PADDING_SZ)
/* RFC 5077 defines this for session tickets. All members need to be a byte or
* array of byte to avoid alignment issues */
@@ -3510,14 +3532,18 @@ typedef struct ExternalTicket {
byte key_name[WOLFSSL_TICKET_NAME_SZ]; /* key context name - 16 */
byte iv[WOLFSSL_TICKET_IV_SZ]; /* this ticket's iv - 16 */
byte enc_len[OPAQUE16_LEN]; /* encrypted length - 2 */
byte enc_ticket[WOLFSSL_TICKET_ENC_SZ];
/* encrypted internal ticket */
byte mac[WOLFSSL_TICKET_MAC_SZ]; /* total mac - 32 */
byte enc_ticket[]; /* encrypted ticket - var length
* + total mac - 32 */
} ExternalTicket;
/* Cast to int to reduce amount of casts in code */
#define SESSION_TICKET_LEN ((int)sizeof(ExternalTicket))
#define WOLFSSL_TICKET_FIXED_SZ (SESSION_TICKET_LEN - WOLFSSL_TICKET_ENC_SZ)
/* Fixed portion of external ticket (key_name + iv + enc_len) */
#define WOLFSSL_TICKET_FIXED_SZ \
(WOLFSSL_TICKET_NAME_SZ + WOLFSSL_TICKET_IV_SZ + OPAQUE16_LEN + \
WOLFSSL_TICKET_MAC_SZ)
/* Maximum session ticket length */
#define SESSION_TICKET_LEN \
((int)(WOLFSSL_TICKET_FIXED_SZ + WOLFSSL_TICKET_ENC_SZ))
typedef struct SessionTicket {
word32 lifetime;
@@ -3559,6 +3585,20 @@ WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket, void* heap);
#endif /* HAVE_SESSION_TICKET */
#ifndef MAX_PSK_ID_LEN
/* max psk identity/hint supported */
#if defined(WOLFSSL_TLS13)
#ifdef SESSION_TICKET_LEN
#define MAX_PSK_ID_LEN SESSION_TICKET_LEN
#else
/* Previous value. Use as fallback for when tickets are disabled. */
#define MAX_PSK_ID_LEN 1536
#endif
#else
#define MAX_PSK_ID_LEN 128
#endif
#endif
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
int TLSX_EncryptThenMac_Respond(WOLFSSL* ssl);
#endif
@@ -6411,12 +6451,20 @@ struct SystemCryptoPolicy {
* for the caller to find so we clear the last error.
*/
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_HAVE_ERROR_QUEUE)
#define CLEAR_ASN_NO_PEM_HEADER_ERROR(err) \
(err) = wolfSSL_ERR_peek_last_error(); \
if (wolfSSL_ERR_GET_LIB(err) == WOLFSSL_ERR_LIB_PEM && \
wolfSSL_ERR_GET_REASON(err) == -WOLFSSL_PEM_R_NO_START_LINE_E) { \
wc_RemoveErrorNode(-1); \
}
#define CLEAR_ASN_NO_PEM_HEADER_ERROR(err) \
do { \
(err) = wolfSSL_ERR_peek_last_error(); \
if (wolfSSL_ERR_GET_LIB(err) == WOLFSSL_ERR_LIB_PEM && \
wolfSSL_ERR_GET_REASON(err) == -WOLFSSL_PEM_R_NO_START_LINE_E) { \
unsigned long peekErr; \
do { \
wc_RemoveErrorNode(-1); \
peekErr = wolfSSL_ERR_peek_last_error(); \
} while (wolfSSL_ERR_GET_LIB(peekErr) == WOLFSSL_ERR_LIB_PEM && \
wolfSSL_ERR_GET_REASON(peekErr) == \
-WOLFSSL_PEM_R_NO_START_LINE_E); \
} \
} while(0)
#else
#define CLEAR_ASN_NO_PEM_HEADER_ERROR(err) (void)(err);
#endif
+4
View File
@@ -379,6 +379,9 @@ int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group,
WOLFSSL_API int wolfSSL_EC_POINT_copy(WOLFSSL_EC_POINT *dest,
const WOLFSSL_EC_POINT *src);
WOLFSSL_API
WOLFSSL_EC_POINT *wolfSSL_EC_POINT_dup(const WOLFSSL_EC_POINT *src,
const WOLFSSL_EC_GROUP *group);
WOLFSSL_API
void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *point);
WOLFSSL_API
int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group,
@@ -479,6 +482,7 @@ typedef WOLFSSL_EC_KEY_METHOD EC_KEY_METHOD;
#define EC_POINT_clear_free wolfSSL_EC_POINT_clear_free
#define EC_POINT_cmp wolfSSL_EC_POINT_cmp
#define EC_POINT_copy wolfSSL_EC_POINT_copy
#define EC_POINT_dup wolfSSL_EC_POINT_dup
#define EC_POINT_is_at_infinity wolfSSL_EC_POINT_is_at_infinity
#define EC_get_builtin_curves wolfSSL_EC_get_builtin_curves
+7 -2
View File
@@ -632,16 +632,18 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS;
#define sk_X509_push wolfSSL_sk_X509_push
#define sk_X509_pop wolfSSL_sk_X509_pop
#define sk_X509_pop_free wolfSSL_sk_X509_pop_free
#define sk_X509_dup wolfSSL_sk_dup
#define sk_X509_dup wolfSSL_shallow_sk_dup
#define sk_X509_free wolfSSL_sk_X509_free
#define X509_chain_up_ref wolfSSL_X509_chain_up_ref
#define sk_X509_CRL_new wolfSSL_sk_X509_CRL_new
#define sk_X509_CRL_new_null wolfSSL_sk_X509_CRL_new_null
#define sk_X509_CRL_pop_free wolfSSL_sk_X509_CRL_pop_free
#define sk_X509_CRL_free wolfSSL_sk_X509_CRL_free
#define sk_X509_CRL_push wolfSSL_sk_X509_CRL_push
#define sk_X509_CRL_value wolfSSL_sk_X509_CRL_value
#define sk_X509_CRL_num wolfSSL_sk_X509_CRL_num
#define sk_X509_CRL_dup wolfSSL_shallow_sk_dup
#define sk_X509_OBJECT_new wolfSSL_sk_X509_OBJECT_new
#define sk_X509_OBJECT_free wolfSSL_sk_X509_OBJECT_free
@@ -824,6 +826,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_
#define X509_CRL_new wolfSSL_X509_CRL_new
#define X509_CRL_dup wolfSSL_X509_CRL_dup
#define X509_CRL_up_ref wolfSSL_X509_CRL_up_ref
#define X509_CRL_free wolfSSL_X509_CRL_free
#define X509_CRL_sign wolfSSL_X509_CRL_sign
#define X509_CRL_get_lastUpdate wolfSSL_X509_CRL_get_lastUpdate
@@ -1333,11 +1336,13 @@ typedef WOLFSSL_SRTP_PROTECTION_PROFILE SRTP_PROTECTION_PROFILE;
#define SSL_SESSION_get_id wolfSSL_SESSION_get_id
#define SSL_get_cipher_bits(s,np) \
wolfSSL_CIPHER_get_bits(SSL_get_current_cipher(s),np)
#define SSL_get_cipher_version(s) \
wolfSSL_CIPHER_get_version(SSL_get_current_cipher(s))
#define sk_SSL_CIPHER_num wolfSSL_sk_SSL_CIPHER_num
#define sk_SSL_COMP_zero wolfSSL_sk_SSL_COMP_zero
#define sk_SSL_CIPHER_value wolfSSL_sk_SSL_CIPHER_value
#endif /* OPENSSL_ALL || WOLFSSL_HAPROXY */
#define sk_SSL_CIPHER_dup wolfSSL_sk_dup
#define sk_SSL_CIPHER_dup wolfSSL_shallow_sk_dup
#define sk_SSL_CIPHER_free wolfSSL_sk_SSL_CIPHER_free
#define sk_SSL_CIPHER_find wolfSSL_sk_SSL_CIPHER_find
+2
View File
@@ -1952,6 +1952,7 @@ WOLFSSL_API WOLFSSL_X509* wolfSSL_sk_X509_pop(WOLF_STACK_OF(WOLFSSL_X509)* sk);
WOLFSSL_API void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509)* sk);
WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_X509_CRL_new(void);
WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_X509_CRL_new_null(void);
WOLFSSL_API void wolfSSL_sk_X509_CRL_pop_free(WOLF_STACK_OF(WOLFSSL_X509_CRL)* sk,
void (*f) (WOLFSSL_X509_CRL*));
WOLFSSL_API void wolfSSL_sk_X509_CRL_free(WOLF_STACK_OF(WOLFSSL_X509_CRL)* sk);
@@ -3517,6 +3518,7 @@ WOLFSSL_API int wolfSSL_X509_REVOKED_get_serial_number(RevokedCert* rev,
#endif
#if defined(HAVE_CRL) && (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL))
WOLFSSL_API WOLFSSL_X509_CRL* wolfSSL_X509_CRL_dup(const WOLFSSL_X509_CRL* crl);
WOLFSSL_API int wolfSSL_X509_CRL_up_ref(WOLFSSL_X509_CRL* crl);
WOLFSSL_API void wolfSSL_X509_CRL_free(WOLFSSL_X509_CRL *crl);
#endif
#if defined(HAVE_CRL) && defined(OPENSSL_EXTRA)
+7
View File
@@ -806,6 +806,13 @@ int wc_AesSivDecrypt_ex(const byte* key, word32 keySz, const AesSivAssoc* assoc,
const byte* in, word32 inSz, byte* siv, byte* out);
#endif
#ifdef WOLFSSL_CMAC
/* forward declaration, in case aes.h is being included by cmac.h */
struct Cmac;
WOLFSSL_LOCAL int wc_local_CmacUpdateAes(struct Cmac *cmac, const byte* in,
word32 inSz);
#endif
#ifdef WOLFSSL_AES_EAX
/* Because of the circular dependency between AES and CMAC, we need to prevent
+6
View File
@@ -2506,6 +2506,12 @@ WOLFSSL_LOCAL word32 SetSet(word32 len, byte* output);
WOLFSSL_API word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz);
WOLFSSL_LOCAL word32 SetAlgoIDEx(int algoOID, byte* output, int type, int curveSz,
byte absentParams);
#if defined(WC_RSA_PSS) && !defined(NO_RSA)
WOLFSSL_LOCAL word32 wc_EncodeRsaPssAlgoId(int hashOID, int saltLen, byte* out,
word32 outSz);
WOLFSSL_TEST_VIS int wc_DecodeRsaPssParams(const byte* params, word32 sz,
enum wc_HashType* hash, int* mgf, int* saltLen);
#endif
WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header);
WOLFSSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output,
word32 outputSz, int maxSnSz);
+7
View File
@@ -388,6 +388,13 @@ struct wc_PKCS7 {
CallbackEccSignRawDigest eccSignRawDigestCb;
#endif
#if defined(WC_RSA_PSS) && !defined(NO_RSA)
int pssSaltLen; /* RSASSA-PSS params from SignerInfo; valid when */
int pssHashType; /* pssParamsPresent == 1; else verify path uses */
int pssMgf; /* RSA_PSS_SALT_LEN_DEFAULT / digest algo defaults */
byte pssParamsPresent;
#endif
/* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */
};
+1 -7
View File
@@ -102,13 +102,7 @@
#define WOLFSSL_NO_HASH_RAW
#endif
#if defined(_MSC_VER)
#define SHA256_NOINLINE __declspec(noinline)
#elif defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__)
#define SHA256_NOINLINE __attribute__((noinline))
#else
#define SHA256_NOINLINE
#endif
#define SHA256_NOINLINE WC_NO_INLINE
#if !defined(NO_OLD_SHA_NAMES)
#define SHA256 WC_SHA256
+1 -7
View File
@@ -80,13 +80,7 @@
#include <wolfssl/wolfcrypt/port/st/stm32.h>
#endif
#if defined(_MSC_VER)
#define SHA512_NOINLINE __declspec(noinline)
#elif defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__)
#define SHA512_NOINLINE __attribute__((noinline))
#else
#define SHA512_NOINLINE
#endif
#define SHA512_NOINLINE WC_NO_INLINE
#ifdef WOLFSSL_SHA512
+1 -12
View File
@@ -48,18 +48,7 @@
#undef WOLFSSL_HAVE_SP_ECC
#endif
#ifdef noinline
#define SP_NOINLINE noinline
#elif defined(_MSC_VER)
#define SP_NOINLINE __declspec(noinline)
#elif defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
#define SP_NOINLINE _Pragma("inline = never")
#elif defined(__GNUC__) || defined(__KEIL__) || defined(__DCC__)
#define SP_NOINLINE __attribute__((noinline))
#else
#define SP_NOINLINE
#endif
#define SP_NOINLINE WC_NO_INLINE
#ifdef __cplusplus
extern "C" {
+27
View File
@@ -2056,6 +2056,33 @@ WOLFSSL_API word32 CheckRunTimeSettings(void);
#define WC_NORETURN
#endif
#ifdef __has_attribute
#if __has_attribute(nonnull)
#ifndef WC_ARG_NOT_NULL
#define WC_ARG_NOT_NULL(a) __attribute__((nonnull(a)))
#endif
#ifndef WC_ARGS_NOT_NULL
/* double-parenthesize, a la WC_ARGS_NOT_NULL((1, 2)) -- this approach
* maintains compatibility with WOLF_NO_VARIADIC_MACROS.
*/
#define WC_ARGS_NOT_NULL(p_a) __attribute__((nonnull p_a))
#endif
#ifndef WC_ALL_ARGS_NOT_NULL
#define WC_ALL_ARGS_NOT_NULL __attribute__((nonnull))
#endif
#endif /* __has_attribute(nonnull) */
#endif /* defined(__has_attribute) */
#ifndef WC_ARG_NOT_NULL
#define WC_ARG_NOT_NULL(a) /* null expansion */
#endif
#ifndef WC_ARGS_NOT_NULL
#define WC_ARGS_NOT_NULL(p_a) /* null expansion */
#endif
#ifndef WC_ALL_ARGS_NOT_NULL
#define WC_ALL_ARGS_NOT_NULL
#endif
#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) || \
defined(WOLFSSL_PUBLIC_MP) || defined(OPENSSL_EXTRA) || \
+1 -9
View File
@@ -44,15 +44,7 @@
#define WOLFSSL_MLKEM_NO_DECAPSULATE
#endif
#ifdef noinline
#define MLKEM_NOINLINE noinline
#elif defined(_MSC_VER)
#define MLKEM_NOINLINE __declspec(noinline)
#elif defined(__GNUC__)
#define MLKEM_NOINLINE __attribute__((noinline))
#else
#define MLKEM_NOINLINE
#endif
#define MLKEM_NOINLINE WC_NO_INLINE
enum {
/* Flags of Kyber keys. */
+15 -1
View File
@@ -104,7 +104,7 @@
#else
#define WC_DEPRECATED(msg) /* null expansion */
#endif
#endif /* !WC_MAYBE_UNUSED */
#endif /* !WC_DEPRECATED */
/* use inlining if compiler allows */
#ifndef WC_INLINE
@@ -143,6 +143,20 @@
#endif
#endif
#ifndef WC_NO_INLINE
#ifdef noinline
#define WC_NO_INLINE noinline
#elif defined(_MSC_VER)
#define WC_NO_INLINE __declspec(noinline)
#elif defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__)
#define WC_NO_INLINE _Pragma("inline = never")
#elif defined(__GNUC__) || defined(__KEIL__) || defined(__DCC__)
#define WC_NO_INLINE __attribute__((noinline))
#else
#define WC_NO_INLINE
#endif
#endif
#ifndef WC_OMIT_FRAME_POINTER
#if defined(__GNUC__)
#define WC_OMIT_FRAME_POINTER \
+16
View File
@@ -312,6 +312,22 @@ fn scan_cfg() -> Result<()> {
println!("cargo:rustc-cfg=rsa_const_api");
}
/* dilithium / ML-DSA */
check_cfg(&binding, "wc_dilithium_init", "dilithium");
check_cfg(&binding, "wc_dilithium_make_key", "dilithium_make_key");
check_cfg(&binding, "wc_dilithium_make_key_from_seed", "dilithium_make_key_from_seed");
check_cfg(&binding, "wc_dilithium_sign_msg", "dilithium_sign");
check_cfg(&binding, "wc_dilithium_sign_msg_with_seed", "dilithium_sign_with_seed");
check_cfg(&binding, "wc_dilithium_verify_msg", "dilithium_verify");
check_cfg(&binding, "wc_dilithium_import_public", "dilithium_import");
check_cfg(&binding, "wc_dilithium_export_public", "dilithium_export");
check_cfg(&binding, "wc_dilithium_check_key", "dilithium_check_key");
check_cfg(&binding, "DILITHIUM_LEVEL2_KEY_SIZE", "dilithium_level2");
check_cfg(&binding, "DILITHIUM_LEVEL3_KEY_SIZE", "dilithium_level3");
check_cfg(&binding, "DILITHIUM_LEVEL5_KEY_SIZE", "dilithium_level5");
check_cfg(&binding, "DILITHIUM_SEED_SZ", "dilithium_make_key_seed_sz");
check_cfg(&binding, "DILITHIUM_RND_SZ", "dilithium_rnd_sz");
/* sha */
check_cfg(&binding, "wc_InitSha", "sha");
check_cfg(&binding, "wc_InitSha224", "sha224");
+1
View File
@@ -19,3 +19,4 @@
#include "wolfssl/wolfcrypt/logging.h"
#include "wolfssl/wolfcrypt/aes.h"
#include "wolfssl/wolfcrypt/pwdbased.h"
#include "wolfssl/wolfcrypt/dilithium.h"
File diff suppressed because it is too large Load Diff
@@ -29,6 +29,7 @@ pub mod chacha20_poly1305;
pub mod cmac;
pub mod curve25519;
pub mod dh;
pub mod dilithium;
pub mod ecc;
pub mod ed25519;
pub mod ed448;
@@ -5,6 +5,7 @@ fn setup_fips()
fips::set_private_key_read_enable(1).expect("Error with set_private_key_read_enable()");
}
#[allow(dead_code)]
pub fn setup()
{
#[cfg(fips)]
@@ -0,0 +1,437 @@
/*
* Copyright (C) 2006-2026 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
*/
#![cfg(dilithium)]
mod common;
use wolfssl_wolfcrypt::dilithium::Dilithium;
#[cfg(all(random, any(dilithium_make_key, dilithium_sign)))]
use wolfssl_wolfcrypt::random::RNG;
/// Verify the level constants have the correct numeric values required by
/// the wolfCrypt API.
#[test]
fn test_level_constants() {
assert_eq!(Dilithium::LEVEL_44, 2);
assert_eq!(Dilithium::LEVEL_65, 3);
assert_eq!(Dilithium::LEVEL_87, 5);
}
/// Verify `new()` + `set_level()` + `get_level()` for all three parameter sets.
#[test]
fn test_new_and_level() {
common::setup();
let mut key = Dilithium::new().expect("Error with new()");
key.set_level(Dilithium::LEVEL_44).expect("Error with set_level()");
assert_eq!(key.get_level().expect("Error with get_level()"), Dilithium::LEVEL_44);
key.set_level(Dilithium::LEVEL_65).expect("Error with set_level()");
assert_eq!(key.get_level().expect("Error with get_level()"), Dilithium::LEVEL_65);
key.set_level(Dilithium::LEVEL_87).expect("Error with set_level()");
assert_eq!(key.get_level().expect("Error with get_level()"), Dilithium::LEVEL_87);
}
/// Verify that `new_ex()` accepts the optional heap and device ID parameters.
#[test]
fn test_new_ex() {
common::setup();
let mut key = Dilithium::new_ex(None, None).expect("Error with new_ex()");
key.set_level(Dilithium::LEVEL_44).expect("Error with set_level()");
assert_eq!(key.get_level().expect("Error with get_level()"), Dilithium::LEVEL_44);
}
/// Verify the runtime size queries match the compile-time constants for
/// ML-DSA-44.
#[test]
#[cfg(all(dilithium_make_key, dilithium_level2))]
fn test_sizes_level44() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key = Dilithium::generate(Dilithium::LEVEL_44, &mut rng)
.expect("Error with generate()");
assert_eq!(key.size().expect("Error with size()"), Dilithium::LEVEL2_KEY_SIZE);
assert_eq!(key.priv_size().expect("Error with priv_size()"), Dilithium::LEVEL2_PRV_KEY_SIZE);
assert_eq!(key.pub_size().expect("Error with pub_size()"), Dilithium::LEVEL2_PUB_KEY_SIZE);
assert_eq!(key.sig_size().expect("Error with sig_size()"), Dilithium::LEVEL2_SIG_SIZE);
}
/// Verify the runtime size queries match the compile-time constants for
/// ML-DSA-65.
#[test]
#[cfg(all(dilithium_make_key, dilithium_level3))]
fn test_sizes_level65() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key = Dilithium::generate(Dilithium::LEVEL_65, &mut rng)
.expect("Error with generate()");
assert_eq!(key.size().expect("Error with size()"), Dilithium::LEVEL3_KEY_SIZE);
assert_eq!(key.priv_size().expect("Error with priv_size()"), Dilithium::LEVEL3_PRV_KEY_SIZE);
assert_eq!(key.pub_size().expect("Error with pub_size()"), Dilithium::LEVEL3_PUB_KEY_SIZE);
assert_eq!(key.sig_size().expect("Error with sig_size()"), Dilithium::LEVEL3_SIG_SIZE);
}
/// Verify the runtime size queries match the compile-time constants for
/// ML-DSA-87.
#[test]
#[cfg(all(dilithium_make_key, dilithium_level5))]
fn test_sizes_level87() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key = Dilithium::generate(Dilithium::LEVEL_87, &mut rng)
.expect("Error with generate()");
assert_eq!(key.size().expect("Error with size()"), Dilithium::LEVEL5_KEY_SIZE);
assert_eq!(key.priv_size().expect("Error with priv_size()"), Dilithium::LEVEL5_PRV_KEY_SIZE);
assert_eq!(key.pub_size().expect("Error with pub_size()"), Dilithium::LEVEL5_PUB_KEY_SIZE);
assert_eq!(key.sig_size().expect("Error with sig_size()"), Dilithium::LEVEL5_SIG_SIZE);
}
/// Verify that `check_key()` accepts a freshly generated ML-DSA-44 key pair.
#[test]
#[cfg(all(dilithium_make_key, dilithium_check_key))]
fn test_check_key_level44() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key = Dilithium::generate(Dilithium::LEVEL_44, &mut rng)
.expect("Error with generate()");
key.check_key().expect("Error with check_key()");
}
/// Verify that `check_key()` accepts a freshly generated ML-DSA-65 key pair.
#[test]
#[cfg(all(dilithium_make_key, dilithium_check_key))]
fn test_check_key_level65() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key = Dilithium::generate(Dilithium::LEVEL_65, &mut rng)
.expect("Error with generate()");
key.check_key().expect("Error with check_key()");
}
/// Verify that `check_key()` accepts a freshly generated ML-DSA-87 key pair.
#[test]
#[cfg(all(dilithium_make_key, dilithium_check_key))]
fn test_check_key_level87() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key = Dilithium::generate(Dilithium::LEVEL_87, &mut rng)
.expect("Error with generate()");
key.check_key().expect("Error with check_key()");
}
/// Sign and verify a message round-trip using ML-DSA-44.
///
/// Also verifies that a tampered message or signature produces a
/// verification failure rather than an error.
#[test]
#[cfg(all(dilithium_make_key, dilithium_sign, dilithium_verify))]
fn test_sign_verify_level44() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key = Dilithium::generate(Dilithium::LEVEL_44, &mut rng)
.expect("Error with generate()");
let message = b"Hello, ML-DSA-44!";
let mut sig = vec![0u8; key.sig_size().expect("Error with sig_size()")];
let sig_len = key.sign_msg(message, &mut sig, &mut rng)
.expect("Error with sign_msg()");
assert_eq!(sig_len, sig.len());
let valid = key.verify_msg(&sig, message).expect("Error with verify_msg()");
assert!(valid, "Valid signature should verify");
// A different message must not verify with the original signature.
let valid = key.verify_msg(&sig, b"Tampered message")
.expect("Error with verify_msg() on tampered message");
assert!(!valid, "Tampered message should not verify");
}
/// Sign and verify a message round-trip using ML-DSA-65.
#[test]
#[cfg(all(dilithium_make_key, dilithium_sign, dilithium_verify))]
fn test_sign_verify_level65() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key = Dilithium::generate(Dilithium::LEVEL_65, &mut rng)
.expect("Error with generate()");
let message = b"Hello, ML-DSA-65!";
let mut sig = vec![0u8; key.sig_size().expect("Error with sig_size()")];
let sig_len = key.sign_msg(message, &mut sig, &mut rng)
.expect("Error with sign_msg()");
assert_eq!(sig_len, sig.len());
let valid = key.verify_msg(&sig, message).expect("Error with verify_msg()");
assert!(valid, "Valid signature should verify");
}
/// Sign and verify a message round-trip using ML-DSA-87.
#[test]
#[cfg(all(dilithium_make_key, dilithium_sign, dilithium_verify))]
fn test_sign_verify_level87() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key = Dilithium::generate(Dilithium::LEVEL_87, &mut rng)
.expect("Error with generate()");
let message = b"Hello, ML-DSA-87!";
let mut sig = vec![0u8; key.sig_size().expect("Error with sig_size()")];
let sig_len = key.sign_msg(message, &mut sig, &mut rng)
.expect("Error with sign_msg()");
assert_eq!(sig_len, sig.len());
let valid = key.verify_msg(&sig, message).expect("Error with verify_msg()");
assert!(valid, "Valid signature should verify");
}
/// Sign with a context string and verify using ML-DSA-44.
///
/// Also verifies that a mismatched context causes verification to fail.
#[test]
#[cfg(all(dilithium_make_key, dilithium_sign, dilithium_verify))]
fn test_sign_ctx_verify_level44() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key = Dilithium::generate(Dilithium::LEVEL_44, &mut rng)
.expect("Error with generate()");
let message = b"Context-bound message";
let ctx = b"my context";
let mut sig = vec![0u8; key.sig_size().expect("Error with sig_size()")];
let sig_len = key.sign_ctx_msg(ctx, message, &mut sig, &mut rng)
.expect("Error with sign_ctx_msg()");
let valid = key.verify_ctx_msg(&sig[..sig_len], ctx, message)
.expect("Error with verify_ctx_msg()");
assert!(valid, "Valid context signature should verify");
// Wrong context must not verify.
let valid = key.verify_ctx_msg(&sig[..sig_len], b"wrong context", message)
.expect("Error with verify_ctx_msg() with wrong context");
assert!(!valid, "Wrong context should not verify");
}
/// Export both keys, re-import them separately, and verify that:
/// - a signature from the original key is accepted by a public-key-only
/// import, and
/// - the re-imported private key can sign messages that verify with the
/// original public key.
#[test]
#[cfg(all(dilithium_make_key, dilithium_import, dilithium_export, dilithium_sign, dilithium_verify))]
fn test_import_export_level44() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key = Dilithium::generate(Dilithium::LEVEL_44, &mut rng)
.expect("Error with generate()");
let priv_size = key.size().expect("Error with size()");
let pub_size = key.pub_size().expect("Error with pub_size()");
let sig_size = key.sig_size().expect("Error with sig_size()");
let mut priv_buf = vec![0u8; priv_size];
let mut pub_buf = vec![0u8; pub_size];
key.export_key(&mut priv_buf, &mut pub_buf).expect("Error with export_key()");
// Verify export_public and export_private return the same bytes.
let mut pub_buf2 = vec![0u8; pub_size];
let pub_written = key.export_public(&mut pub_buf2).expect("Error with export_public()");
assert_eq!(pub_written, pub_size);
assert_eq!(pub_buf2, pub_buf);
let mut priv_buf2 = vec![0u8; priv_size];
let priv_written = key.export_private(&mut priv_buf2).expect("Error with export_private()");
assert_eq!(priv_written, priv_size);
assert_eq!(priv_buf2, priv_buf);
// Sign with the original key.
let message = b"Import/export test message";
let mut sig = vec![0u8; sig_size];
let sig_len = key.sign_msg(message, &mut sig, &mut rng)
.expect("Error with sign_msg()");
// Re-import public key only and verify.
let mut pub_key = Dilithium::new().expect("Error with new()");
pub_key.set_level(Dilithium::LEVEL_44).expect("Error with set_level()");
pub_key.import_public(&pub_buf).expect("Error with import_public()");
let valid = pub_key.verify_msg(&sig[..sig_len], message)
.expect("Error with verify_msg() via imported public key");
assert!(valid, "Imported public key should accept original signature");
// Re-import private key, sign a message, and verify with the original key.
let mut priv_key = Dilithium::new().expect("Error with new()");
priv_key.set_level(Dilithium::LEVEL_44).expect("Error with set_level()");
priv_key.import_private(&priv_buf).expect("Error with import_private()");
let mut sig2 = vec![0u8; sig_size];
let sig2_len = priv_key.sign_msg(message, &mut sig2, &mut rng)
.expect("Error with sign_msg() from imported private key");
let valid = key.verify_msg(&sig2[..sig2_len], message)
.expect("Error with verify_msg() after import_private");
assert!(valid, "Signature from re-imported private key should verify");
}
/// Export both keys, import them together via `import_key()`, then sign and
/// verify using the re-imported key pair.
#[test]
#[cfg(all(dilithium_make_key, dilithium_import, dilithium_export, dilithium_sign, dilithium_verify))]
fn test_import_key_level44() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key = Dilithium::generate(Dilithium::LEVEL_44, &mut rng)
.expect("Error with generate()");
let priv_size = key.size().expect("Error with size()");
let pub_size = key.pub_size().expect("Error with pub_size()");
let sig_size = key.sig_size().expect("Error with sig_size()");
let mut priv_buf = vec![0u8; priv_size];
let mut pub_buf = vec![0u8; pub_size];
key.export_key(&mut priv_buf, &mut pub_buf).expect("Error with export_key()");
let mut key2 = Dilithium::new().expect("Error with new()");
key2.set_level(Dilithium::LEVEL_44).expect("Error with set_level()");
key2.import_key(&priv_buf, &pub_buf).expect("Error with import_key()");
let message = b"import_key round-trip";
let mut sig = vec![0u8; sig_size];
let sig_len = key2.sign_msg(message, &mut sig, &mut rng)
.expect("Error with sign_msg() from imported key pair");
let valid = key.verify_msg(&sig[..sig_len], message)
.expect("Error with verify_msg()");
assert!(valid, "Imported key pair should produce valid signatures");
}
/// Verify that `generate_from_seed()` is deterministic: the same seed
/// produces the same key pair on repeated calls.
#[test]
#[cfg(all(dilithium_make_key_from_seed, dilithium_export))]
fn test_generate_from_seed_determinism() {
common::setup();
// DILITHIUM_SEED_SZ = 32 bytes
let seed = [0x42u8; 32];
let mut key1 = Dilithium::generate_from_seed(Dilithium::LEVEL_44, &seed)
.expect("Error with generate_from_seed() first call");
let mut key2 = Dilithium::generate_from_seed(Dilithium::LEVEL_44, &seed)
.expect("Error with generate_from_seed() second call");
let pub_size = key1.pub_size().expect("Error with pub_size()");
let mut pub1 = vec![0u8; pub_size];
let mut pub2 = vec![0u8; pub_size];
key1.export_public(&mut pub1).expect("Error with export_public() key1");
key2.export_public(&mut pub2).expect("Error with export_public() key2");
assert_eq!(pub1, pub2, "Same seed must yield same public key");
let priv_size = key1.size().expect("Error with size()");
let mut priv1 = vec![0u8; priv_size];
let mut priv2 = vec![0u8; priv_size];
key1.export_private(&mut priv1).expect("Error with export_private() key1");
key2.export_private(&mut priv2).expect("Error with export_private() key2");
assert_eq!(priv1, priv2, "Same seed must yield same private key");
}
/// Verify that `sign_msg_with_seed()` is deterministic: the same key,
/// message, and signing seed always produce the same signature bytes, and
/// the signature verifies correctly.
#[test]
#[cfg(all(dilithium_make_key_from_seed, dilithium_sign_with_seed, dilithium_verify))]
fn test_sign_with_seed_determinism() {
common::setup();
// DILITHIUM_SEED_SZ = 32 bytes
let key_seed = [0x42u8; 32];
// DILITHIUM_RND_SZ = 32 bytes
let sign_seed = [0x55u8; 32];
let message = b"Deterministic ML-DSA signing test";
let mut key = Dilithium::generate_from_seed(Dilithium::LEVEL_44, &key_seed)
.expect("Error with generate_from_seed()");
let sig_size = key.sig_size().expect("Error with sig_size()");
let mut sig1 = vec![0u8; sig_size];
let mut sig2 = vec![0u8; sig_size];
let len1 = key.sign_msg_with_seed(message, &mut sig1, &sign_seed)
.expect("Error with sign_msg_with_seed() first call");
let len2 = key.sign_msg_with_seed(message, &mut sig2, &sign_seed)
.expect("Error with sign_msg_with_seed() second call");
assert_eq!(len1, len2, "Signature lengths must match");
assert_eq!(sig1[..len1], sig2[..len2], "Same inputs must yield same signature");
let valid = key.verify_msg(&sig1[..len1], message)
.expect("Error with verify_msg()");
assert!(valid, "Deterministically signed message should verify");
}
/// Verify that `sign_ctx_msg_with_seed()` is deterministic and that the
/// produced signature verifies with `verify_ctx_msg()`.
#[test]
#[cfg(all(dilithium_make_key_from_seed, dilithium_sign_with_seed, dilithium_verify))]
fn test_sign_ctx_with_seed_determinism() {
common::setup();
let key_seed = [0x11u8; 32];
let sign_seed = [0x22u8; 32];
let message = b"Context deterministic signing test";
let ctx = b"test-context";
let mut key = Dilithium::generate_from_seed(Dilithium::LEVEL_44, &key_seed)
.expect("Error with generate_from_seed()");
let sig_size = key.sig_size().expect("Error with sig_size()");
let mut sig1 = vec![0u8; sig_size];
let mut sig2 = vec![0u8; sig_size];
let len1 = key.sign_ctx_msg_with_seed(ctx, message, &mut sig1, &sign_seed)
.expect("Error with sign_ctx_msg_with_seed() first call");
let len2 = key.sign_ctx_msg_with_seed(ctx, message, &mut sig2, &sign_seed)
.expect("Error with sign_ctx_msg_with_seed() second call");
assert_eq!(len1, len2);
assert_eq!(sig1[..len1], sig2[..len2], "Same inputs must yield same signature");
let valid = key.verify_ctx_msg(&sig1[..len1], ctx, message)
.expect("Error with verify_ctx_msg()");
assert!(valid, "Context-signed message should verify");
}
/// Verify that `generate_from_seed()` + `sign_msg_with_seed()` +
/// `verify_msg()` work across all three security levels.
#[test]
#[cfg(all(dilithium_make_key_from_seed, dilithium_sign_with_seed, dilithium_verify))]
fn test_seed_sign_verify_all_levels() {
common::setup();
let key_seed = [0xABu8; 32];
let sign_seed = [0xCDu8; 32];
let message = b"All-levels seed sign/verify test";
for level in [Dilithium::LEVEL_44, Dilithium::LEVEL_65, Dilithium::LEVEL_87] {
let mut key = Dilithium::generate_from_seed(level, &key_seed)
.expect("Error with generate_from_seed()");
let sig_size = key.sig_size().expect("Error with sig_size()");
let mut sig = vec![0u8; sig_size];
let sig_len = key.sign_msg_with_seed(message, &mut sig, &sign_seed)
.expect("Error with sign_msg_with_seed()");
let valid = key.verify_msg(&sig[..sig_len], message)
.expect("Error with verify_msg()");
assert!(valid, "Level {} seed-signed message should verify", level);
}
}