mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-10 14:30:56 +02:00
Merge branch 'master' of https://github.com/wolfSSL/wolfssl into zd21204
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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 }}
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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'' ',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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: |
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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),
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
*/
|
||||
|
||||
@@ -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), \
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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, ¶mTag, inSz) != 0 ||
|
||||
GetLength(in, &idx, ¶mLen, 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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 !! */
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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" {
|
||||
|
||||
@@ -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) || \
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user