diff --git a/.github/workflows/cmake-autoconf.yml b/.github/workflows/cmake-autoconf.yml
new file mode 100644
index 0000000000..a29636ea75
--- /dev/null
+++ b/.github/workflows/cmake-autoconf.yml
@@ -0,0 +1,41 @@
+name: WolfSSL CMake Autoconf Interworking Test
+
+on:
+ push:
+ branches: [ 'master', 'main', 'release/**' ]
+ pull_request:
+ branches: [ '*' ]
+
+jobs:
+ build:
+ if: github.repository_owner == 'wolfssl'
+ runs-on: ubuntu-latest
+
+ steps:
+# pull wolfSSL
+ - uses: actions/checkout@v4
+
+# install cmake and autotools
+ - name: Install cmake
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y cmake autoconf automake libtool
+
+# build and install wolfssl via autotools for CMake consumer test
+ - name: Build wolfssl with autotools
+ run: |
+ ./autogen.sh
+ ./configure --prefix="$GITHUB_WORKSPACE/install-autoconf" --enable-all
+ make -j $(nproc)
+ make install
+
+# CMake consumer test using the autotools install
+ - name: CMake consumer test (autotools install)
+ run: |
+ mkdir -p cmake/consumer/build
+ cd cmake/consumer/build
+ cmake -DCMAKE_PREFIX_PATH="$GITHUB_WORKSPACE/install-autoconf" ..
+ cmake --build .
+ ./wolfssl_consumer
+ cd ..
+ rm -rf build
diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml
index 0e9b800acc..9639a7a6e9 100644
--- a/.github/workflows/cmake.yml
+++ b/.github/workflows/cmake.yml
@@ -13,7 +13,7 @@ jobs:
steps:
# pull wolfSSL
- - uses: actions/checkout@master
+ - uses: actions/checkout@v4
# install cmake
- name: Install cmake
@@ -21,24 +21,16 @@ jobs:
sudo apt-get update
sudo apt-get install -y cmake
-# pull wolfssl
- - name: Checkout wolfssl
- uses: actions/checkout@master
- with:
- repository: wolfssl/wolfssl
- path: wolfssl
-
# build wolfssl
- name: Build wolfssl
- working-directory: ./wolfssl
run: |
mkdir build
cd build
cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DWOLFSSL_INSTALL=yes -DCMAKE_INSTALL_PREFIX="$GITHUB_WORKSPACE/install" \
-DWOLFSSL_16BIT:BOOL=no -DWOLFSSL_32BIT:BOOL=no -DWOLFSSL_AES:BOOL=yes \
- -DWOLFSSL_AESCBC:BOOL=yes -DWOLFSSL_AESCCM:BOOL=yes -DWOLFSSL_AESCFB:BOOL=yes \
+ -DWOLFSSL_AESCBC:BOOL=yes -DWOLFSSL_AESCCM:BOOL=yes -DWOLFSSL_AESCFB:BOOL=yes -DWOLFSSL_AESECB:BOOL=yes \
-DWOLFSSL_AESCTR:BOOL=yes -DWOLFSSL_AESGCM:STRING=yes -DWOLFSSL_AESKEYWRAP:BOOL=yes \
- -DWOLFSSL_AESOFB:BOOL=yes -DWOLFSSL_AESSIV:BOOL=yes -DWOLFSSL_ALIGN_DATA:BOOL=yes \
+ -DWOLFSSL_AESOFB:BOOL=yes -DWOLFSSL_AESCTS:BOOL=yes -DWOLFSSL_AESSIV:BOOL=yes -DWOLFSSL_ALIGN_DATA:BOOL=yes \
-DWOLFSSL_ALPN:BOOL=ON -DWOLFSSL_ALT_CERT_CHAINS:BOOL=ON -DWOLFSSL_ARC4:BOOL=yes \
-DWOLFSSL_ARIA:BOOL=no -DWOLFSSL_ASIO:BOOL=no -DWOLFSSL_ASM:BOOL=yes -DWOLFSSL_ASN:BOOL=yes \
-DWOLFSSL_ASYNC_THREADS:BOOL=no -DWOLFSSL_BASE64_ENCODE:BOOL=yes -DWOLFSSL_CAAM:BOOL=no \
@@ -51,7 +43,7 @@ jobs:
-DWOLFSSL_CURVE448:STRING=yes -DWOLFSSL_DEBUG:BOOL=yes -DWOLFSSL_DES3:BOOL=ON \
-DWOLFSSL_DES3_TLS_SUITES:BOOL=no -DWOLFSSL_DH:STRING=yes -DWOLFSSL_DH_DEFAULT_PARAMS:BOOL=yes \
-DWOLFSSL_DSA:BOOL=yes -DWOLFSSL_DTLS:BOOL=ON -DWOLFSSL_DTLS13:BOOL=yes \
- -DWOLFSSL_DTLS_CID:BOOL=yes -DWOLFSSL_ECC:STRING=yes \
+ -DWOLFSSL_DTLS_CID:BOOL=yes -DWOLFSSL_DTLS_CH_FRAG:BOOL=yes -DWOLFSSL_ECC:STRING=yes \
-DWOLFSSL_ECCCUSTCURVES:STRING=all -DWOLFSSL_ECCSHAMIR:BOOL=yes \
-DWOLFSSL_ECH:BOOL=yes -DWOLFSSL_ED25519:BOOL=yes -DWOLFSSL_ED448:STRING=yes \
-DWOLFSSL_ENCKEYS:BOOL=yes -DWOLFSSL_ENC_THEN_MAC:BOOL=yes -DWOLFSSL_ERROR_QUEUE:BOOL=yes \
@@ -80,7 +72,7 @@ jobs:
-DWOLFSSL_MLKEM=1 -DWOLFSSL_LMS=1 -DWOLFSSL_LMSSHA256192=1 -DWOLFSSL_EXPERIMENTAL=1 \
-DWOLFSSL_X963KDF:BOOL=yes -DWOLFSSL_DILITHIUM:BOOL=yes -DWOLFSSL_PKCS11:BOOL=yes \
-DWOLFSSL_ECCSI:BOOL=yes -DWOLFSSL_SAKKE:BOOL=yes -DWOLFSSL_SIPHASH:BOOL=yes \
- -DCMAKE_C_FLAGS="-DWOLFSSL_DTLS_CH_FRAG" \
+ -DWOLFSSL_WC_RSA_DIRECT:BOOL=yes -DWOLFSSL_PUBLIC_MP:BOOL=yes \
..
cmake --build .
ctest -j $(nproc)
@@ -92,7 +84,6 @@ jobs:
# build "lean-tls" wolfssl
- name: Build wolfssl with lean-tls
- working-directory: ./wolfssl
run: |
mkdir build
cd build
@@ -108,7 +99,6 @@ jobs:
# CMake build with user_settings.h
- name: Build wolfssl with user_settings.h
- working-directory: ./wolfssl
run: |
mkdir build
cp examples/configs/user_settings_all.h ./build/user_settings.h
diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml
index 2c35f6da5d..2e6c32d04f 100644
--- a/.github/workflows/os-check.yml
+++ b/.github/workflows/os-check.yml
@@ -70,6 +70,9 @@ jobs:
'--enable-all --enable-certgencache',
'--enable-sessionexport --enable-dtls --enable-dtls13',
'--enable-sessionexport',
+ '--enable-cryptocb --enable-aesgcm CPPFLAGS="-DWOLF_CRYPTO_CB_AES_SETKEY -DWOLF_CRYPTO_CB_FREE"',
+ '--disable-tls --enable-cryptocb --enable-aesgcm CPPFLAGS="-DWOLF_CRYPTO_CB_AES_SETKEY -DWOLF_CRYPTO_CB_FREE"',
+ '--enable-cryptocb --enable-aesgcm CPPFLAGS="-DWOLF_CRYPTO_CB_AES_SETKEY"',
'--disable-examples CPPFLAGS=-DWOLFSSL_NO_MALLOC',
'CPPFLAGS=-DNO_WOLFSSL_CLIENT',
'CPPFLAGS=-DNO_WOLFSSL_SERVER',
diff --git a/.gitignore b/.gitignore
index 0ef9644175..2d8bcc1cf9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,6 +41,9 @@ tags
.tags*
cyassl-config
wolfssl-config
+cmake/wolfssl-config.cmake
+cmake/wolfssl-config-version.cmake
+cmake/wolfssl-targets.cmake
cyassl.sublime*
fips.h
fips.c
@@ -239,12 +242,17 @@ linuxkm/linuxkm
linuxkm/src
linuxkm/patches/src
*.nds
+
+# Generated during FreeBSD kernel module build.
bsdkm/export_syms
bsdkm/i386
bsdkm/libwolfssl.ko
bsdkm/machine
bsdkm/opt_global.h
bsdkm/x86
+bsdkm/bus_if.h
+bsdkm/cryptodev_if.h
+bsdkm/device_if.h
# autotools generated
scripts/unit.test
@@ -386,6 +394,7 @@ IDE/**/DerivedData
CMakeFiles/
CMakeCache.txt
cmake_install.cmake
+!cmake/Config.cmake.in
# GDB Settings
\.gdbinit
@@ -470,3 +479,6 @@ wolfssl/debug-trace-error-codes.h
wolfssl/debug-untrace-error-codes.h
AGENTS.md
+
+# Code navigation files
+compile_commands.json
diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras
index af5a97f080..a56621e980 100644
--- a/.wolfssl_known_macro_extras
+++ b/.wolfssl_known_macro_extras
@@ -36,6 +36,7 @@ BLAKE2B_SELFTEST
BLAKE2S_SELFTEST
BLOCKING
BSDKM_EXPORT_SYMS
+ENABLED_BSDKM_REGISTER
BSP_DEFAULT_IO_CHANNEL_DEFINED
BSP_LED_0
BSP_LED_1
@@ -280,7 +281,10 @@ HAVE_INTEL_QAT_SYNC
HAVE_INTEL_SPEEDUP
HAVE_MDK_RTX
HAVE_NETX_BSD
+HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK
HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK
+HAVE_PKCS11_STATIC
+HAVE_PKCS11_V3_STATIC
HAVE_POCO_LIB
HAVE_RTP_SYS
HAVE_SECURE_GETENV
@@ -637,7 +641,6 @@ WC_RSA_NONBLOCK
WC_RSA_NONBLOCK_TIME
WC_RSA_NO_FERMAT_CHECK
WC_RWLOCK_OPS_INLINE
-WC_SHA3_HARDEN
WC_SHA384
WC_SHA384_DIGEST_SIZE
WC_SHA512
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f6c41c410e..c915843737 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -427,6 +427,18 @@ if(WOLFSSL_DTLS_CID)
list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_DTLS_CID")
endif()
+# DTLS 1.3 Fragment ClientHello
+add_option("WOLFSSL_DTLS_CH_FRAG"
+ "Enable wolfSSL DTLS 1.3 Fragment ClientHello (default: disabled)"
+ "no" "yes;no")
+
+if(WOLFSSL_DTLS_CH_FRAG)
+ if(NOT WOLFSSL_DTLS13)
+ message(FATAL_ERROR "DTLS 1.3 Fragment ClientHello is supported only for DTLSv1.3")
+ endif()
+ list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_DTLS_CH_FRAG")
+endif()
+
# RNG
add_option("WOLFSSL_RNG"
"Enable compiling and using RNG (default: enabled)"
@@ -511,9 +523,6 @@ if(WOLFSSL_WOLFSSH)
list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_WOLFSSH")
endif()
-if(WOLFSSL_WOLFSSH OR WOLFSSL_WPAS)
- list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_PUBLIC_MP")
-endif()
# TODO: - DTLS-SCTP
# - DTLS multicast
@@ -881,6 +890,27 @@ add_option("WOLFSSL_AESOFB"
"Enable wolfSSL AES-OFB support (default: disabled)"
"no" "yes;no")
+# AES-ECB
+add_option("WOLFSSL_AESECB"
+ "Enable wolfSSL AES-ECB support (default: disabled)"
+ "no" "yes;no")
+
+if(WOLFSSL_AESECB)
+ list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_AES_ECB")
+endif()
+
+# AES-CTS
+add_option("WOLFSSL_AESCTS"
+ "Enable wolfSSL AES-CTS support (default: disabled)"
+ "no" "yes;no")
+
+if(WOLFSSL_AESCTS)
+ if(NOT WOLFSSL_AESCBC)
+ message(FATAL_ERROR "AES-CTS requires AES-CBC.")
+ endif()
+ list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_AES_CTS")
+endif()
+
# TODO: - AES-GCM stream
# - AES-ARM
# - Xilinx hardened crypto
@@ -1080,7 +1110,7 @@ if(WOLFSSL_ECCSI)
message(FATAL_ERROR "cannot enable ECCSI without enabling ECC.")
endif()
- list(APPEND WOLFSSL_DEFINITIONS "-DWOLFCRYPT_HAVE_ECCSI -DWOLFSSL_PUBLIC_MP")
+ list(APPEND WOLFSSL_DEFINITIONS "-DWOLFCRYPT_HAVE_ECCSI")
endif()
# SAKKE
@@ -1105,6 +1135,18 @@ if(WOLFSSL_SIPHASH)
list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_SIPHASH")
endif()
+add_option("WOLFSSL_PUBLIC_MP"
+ "Enable public MP API (default: disabled)"
+ "no" "yes;no")
+
+if(WOLFSSL_WOLFSSH OR WOLFSSL_WPAS OR WOLFSSL_ECCSI)
+ override_cache(WOLFSSL_PUBLIC_MP "yes")
+endif()
+
+if(WOLFSSL_PUBLIC_MP)
+ list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_PUBLIC_MP")
+endif()
+
# TODO: - Compressed key
# - FP ECC, fixed point cache ECC
# - ECC encrypt
@@ -1310,6 +1352,15 @@ else()
endif()
endif()
+# RSA Direct
+add_option("WOLFSSL_WC_RSA_DIRECT"
+ "Enable RSA Direct (default: disabled)"
+ "no" "yes;no")
+
+if(WOLFSSL_RSA AND WOLFSSL_WC_RSA_DIRECT)
+ list(APPEND WOLFSSL_DEFINITIONS "-DWC_RSA_DIRECT")
+endif()
+
# OAEP
add_option("WOLFSSL_OAEP"
"Enable RSA OAEP (default: enabled)"
@@ -1435,6 +1486,12 @@ if(NOT WOLFSSL_AES)
if(WOLFSSL_AESCTR)
message(FATAL_ERROR "AESCTR requires AES.")
endif()
+ if(WOLFSSL_AESECB)
+ message(FATAL_ERROR "AES-ECB requires AES.")
+ endif()
+ if(WOLFSSL_AESCTS)
+ message(FATAL_ERROR "AES-CTS requires AES.")
+ endif()
else()
if(WOLFSSL_LEAN_PSK)
list(APPEND WOLFSSL_DEFINITIONS "-DNO_AES")
@@ -2196,13 +2253,14 @@ if(WOLFSSL_AESOFB)
endif()
if(WOLFSSL_TPM)
- override_cache(WOLFSSL_KEYGEN "yes")
- override_cache(WOLFSSL_CERTGEN "yes")
- override_cache(WOLFSSL_CRYPTOCB "yes")
- override_cache(WOLFSSL_CERTREQ "yes")
- override_cache(WOLFSSL_CERTEXT "yes")
- override_cache(WOLFSSL_PKCS7 "yes")
- override_cache(WOLFSSL_AESCFB "yes")
+ override_cache(WOLFSSL_KEYGEN "yes")
+ override_cache(WOLFSSL_CERTGEN "yes")
+ override_cache(WOLFSSL_CRYPTOCB "yes")
+ override_cache(WOLFSSL_CERTREQ "yes")
+ override_cache(WOLFSSL_CERTEXT "yes")
+ override_cache(WOLFSSL_PKCS7 "yes")
+ override_cache(WOLFSSL_AESCFB "yes")
+ override_cache(WOLFSSL_PUBLIC_MP "yes")
list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_ALLOW_ENCODING_CA_FALSE")
endif()
@@ -2600,7 +2658,7 @@ target_compile_definitions(wolfssl PRIVATE "BUILDING_WOLFSSL")
if(${BUILD_SHARED_LIBS})
target_compile_definitions(wolfssl PUBLIC "WOLFSSL_DLL")
endif()
-target_compile_definitions(wolfssl PUBLIC ${WOLFSSL_DEFINITIONS})
+target_compile_definitions(wolfssl PRIVATE ${WOLFSSL_DEFINITIONS})
####################################################
# Include Directories
@@ -2663,6 +2721,7 @@ if(WOLFSSL_EXAMPLES)
add_executable(client
${CMAKE_CURRENT_SOURCE_DIR}/examples/client/client.c)
target_link_libraries(client wolfssl)
+ target_compile_definitions(client PRIVATE ${WOLFSSL_DEFINITIONS})
set_property(TARGET client
PROPERTY RUNTIME_OUTPUT_DIRECTORY
${WOLFSSL_OUTPUT_BASE}/examples/client)
@@ -2671,6 +2730,7 @@ if(WOLFSSL_EXAMPLES)
add_executable(server
${CMAKE_CURRENT_SOURCE_DIR}/examples/server/server.c)
target_link_libraries(server wolfssl)
+ target_compile_definitions(server PRIVATE ${WOLFSSL_DEFINITIONS})
set_property(TARGET server
PROPERTY RUNTIME_OUTPUT_DIRECTORY
${WOLFSSL_OUTPUT_BASE}/examples/server)
@@ -2681,6 +2741,7 @@ if(WOLFSSL_EXAMPLES)
target_include_directories(echoclient PRIVATE
${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(echoclient wolfssl)
+ target_compile_definitions(echoclient PRIVATE ${WOLFSSL_DEFINITIONS})
set_property(TARGET echoclient
PROPERTY RUNTIME_OUTPUT_DIRECTORY
${WOLFSSL_OUTPUT_BASE}/examples/echoclient)
@@ -2691,6 +2752,7 @@ if(WOLFSSL_EXAMPLES)
target_include_directories(echoserver PRIVATE
${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(echoserver wolfssl)
+ target_compile_definitions(echoserver PRIVATE ${WOLFSSL_DEFINITIONS})
set_property(TARGET echoserver
PROPERTY RUNTIME_OUTPUT_DIRECTORY
${WOLFSSL_OUTPUT_BASE}/examples/echoserver)
@@ -2700,6 +2762,7 @@ if(WOLFSSL_EXAMPLES)
add_executable(tls_bench
${CMAKE_CURRENT_SOURCE_DIR}/examples/benchmark/tls_bench.c)
target_link_libraries(tls_bench wolfssl)
+ target_compile_definitions(tls_bench PRIVATE ${WOLFSSL_DEFINITIONS})
if(CMAKE_USE_PTHREADS_INIT)
target_link_libraries(tls_bench Threads::Threads)
endif()
@@ -2804,6 +2867,7 @@ if(WOLFSSL_EXAMPLES)
${CMAKE_CURRENT_BINARY_DIR})
target_compile_options(unit_test PUBLIC "-DNO_MAIN_DRIVER")
target_link_libraries(unit_test wolfssl)
+ target_compile_definitions(unit_test PRIVATE ${WOLFSSL_DEFINITIONS})
if(CMAKE_USE_PTHREADS_INIT)
target_link_libraries(unit_test Threads::Threads)
endif()
@@ -2829,6 +2893,7 @@ if(WOLFSSL_CRYPT_TESTS)
${CMAKE_CURRENT_SOURCE_DIR}/wolfcrypt/test/test.c)
set_target_properties(wolfcrypttest_lib PROPERTIES OUTPUT_NAME "wolfcrypttest")
target_link_libraries(wolfcrypttest_lib wolfssl)
+ target_compile_definitions(wolfcrypttest_lib PRIVATE ${WOLFSSL_DEFINITIONS})
target_compile_options(wolfcrypttest_lib PRIVATE "-DNO_MAIN_DRIVER")
if(WOLFSSL_CRYPT_TESTS_HELP)
target_compile_options(wolfcrypttest_lib PRIVATE "-DHAVE_WOLFCRYPT_TEST_OPTIONS")
@@ -2839,6 +2904,7 @@ if(WOLFSSL_CRYPT_TESTS)
${CMAKE_CURRENT_SOURCE_DIR}/wolfcrypt/benchmark/benchmark.c)
set_target_properties(wolfcryptbench_lib PROPERTIES OUTPUT_NAME "wolfcryptbench")
target_link_libraries(wolfcryptbench_lib wolfssl)
+ target_compile_definitions(wolfcryptbench_lib PRIVATE ${WOLFSSL_DEFINITIONS})
target_compile_options(wolfcryptbench_lib PRIVATE "-DNO_MAIN_DRIVER")
endif()
@@ -2846,6 +2912,7 @@ if(WOLFSSL_CRYPT_TESTS)
add_executable(wolfcrypttest
${CMAKE_CURRENT_SOURCE_DIR}/wolfcrypt/test/test.c)
target_link_libraries(wolfcrypttest wolfssl)
+ target_compile_definitions(wolfcrypttest PRIVATE ${WOLFSSL_DEFINITIONS})
set_property(TARGET wolfcrypttest
PROPERTY RUNTIME_OUTPUT_DIRECTORY
${WOLFSSL_OUTPUT_BASE}/wolfcrypt/test)
@@ -2865,6 +2932,7 @@ if(WOLFSSL_CRYPT_TESTS)
target_include_directories(wolfcryptbench PRIVATE
${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(wolfcryptbench wolfssl)
+ target_compile_definitions(wolfcryptbench PRIVATE ${WOLFSSL_DEFINITIONS})
set_property(TARGET wolfcryptbench
PROPERTY RUNTIME_OUTPUT_DIRECTORY
${WOLFSSL_OUTPUT_BASE}/wolfcrypt/benchmark)
@@ -3019,9 +3087,9 @@ if(WOLFSSL_INSTALL)
# Install the library
install(TARGETS wolfssl
EXPORT wolfssl-targets
- LIBRARY DESTINATION lib
- ARCHIVE DESTINATION lib
- RUNTIME DESTINATION bin
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
# Install the headers
install(DIRECTORY ${WOLFSSL_OUTPUT_BASE}/wolfssl/
diff --git a/IDE/Renesas/e2studio/RX72N/EnvisionKit/Simple/test/.cproject b/IDE/Renesas/e2studio/RX72N/EnvisionKit/Simple/test/.cproject
index 9638725c01..84f642eef5 100644
--- a/IDE/Renesas/e2studio/RX72N/EnvisionKit/Simple/test/.cproject
+++ b/IDE/Renesas/e2studio/RX72N/EnvisionKit/Simple/test/.cproject
@@ -14,7 +14,7 @@
-
+
@@ -24,13 +24,13 @@
-
-
+
+
-
+
-
+
@@ -39,12 +39,12 @@
-
+
-
-
+
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
+
+
+
-
-
-
+
-
-
-
+
+
-
-
-
+
@@ -246,13 +503,13 @@
-
-
+
+
-
+
-
+
@@ -261,12 +518,12 @@
-
+
-
-
+
-
-
-
-
-
-
+
+
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
+
+
+
-
-
-
+
-
-
+
-
-
-
+
diff --git a/IDE/Renesas/e2studio/RX72N/EnvisionKit/Simple/wolfssl/.cproject b/IDE/Renesas/e2studio/RX72N/EnvisionKit/Simple/wolfssl/.cproject
index 03765b97e8..d76e8ab22b 100644
--- a/IDE/Renesas/e2studio/RX72N/EnvisionKit/Simple/wolfssl/.cproject
+++ b/IDE/Renesas/e2studio/RX72N/EnvisionKit/Simple/wolfssl/.cproject
@@ -24,10 +24,10 @@
-
+
-
+
@@ -35,12 +35,13 @@
-
-
+
+
+
-
-
+
-
-
-
+
+
@@ -63,14 +64,14 @@
-
-
+
-
-
+
-
-
+
+
-
+
@@ -162,6 +163,7 @@
+
diff --git a/IDE/Renesas/e2studio/RX72N/EnvisionKit/wolfssl_demo/key_data.c b/IDE/Renesas/e2studio/RX72N/EnvisionKit/wolfssl_demo/key_data.c
index c49bd62ae3..8b69c2e3db 100644
--- a/IDE/Renesas/e2studio/RX72N/EnvisionKit/wolfssl_demo/key_data.c
+++ b/IDE/Renesas/e2studio/RX72N/EnvisionKit/wolfssl_demo/key_data.c
@@ -186,64 +186,64 @@ const uint32_t encrypted_user_key_type =
const unsigned char ca_ecc_cert_der_sig[] =
{
- 0x58, 0x3F, 0x3C, 0x27, 0x4A, 0xC0, 0xA8, 0x35, 0x31, 0xAA,
- 0xB6, 0x49, 0x4C, 0x69, 0x48, 0xF6, 0x63, 0xA5, 0x2E, 0x8C,
- 0xA4, 0x1E, 0xAF, 0x18, 0x14, 0x11, 0x6A, 0xF7, 0x25, 0xF2,
- 0xE1, 0x82, 0x6E, 0xAA, 0x3C, 0xE2, 0x75, 0x6E, 0x81, 0x59,
- 0x2E, 0xF1, 0xED, 0xDD, 0xD1, 0x1C, 0xA3, 0xE7, 0xEC, 0x89,
- 0xD3, 0x19, 0x1A, 0x59, 0xEB, 0xBA, 0x1D, 0x65, 0xFD, 0x53,
- 0x4A, 0x90, 0x6F, 0xA1, 0x06, 0xB3, 0x08, 0xE4, 0x00, 0xF4,
- 0x91, 0x45, 0xD8, 0xC9, 0xD8, 0x30, 0x8A, 0x94, 0x9B, 0x48,
- 0x60, 0x68, 0xD1, 0x09, 0x84, 0xAE, 0x51, 0xD8, 0xD8, 0x67,
- 0x58, 0x58, 0x9B, 0x57, 0x9E, 0x09, 0x9D, 0x1B, 0x3B, 0x22,
- 0x67, 0x6A, 0x50, 0x91, 0xF2, 0x60, 0x5E, 0x78, 0x86, 0xF9,
- 0x2F, 0xF4, 0xB4, 0xAE, 0x6A, 0xF6, 0x0D, 0xAB, 0x8B, 0xF6,
- 0x60, 0x47, 0x8D, 0xD4, 0xEC, 0xE6, 0x9E, 0x57, 0x6C, 0xCC,
- 0x4F, 0xF5, 0xCD, 0x20, 0xD7, 0x15, 0x70, 0x50, 0x53, 0x96,
- 0x84, 0x6B, 0x9A, 0x07, 0x90, 0x41, 0x14, 0x08, 0x62, 0x87,
- 0xF5, 0x20, 0x0E, 0x82, 0xE2, 0x12, 0x5C, 0x1E, 0x72, 0x73,
- 0xB8, 0x18, 0x90, 0xCF, 0x98, 0x14, 0xC3, 0xE6, 0xED, 0x89,
- 0xA3, 0x7C, 0x67, 0x50, 0x01, 0xCC, 0x48, 0xD2, 0x6A, 0x9C,
- 0x9E, 0x4D, 0x44, 0x49, 0x82, 0x5F, 0xC1, 0x2E, 0x18, 0xBE,
- 0x23, 0x53, 0xCD, 0x09, 0x85, 0x16, 0x9D, 0x5F, 0x99, 0x78,
- 0xA1, 0x78, 0x51, 0xC9, 0x5A, 0x3E, 0x04, 0xBE, 0xE2, 0xF5,
- 0x74, 0x7E, 0x6F, 0x89, 0xD9, 0x05, 0x29, 0xC1, 0x5B, 0x57,
- 0x3D, 0xE3, 0x5E, 0xB8, 0x4B, 0x93, 0x7D, 0x68, 0x78, 0xF9,
- 0x88, 0x1B, 0x8E, 0x78, 0x04, 0x00, 0x54, 0x20, 0x3F, 0x0C,
- 0x99, 0x11, 0x1D, 0x90, 0x2C, 0x10, 0x4C, 0xCE, 0xA3, 0x17,
- 0xA7, 0xF8, 0xB4, 0xC6, 0xF8, 0x12
+ 0x0B, 0x1D, 0x49, 0x40, 0xE8, 0xDA, 0x46, 0xAE, 0x1C, 0x50,
+ 0xC8, 0x76, 0xF3, 0x57, 0x05, 0x95, 0x89, 0xE1, 0x8B, 0x13,
+ 0x6B, 0x0F, 0xEB, 0x47, 0x0E, 0x1E, 0x9C, 0x87, 0xBB, 0x07,
+ 0x6E, 0xE4, 0x6B, 0xDF, 0x5B, 0xEF, 0xA3, 0x2C, 0xD8, 0x07,
+ 0x91, 0x5B, 0x4E, 0x5B, 0xA1, 0xD0, 0x3E, 0x07, 0x22, 0xAF,
+ 0x12, 0xF3, 0x0F, 0x62, 0x35, 0x45, 0x82, 0xFC, 0x26, 0x2B,
+ 0xD1, 0x03, 0x51, 0xAB, 0x35, 0xFE, 0x48, 0x80, 0xC9, 0x68,
+ 0xA0, 0xE0, 0x54, 0x4A, 0x8F, 0xA7, 0x59, 0xA1, 0xED, 0x57,
+ 0x3D, 0x9D, 0xC0, 0x6B, 0x22, 0x20, 0xDA, 0x1A, 0xFF, 0xDB,
+ 0x01, 0x60, 0x59, 0x21, 0x88, 0xD5, 0x5A, 0x40, 0x25, 0x82,
+ 0xB0, 0x27, 0x54, 0xDC, 0x37, 0x79, 0x70, 0xD1, 0x6C, 0x63,
+ 0x63, 0xC6, 0x98, 0x63, 0xA9, 0xE6, 0xB7, 0x6C, 0x50, 0xC1,
+ 0x40, 0xCF, 0xE9, 0x84, 0xC7, 0xB9, 0x8F, 0x7C, 0xC3, 0xE1,
+ 0xE2, 0x96, 0x67, 0xC6, 0x48, 0x25, 0xD8, 0xB3, 0x40, 0x94,
+ 0x13, 0xF3, 0x55, 0xF8, 0xC3, 0xEA, 0x39, 0xE1, 0xE9, 0x36,
+ 0xD1, 0xBE, 0xB2, 0x9C, 0x86, 0xD1, 0x78, 0xE1, 0xC7, 0x67,
+ 0x3B, 0xD0, 0x10, 0x57, 0x7B, 0x09, 0x33, 0x03, 0x01, 0x8A,
+ 0xDA, 0x30, 0x1F, 0x74, 0xED, 0x99, 0x8F, 0x93, 0xA2, 0x73,
+ 0x7B, 0xA6, 0x3A, 0x44, 0x74, 0x9C, 0x5E, 0x19, 0x1B, 0x0B,
+ 0x63, 0x3A, 0xAF, 0x5C, 0xD5, 0xB4, 0x1C, 0xF0, 0x0B, 0x3F,
+ 0x15, 0xB3, 0x6B, 0x10, 0x88, 0x93, 0x6C, 0xAB, 0xB4, 0x65,
+ 0x35, 0xCC, 0x91, 0x9A, 0x19, 0x5D, 0xDF, 0xE0, 0xAC, 0x75,
+ 0xC3, 0x14, 0x46, 0x2E, 0x7B, 0xF8, 0x73, 0xEB, 0x75, 0xD8,
+ 0x47, 0xAF, 0x1E, 0x7B, 0x5B, 0xE5, 0x09, 0x01, 0x42, 0x5C,
+ 0xB3, 0xC6, 0xEB, 0x92, 0xC5, 0x85, 0x6B, 0xD4, 0x22, 0x39,
+ 0x77, 0x92, 0x13, 0x8A, 0x42, 0x2C
};
const int sizeof_ca_ecc_cert_sig = sizeof(ca_ecc_cert_der_sig);
/* ./ca-cert.der.sign, */
const unsigned char ca_cert_der_sig[] =
{
- 0x55, 0x93, 0xCF, 0x28, 0xF7, 0x38, 0x1E, 0xF1, 0x29, 0x5A,
- 0xDE, 0x41, 0xCD, 0x83, 0x00, 0x06, 0x79, 0xB3, 0x12, 0x56,
- 0xBD, 0x04, 0xCB, 0x97, 0xCC, 0xD2, 0x39, 0x3C, 0x36, 0x94,
- 0x8D, 0x66, 0xB0, 0x41, 0xF4, 0xBD, 0x82, 0x8F, 0x03, 0x24,
- 0x25, 0x65, 0xA1, 0x85, 0x87, 0xCE, 0x58, 0x0A, 0x45, 0xC6,
- 0xB6, 0x38, 0x27, 0x44, 0x2A, 0x7A, 0x9B, 0xA2, 0x71, 0x67,
- 0x92, 0xDA, 0xFD, 0x71, 0x88, 0x52, 0xF2, 0xFE, 0x61, 0x33,
- 0xCB, 0x7F, 0xB4, 0x47, 0x3D, 0x60, 0xC6, 0x3A, 0x48, 0x44,
- 0x6F, 0xA2, 0x16, 0x07, 0xA2, 0x94, 0x50, 0x99, 0x09, 0x7B,
- 0x43, 0x04, 0xAD, 0xCA, 0x9C, 0x34, 0xD4, 0x72, 0x4B, 0x79,
- 0x31, 0xE1, 0xC5, 0x6C, 0xA7, 0xB4, 0xD8, 0xED, 0x80, 0x79,
- 0xBB, 0x69, 0xA0, 0xA6, 0x7A, 0x63, 0x99, 0x02, 0xF7, 0x64,
- 0xF0, 0x6D, 0xBB, 0xC5, 0xDA, 0x55, 0x0D, 0x43, 0x7C, 0x30,
- 0x74, 0x21, 0x05, 0x35, 0x63, 0xAD, 0x32, 0x76, 0x11, 0xA5,
- 0x75, 0xF3, 0x83, 0xEE, 0x05, 0xFB, 0x91, 0x18, 0x5E, 0xCC,
- 0x71, 0x49, 0x26, 0x0D, 0xE2, 0xE3, 0xB3, 0xAD, 0xFF, 0x65,
- 0xA9, 0x9B, 0xF0, 0x81, 0xE1, 0x5D, 0xC3, 0x4C, 0x82, 0x83,
- 0x33, 0xDA, 0xF6, 0x29, 0xC7, 0xC2, 0xA0, 0x23, 0x5D, 0xB1,
- 0xCE, 0x82, 0x94, 0x49, 0xC5, 0xC0, 0xE5, 0xED, 0x3B, 0xF6,
- 0x79, 0x21, 0x3B, 0xFC, 0x6D, 0xB5, 0x2A, 0xF6, 0x6D, 0xD9,
- 0x4C, 0x3E, 0xBF, 0x2E, 0x13, 0xA2, 0x75, 0x93, 0x5A, 0xB4,
- 0x2B, 0xF5, 0x74, 0xEF, 0xAE, 0x48, 0xFE, 0x06, 0x2D, 0x3F,
- 0xA3, 0xFE, 0x1A, 0xC9, 0x45, 0x1D, 0x15, 0xC8, 0xEF, 0x95,
- 0xE2, 0x6F, 0x7D, 0x1E, 0x96, 0xCD, 0x4D, 0xC5, 0x5F, 0xEB,
- 0x57, 0x85, 0x54, 0xE4, 0x7F, 0xE0, 0x0F, 0xAD, 0xC3, 0xEE,
- 0xBF, 0xFB, 0x43, 0xA6, 0xAB, 0x92
+ 0x67, 0xBD, 0x28, 0x1E, 0x1A, 0x17, 0xFD, 0x88, 0x03, 0x8B,
+ 0xA2, 0x5A, 0x65, 0xB3, 0xF2, 0x17, 0x61, 0xE1, 0x7F, 0x9B,
+ 0xC3, 0x50, 0xEC, 0x55, 0x61, 0x46, 0x0C, 0xC1, 0x2B, 0x9D,
+ 0x02, 0xDB, 0x0A, 0x36, 0xA1, 0x49, 0x95, 0x42, 0xD1, 0x1A,
+ 0x75, 0xEC, 0x39, 0xC2, 0x10, 0xC5, 0x9F, 0xDC, 0x8C, 0xBC,
+ 0x4E, 0x04, 0xC9, 0x5E, 0x52, 0x6B, 0x42, 0xF0, 0x4E, 0x8D,
+ 0x0D, 0xDD, 0x01, 0x05, 0x14, 0x77, 0x28, 0x75, 0xB6, 0x36,
+ 0xA8, 0xD1, 0xA9, 0xB4, 0x46, 0xB5, 0xED, 0xD9, 0x10, 0x62,
+ 0xEC, 0x3B, 0xA5, 0x5B, 0x10, 0xB7, 0xE2, 0xC7, 0x67, 0x4F,
+ 0x1A, 0x48, 0x9B, 0xAF, 0x31, 0x9D, 0x21, 0xDC, 0x3B, 0x06,
+ 0xAC, 0x95, 0x78, 0xE6, 0x2D, 0x5F, 0xA8, 0xAD, 0xCC, 0xD2,
+ 0x4E, 0xF3, 0x4A, 0xC9, 0x7E, 0x4A, 0x28, 0x51, 0x6D, 0xBC,
+ 0x8D, 0xA5, 0x57, 0x49, 0x32, 0xC0, 0xE2, 0x48, 0x57, 0x8B,
+ 0x7D, 0x4D, 0x9B, 0x43, 0x99, 0xF0, 0xC0, 0x21, 0xD0, 0xAF,
+ 0x3D, 0x5B, 0xE0, 0x4F, 0xC2, 0x7C, 0xCF, 0xCC, 0xDB, 0x9A,
+ 0x79, 0xB6, 0x7E, 0xA0, 0x53, 0xAA, 0x4D, 0x5B, 0xD0, 0x3A,
+ 0xBA, 0x7F, 0xCC, 0x99, 0xD6, 0x68, 0xD7, 0x14, 0x85, 0xD7,
+ 0x8E, 0xE0, 0x1A, 0x6E, 0xE7, 0xC1, 0xD5, 0x2B, 0x35, 0x94,
+ 0x8E, 0xC1, 0x59, 0xC5, 0xAE, 0x48, 0x22, 0x87, 0x36, 0xC1,
+ 0xA4, 0xD9, 0x58, 0xC1, 0x2A, 0xD6, 0xFE, 0x45, 0x63, 0xCA,
+ 0x8F, 0x93, 0x86, 0xEC, 0x8D, 0xC2, 0xFD, 0xE3, 0x62, 0xD6,
+ 0x4C, 0x43, 0xFE, 0x82, 0x4F, 0xC9, 0x9D, 0xA9, 0xD8, 0xE4,
+ 0x5C, 0x15, 0x6D, 0xDE, 0xF9, 0x3D, 0x76, 0xB7, 0xBA, 0xF7,
+ 0x1C, 0xFB, 0x90, 0x74, 0xBB, 0x60, 0x93, 0xA4, 0x0C, 0xA4,
+ 0xFF, 0x41, 0x1C, 0x18, 0x7E, 0xE8, 0xE3, 0x78, 0xF5, 0x52,
+ 0x98, 0x50, 0xFD, 0xA8, 0x07, 0xAD
};
const int sizeof_ca_cert_sig = sizeof(ca_cert_der_sig);
/* ./client-cert.der.sign, */
diff --git a/IDE/Renesas/e2studio/RX72N/EnvisionKit/wolfssl_demo/user_settings.h b/IDE/Renesas/e2studio/RX72N/EnvisionKit/wolfssl_demo/user_settings.h
index 99c6b485cb..bf8a3a335f 100644
--- a/IDE/Renesas/e2studio/RX72N/EnvisionKit/wolfssl_demo/user_settings.h
+++ b/IDE/Renesas/e2studio/RX72N/EnvisionKit/wolfssl_demo/user_settings.h
@@ -294,5 +294,3 @@
/*-- strcasecmp */
#define XSTRCASECMP(s1,s2) strcmp((s1),(s2))
-/* use original ASN parsing */
-#define WOLFSSL_ASN_ORIGINAL
diff --git a/INSTALL b/INSTALL
index a0f649a563..dc6e2908c1 100644
--- a/INSTALL
+++ b/INSTALL
@@ -16,6 +16,9 @@
all the generated build options. This file needs to be included in your application
before any other wolfSSL headers. Optionally your application can define
WOLFSSL_USE_OPTIONS_H to do this automatically.
+ Note: Building with configure also installs CMake package files under
+ $(libdir)/cmake/wolfssl to support find_package(wolfssl). You can disable this
+ with ./configure --disable-cmake-install.
2. Building on iOS
diff --git a/Makefile.am b/Makefile.am
index b7fc4db2fb..721e471eff 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -78,6 +78,9 @@ CLEANFILES+= ecc-key.der \
pkcs7encryptedDataDES3.der \
pkcs7encryptedDataDES.der \
pkcs7envelopedDataAES256CBC_ECDH.der \
+ cmake/wolfssl-config.cmake \
+ cmake/wolfssl-config-version.cmake \
+ cmake/wolfssl-targets.cmake \
pkcs7envelopedDataAES128CBC_ECDH_SHA1KDF.der \
pkcs7envelopedDataAES256CBC_ECDH_SHA256KDF.der \
pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF.der \
@@ -247,8 +250,9 @@ if BUILD_BSDKM
EXTRA_CFLAGS EXTRA_CPPFLAGS EXTRA_CCASFLAGS EXTRA_LDFLAGS \
AM_CPPFLAGS CPPFLAGS AM_CFLAGS CFLAGS \
AM_CCASFLAGS CCASFLAGS \
- src_libwolfssl_la_OBJECTS ENABLED_CRYPT_TESTS
-
+ src_libwolfssl_la_OBJECTS ENABLED_CRYPT_TESTS ENABLED_BSDKM_REGISTER \
+ ENABLED_ASM ENABLED_INTELASM ENABLED_AESNI ENABLED_AESNI_WITH_AVX \
+ ENABLED_KERNEL_BENCHMARKS
endif
diff --git a/README.md b/README.md
index 94b71b812d..1cd6bb1522 100644
--- a/README.md
+++ b/README.md
@@ -57,6 +57,29 @@ suites are available. You can remove this error by defining
`WOLFSSL_ALLOW_NO_SUITES` in the event that you desire that, i.e., you're
not using TLS cipher suites.
+### AES CryptoCB Key Import Support
+
+wolfSSL supports hardware-accelerated AES operations via CryptoCB.
+
+When `WOLF_CRYPTO_CB_AES_SETKEY` is defined, wolfSSL invokes a CryptoCB
+callback during AES key setup. The callback behavior determines the mode:
+
+**If callback returns 0 (success):**
+- Key is imported to Secure Element/HSM
+- Key is NOT copied to wolfSSL RAM (true key isolation)
+- GCM tables are NOT generated (full hardware offload)
+- All subsequent AES operations route through CryptoCB
+
+**If callback returns CRYPTOCB_UNAVAILABLE:**
+- SE doesn't support key import
+- Normal software AES path is used
+- Key is copied to devKey for CryptoCB encrypt/decrypt acceleration
+
+This feature enables TLS 1.3 traffic key protection on embedded platforms
+where symmetric keys must never exist in main RAM.
+
+Enable with: `CPPFLAGS="-DWOLF_CRYPTO_CB_AES_SETKEY -DWOLF_CRYPTO_CB_FREE"`
+
### Note 2
wolfSSL takes a different approach to certificate verification than OpenSSL
does. The default policy for the client is to verify the server, this means
diff --git a/bsdkm/Makefile b/bsdkm/Makefile
index dd6bbcbd77..5a191080f7 100644
--- a/bsdkm/Makefile
+++ b/bsdkm/Makefile
@@ -1,19 +1,27 @@
-# wolfssl kernel module name and source, and root dir.
-KMOD=libwolfssl
-SRCS=wolfkmod.c
-WOLFSSL_DIR=../
+# wolfssl kernel module name and main source, and wolfssl root dir.
+KMOD = libwolfssl
+SRCS = wolfkmod.c
+WOLFSSL_DIR = ../
-CFLAGS+=-I${WOLFSSL_DIR}
-CFLAGS+=-DWOLFSSL_IGNORE_FILE_WARN -DHAVE_CONFIG_H -DNO_MAIN_DRIVER
+CFLAGS += -I${WOLFSSL_DIR}
+CFLAGS += -DWOLFSSL_IGNORE_FILE_WARN -DHAVE_CONFIG_H -DNO_MAIN_DRIVER
#
# debug options
# verbose printing:
-# CFLAGS+=-DWOLFSSL_BSDKM_VERBOSE_DEBUG
+# CFLAGS += -DWOLFSSL_BSDKM_VERBOSE_DEBUG
#
# print memory mallocs / frees:
-# CFLAGS+=-DWOLFSSL_BSDKM_MEMORY_DEBUG
+# CFLAGS += -DWOLFSSL_BSDKM_MEMORY_DEBUG
#
-CFLAGS+=$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS)
+# print fpu_kern_enter / leave:
+# CFLAGS += WOLFSSL_BSDKM_FPU_DEBUG
+#
+CFLAGS += $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS)
+
+.if defined(ENABLED_BSDKM_REGISTER)
+ # These device header files are generated during build.
+ SRCS += bus_if.h cryptodev_if.h device_if.h
+.endif
# FreeBSD make does not support GNU make's patsubst and related. Filter
# through sed instead.
@@ -21,19 +29,26 @@ WOLFSSL_OBJS != echo ${src_libwolfssl_la_OBJECTS} | \
sed 's|src_libwolfssl_la-||g' | sed 's|\.lo|.o|g' | \
sed 's|wolfcrypt/src/|${WOLFSSL_DIR}/wolfcrypt/src/|g'
+# wolfcrypt test
.if ${ENABLED_CRYPT_TESTS} == "yes"
WOLFSSL_OBJS += ${WOLFSSL_DIR}/wolfcrypt/test/test.o
.else
- CFLAGS+=-DNO_CRYPT_TEST
+ CFLAGS += -DNO_CRYPT_TEST
+.endif
+
+# wolfcrypt benchmark
+.if ${ENABLED_KERNEL_BENCHMARKS} == "yes"
+ WOLFSSL_OBJS += ${WOLFSSL_DIR}/wolfcrypt/benchmark/benchmark.o
+ CFLAGS += -DWOLFSSL_NO_FLOAT_FMT
.endif
OBJS += ${WOLFSSL_OBJS}
# Export no public symbols by default.
.if !defined(BSDKM_EXPORT_SYMS)
- EXPORT_SYMS=NO
+ EXPORT_SYMS = NO
.else
- EXPORT_SYMS=${BSDKM_EXPORT_SYMS}
+ EXPORT_SYMS = ${BSDKM_EXPORT_SYMS}
.endif
# Default to live kernel src tree makefile at
@@ -45,12 +60,52 @@ OBJS += ${WOLFSSL_OBJS}
.endif
.include "${SYSDIR}/conf/kmod.mk"
+#
+# To use aesni and friends in FreeBSD kernel we need to adjust build flags.
+# See these kernel makefiles for reference:
+# - /usr/src/sys/modules/aesni/Makefile
+# - /usr/src/sys/conf/kern.mk
+#
+WOLFKMOD_SIMD_BASE = -msse -msse2 -msse4.1
+WOLFKMOD_SIMD_AES = -maes -mpclmul
+WOLFKMOD_SIMD_AVX = -mavx -mavx2
+
+.if ${ENABLED_AESNI} == "yes"
+ CFLAGS.aes.c += ${WOLFKMOD_SIMD_BASE}
+ CFLAGS.aes.c += ${WOLFKMOD_SIMD_AES}
+.if ${ENABLED_AESNI_WITH_AVX} == "yes"
+ CFLAGS.aes.c += ${WOLFKMOD_SIMD_AVX}
+.endif # ENABLED_AESNI_WITH_AVX #
+ CFLAGS.aes.c := ${CFLAGS.aes.c:N-nostdinc}
+ CFLAGS.aes.c += -I${SYSDIR}/../contrib/llvm-project/clang/lib/Headers
+.PATH: ${SYSDIR}/../contrib/llvm-project/clang/lib/Headers
+.endif # ENABLED_AESNI
+
+.if ${ENABLED_ASM} == "yes"
+.for f in chacha dilithium poly1305 sha sha256 sha3 sha512
+ CFLAGS.${f}.c += ${WOLFKMOD_SIMD_BASE}
+ CFLAGS.${f}.c += ${WOLFKMOD_SIMD_AVX}
+ CFLAGS.${f}.c := ${CFLAGS.${f}.c:N-nostdinc}
+ CFLAGS.${f}.c += -I${SYSDIR}/../contrib/llvm-project/clang/lib/Headers
+.endfor
+
+.PATH: ${SYSDIR}/../contrib/llvm-project/clang/lib/Headers
+.endif # ENABLED_ASM == "yes"
+
+# wolfcrypt benchmark always needs simd for the floating point timings.
+.if ${ENABLED_KERNEL_BENCHMARKS} == "yes"
+ CFLAGS.benchmark.c += ${WOLFKMOD_SIMD_BASE}
+ CFLAGS.benchmark.c := ${CFLAGS.benchmark.c:N-nostdinc}
+ CFLAGS.benchmark.c += -I${SYSDIR}/../contrib/llvm-project/clang/lib/Headers
+ .PATH: ${SYSDIR}/../contrib/llvm-project/clang/lib/Headers
+.endif
+
# Smooth out a few inconsistencies between FreeBSD default compiler flags
# in /usr/src/sys/conf/kern.mk, vs wolfssl harden flags in
# m4/ax_harden_compiler_flags.m4. E.g. some FreeBSD header files shorten
# 64 to 32 bit, and some wolfcrypt functions cast away const.
-CFLAGS+= -Wno-unused-function
-CFLAGS+= -Wno-cast-qual
-CFLAGS+= -Wno-error=cast-qual
-CFLAGS+= -Wno-shorten-64-to-32
-CFLAGS+= -DLIBWOLFSSL_GLOBAL_EXTRA_CFLAGS="\" $(KERNEL_EXTRA_CFLAGS)\""
+CFLAGS += -Wno-unused-function
+CFLAGS += -Wno-cast-qual
+CFLAGS += -Wno-error=cast-qual
+CFLAGS += -Wno-shorten-64-to-32
+CFLAGS += -DLIBWOLFSSL_GLOBAL_EXTRA_CFLAGS="\" $(KERNEL_EXTRA_CFLAGS)\""
diff --git a/bsdkm/README.md b/bsdkm/README.md
index b84c2588ff..0c23ceb251 100644
--- a/bsdkm/README.md
+++ b/bsdkm/README.md
@@ -7,10 +7,10 @@ other loadable modules to link to wolfCrypt.
Supported features:
- wolfCrypt in kernel.
- FIPS-wolfcrypt.
+- crypto acceleration: AES-NI, AVX, etc.
Planned features:
-- crypto acceleration: AES-NI, AVX, etc.
-- kernel opencrypto driver registration.
+- kernel opencrypto driver registration (supported for internal testing presently).
- full wolfSSL in kernel (kernel TLS).
## Building and Installing
@@ -44,10 +44,12 @@ sudo kldunload libwolfssl
### options
-| freebsdkm option | description |
-| :------------------------------- | :--------------------------------------- |
-| --with-bsd-export-syms=LIST | Export list of symbols as global.
. Options are 'all', 'none', or
comma separated list of symbols. |
-| --with-kernel-source=PATH | Path to kernel tree root (default `/usr/src/sys`) |
+| freebsdkm option | description |
+| :--------------------------------- | :--------------------------------------- |
+| --with-bsd-export-syms=LIST | Export list of symbols as global.
. Options are 'all', 'none', or
comma separated list of symbols. |
+| --with-kernel-source=PATH | Path to kernel tree root (default `/usr/src/sys`) |
+| --enable-kernel-benchmarks | Run wolfcrypt benchmark at module load |
+| --enable-freebsdkm-crypto-register | Register with the FreeBSD kernel opencrypto
framework (preliminary, for testing) |
### FIPS
diff --git a/bsdkm/bsdkm_wc_port.h b/bsdkm/bsdkm_wc_port.h
index 2a5524d5f5..0bd80f092b 100644
--- a/bsdkm/bsdkm_wc_port.h
+++ b/bsdkm/bsdkm_wc_port.h
@@ -61,13 +61,13 @@ static inline time_t wolfkmod_time(time_t * tloc) {
#define WOLFSSL_DEBUG_PRINTF_FN printf
/* str and char utility functions */
-#define XATOI(s) ({ \
- char * endptr = NULL; \
- long _xatoi_ret = strtol(s, &endptr, 10); \
- if ((s) == endptr || *endptr != '\0') { \
- _xatoi_ret = 0; \
- } \
- (int)_xatoi_ret; \
+#define XATOI(s) ({ \
+ char * endptr = NULL; \
+ long _xatoi_ret = strtol(s, &endptr, 10); \
+ if ((s) == endptr || *endptr != '\0') { \
+ _xatoi_ret = 0; \
+ } \
+ (int)_xatoi_ret; \
})
#if !defined(XMALLOC_OVERRIDE)
@@ -103,6 +103,33 @@ extern struct malloc_type M_WOLFSSL[1];
})
#endif /* WOLFSSL_BSDKM_DEBUG_MEMORY */
+
+#if defined(WOLFSSL_AESNI) || defined(WOLFSSL_KERNEL_BENCHMARKS)
+ int wolfkmod_vecreg_init(void);
+ void wolfkmod_vecreg_exit(void);
+ int wolfkmod_vecreg_save(int flags_unused);
+ void wolfkmod_vecreg_restore(void);
+ /* wrapper defines for FPU_KERN(9).
+ * /usr/src/sys/amd64/amd64/fpu.c
+ * /usr/src/sys/amd64/include/pcb.h
+ * */
+ #ifndef WOLFSSL_USE_SAVE_VECTOR_REGISTERS
+ #define WOLFSSL_USE_SAVE_VECTOR_REGISTERS
+ #endif
+
+ #define SAVE_VECTOR_REGISTERS(fail_clause) { \
+ int _svr_ret = wolfkmod_vecreg_save(0); \
+ if (_svr_ret != 0) { \
+ fail_clause \
+ } \
+ }
+
+ #define SAVE_VECTOR_REGISTERS2() wolfkmod_vecreg_save(0)
+
+ #define RESTORE_VECTOR_REGISTERS() wolfkmod_vecreg_restore()
+
+#endif /* WOLFSSL_AESNI || WOLFSSL_KERNEL_BENCHMARKS */
+
#if !defined(SINGLE_THREADED)
#define WC_MUTEX_OPS_INLINE
@@ -149,7 +176,8 @@ extern struct malloc_type M_WOLFSSL[1];
typedef volatile int wolfSSL_Atomic_Int;
typedef volatile unsigned int wolfSSL_Atomic_Uint;
#define WOLFSSL_ATOMIC_INITIALIZER(x) (x)
- #define WOLFSSL_ATOMIC_LOAD(x) (int)atomic_load_acq_int(&(x))
+ #define WOLFSSL_ATOMIC_LOAD(x) (int)atomic_load_acq_int(&(x))
+ #define WOLFSSL_ATOMIC_LOAD_UINT(x) atomic_load_acq_int(&(x))
#define WOLFSSL_ATOMIC_STORE(x, v) atomic_store_rel_int(&(x), (v))
#define WOLFSSL_ATOMIC_OPS
diff --git a/bsdkm/include.am b/bsdkm/include.am
index 896a5447c9..44666b6c08 100644
--- a/bsdkm/include.am
+++ b/bsdkm/include.am
@@ -2,8 +2,10 @@
# included from Top Level Makefile.am
# All paths should be given relative to the root
-EXTRA_DIST += m4/ax_bsdkm.m4 \
- bsdkm/Makefile \
- bsdkm/README.md \
- bsdkm/wolfkmod.c \
+EXTRA_DIST += m4/ax_bsdkm.m4 \
+ bsdkm/Makefile \
+ bsdkm/README.md \
+ bsdkm/wolfkmod.c \
+ bsdkm/wolfkmod_aes.c \
+ bsdkm/x86_vecreg.c \
bsdkm/bsdkm_wc_port.h
diff --git a/bsdkm/wolfkmod.c b/bsdkm/wolfkmod.c
index bb03e8ebbc..38454d125a 100644
--- a/bsdkm/wolfkmod.c
+++ b/bsdkm/wolfkmod.c
@@ -26,6 +26,12 @@
#include
#include
+#if defined(BSDKM_CRYPTO_REGISTER)
+ #include
+ #include
+ #include "cryptodev_if.h"
+#endif
+
/* wolf includes */
#include
#ifdef WOLFCRYPT_ONLY
@@ -44,15 +50,42 @@
#if !defined(NO_CRYPT_TEST)
#include
#endif
+#if defined(WOLFSSL_KERNEL_BENCHMARKS)
+ #include
+#endif
#include
MALLOC_DEFINE(M_WOLFSSL, "libwolfssl", "wolfSSL kernel memory");
-static int wolfkmod_init(void);
-static int wolfkmod_cleanup(void);
-static int wolfkmod_load(void);
-static int wolfkmod_unload(void);
+#if defined(BSDKM_CRYPTO_REGISTER)
+ #include "bsdkm/wolfkmod_aes.c"
+#endif
+
+/* common functions. */
+static int wolfkmod_init(void);
+static int wolfkmod_cleanup(void);
+#if !defined(BSDKM_CRYPTO_REGISTER)
+/* functions specific to a pure kernel module library build. */
+static int wolfkmod_load(void);
+static int wolfkmod_unload(void);
+#else
+/* functions specific to a kernel crypto driver module build. */
+static void wolfkdriv_identify(driver_t * driver, device_t parent);
+static int wolfkdriv_probe(device_t dev);
+static int wolfkdriv_attach(device_t dev);
+static int wolfkdriv_detach(device_t dev);
+static int wolfkdriv_probesession(device_t dev,
+ const struct crypto_session_params *csp);
+static int wolfkdriv_newsession(device_t dev, crypto_session_t cses,
+ const struct crypto_session_params *csp);
+static void wolfkdriv_freesession(device_t dev, crypto_session_t cses);
+static int wolfkdriv_process(device_t dev, struct cryptop *crp, int hint);
+#endif /* !BSDKM_CRYPTO_REGISTER */
+
+#if defined(WOLFSSL_AESNI) || defined(WOLFSSL_KERNEL_BENCHMARKS)
+ #include "bsdkm/x86_vecreg.c"
+#endif /* WOLFSSL_AESNI || WOLFSSL_KERNEL_BENCHMARKS*/
#ifdef HAVE_FIPS
#define WOLFKMOD_FIPS_ERR_MSG(hash) ({ \
@@ -82,6 +115,14 @@ static int wolfkmod_init(void)
{
int error = 0;
+ #if defined(WOLFSSL_AESNI) || defined(WOLFSSL_KERNEL_BENCHMARKS)
+ error = wolfkmod_vecreg_init();
+ if (error != 0) {
+ printf("error: wolfkmod_vecreg_init: %d\n", error);
+ return (ECANCELED);
+ }
+ #endif /* WOLFSSL_AESNI || WOLFSSL_KERNEL_BENCHMARKS*/
+
#ifdef HAVE_FIPS
error = wolfCrypt_SetCb_fips(wolfkmod_fips_cb);
if (error != 0) {
@@ -174,14 +215,16 @@ static int wolfkmod_cleanup(void)
if (error != 0) {
printf("error: wolfCrypt_Cleanup failed: %s\n",
wc_GetErrorString(error));
- return (ECANCELED);
+ error = ECANCELED;
+ goto wolfkmod_cleanup_out;
}
#else
error = wolfSSL_Cleanup();
if (error != WOLFSSL_SUCCESS) {
printf("error: wolfSSL_Cleanup failed: %s\n",
wc_GetErrorString(error));
- return (ECANCELED);
+ error = ECANCELED;
+ goto wolfkmod_cleanup_out;
}
#endif /* WOLFCRYPT_ONLY */
@@ -189,10 +232,17 @@ static int wolfkmod_cleanup(void)
printf("info: libwolfssl " LIBWOLFSSL_VERSION_STRING
" cleanup complete.\n");
#endif /* WOLFSSL_BSDKM_VERBOSE_DEBUG */
+ error = 0;
- return (0);
+wolfkmod_cleanup_out:
+ #if defined(WOLFSSL_AESNI) || defined(WOLFSSL_KERNEL_BENCHMARKS)
+ wolfkmod_vecreg_exit();
+ #endif /* WOLFSSL_AESNI || WOLFSSL_KERNEL_BENCHMARKS*/
+
+ return (error);
}
+#if !defined(BSDKM_CRYPTO_REGISTER)
static int wolfkmod_load(void)
{
int error = 0;
@@ -212,10 +262,15 @@ static int wolfkmod_load(void)
printf("info: wolfCrypt self-test passed.\n");
#endif /* NO_CRYPT_TEST */
- /**
- * todo: register wolfcrypt algs here with crypto_get_driverid
- * and related.
- * */
+ #ifdef WOLFSSL_KERNEL_BENCHMARKS
+ error = benchmark_test(NULL);
+ if (error != 0) {
+ printf("error: wolfcrypt benchmark failed: %d\n", error);
+ (void)wolfkmod_cleanup();
+ return (ECANCELED);
+ }
+ printf("info: wolfCrypt benchmark passed.\n");
+ #endif /* WOLFSSL_KERNEL_BENCHMARKS */
printf("info: libwolfssl loaded\n");
@@ -239,11 +294,6 @@ static int wolfkmod_unload(void)
error = wolfkmod_cleanup();
- /**
- * todo: unregister wolfcrypt algs here with crypto_unregister_all
- * and related.
- * */
-
if (error == 0) {
printf("info: libwolfssl unloaded\n");
}
@@ -294,7 +344,718 @@ wolfkmod_event(struct module * m, int what, void * arg)
return (error);
}
+#endif /* !BSDKM_CRYPTO_REGISTER */
+#if defined(BSDKM_CRYPTO_REGISTER)
+/* wolfkdriv device driver software context. */
+struct wolfkdriv_softc {
+ int32_t crid;
+ device_t dev;
+};
+
+struct km_aes_ctx {
+ Aes aes_encrypt;
+ Aes aes_decrypt;
+};
+
+typedef struct km_aes_ctx km_aes_ctx;
+
+struct wolfkdriv_session {
+ km_aes_ctx aes_ctx;
+ int32_t crid;
+ int type;
+ int ivlen;
+ int klen;
+};
+
+typedef struct wolfkdriv_session wolfkdriv_session_t;
+
+static void km_AesFree(Aes * aes) {
+ if (aes == NULL) {
+ return;
+ }
+ wc_AesFree(aes);
+ #if defined(HAVE_FIPS) && FIPS_VERSION3_LT(6,0,0)
+ ForceZero(aes, sizeof(*aes));
+ #endif
+}
+
+static void wolfkdriv_aes_ctx_clear(km_aes_ctx * ctx)
+{
+ if (ctx != NULL) {
+ km_AesFree(&ctx->aes_encrypt);
+ km_AesFree(&ctx->aes_decrypt);
+ }
+
+ #ifdef WOLFKM_DEBUG_AES
+ printf("info: exiting km_AesExitCommon\n");
+ #endif /* WOLFKM_DEBUG_AES */
+}
+
+static void wolfkdriv_identify(driver_t * driver, device_t parent)
+{
+ (void)driver;
+
+ /* don't double add wolfkdriv child. */
+ if (device_find_child(parent, "libwolf", -1) != NULL) {
+ return;
+ }
+
+ BUS_ADD_CHILD(parent, 10, "libwolf", -1);
+}
+
+static int wolfkdriv_probe(device_t dev)
+{
+ device_set_desc(dev, "wolfSSL crypto");
+ return (BUS_PROBE_DEFAULT);
+}
+
+/*
+ * unregister libwolfssl crypto driver
+ */
+static void wolfkdriv_unregister(struct wolfkdriv_softc * softc)
+{
+ if (softc && softc->crid >= 0) {
+ crypto_unregister_all(softc->crid);
+ device_printf(softc->dev, "info: crid unregistered: %d\n", softc->crid);
+ softc->crid = -1;
+ }
+
+ return;
+}
+
+static int wolfkdriv_attach(device_t dev)
+{
+ struct wolfkdriv_softc * softc = NULL;
+ int flags = CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC |
+ CRYPTOCAP_F_ACCEL_SOFTWARE | CRYPTOCAP_F_HARDWARE;
+ int ret = 0;
+ int crid = 0;
+ int error = 0;
+
+ ret = wolfkmod_init();
+ if (ret != 0) {
+ return (ECANCELED);
+ }
+
+ /**
+ * register wolfcrypt algs here with crypto_get_driverid.
+ *
+ * The crid is the literal index into the kernel crypto_drivers array:
+ * - crid >= 0 is valid.
+ * - crid < 0 is error.
+ * */
+ softc = device_get_softc(dev);
+ softc->dev = dev;
+
+ softc->crid = crypto_get_driverid(dev, sizeof(wolfkdriv_session_t), flags);
+ if (softc->crid < 0) {
+ device_printf(dev, "error: crypto_get_driverid failed: %d\n",
+ softc->crid);
+ return (ENXIO);
+ }
+
+ /*
+ * various sanity checks
+ */
+
+ /* 1. we should find ourself by name */
+ crid = crypto_find_driver("libwolf");
+
+ if (crid != softc->crid) {
+ device_printf(dev, "error: attach: got crid %d, expected %d\n", crid,
+ softc->crid);
+ error = ENXIO;
+ goto attach_out;
+ }
+
+ /* 2. test various algs */
+ error = wolfkdriv_test_aes(dev, crid);
+
+ if (error) {
+ device_printf(dev, "error: attach: test_aes: %d\n", error);
+ error = ENXIO;
+ goto attach_out;
+ }
+
+ device_printf(dev, "info: driver loaded: %d\n", crid);
+
+ #if defined(WOLFSSL_BSDKM_VERBOSE_DEBUG)
+ device_printf(dev, "info: exiting attach\n");
+ #endif /* WOLFSSL_BSDKM_VERBOSE_DEBUG */
+
+attach_out:
+ if (error) {
+ wolfkdriv_unregister(softc);
+ error = ENXIO;
+ }
+
+ return (error);
+}
+
+static int wolfkdriv_detach(device_t dev)
+{
+ struct wolfkdriv_softc * softc = NULL;
+ int ret = 0;
+
+ ret = wolfkmod_cleanup();
+
+ if (ret == 0) {
+ /* unregister wolfcrypt algs */
+ softc = device_get_softc(dev);
+ wolfkdriv_unregister(softc);
+ }
+
+ #if defined(WOLFSSL_BSDKM_VERBOSE_DEBUG)
+ device_printf(dev, "info: exiting detach\n");
+ #endif /* WOLFSSL_BSDKM_VERBOSE_DEBUG */
+
+ return (0);
+}
+
+static int wolfkdriv_probesession(device_t dev,
+ const struct crypto_session_params *csp)
+{
+ struct wolfkdriv_softc * softc = NULL;
+ int error = CRYPTODEV_PROBE_ACCEL_SOFTWARE;
+
+ softc = device_get_softc(dev);
+
+ switch (csp->csp_mode) {
+ case CSP_MODE_CIPHER:
+ switch (csp->csp_cipher_alg) {
+ case CRYPTO_AES_CBC:
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ break;
+
+ case CSP_MODE_AEAD:
+ switch (csp->csp_cipher_alg) {
+ case CRYPTO_AES_NIST_GCM_16:
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ break;
+ case CSP_MODE_DIGEST:
+ case CSP_MODE_ETA:
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ (void)softc;
+ (void)csp;
+
+ #if defined(WOLFSSL_BSDKM_VERBOSE_DEBUG)
+ device_printf(dev, "info: probesession: mode=%d, cipher_alg=%d, error=%d\n",
+ csp->csp_mode, csp->csp_cipher_alg, error);
+ #endif /* WOLFSSL_BSDKM_VERBOSE_DEBUG */
+ return (error);
+}
+
+static int wolfkdriv_newsession_aes(device_t dev,
+ wolfkdriv_session_t * session,
+ const struct crypto_session_params *csp)
+{
+ int error = 0;
+ int klen = csp->csp_cipher_klen; /* key len in bytes */
+
+ switch (csp->csp_cipher_alg) {
+ case CRYPTO_AES_NIST_GCM_16:
+ session->type = CRYPTO_AES_NIST_GCM_16;
+ break;
+ case CRYPTO_AES_CBC:
+ session->type = CRYPTO_AES_CBC;
+ break;
+ default:
+ return (EOPNOTSUPP);
+ }
+
+ if (klen != 16 && klen != 24 && klen != 32) {
+ device_printf(dev, "info: newsession_cipher: invalid klen: %d\n", klen);
+ return (EINVAL);
+ }
+
+ session->klen = klen;
+ session->ivlen = csp->csp_ivlen;
+
+ /* encrypt */
+ error = wc_AesInit(&session->aes_ctx.aes_encrypt, NULL, INVALID_DEVID);
+ if (error) {
+ device_printf(dev, "error: newsession_cipher: aes init: %d\n", error);
+ goto newsession_cipher_out;
+ }
+
+ if (session->type == CRYPTO_AES_CBC) {
+ /* Need a separate decrypt structure for aes-cbc. */
+ error = wc_AesInit(&session->aes_ctx.aes_decrypt, NULL, INVALID_DEVID);
+ if (error) {
+ device_printf(dev, "error: newsession_cipher: aes init: %d\n",
+ error);
+ goto newsession_cipher_out;
+ }
+ }
+
+newsession_cipher_out:
+
+ if (error != 0) {
+ wolfkdriv_aes_ctx_clear(&session->aes_ctx);
+ return (EINVAL);
+ }
+
+ return (error);
+}
+
+static int wolfkdriv_newsession(device_t dev, crypto_session_t cses,
+ const struct crypto_session_params *csp)
+{
+ wolfkdriv_session_t * session = NULL;
+ int error = 0;
+
+ /* get the wolfkdriv_session_t context */
+ session = crypto_get_driver_session(cses);
+
+ switch (csp->csp_mode) {
+ case CSP_MODE_DIGEST:
+ case CSP_MODE_ETA:
+ device_printf(dev, "info: not supported: %d\n", csp->csp_mode);
+ error = EOPNOTSUPP;
+ break;
+ case CSP_MODE_CIPHER:
+ case CSP_MODE_AEAD:
+ error = wolfkdriv_newsession_aes(dev, session, csp);
+ break;
+ default:
+ __assert_unreachable();
+ }
+
+ #if defined(WOLFSSL_BSDKM_VERBOSE_DEBUG)
+ device_printf(dev, "info: newsession: mode=%d, cipher_alg=%d, error=%d\n",
+ csp->csp_mode, csp->csp_cipher_alg, error);
+ #endif /* WOLFSSL_BSDKM_VERBOSE_DEBUG */
+
+ return (error);
+}
+
+static void
+wolfkdriv_freesession(device_t dev, crypto_session_t cses)
+{
+ wolfkdriv_session_t * session = NULL;
+ (void)dev;
+
+ /* get the wolfkdriv_session_t context */
+ session = crypto_get_driver_session(cses);
+
+ /* clean it up */
+ wolfkdriv_aes_ctx_clear(&session->aes_ctx);
+
+ #if defined(WOLFSSL_BSDKM_VERBOSE_DEBUG)
+ device_printf(dev, "info: exiting freesession\n");
+ #endif /* WOLFSSL_BSDKM_VERBOSE_DEBUG */
+ return;
+}
+
+static int wolfkdriv_cbc_work(device_t dev, wolfkdriv_session_t * session,
+ struct cryptop * crp,
+ const struct crypto_session_params * csp)
+{
+ struct crypto_buffer_cursor cc_in;
+ struct crypto_buffer_cursor cc_out;
+ const unsigned char * in_block = NULL;
+ const unsigned char * in_seg = NULL;
+ unsigned char * out_block = NULL;
+ unsigned char * out_seg = NULL;
+ Aes aes;
+ uint8_t iv[WC_AES_BLOCK_SIZE];
+ uint8_t block[EALG_MAX_BLOCK_LEN];
+ size_t data_len = 0;
+ size_t seg_len = 0;
+ size_t in_len = 0;
+ size_t out_len = 0;
+ int error = 0;
+ int is_encrypt = 0;
+ int type = AES_ENCRYPTION;
+
+ if (csp->csp_cipher_alg != CRYPTO_AES_CBC) {
+ error = EINVAL;
+ goto cbc_work_out;
+ }
+
+ data_len = crp->crp_payload_length;
+ if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
+ is_encrypt = 1;
+ type = AES_ENCRYPTION;
+ memcpy(&aes, &session->aes_ctx.aes_encrypt, sizeof(aes));
+ }
+ else {
+ is_encrypt = 0;
+ type = AES_DECRYPTION;
+ memcpy(&aes, &session->aes_ctx.aes_decrypt, sizeof(aes));
+ }
+
+ /* must be multiple of block size */
+ if (data_len % WC_AES_BLOCK_SIZE) {
+ error = EINVAL;
+ goto cbc_work_out;
+ }
+
+ crypto_read_iv(crp, iv);
+ error = wc_AesSetKey(&aes, csp->csp_cipher_key,
+ csp->csp_cipher_klen, iv, type);
+ if (error) {
+ device_printf(dev, "error: wc_AesSetKey: %d\n", error);
+ goto cbc_work_out;
+ }
+
+ /* set up the crypto buffers */
+ crypto_cursor_init(&cc_in, &crp->crp_buf);
+ crypto_cursor_advance(&cc_in, crp->crp_payload_start);
+
+ in_seg = crypto_cursor_segment(&cc_in, &in_len);
+
+ /* handle if the user supplied a separate out buffer. */
+ if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
+ crypto_cursor_init(&cc_out, &crp->crp_obuf);
+ crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
+ }
+ else {
+ cc_out = cc_in;
+ }
+
+ out_seg = crypto_cursor_segment(&cc_out, &out_len);
+
+ while (data_len) {
+ /* set up input buffers */
+ if (in_len < WC_AES_BLOCK_SIZE) {
+ /* less than a block in segment */
+ crypto_cursor_copydata(&cc_in, WC_AES_BLOCK_SIZE, block);
+ in_block = block;
+ in_len = WC_AES_BLOCK_SIZE;
+ }
+ else {
+ in_block = in_seg;
+ }
+
+ /* set up output buffers */
+ if (out_len < WC_AES_BLOCK_SIZE) {
+ out_block = block;
+ out_len = WC_AES_BLOCK_SIZE;
+ }
+ else {
+ out_block = out_seg;
+ }
+
+ /* choose which of data_len, in_len, out_len, is shorter.
+ * round down to multiple of aes block size. */
+ seg_len = rounddown(MIN(data_len, MIN(in_len, out_len)),
+ WC_AES_BLOCK_SIZE);
+
+ if (is_encrypt) {
+ error = wc_AesCbcEncrypt(&aes, out_block, in_block, seg_len);
+ if (error) {
+ device_printf(dev, "error: wc_AesCbcEncrypt: %d\n", error);
+ goto cbc_work_out;
+ }
+ }
+ else {
+ error = wc_AesCbcDecrypt(&aes, out_block, in_block, seg_len);
+ if (error) {
+ device_printf(dev, "error: wc_AesCbcEncrypt: %d\n", error);
+ goto cbc_work_out;
+ }
+ }
+
+ if (out_block == block) {
+ /* we used the block as local output buffer. copy to cc_out,
+ * and grab the next out cursor segment. */
+ crypto_cursor_copyback(&cc_out, WC_AES_BLOCK_SIZE, block);
+ out_seg = crypto_cursor_segment(&cc_out, &out_len);
+ } else {
+ /* we worked directly in cc_out. advance the cursor. */
+ crypto_cursor_advance(&cc_out, seg_len);
+ out_seg += seg_len;
+ out_len -= seg_len;
+ }
+
+ if (in_block == block) {
+ /* grab a new in cursor segment. */
+ in_seg = crypto_cursor_segment(&cc_in, &in_len);
+ } else {
+ /* else advance existing in cursor. */
+ crypto_cursor_advance(&cc_in, seg_len);
+ in_seg += seg_len;
+ in_len -= seg_len;
+ }
+
+ data_len -= seg_len;
+ }
+
+cbc_work_out:
+ /* cleanup. */
+ wc_ForceZero(iv, sizeof(iv));
+ wc_ForceZero(block, sizeof(block));
+
+ #if defined(WOLFSSL_BSDKM_VERBOSE_DEBUG)
+ device_printf(dev, "info: cbc_work: mode=%d, cipher_alg=%d, "
+ "payload_length=%d, error=%d\n",
+ csp->csp_mode, csp->csp_cipher_alg, crp->crp_payload_length,
+ error);
+ #endif /* WOLFSSL_BSDKM_VERBOSE_DEBUG */
+
+ return (error);
+}
+
+static int wolfkdriv_gcm_work(device_t dev, wolfkdriv_session_t * session,
+ struct cryptop * crp,
+ const struct crypto_session_params * csp)
+{
+ struct crypto_buffer_cursor cc_in;
+ struct crypto_buffer_cursor cc_out;
+ const unsigned char * in_seg = NULL;
+ unsigned char * out_seg = NULL;
+ Aes aes;
+ uint8_t iv[WC_AES_BLOCK_SIZE];
+ uint8_t auth_tag[WC_AES_BLOCK_SIZE];
+ size_t data_len = 0;
+ size_t seg_len = 0;
+ size_t in_len = 0;
+ size_t out_len = 0;
+ int error = 0;
+ int is_encrypt = 0;
+
+ memcpy(&aes, &session->aes_ctx.aes_encrypt, sizeof(aes));
+
+ if (csp->csp_cipher_alg != CRYPTO_AES_NIST_GCM_16) {
+ error = EINVAL;
+ goto gcm_work_out;
+ }
+
+ data_len = crp->crp_payload_length;
+ if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
+ is_encrypt = 1;
+ }
+ else {
+ is_encrypt = 0;
+ }
+
+ error = wc_AesGcmSetKey(&aes, csp->csp_cipher_key,
+ csp->csp_cipher_klen);
+ if (error) {
+ device_printf(dev, "error: wc_AesGcmSetKey: %d\n", error);
+ goto gcm_work_out;
+ }
+
+ crypto_read_iv(crp, iv);
+ error = wc_AesGcmInit(&aes, NULL /* key */, 0 /* keylen */,
+ iv, csp->csp_ivlen);
+ if (error) {
+ device_printf(dev, "error: wc_AesGcmInit: %d\n", error);
+ goto gcm_work_out;
+ }
+
+ /* process aad first */
+ if (crp->crp_aad != NULL) {
+ /* they passed aad in separate buffer. */
+ if (is_encrypt) {
+ error = wc_AesGcmEncryptUpdate(&aes, NULL, NULL, 0,
+ crp->crp_aad, crp->crp_aad_length);
+ }
+ else {
+ error = wc_AesGcmDecryptUpdate(&aes, NULL, NULL, 0,
+ crp->crp_aad, crp->crp_aad_length);
+ }
+
+ if (error) {
+ error = EINVAL;
+ }
+ }
+ else {
+ /* we need to pull aad out of crp->crp_buf from crp_aad_start. */
+ size_t aad_len = 0;
+
+ crypto_cursor_init(&cc_in, &crp->crp_buf);
+ crypto_cursor_advance(&cc_in, crp->crp_aad_start);
+
+ for (aad_len = crp->crp_aad_length; aad_len > 0; aad_len -= seg_len) {
+ in_seg = crypto_cursor_segment(&cc_in, &in_len);
+ seg_len = MIN(aad_len, in_len);
+
+ if (is_encrypt) {
+ error = wc_AesGcmEncryptUpdate(&aes, NULL, NULL, 0,
+ in_seg, seg_len);
+ }
+ else {
+ error = wc_AesGcmDecryptUpdate(&aes, NULL, NULL, 0,
+ in_seg, seg_len);
+ }
+
+ if (error) {
+ error = EINVAL;
+ goto gcm_work_out;
+ }
+
+ crypto_cursor_advance(&cc_in, seg_len);
+ }
+ }
+
+ /*
+ * process cipher/plaintext next
+ */
+
+ /* set up the crypto buffers */
+ crypto_cursor_init(&cc_in, &crp->crp_buf);
+ crypto_cursor_advance(&cc_in, crp->crp_payload_start);
+
+ in_seg = crypto_cursor_segment(&cc_in, &in_len);
+
+ /* handle if the user supplied a separate out buffer. */
+ if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
+ crypto_cursor_init(&cc_out, &crp->crp_obuf);
+ crypto_cursor_advance(&cc_out, crp->crp_payload_output_start);
+ }
+ else {
+ cc_out = cc_in;
+ }
+
+ out_seg = crypto_cursor_segment(&cc_out, &out_len);
+
+ while (data_len) {
+ /* process through the available segments. */
+ in_seg = crypto_cursor_segment(&cc_in, &in_len);
+ out_seg = crypto_cursor_segment(&cc_out, &out_len);
+ seg_len = MIN(data_len, MIN(in_len, out_len));
+
+ if (is_encrypt) {
+ error = wc_AesGcmEncryptUpdate(&aes, out_seg, in_seg, seg_len,
+ NULL, 0);
+ if (error) {
+ device_printf(dev, "error: wc_AesGcmEncrypt: %d\n", error);
+ goto gcm_work_out;
+ }
+ }
+ else {
+ error = wc_AesGcmDecryptUpdate(&aes, out_seg, in_seg, seg_len,
+ NULL, 0);
+ if (error) {
+ device_printf(dev, "error: wc_AesGcmDecrypt: %d\n", error);
+ goto gcm_work_out;
+ }
+ }
+
+ /* advance the cursors by amount processed */
+ crypto_cursor_advance(&cc_in, seg_len);
+ crypto_cursor_advance(&cc_out, seg_len);
+
+ data_len -= seg_len;
+ }
+
+ /* process auth tag finally */
+ if (is_encrypt) {
+ error = wc_AesGcmEncryptFinal(&aes, auth_tag, WC_AES_BLOCK_SIZE);
+ if (error == 0) {
+ crypto_copyback(crp, crp->crp_digest_start, WC_AES_BLOCK_SIZE,
+ auth_tag);
+ }
+ }
+ else {
+ crypto_copydata(crp, crp->crp_digest_start, WC_AES_BLOCK_SIZE,
+ auth_tag);
+ error = wc_AesGcmDecryptFinal(&aes, auth_tag, WC_AES_BLOCK_SIZE);
+ if (error) {
+ error = EBADMSG;
+ }
+ }
+
+gcm_work_out:
+ /* cleanup. */
+ wc_ForceZero(iv, sizeof(iv));
+ wc_ForceZero(auth_tag, sizeof(auth_tag));
+
+ #if defined(WOLFSSL_BSDKM_VERBOSE_DEBUG)
+ device_printf(dev, "info: gcm_work: mode=%d, cipher_alg=%d, "
+ "payload_length=%d, error=%d\n",
+ csp->csp_mode, csp->csp_cipher_alg, crp->crp_payload_length,
+ error);
+ #endif /* WOLFSSL_BSDKM_VERBOSE_DEBUG */
+
+ return (error);
+}
+
+static int wolfkdriv_process(device_t dev, struct cryptop * crp, int hint)
+{
+ const struct crypto_session_params * csp = NULL;
+ wolfkdriv_session_t * session = NULL;
+ int error = 0;
+ (void)hint;
+
+ session = crypto_get_driver_session(crp->crp_session);
+ csp = crypto_get_params(crp->crp_session);
+
+ switch (csp->csp_mode) {
+ case CSP_MODE_CIPHER:
+ error = wolfkdriv_cbc_work(dev, session, crp, csp);
+ break;
+ case CSP_MODE_DIGEST:
+ case CSP_MODE_ETA:
+ error = EINVAL;
+ break;
+ case CSP_MODE_AEAD:
+ error = wolfkdriv_gcm_work(dev, session, crp, csp);
+ break;
+ default:
+ __assert_unreachable();
+ }
+
+ crp->crp_etype = error;
+ crypto_done(crp);
+
+ #if defined(WOLFSSL_BSDKM_VERBOSE_DEBUG)
+ device_printf(dev, "info: process: mode=%d, cipher_alg=%d, error=%d\n",
+ csp->csp_mode, csp->csp_cipher_alg, error);
+ #endif /* WOLFSSL_BSDKM_VERBOSE_DEBUG */
+
+ return (error);
+}
+
+/*
+ * wolfkmod as a crypto device driver.
+ */
+static device_method_t wolfkdriv_methods[] = {
+ /* device interface methods: called during device setup, etc. */
+ DEVMETHOD(device_identify, wolfkdriv_identify),
+ DEVMETHOD(device_probe, wolfkdriv_probe),
+ DEVMETHOD(device_attach, wolfkdriv_attach),
+ DEVMETHOD(device_detach, wolfkdriv_detach),
+
+ /* crypto device session methods: called during crypto session setup,
+ * work, etc. */
+ DEVMETHOD(cryptodev_probesession, wolfkdriv_probesession),
+ DEVMETHOD(cryptodev_newsession, wolfkdriv_newsession),
+ DEVMETHOD(cryptodev_freesession, wolfkdriv_freesession),
+ DEVMETHOD(cryptodev_process, wolfkdriv_process),
+
+ DEVMETHOD_END
+};
+
+static driver_t wolfkdriv_driver = {
+ .name = "libwolf",
+ .methods = wolfkdriv_methods,
+ .size = sizeof(struct wolfkdriv_softc),
+};
+
+/* on x86, software-only drivers usually attach to nexus bus. */
+DRIVER_MODULE(libwolfssl, nexus, wolfkdriv_driver, NULL, NULL);
+#endif /* BSDKM_CRYPTO_REGISTER */
+
+#if !defined(BSDKM_CRYPTO_REGISTER)
+/*
+ * wolfkmod as a pure kernel module.
+ */
static moduledata_t libwolfmod = {
#ifdef HAVE_FIPS
"libwolfssl_fips", /* module name */
@@ -305,6 +1066,8 @@ static moduledata_t libwolfmod = {
NULL /* extra data, unused */
};
-MODULE_VERSION(libwolfssl, 1);
DECLARE_MODULE(libwolfssl, libwolfmod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
+#endif /* !BSDKM_CRYPTO_REGISTER */
+
+MODULE_VERSION(libwolfssl, 1);
#endif /* WOLFSSL_BSDKM */
diff --git a/bsdkm/wolfkmod_aes.c b/bsdkm/wolfkmod_aes.c
new file mode 100644
index 0000000000..9fb776e988
--- /dev/null
+++ b/bsdkm/wolfkmod_aes.c
@@ -0,0 +1,347 @@
+#if !defined(WC_SKIP_INCLUDED_C_FILES) && defined(BSDKM_CRYPTO_REGISTER)
+#include
+
+/*
+ * the cryptodev framework always calls a callback, even when CRYPTOCAP_F_SYNC.
+ */
+static int
+wolfkdriv_test_crp_callback(struct cryptop * crp)
+{
+ (void)crp;
+ return (0);
+}
+
+/* Test aes-cbc with a buffer larger than aes block size.
+ * Verify direct wolfcrypt API and opencrypto framework return
+ * same result. */
+static int wolfkdriv_test_aes_cbc_big(device_t dev, int crid)
+{
+ crypto_session_t session = NULL;
+ struct crypto_session_params csp;
+ struct cryptop * crp = NULL;
+ Aes * aes_encrypt = NULL;
+ int error = 0;
+ byte msg[] = {
+ 0x6e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,
+ 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20,
+ 0x6e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,
+ 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20,
+ 0x6e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,
+ 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20
+ };
+ byte work1[WC_AES_BLOCK_SIZE * 3]; /* wolfcrypt buffer */
+ byte work2[WC_AES_BLOCK_SIZE * 3]; /* opencrypto buffer */
+ /* padded to 16-bytes */
+ const byte key[] = "0123456789abcdef ";
+ /* padded to 16-bytes */
+ const byte iv[] = "1234567890abcdef ";
+
+ memset(&csp, 0, sizeof(csp));
+ memcpy(work1, msg, sizeof(msg)); /* wolfcrypt work buffer */
+ memcpy(work2, msg, sizeof(msg)); /* opencrypto work buffer */
+
+ /* wolfcrypt encrypt */
+ aes_encrypt = (Aes *)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_AES);
+ if (aes_encrypt == NULL) {
+ error = ENOMEM;
+ device_printf(dev, "error: malloc failed\n");
+ goto test_aes_cbc_big_out;
+ }
+
+ error = wc_AesInit(aes_encrypt, NULL, INVALID_DEVID);
+ if (error) {
+ device_printf(dev, "error: newsession_cipher: aes init: %d\n", error);
+ goto test_aes_cbc_big_out;
+ }
+
+ error = wc_AesSetKey(aes_encrypt, key, 16, iv, AES_ENCRYPTION);
+ if (error) {
+ device_printf(dev, "error: wc_AesSetKey: %d\n", error);
+ goto test_aes_cbc_big_out;
+ }
+
+ error = wc_AesCbcEncrypt(aes_encrypt, work1, work1, sizeof(work1));
+ if (error) {
+ device_printf(dev, "error: wc_AesCbcEncrypt: %d\n", error);
+ goto test_aes_cbc_big_out;
+ }
+
+ /* opencrypto encrypt */
+ csp.csp_mode = CSP_MODE_CIPHER;
+ csp.csp_cipher_alg = CRYPTO_AES_CBC;
+ csp.csp_ivlen = WC_AES_BLOCK_SIZE;
+ csp.csp_cipher_key = key;
+ csp.csp_cipher_klen = WC_AES_BLOCK_SIZE;
+ error = crypto_newsession(&session, &csp, crid);
+ if (error || session == NULL) {
+ goto test_aes_cbc_big_out;
+ }
+
+ crp = crypto_getreq(session, M_WAITOK);
+ if (crp == NULL) {
+ device_printf(dev, "error: test_aes: crypto_getreq failed\n");
+ goto test_aes_cbc_big_out;
+ }
+
+ crp->crp_callback = wolfkdriv_test_crp_callback;
+ crp->crp_op = CRYPTO_OP_ENCRYPT;
+ crp->crp_flags = CRYPTO_F_IV_SEPARATE;
+
+ memcpy(crp->crp_iv, iv, WC_AES_BLOCK_SIZE);
+
+ crypto_use_buf(crp, work2, sizeof(work2));
+ crp->crp_payload_start = 0;
+ crp->crp_payload_length = sizeof(work2);
+
+ error = crypto_dispatch(crp);
+ if (error) {
+ goto test_aes_cbc_big_out;
+ }
+
+ error = XMEMCMP(work1, work2, sizeof(work2));
+ if (error) {
+ device_printf(dev, "error: test_aes: enc vectors diff: %d\n", error);
+ goto test_aes_cbc_big_out;
+ }
+
+ /* opencrypto decrypt */
+ crp->crp_op = CRYPTO_OP_DECRYPT;
+
+ error = crypto_dispatch(crp);
+ if (error) {
+ goto test_aes_cbc_big_out;
+ }
+
+ error = XMEMCMP(work2, msg, sizeof(msg));
+ if (error) {
+ device_printf(dev, "error: test_aes: dec vectors diff: %d\n", error);
+ goto test_aes_cbc_big_out;
+ }
+
+test_aes_cbc_big_out:
+ #if defined(WOLFSSL_BSDKM_VERBOSE_DEBUG)
+ device_printf(dev, "info: test_aes_cbc_big: error=%d, session=%p, crp=%p\n",
+ error, (void *)session, (void*)crp);
+ #endif /* WOLFSSL_BSDKM_VERBOSE_DEBUG */
+
+ if (crp != NULL) {
+ crypto_freereq(crp);
+ crp = NULL;
+ }
+
+ if (session != NULL) {
+ crypto_freesession(session);
+ session = NULL;
+ }
+
+ if (aes_encrypt != NULL) {
+ wc_AesFree(aes_encrypt);
+ XFREE(aes_encrypt, NULL, DYNAMIC_TYPE_AES);
+ aes_encrypt = NULL;
+ }
+
+ return (error);
+}
+
+/* Test aes-gcm encrypt and decrypt a small buffer with opencrypto
+ * framework and wolfcrypt.
+ */
+static int wolfkdriv_test_aes_gcm(device_t dev, int crid)
+{
+ crypto_session_t session = NULL;
+ struct crypto_session_params csp;
+ struct cryptop * crp = NULL;
+ Aes * enc = NULL;
+ int error = 0;
+
+ WOLFSSL_SMALL_STACK_STATIC const byte p[] =
+ {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39
+ };
+
+ WOLFSSL_SMALL_STACK_STATIC const byte c1[] =
+ {
+ 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+ 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+ 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+ 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+ 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+ 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+ 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+ 0xbc, 0xc9, 0xf6, 0x62
+ };
+
+ WOLFSSL_SMALL_STACK_STATIC byte a[] =
+ {
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2
+ };
+
+ WOLFSSL_SMALL_STACK_STATIC const byte k1[] =
+ {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
+ };
+
+ WOLFSSL_SMALL_STACK_STATIC const byte iv1[] =
+ {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88
+ };
+
+ WOLFSSL_SMALL_STACK_STATIC const byte t1[] =
+ {
+ 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
+ 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b
+ };
+
+ byte resultT[sizeof(t1) + WC_AES_BLOCK_SIZE];
+ byte resultC[sizeof(p) + WC_AES_BLOCK_SIZE];
+ byte resultC2[sizeof(p) + WC_AES_BLOCK_SIZE];
+
+ XMEMSET(resultT, 0, sizeof(resultT));
+ XMEMSET(resultC, 0, sizeof(resultC));
+
+ XMEMSET(resultC2, 0, sizeof(resultC));
+ XMEMCPY(resultC2, p, sizeof(p));
+
+ /* wolfcrypt encrypt */
+ enc = (Aes *)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_AES);
+ if (enc == NULL) {
+ error = ENOMEM;
+ device_printf(dev, "error: malloc failed\n");
+ goto test_aes_gcm_out;
+ }
+
+ error = wc_AesGcmEncryptInit(enc, k1, sizeof(k1), iv1, sizeof(iv1));
+ if (error) { goto test_aes_gcm_out; }
+
+ error = wc_AesGcmEncryptUpdate(enc, resultC, p, sizeof(p), a, sizeof(a));
+ if (error) { goto test_aes_gcm_out; }
+
+ error = wc_AesGcmEncryptFinal(enc, resultT, sizeof(t1));
+ if (error) { goto test_aes_gcm_out; }
+
+ error = XMEMCMP(resultC, c1, sizeof(c1));
+ if (error) { goto test_aes_gcm_out; }
+
+ error = XMEMCMP(resultT, t1, sizeof(t1));
+ if (error) { goto test_aes_gcm_out; }
+
+ /*
+ * opencrypto encrypt
+ * */
+
+ /* set crypto session params */
+ memset(&csp, 0, sizeof(csp));
+ csp.csp_flags |= CSP_F_SEPARATE_AAD;
+ csp.csp_mode = CSP_MODE_AEAD;
+ csp.csp_cipher_alg = CRYPTO_AES_NIST_GCM_16;
+ csp.csp_ivlen = sizeof(iv1);
+ csp.csp_cipher_key = k1;
+ csp.csp_cipher_klen = sizeof(k1);
+
+ /* get crypto session handle */
+ error = crypto_newsession(&session, &csp, crid);
+ if (error || session == NULL) {
+ device_printf(dev, "error: test_aes: crypto_newsession: %d, %p\n",
+ error, (void *)session);
+ goto test_aes_gcm_out;
+ }
+
+ /* get a crypto op handle */
+ crp = crypto_getreq(session, M_WAITOK);
+ if (crp == NULL) {
+ device_printf(dev, "error: test_aes: crypto_getreq failed\n");
+ goto test_aes_gcm_out;
+ }
+
+ /* configure it */
+ crp->crp_callback = wolfkdriv_test_crp_callback;
+ crp->crp_op = (CRYPTO_OP_ENCRYPT | CRYPTO_OP_COMPUTE_DIGEST);
+ crp->crp_flags = CRYPTO_F_IV_SEPARATE;
+
+ memcpy(crp->crp_iv, iv1, sizeof(iv1));
+
+ crypto_use_buf(crp, resultC2, sizeof(resultC2));
+ crp->crp_payload_start = 0;
+ crp->crp_payload_length = sizeof(p);
+
+ crp->crp_aad = a;
+ crp->crp_aad_start = 0;
+ crp->crp_aad_length = sizeof(a);
+ crp->crp_digest_start = crp->crp_payload_start + sizeof(p);
+
+ error = crypto_dispatch(crp);
+ if (error) {
+ goto test_aes_gcm_out;
+ }
+
+ error = XMEMCMP(resultC2, c1, sizeof(c1));
+ if (error) { goto test_aes_gcm_out; }
+
+ error = XMEMCMP(resultC2 + sizeof(p), t1, sizeof(t1));
+ if (error) { goto test_aes_gcm_out; }
+
+ /* opencrypto decrypt */
+ crp->crp_op = (CRYPTO_OP_DECRYPT | CRYPTO_OP_VERIFY_DIGEST);
+
+ error = crypto_dispatch(crp);
+ if (error) {
+ goto test_aes_gcm_out;
+ }
+
+ error = XMEMCMP(resultC2, p, sizeof(p));
+ if (error) { goto test_aes_gcm_out; }
+
+test_aes_gcm_out:
+ #if defined(WOLFSSL_BSDKM_VERBOSE_DEBUG)
+ device_printf(dev, "info: test_aes_gcm: error=%d, session=%p, crp=%p\n",
+ error, (void *)session, (void*)crp);
+ #endif /* WOLFSSL_BSDKM_VERBOSE_DEBUG */
+
+ if (crp != NULL) {
+ crypto_freereq(crp);
+ crp = NULL;
+ }
+
+ if (session != NULL) {
+ crypto_freesession(session);
+ session = NULL;
+ }
+
+ if (enc != NULL) {
+ wc_AesFree(enc);
+ XFREE(enc, NULL, DYNAMIC_TYPE_AES);
+ enc = NULL;
+ }
+
+ return (error);
+}
+
+
+static int wolfkdriv_test_aes(device_t dev, int crid)
+{
+ int error = 0;
+
+ if (error == 0) {
+ error = wolfkdriv_test_aes_cbc_big(dev, crid);
+ }
+
+ if (error == 0) {
+ error = wolfkdriv_test_aes_gcm(dev, crid);
+ }
+
+ return (error);
+}
+#endif /* !WC_SKIP_INCLUDED_C_FILES && BSDKM_CRYPTO_REGISTER */
diff --git a/bsdkm/x86_vecreg.c b/bsdkm/x86_vecreg.c
new file mode 100644
index 0000000000..7b58c84f65
--- /dev/null
+++ b/bsdkm/x86_vecreg.c
@@ -0,0 +1,225 @@
+/* x86_vecreg.c -- logic to save and restore vector registers
+ * on amd64 in FreeBSD kernel.
+ *
+ * Copyright (C) 2006-2025 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* included by bsdkm/wolfkmod.c */
+#ifndef WC_SKIP_INCLUDED_C_FILES
+
+#include
+#include
+#include
+#include
+
+struct wolfkmod_fpu_state_t {
+ volatile lwpid_t td_tid;
+ volatile u_int nest;
+};
+
+typedef struct wolfkmod_fpu_state_t wolfkmod_fpu_state_t;
+
+/* fpu_states array tracks thread id and nesting level of save/restore
+ * and push/pop vector registers macro calls. It is indexed by raw cpu id,
+ * and only accessed after the thread calls fpu_kern_enter(), and before
+ * calling fpu_kern_leave(), and only indexed by the thread's PCPU_GET(cpuid).
+ *
+ * after calling fpu_kern_enter():
+ * - kernel fpu is enabled
+ * - migration is disabled
+ * - soft preempts are disabled
+ * Hard irq are still possible , but hard irq are forbidden from using FPU
+ * in FreeBSD kernel.
+ * */
+static wolfkmod_fpu_state_t * fpu_states = NULL;
+
+/* check for active td_tid with atomic before proceeding.
+ * technically not necessary because fpu_kern_enter() gives thread pinning
+ * to cpu, but just to be safe...
+ * */
+#define wolfkmod_fpu_get_tid() \
+ atomic_load_acq_int(&fpu_states[PCPU_GET(cpuid)].td_tid)
+
+int wolfkmod_vecreg_init(void)
+{
+ if (mp_ncpus <= 0) {
+ printf("error: wolfkmod_vecreg_init: mp_ncpus = %d\n", mp_ncpus);
+ return (EINVAL);
+ }
+
+ fpu_states = malloc(mp_ncpus * sizeof(wolfkmod_fpu_state_t),
+ M_WOLFSSL, M_WAITOK | M_ZERO);
+ if (fpu_states == NULL) {
+ printf("error: wolfkmod_vecreg_init: malloc(%lu) failed\n",
+ mp_ncpus * sizeof(wolfkmod_fpu_state_t));
+ return (ENOMEM);
+ }
+
+ return (0);
+}
+
+void wolfkmod_vecreg_exit(void)
+{
+ int i = 0;
+
+ if (fpu_states == NULL) {
+ return;
+ }
+
+ for (i = 0; i < mp_ncpus; ++i) {
+ #if defined(WOLFSSL_BSDKM_FPU_DEBUG)
+ printf("info: wolfkmod_vecreg_exit: fpu_states[%d] = %d, %d\n",
+ i, fpu_states[i].nest, fpu_states[i].td_tid);
+ #endif /* WOLFSSL_BSDKM_FPU_DEBUG */
+
+ if (fpu_states[i].nest != 0 || fpu_states[i].td_tid != 0) {
+ /* Check for orphaned fpu state. There's nothing we can do
+ * but log the event and zero the nesting level. */
+ printf("error: wolfkmod_vecreg_exit: fpu_states[%d] = %d, %d\n",
+ i, fpu_states[i].nest, fpu_states[i].td_tid);
+ fpu_states[i].nest = 0;
+ }
+ }
+
+ free(fpu_states, M_WOLFSSL);
+ fpu_states = NULL;
+
+ return;
+}
+
+/* fpu_kern_enter() and fpu_kern_leave() wrapper defines.
+ * Build with WOLFSSL_BSDKM_FPU_DEBUG to see verbose FPU logging.
+ */
+#if defined(WOLFSSL_BSDKM_FPU_DEBUG)
+ #define wolfkmod_print_curthread(what) \
+ printf("%s: cpuid = %d, curthread: td_tid = %d, pid = %d (%s), " \
+ "td_critnest = %d, kernfpu = %02x\n", \
+ (what), PCPU_GET(cpuid), curthread->td_tid, \
+ curthread->td_proc ? curthread->td_proc->p_pid : -1, \
+ curthread->td_proc ? curthread->td_proc->p_comm : "noproc", \
+ curthread->td_critnest, \
+ curthread->td_pcb->pcb_flags & PCB_KERNFPU);
+
+ #define wolfkmod_fpu_kern_enter() \
+ wolfkmod_print_curthread("fpu_kern_enter"); \
+ fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX);
+
+ #define wolfkmod_fpu_kern_leave() \
+ wolfkmod_print_curthread("fpu_kern_leave"); \
+ fpu_kern_leave(curthread, NULL);
+#else
+ #define wolfkmod_fpu_kern_enter() \
+ fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX);
+
+ #define wolfkmod_fpu_kern_leave() \
+ fpu_kern_leave(curthread, NULL);
+#endif /* WOLFSSL_BSDKM_FPU_DEBUG */
+
+int wolfkmod_vecreg_save(int flags_unused)
+{
+ (void)flags_unused;
+
+ #if defined(WOLFSSL_BSDKM_FPU_DEBUG)
+ wolfkmod_print_curthread("wolfkmod_vecreg_save");
+ #endif
+
+ if (is_fpu_kern_thread(0)) {
+ /* kernel fpu threads are special, do nothing. They own a
+ * persistent, dedicated fpu context. */
+ #if defined(WOLFSSL_BSDKM_FPU_DEBUG)
+ printf("info: wolfkmod_vecreg_save: is fpu kern thread\n");
+ #endif
+ return (0);
+ }
+
+ if (curthread->td_pcb->pcb_flags & PCB_KERNFPU) {
+ /* kern fpu is active for this thread. check td_tid and
+ * increment nesting level. */
+ lwpid_t td_tid = wolfkmod_fpu_get_tid();
+ if (td_tid != curthread->td_tid) {
+ printf("error: wolfkmod_vecreg_save: got tid = %d, expected %d\n",
+ td_tid, curthread->td_tid);
+ return (EINVAL);
+ }
+ fpu_states[PCPU_GET(cpuid)].nest++;
+ }
+ else {
+ /* kern fpu not active for this thread, call fpu_kern_enter().
+ * after calling fpu_kern_enter():
+ * - kernel fpu is enabled
+ * - migration is disabled
+ * - soft preempts are disabled */
+ lwpid_t td_tid = 0;
+ wolfkmod_fpu_kern_enter();
+ td_tid = wolfkmod_fpu_get_tid();
+
+ if (fpu_states[PCPU_GET(cpuid)].nest != 0 || td_tid != 0) {
+ printf("error: wolfkmod_fpu_kern_enter() with nest: %d, %d\n",
+ fpu_states[PCPU_GET(cpuid)].nest, td_tid);
+ return (EINVAL);
+ }
+
+ /* increment nest and save td_tid. */
+ fpu_states[PCPU_GET(cpuid)].nest++;
+ fpu_states[PCPU_GET(cpuid)].td_tid = curthread->td_tid;
+ }
+
+ return (0);
+}
+
+void wolfkmod_vecreg_restore(void)
+{
+ #if defined(WOLFSSL_BSDKM_FPU_DEBUG)
+ wolfkmod_print_curthread("wolfkmod_vecreg_restore");
+ #endif
+
+ if (is_fpu_kern_thread(0)) {
+ /* kernel fpu threads are special, do nothing. They own a
+ * persistent, dedicated fpu context. */
+ #if defined(WOLFSSL_BSDKM_FPU_DEBUG)
+ printf("info: wolfkmod_vecreg_restore: is fpu kern thread\n");
+ #endif
+ return;
+ }
+
+ if (curthread->td_pcb->pcb_flags & PCB_KERNFPU) {
+ /* kern fpu is active for this thread. check tid and nesting level. */
+ lwpid_t td_tid = wolfkmod_fpu_get_tid();
+ if (td_tid != curthread->td_tid) {
+ printf("error: wolfkmod_vecreg_restore: got tid = %d, "
+ "expected %d\n", td_tid, curthread->td_tid);
+ return;
+ }
+
+ /* decrement the nesting level. */
+ if (fpu_states[PCPU_GET(cpuid)].nest > 0) {
+ fpu_states[PCPU_GET(cpuid)].nest--;
+ }
+
+ /* if last level, zero the thread id then call fpu_kern_leave */
+ if (fpu_states[PCPU_GET(cpuid)].nest == 0) {
+ fpu_states[PCPU_GET(cpuid)].td_tid = 0;
+ wolfkmod_fpu_kern_leave();
+ }
+ }
+
+ return;
+}
+
+#endif /* !WC_SKIP_INCLUDED_C_FILES */
diff --git a/certs/aia/ca-issuers-cert.pem b/certs/aia/ca-issuers-cert.pem
new file mode 100644
index 0000000000..22630fc366
--- /dev/null
+++ b/certs/aia/ca-issuers-cert.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDUDCCAjigAwIBAgIUQy4lyOzJcvFVekNsQWuUegW0kGgwDQYJKoZIhvcNAQEL
+BQAwGzEZMBcGA1UEAwwQd29sZnNzbC1haWEtdGVzdDAeFw0yNjAxMjYyMzE1NTZa
+Fw0yNzAxMjYyMzE1NTZaMBsxGTAXBgNVBAMMEHdvbGZzc2wtYWlhLXRlc3QwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDM1vUyiX+qtPFhhEqZq3bCUKpd
+6QtswO7YWj+us79yh99mIGE7EZlSfTv0n3rn2//m5bQ7a+TSYMkDyNjPEH6Z+ub2
+qW4EJyc4J9DfC+T9gJM4dvsij+F8TUne/o5iCwFdiZEycEj0vtyYh53du3oqlZTY
+yt8q4k5INoTl+ELCX/L0YqR/+Fl2qaloK7YHUb3EdSqBEGoa/IEfnxHMreZWhVYd
+pSdDnT9rfNqT5Kb2e+eZbZZSouEmebhx9ioRfIXDadSCCa1JNp4fO3YlcDmmEahx
+6TcjEmhUt80+hjhJhqrh4vPlxI24qHmfOe+k2qSimpJse/AUuz7wGRjx6ktfAgMB
+AAGjgYswgYgwHQYDVR0OBBYEFMvT3KE5dvI6t3KNrcuctkm6wvXMMB8GA1UdIwQY
+MBaAFMvT3KE5dvI6t3KNrcuctkm6wvXMMA8GA1UdEwEB/wQFMAMBAf8wNQYIKwYB
+BQUHAQEEKTAnMCUGCCsGAQUFBzAChhlodHRwOi8vZXhhbXBsZS5jb20vY2EucGVt
+MA0GCSqGSIb3DQEBCwUAA4IBAQCjxEHOlxVfmE8xgcQCnr1b4IK5EBuIMUaS7lko
+AHmHvj7z9rr2cxbJhGYQxcttZ4/SQldRqpmiB0cUmko4LbD9yos4FKlyGe3xWvKa
+W17SdpJU2PREShGLLqP7bwiWV6wVyo6puwDHLYSjH5vYr+IcSNNc0GuMZg1OhTWt
+2PYG2vGbHoNR0/UyNibGmaPBimg0nb2GTizY7yWm+N/yXnWa6Wc5yyiF1zExw/GO
+8O/rF0Lg/Gy/v6LnnNmhSOr9ENPKgQEAHFmJRXBXqDYUNhcm2U3PzlfBa06SHFcr
+b59n5jgJmcNSwYDJAYKEhMvjBL40DmiWaRfol2DPoIZ7YtRf
+-----END CERTIFICATE-----
diff --git a/certs/aia/multi-aia-cert.pem b/certs/aia/multi-aia-cert.pem
new file mode 100644
index 0000000000..d0722788f1
--- /dev/null
+++ b/certs/aia/multi-aia-cert.pem
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIIDwTCCAqmgAwIBAgIUEcNoHSMtIkVhW/MmkmUEsVoJVQEwDQYJKoZIhvcNAQEL
+BQAwITEfMB0GA1UEAwwWd29sZnNzbC1haWEtbXVsdGktdGVzdDAeFw0yNjAxMjcw
+MTUwNDRaFw0yNzAxMjcwMTUwNDRaMCExHzAdBgNVBAMMFndvbGZzc2wtYWlhLW11
+bHRpLXRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpVdogPQ2I
+/nErbxSaNGoYhkwoj1qt+Be1/qWnvZzJ0EBOG4EdioMRIkJzP6W3HoAhkGBrueXf
+riN07M3XLocRfE+9C1+jZQxBGRxysns9z7K+i0pBtPN/AXV2RCSz13FFyVyLhLks
+2YAL9By36X9R0wsL+Nd4EAQ4ouf0GglmTmtb5rHf2GIno4xFg9tpWosiUTytwgDC
+K9lQEQnTnPG6E43N2bszqBc4roOPrYDnd7raNTqcv9yTHM8zwffGJuCogE/Fbr2R
+yVubLW28n5/O1Pb47hHuPJv6oHMZgct2SV5OB/mwVgI0eoFMSQZ35o6BpHD0C497
+L2IcoMi8A9rFAgMBAAGjgfAwge0wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAoQw
+gbAGCCsGAQUFBwEBBIGjMIGgMCIGCCsGAQUFBzABhhZodHRwOi8vMTI3LjAuMC4x
+OjIyMjIxMCIGCCsGAQUFBzABhhZodHRwOi8vMTI3LjAuMC4xOjIyMjIyMCkGCCsG
+AQUFBzAChh1odHRwOi8vd3d3LndvbGZzc2wuY29tL2NhLnBlbTArBggrBgEFBQcw
+AoYfaHR0cHM6Ly93d3cud29sZnNzbC5jb20vY2EyLnBlbTAdBgNVHQ4EFgQU1GNm
+eP/LXQk0tFaTeWoNHyLhLZkwDQYJKoZIhvcNAQELBQADggEBACwuXdKYI2Q/Vhd7
+TJFvKdp7BuUopQGEQ+4vR+FoesYXc9MHjZJfMqEffv1MArTeY46At/zvcTeszagi
+io+jjGBLOutsAf9WK3PnKMIkGGfro6btZ8QFyKiZ6unMMlqe6cGqrCrNKp8jLP3k
+CKZltR5c+MIPhpjoOhNDMOcPMwZBGQJWubwOb4uOu3wv7UWJk/ovKP9WJCUn6wLH
+soDs+MHMICkxOvDfPf+F4URVqTbzE8IvSMv38z4cAqsyEfWxr32Dg34S/NmeePFV
+7sSDpksvyITGsxjnQulSuUFSmldumQ6GnA4ZUXvCNdJ0zbD/Iib9ud6K05VdWYZP
+uyCRkjY=
+-----END CERTIFICATE-----
diff --git a/certs/aia/overflow-aia-cert.pem b/certs/aia/overflow-aia-cert.pem
new file mode 100644
index 0000000000..1054df14ea
--- /dev/null
+++ b/certs/aia/overflow-aia-cert.pem
@@ -0,0 +1,26 @@
+-----BEGIN CERTIFICATE-----
+MIIEcDCCA1igAwIBAgIUN5kIU1GLRP5bRKctP271p7IGFVowDQYJKoZIhvcNAQEL
+BQAwJDEiMCAGA1UEAwwZd29sZnNzbC1haWEtb3ZlcmZsb3ctdGVzdDAeFw0yNjAx
+MjcwMTU1NTBaFw0yNzAxMjcwMTU1NTBaMCQxIjAgBgNVBAMMGXdvbGZzc2wtYWlh
+LW92ZXJmbG93LXRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDS
+eHeAzVuCe44SU8bcyIWLwkA2AABw/ctSBWKAFEd7DYHduRr3diblHERU1Fv5JzYx
+JnZquj1IO/qsnSFJYDc9sQmYea89iW8KNPVXKDzdbzhpiQLZL7Yq71ICxxqVLfRr
+91lyAj0+Syncrp96olSpMJochVnQ6PqLcc/Gq7CMtrKn5KAN7Mn3+LdAQYU8JjRa
+zqEJ8fmkBKbS5watzgnkP2o5jWSpWzpDOxTdw85hju4H9m5Gmun3XVO9dEAN/dqK
+vklkzgQGvAMMQMIcgOzw0HxAuvsSNtjgEpIlOir0M7YiC0pYqtMO+thSCmVCvsDR
+/nG/iqe6YBSXh6oszGwTAgMBAAGjggGYMIIBlDAMBgNVHRMEBTADAQH/MAsGA1Ud
+DwQEAwIChDCCAVYGCCsGAQUFBwEBBIIBSDCCAUQwIgYIKwYBBQUHMAGGFmh0dHA6
+Ly8xMjcuMC4wLjE6MjIyMjAwIgYIKwYBBQUHMAGGFmh0dHA6Ly8xMjcuMC4wLjE6
+MjIyMjEwIgYIKwYBBQUHMAGGFmh0dHA6Ly8xMjcuMC4wLjE6MjIyMjIwIgYIKwYB
+BQUHMAGGFmh0dHA6Ly8xMjcuMC4wLjE6MjIyMjMwIgYIKwYBBQUHMAGGFmh0dHA6
+Ly8xMjcuMC4wLjE6MjIyMjQwIgYIKwYBBQUHMAGGFmh0dHA6Ly8xMjcuMC4wLjE6
+MjIyMjUwIgYIKwYBBQUHMAGGFmh0dHA6Ly8xMjcuMC4wLjE6MjIyMjYwIgYIKwYB
+BQUHMAGGFmh0dHA6Ly8xMjcuMC4wLjE6MjIyMjcwIgYIKwYBBQUHMAGGFmh0dHA6
+Ly8xMjcuMC4wLjE6MjIyMjgwHQYDVR0OBBYEFJt6TNgqMFBebotXaauIYPpUJi1S
+MA0GCSqGSIb3DQEBCwUAA4IBAQA5noHB343sKQqVmmLds0gC/k1UhVA5iftAGmes
+uRdNOOCdo2i739DmRAXggetgtatcjDfjxkrvq0Qi+geozZra6uX9FT/hgfw6kDpU
+HKzJFy4E0G0HTM8mtJi+aGDZL3Lts+h272eahkT1jVKGAPFugqfz7fKRsMce6eCE
+UD5cvtQXX16fGhBxxmUCZPnxMKcj2oNl7RliHphK6ofXuNbKjqjVQfxsTUXSQDyS
+ApH5w6iUnAvC5l19qYrBcCVOB6CNJ2CdmvFI//Ox8Jc56HRYYDIdVp2Q3FFA5Z4s
+gTLvlumVgihAekD+0zVF9q+AJ4TSbE3cqsQgHF/+p84KxWid
+-----END CERTIFICATE-----
diff --git a/certs/crl/crlEccOut.der b/certs/crl/crlEccOut.der
new file mode 100644
index 0000000000..b26615ca5a
Binary files /dev/null and b/certs/crl/crlEccOut.der differ
diff --git a/certs/crl/crlEccOut.pem b/certs/crl/crlEccOut.pem
new file mode 100644
index 0000000000..b9d0146f89
--- /dev/null
+++ b/certs/crl/crlEccOut.pem
@@ -0,0 +1,10 @@
+-----BEGIN X509 CRL-----
+MIIBdDCCARkCAQEwCgYIKoZIzj0EAwIwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
+DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NM
+MRQwEgYDVQQLDAtEZXZlbG9wbWVudDEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29t
+MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tFw0yNjAyMDQwMzU0Mjla
+Fw0yNjAzMDYwMzU0MjlaMFAwEgIBAhcNMjYwMjA0MDM1NDI5WjASAgEDFw0yNjAy
+MDQwMzU0MjlaMBICAQQXDTI2MDIwNDAzNTQyOVowEgIBAxcNMjYwMjA0MDM1NDI5
+WjAKBggqhkjOPQQDAgNJADBGAiEA6xz109x9tZwaxxs3iLvW65h9AGL8+e1gTnbr
+GoEsXaQCIQDzxO4LU1d6seHETQDKjUEXivHuvC6f0Nq5uARmWX0DOA==
+-----END X509 CRL-----
diff --git a/certs/crl/crlRsaOut.der b/certs/crl/crlRsaOut.der
new file mode 100644
index 0000000000..97d7a5485a
Binary files /dev/null and b/certs/crl/crlRsaOut.der differ
diff --git a/certs/crl/crlRsaOut.pem b/certs/crl/crlRsaOut.pem
new file mode 100644
index 0000000000..e238f5b829
--- /dev/null
+++ b/certs/crl/crlRsaOut.pem
@@ -0,0 +1,14 @@
+-----BEGIN X509 CRL-----
+MIICMTCCARkCAQEwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVTMRAwDgYD
+VQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhTYXd0b290
+aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29t
+MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tFw0yNjAyMDQwMzU0Mjla
+Fw0yNjAzMDYwMzU0MjlaMFAwEgIBAhcNMjYwMjA0MDM1NDI5WjASAgEDFw0yNjAy
+MDQwMzU0MjlaMBICAQQXDTI2MDIwNDAzNTQyOVowEgIBARcNMjYwMjA0MDM1NDI5
+WjANBgkqhkiG9w0BAQsFAAOCAQEAid2CDa/invAbnAJaeVVkS8mRjI/kR0aPHwt1
+/Sz6w+j163+KZnBwUNgrMmLSMbssm8oxQ8i8zNvBeYd6u1x2N/jw/cwH2rxhZ3zQ
+bOkDQKKe2eRYXMykAl1uj2VwCeu8/ivqbimYReq7iloEHo8PUiizs1Pj6zJ59I1u
+LRZDDlS9wiY+VVkKx28dxyClsqtJNCvz5ezNB8GeH+gekaJ1tJVbd3TujBajPPAx
+R6FobbOOavCZPyGkeZlU/T9S5FwIi07qga5Zuq/9Dy7YwiVya3sAZ/nTYY++HKDQ
+DL0Bs3/05Lf8BLaf2CX2vGvan4JCQv9CMdnlYBifwvQCeUToyQ==
+-----END X509 CRL-----
diff --git a/certs/crl/include.am b/certs/crl/include.am
index 6f7f6f26bf..f3ca111ecf 100644
--- a/certs/crl/include.am
+++ b/certs/crl/include.am
@@ -22,7 +22,9 @@ EXTRA_DIST += \
EXTRA_DIST += \
certs/crl/crl.revoked \
certs/crl/extra-crls/ca-int-cert-revoked.pem \
- certs/crl/extra-crls/general-server-crl.pem
+ certs/crl/extra-crls/general-server-crl.pem \
+ certs/crl/extra-crls/large_crlnum.pem \
+ certs/crl/extra-crls/large_crlnum2.pem
# Intermediate cert CRL's
EXTRA_DIST += \
diff --git a/certs/include.am b/certs/include.am
index 68fcd1e2ea..26c5f959d2 100644
--- a/certs/include.am
+++ b/certs/include.am
@@ -85,6 +85,11 @@ EXTRA_DIST += \
certs/dh-pub-2048.pem \
certs/dsa2048.pem
+EXTRA_DIST += \
+ certs/aia/ca-issuers-cert.pem \
+ certs/aia/multi-aia-cert.pem \
+ certs/aia/overflow-aia-cert.pem
+
EXTRA_DIST += \
certs/ca-key.der \
certs/ca-cert.der \
@@ -154,4 +159,3 @@ include certs/sphincs/include.am
include certs/rpk/include.am
include certs/acert/include.am
include certs/mldsa/include.am
-
diff --git a/certs/renewcerts.sh b/certs/renewcerts.sh
index 5aed648817..535ae8ff73 100755
--- a/certs/renewcerts.sh
+++ b/certs/renewcerts.sh
@@ -31,6 +31,9 @@
# fpki-cert.der
# fpki-certpol-cert.der
# rid-cert.der
+# aia/ca-issuers-cert.pem
+# aia/multi-aia-cert.pem
+# aia/overflow-aia-cert.pem
# updates the following crls:
# crl/cliCrl.pem
# crl/crl.pem
@@ -292,6 +295,60 @@ run_renewcerts(){
echo "End of section"
echo "---------------------------------------------------------------------"
############################################################
+ ########## update AIA test certs ###########################
+ ############################################################
+ echo "Updating AIA test certs"
+ echo ""
+ mkdir -p aia
+
+ echo "Updating aia/ca-issuers-cert.pem"
+ echo ""
+ openssl req -new -newkey rsa:2048 -nodes -keyout aia/ca-issuers-key.pem -subj "/CN=wolfssl-aia-test" -out aia/ca-issuers-cert.csr
+ check_result $? "Step AIA-1"
+
+ openssl x509 -req -in aia/ca-issuers-cert.csr -days 365 -extfile wolfssl.cnf -extensions aia_ca_issuers -signkey aia/ca-issuers-key.pem -out aia/ca-issuers-cert.pem
+ check_result $? "Step AIA-2"
+ rm aia/ca-issuers-cert.csr
+
+ openssl x509 -in aia/ca-issuers-cert.pem -text > tmp.pem
+ check_result $? "Step AIA-3"
+ mv tmp.pem aia/ca-issuers-cert.pem
+ rm aia/ca-issuers-key.pem
+ echo "End of section"
+ echo "---------------------------------------------------------------------"
+
+ echo "Updating aia/multi-aia-cert.pem"
+ echo ""
+ openssl req -new -newkey rsa:2048 -nodes -keyout aia/multi-aia-key.pem -subj "/CN=wolfssl-aia-multi-test" -out aia/multi-aia-cert.csr
+ check_result $? "Step AIA-4"
+
+ openssl x509 -req -in aia/multi-aia-cert.csr -days 365 -extfile wolfssl.cnf -extensions aia_multi -signkey aia/multi-aia-key.pem -out aia/multi-aia-cert.pem
+ check_result $? "Step AIA-5"
+ rm aia/multi-aia-cert.csr
+
+ openssl x509 -in aia/multi-aia-cert.pem -text > tmp.pem
+ check_result $? "Step AIA-6"
+ mv tmp.pem aia/multi-aia-cert.pem
+ rm aia/multi-aia-key.pem
+ echo "End of section"
+ echo "---------------------------------------------------------------------"
+
+ echo "Updating aia/overflow-aia-cert.pem"
+ echo ""
+ openssl req -new -newkey rsa:2048 -nodes -keyout aia/overflow-aia-key.pem -subj "/CN=wolfssl-aia-overflow-test" -out aia/overflow-aia-cert.csr
+ check_result $? "Step AIA-7"
+
+ openssl x509 -req -in aia/overflow-aia-cert.csr -days 365 -extfile wolfssl.cnf -extensions aia_overflow -signkey aia/overflow-aia-key.pem -out aia/overflow-aia-cert.pem
+ check_result $? "Step AIA-8"
+ rm aia/overflow-aia-cert.csr
+
+ openssl x509 -in aia/overflow-aia-cert.pem -text > tmp.pem
+ check_result $? "Step AIA-9"
+ mv tmp.pem aia/overflow-aia-cert.pem
+ rm aia/overflow-aia-key.pem
+ echo "End of section"
+ echo "---------------------------------------------------------------------"
+ ############################################################
########## update the self-signed ca-cert-chain.der ########
############################################################
echo "Updating ca-cert-chain.der"
diff --git a/certs/renewcerts/wolfssl.cnf b/certs/renewcerts/wolfssl.cnf
index a4d5b27426..f02081d143 100644
--- a/certs/renewcerts/wolfssl.cnf
+++ b/certs/renewcerts/wolfssl.cnf
@@ -321,6 +321,45 @@ keyUsage=critical, digitalSignature, keyCertSign, cRLSign
[ crl_dist_points ]
crlDistributionPoints=URI:http://www.wolfssl.com/crl.pem
+# AIA test certs
+[ aia_ca_issuers ]
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always,issuer:always
+basicConstraints=critical,CA:true
+authorityInfoAccess=@aia_ca_issuers_info
+
+[ aia_ca_issuers_info ]
+caIssuers;URI.0=http://example.com/ca.pem
+
+[ aia_multi ]
+subjectKeyIdentifier=hash
+basicConstraints=CA:true
+keyUsage=digitalSignature, keyCertSign
+authorityInfoAccess=@aia_multi_info
+
+[ aia_multi_info ]
+OCSP;URI.0=http://127.0.0.1:22221
+OCSP;URI.1=http://127.0.0.1:22222
+caIssuers;URI.0=http://www.wolfssl.com/ca.pem
+caIssuers;URI.1=https://www.wolfssl.com/ca2.pem
+
+[ aia_overflow ]
+subjectKeyIdentifier=hash
+basicConstraints=CA:true
+keyUsage=digitalSignature, keyCertSign
+authorityInfoAccess=@aia_overflow_info
+
+[ aia_overflow_info ]
+OCSP;URI.0=http://127.0.0.1:22220
+OCSP;URI.1=http://127.0.0.1:22221
+OCSP;URI.2=http://127.0.0.1:22222
+OCSP;URI.3=http://127.0.0.1:22223
+OCSP;URI.4=http://127.0.0.1:22224
+OCSP;URI.5=http://127.0.0.1:22225
+OCSP;URI.6=http://127.0.0.1:22226
+OCSP;URI.7=http://127.0.0.1:22227
+OCSP;URI.8=http://127.0.0.1:22228
+
#tsa default
[ tsa ]
default_tsa = tsa_config1
@@ -404,4 +443,3 @@ DNS.1 = www.example.org
URI.1 = https://www.wolfssl.com/
otherName.2 = 2.16.840.1.101.3.6.6;FORMAT:HEX,OCT:D1:38:10:D8:28:AF:2C:10:84:35:15:A1:68:58:28:AF:02:10:86:A2:84:E7:39:C3:EB
-
diff --git a/cmake/Config.cmake.in b/cmake/Config.cmake.in
index 3b8098b6b3..6e115b0a9b 100644
--- a/cmake/Config.cmake.in
+++ b/cmake/Config.cmake.in
@@ -1,4 +1,9 @@
@PACKAGE_INIT@
+# Autoconf-generated configs won't define PACKAGE_PREFIX_DIR; fall back to the
+# configured install prefix for non-relocatable packages.
+if (NOT DEFINED PACKAGE_PREFIX_DIR)
+ set(PACKAGE_PREFIX_DIR "@WOLFSSL_PREFIX_ABS@")
+endif()
include(CMakeFindDependencyMacro)
if (@HAVE_PTHREAD@)
diff --git a/cmake/README.md b/cmake/README.md
index bb4efb4e31..66b8f9403f 100644
--- a/cmake/README.md
+++ b/cmake/README.md
@@ -3,6 +3,9 @@
This directory contains some supplementary functions for the [CMakeLists.txt](../CMakeLists.txt) in the root.
See also cmake notes in the [INSTALL](../INSTALL) documentation file.
+When building with autoconf/automake, CMake package files are installed by default
+under $(libdir)/cmake/wolfssl to support find_package(wolfssl). Disable with
+./configure --disable-cmake-install.
If new CMake build options are added `cmake/options.h.in` must also be updated.
@@ -56,4 +59,3 @@ See the Microsoft [CMakeSettings.json schema reference](https://learn.microsoft.
* Specific environment variables
* *UI-related tweaks
-
diff --git a/cmake/consumer/CMakeLists.txt b/cmake/consumer/CMakeLists.txt
new file mode 100644
index 0000000000..3ea3bde38f
--- /dev/null
+++ b/cmake/consumer/CMakeLists.txt
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 3.10)
+
+project(wolfssl_consumer C)
+
+find_package(wolfssl CONFIG REQUIRED)
+
+add_executable(wolfssl_consumer main.c)
+target_link_libraries(wolfssl_consumer PRIVATE wolfssl::wolfssl)
diff --git a/cmake/consumer/README.md b/cmake/consumer/README.md
new file mode 100644
index 0000000000..2353fe1af4
--- /dev/null
+++ b/cmake/consumer/README.md
@@ -0,0 +1,12 @@
+# CMake consumer test
+
+This is a minimal CMake project that consumes the installed wolfSSL
+package config.
+
+## Build
+
+```
+cmake -S . -B build -DCMAKE_PREFIX_PATH=/path/to/wolfssl/install
+cmake --build build
+./build/wolfssl_consumer
+```
diff --git a/cmake/consumer/main.c b/cmake/consumer/main.c
new file mode 100644
index 0000000000..c052969a55
--- /dev/null
+++ b/cmake/consumer/main.c
@@ -0,0 +1,11 @@
+#include
+#include
+
+int main(void)
+{
+ if (wolfSSL_Init() != WOLFSSL_SUCCESS) {
+ return 1;
+ }
+ wolfSSL_Cleanup();
+ return 0;
+}
diff --git a/cmake/include.am b/cmake/include.am
index b7cd6c7911..709ffa65f2 100644
--- a/cmake/include.am
+++ b/cmake/include.am
@@ -1,7 +1,19 @@
EXTRA_DIST += cmake/README.md
EXTRA_DIST += cmake/Config.cmake.in
+EXTRA_DIST += cmake/wolfssl-config-version.cmake.in
+EXTRA_DIST += cmake/wolfssl-targets.cmake.in
+EXTRA_DIST += cmake/consumer/CMakeLists.txt
+EXTRA_DIST += cmake/consumer/main.c
+EXTRA_DIST += cmake/consumer/README.md
EXTRA_DIST += cmake/config.in
EXTRA_DIST += cmake/functions.cmake
EXTRA_DIST += cmake/options.h.in
EXTRA_DIST += cmake/modules/FindARIA.cmake
EXTRA_DIST += cmake/modules/FindOQS.cmake
+
+if CMAKE_INSTALL
+cmakedir = $(libdir)/cmake/wolfssl
+cmake_DATA = cmake/wolfssl-config.cmake \
+ cmake/wolfssl-config-version.cmake \
+ cmake/wolfssl-targets.cmake
+endif
diff --git a/cmake/options.h.in b/cmake/options.h.in
index 796d446578..49c55694e8 100644
--- a/cmake/options.h.in
+++ b/cmake/options.h.in
@@ -270,6 +270,10 @@ extern "C" {
#cmakedefine WOLFSSL_AES_OFB
#undef WOLFSSL_AES_SIV
#cmakedefine WOLFSSL_AES_SIV
+#undef HAVE_AES_ECB
+#cmakedefine HAVE_AES_ECB
+#undef WOLFSSL_AES_CTS
+#cmakedefine WOLFSSL_AES_CTS
#undef WOLFSSL_ALT_CERT_CHAINS
#cmakedefine WOLFSSL_ALT_CERT_CHAINS
#undef WOLFSSL_APPLE_NATIVE_CERT_VALIDATION
@@ -302,6 +306,8 @@ extern "C" {
#cmakedefine WOLFSSL_DTLS_CID
#undef WOLFSSL_DTLS13
#cmakedefine WOLFSSL_DTLS13
+#undef WOLFSSL_DTLS_CH_FRAG
+#cmakedefine WOLFSSL_DTLS_CH_FRAG
#undef WOLFSSL_EITHER_SIDE
#cmakedefine WOLFSSL_EITHER_SIDE
#undef WOLFSSL_ENCRYPTED_KEYS
@@ -402,6 +408,8 @@ extern "C" {
#cmakedefine WOLFSSL_WC_XMSS
#undef HAVE_SECRET_CALLBACK
#cmakedefine HAVE_SECRET_CALLBACK
+#undef WC_RSA_DIRECT
+#cmakedefine WC_RSA_DIRECT
#ifdef __cplusplus
}
diff --git a/cmake/wolfssl-config-version.cmake.in b/cmake/wolfssl-config-version.cmake.in
new file mode 100644
index 0000000000..bc136fad8f
--- /dev/null
+++ b/cmake/wolfssl-config-version.cmake.in
@@ -0,0 +1,17 @@
+# Generated by autoconf; do not edit.
+
+set(PACKAGE_VERSION "@PACKAGE_VERSION@")
+
+# Keep behavior aligned with the native CMake build's AnyNewerVersion semantics:
+# compatible when the installed version is >= the requested version.
+set(PACKAGE_VERSION_COMPATIBLE FALSE)
+set(PACKAGE_VERSION_EXACT FALSE)
+
+if (PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
+ # not compatible
+else ()
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
+ if (PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
+ set(PACKAGE_VERSION_EXACT TRUE)
+ endif ()
+endif ()
diff --git a/cmake/wolfssl-targets.cmake.in b/cmake/wolfssl-targets.cmake.in
new file mode 100644
index 0000000000..afbe1ab7f7
--- /dev/null
+++ b/cmake/wolfssl-targets.cmake.in
@@ -0,0 +1,27 @@
+# Generated by autoconf; do not edit.
+
+if (NOT TARGET wolfssl::wolfssl)
+ add_library(wolfssl::wolfssl UNKNOWN IMPORTED)
+
+ set(_wolfssl_libdir "@WOLFSSL_LIBDIR_ABS@")
+ set(_wolfssl_includedir "@WOLFSSL_INCLUDEDIR_ABS@")
+
+ find_library(WOLFSSL_LIBRARY NAMES wolfssl PATHS "${_wolfssl_libdir}" NO_DEFAULT_PATH)
+ if (NOT WOLFSSL_LIBRARY)
+ find_library(WOLFSSL_LIBRARY NAMES wolfssl)
+ endif()
+ if (NOT WOLFSSL_LIBRARY)
+ message(FATAL_ERROR "wolfssl library not found. Looked in: ${_wolfssl_libdir}")
+ endif()
+
+ set_target_properties(wolfssl::wolfssl PROPERTIES
+ IMPORTED_LOCATION "${WOLFSSL_LIBRARY}"
+ INTERFACE_INCLUDE_DIRECTORIES "${_wolfssl_includedir}"
+ )
+
+ if (@WOLFSSL_HAVE_PTHREAD@)
+ set_property(TARGET wolfssl::wolfssl APPEND PROPERTY
+ INTERFACE_LINK_LIBRARIES Threads::Threads
+ )
+ endif()
+endif()
diff --git a/configure.ac b/configure.ac
index e248005e0b..ed7a512a47 100644
--- a/configure.ac
+++ b/configure.ac
@@ -33,6 +33,13 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
AC_ARG_PROGRAM
+# Optional CMake package install (enabled by default)
+AC_ARG_ENABLE([cmake-install],
+ [AS_HELP_STRING([--disable-cmake-install],[Disable installation of CMake package files])],
+ [ ENABLED_CMAKE_INSTALL=$enableval ],
+ [ ENABLED_CMAKE_INSTALL=yes ])
+AM_CONDITIONAL([CMAKE_INSTALL],[test "x$ENABLED_CMAKE_INSTALL" = "xyes"])
+
AC_CONFIG_HEADERS([config.h:config.in])
LT_PREREQ([2.4.2])
@@ -123,9 +130,18 @@ then
AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_EXPERIMENTAL_SETTINGS"
fi
+# Kernel module benchmark
+ENABLED_KERNEL_BENCHMARKS=""
+AC_ARG_ENABLE([kernel-benchmarks],
+ [AS_HELP_STRING([--enable-kernel-benchmarks],[Enable crypto benchmarking autorun at module load time for kernel module (default: disabled)])],
+ [ENABLED_KERNEL_BENCHMARKS=$enableval])
+if test "$ENABLED_KERNEL_BENCHMARKS" = "yes"
+then
+ AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KERNEL_BENCHMARKS"
+fi
+AC_SUBST([ENABLED_KERNEL_BENCHMARKS])
# Linux Kernel Module options (more options later)
-
AC_ARG_ENABLE([linuxkm],
[AS_HELP_STRING([--enable-linuxkm],[Enable Linux Kernel Module (default: disabled)])],
[ENABLED_LINUXKM=$enableval],
@@ -145,6 +161,12 @@ AC_ARG_ENABLE([freebsdkm],
[ENABLED_BSDKM=no]
)
+AC_ARG_ENABLE([freebsdkm-crypto-register],
+ [AS_HELP_STRING([--enable-freebsdkm-crypto-register],[Register wolfCrypt implementations with the FreeBSD kernel opencrypto framework. (default: disabled)])],
+ [ENABLED_BSDKM_REGISTER=$enableval],
+ [ENABLED_BSDKM_REGISTER=no]
+ )
+
AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h netdb.h netinet/in.h stddef.h time.h sys/ioctl.h sys/socket.h sys/time.h errno.h sys/un.h ctype.h sys/random.h])
AC_CHECK_LIB([network],[socket])
AC_C_BIGENDIAN
@@ -727,10 +749,8 @@ AC_SUBST([ENABLED_LINUXKM_PIE])
AC_ARG_ENABLE([linuxkm-benchmarks],
[AS_HELP_STRING([--enable-linuxkm-benchmarks],[Enable crypto benchmarking autorun at module load time for Linux kernel module (default: disabled)])],
- [ENABLED_KERNEL_BENCHMARKS=$enableval],
- [ENABLED_KERNEL_BENCHMARKS=no]
- )
-if test "$ENABLED_KERNEL_BENCHMARKS" = "yes"
+ [ENABLED_KERNEL_BENCHMARKS=$enableval])
+if test "$ENABLED_LINUXKM" = "yes" && test "$ENABLED_KERNEL_BENCHMARKS" = "yes"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_LINUXKM_BENCHMARKS"
fi
@@ -819,17 +839,15 @@ AC_ARG_WITH([bsd-export-syms],
if test "x$ENABLED_BSDKM" = "xyes"
then
- # wolfcrypt only, no-asm supported for now.
+ # note: bsdkm is wolfcrypt only for now.
HAVE_KERNEL_MODE=yes
KERNEL_MODE_DEFAULTS=yes
ENABLED_NO_LIBRARY=yes
ENABLED_BENCHMARK=no
- ENABLED_ASM=no
output_objdir="$(realpath "$output_objdir")/bsdkm"
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_BSDKM -DWC_SIPHASH_NO_ASM"
- AM_CFLAGS="$AM_CFLAGS -DTFM_NO_ASM -DWOLFSSL_NO_ASM"
AM_CFLAGS="$AM_CFLAGS -DNO_DEV_RANDOM -DNO_WRITEV -DNO_STDIO_FILESYSTEM"
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_SOCK -DWOLFSSL_USER_IO"
AM_CFLAGS="$AM_CFLAGS -DXMALLOC_OVERRIDE -DWOLFCRYPT_ONLY"
@@ -846,7 +864,16 @@ then
fi
AC_SUBST([KERNEL_ROOT])
AC_SUBST([BSDKM_EXPORT_SYMS])
+fi
+if test "x$ENABLED_BSDKM_REGISTER" = "xyes"
+then
+ if test "$ENABLED_AESGCM" != "no" && test "$ENABLED_AESGCM_STREAM" = "no" && test "$enable_aesgcm_stream" != "no" && (test "$ENABLED_FIPS" = "no" || test $HAVE_FIPS_VERSION -ge 6); then
+ ENABLED_AESGCM_STREAM=yes
+ fi
+
+ AM_CFLAGS="$AM_CFLAGS -DBSDKM_CRYPTO_REGISTER"
+ AC_SUBST([ENABLED_BSDKM_REGISTER])
fi
# end FreeBSD configure
@@ -1383,13 +1410,13 @@ then
esac
fi
-# 32 bit armasm and RISC-V asm don't yet support WOLFSSL_AESGCM_STREAM. Disable
+# RISC-V asm doesn't yet support WOLFSSL_AESGCM_STREAM. Disable
# implicit activation, and error on explicit activation.
-if test "$enable_riscv_asm" = "yes" || (test "$enable_armasm" = "yes" && test "$host_cpu" != "aarch64" && test "$host_cpu" != "aarch64_be")
+if test "$enable_riscv_asm" = "yes"
then
if test "$enable_aesgcm_stream" = "yes"
then
- AC_MSG_ERROR([32 bit armasm and RISC-V asm don't yet support WOLFSSL_AESGCM_STREAM.])
+ AC_MSG_ERROR([RISC-V asm doesn't yet support WOLFSSL_AESGCM_STREAM.])
fi
enable_aesgcm_stream=no
fi
@@ -2061,9 +2088,11 @@ AC_ARG_ENABLE([singlethreaded],
[ ENABLED_SINGLETHREADED=$enableval ],
[ ENABLED_SINGLETHREADED=no ])
+WOLFSSL_HAVE_PTHREAD=0
AS_IF([ test "x$ENABLED_SINGLETHREADED" = "xno" ],[
AX_PTHREAD([
AC_DEFINE([HAVE_PTHREAD], [1], [Define if you have POSIX threads libraries and header files.])
+ WOLFSSL_HAVE_PTHREAD=1
# If AX_PTHREAD is adding -Qunused-arguments, need to prepend with -Xcompiler libtool will use it. Newer
# versions of clang don't need the -Q flag when using pthreads.
AS_CASE([$PTHREAD_CFLAGS],[-Qunused-arguments*],[PTHREAD_CFLAGS="-Xcompiler $PTHREAD_CFLAGS"])
@@ -3969,6 +3998,8 @@ then
ENABLED_X86_ASM=yes
fi
fi
+AC_SUBST([ENABLED_AESNI])
+AC_SUBST([ENABLED_AESNI_WITH_AVX])
AC_ARG_ENABLE([aligndata],
[AS_HELP_STRING([--enable-aligndata],[align data for ciphers (default: enabled)])],
@@ -10689,11 +10720,9 @@ then
if test "$ENABLED_AESGCM" = "no"
then
AC_MSG_ERROR([AES-GCM streaming is enabled but AES-GCM is disabled.])
- elif test "$ENABLED_RISCV_ASM" = "yes" || \
- (test "$ENABLED_ARMASM" = "yes" && \
- test "$host_cpu" != "aarch64" && test "$host_cpu" != "aarch64_be")
+ elif test "$ENABLED_RISCV_ASM" = "yes"
then
- AC_MSG_ERROR([32 bit armasm and RISC-V asm don't yet support WOLFSSL_AESGCM_STREAM.])
+ AC_MSG_ERROR([RISC-V asm doesn't yet support WOLFSSL_AESGCM_STREAM.])
else
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AESGCM_STREAM"
AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_AESGCM_STREAM"
@@ -11263,6 +11292,26 @@ AC_SUBST([LIB_ADD])
AC_SUBST([LIB_STATIC_ADD])
AC_SUBST([LIBM])
AC_SUBST([PC_LIBS_PRIVATE])
+AC_SUBST([WOLFSSL_HAVE_PTHREAD])
+HAVE_PTHREAD=$WOLFSSL_HAVE_PTHREAD
+AC_SUBST([HAVE_PTHREAD])
+PACKAGE_INIT=''
+AC_SUBST([PACKAGE_INIT])
+WOLFSSL_PREFIX_ABS=$prefix
+if test "x$WOLFSSL_PREFIX_ABS" = "xNONE"; then
+ WOLFSSL_PREFIX_ABS=$ac_default_prefix
+fi
+WOLFSSL_EXEC_PREFIX_ABS=$exec_prefix
+if test "x$WOLFSSL_EXEC_PREFIX_ABS" = "xNONE"; then
+ WOLFSSL_EXEC_PREFIX_ABS=$WOLFSSL_PREFIX_ABS
+fi
+prefix=$WOLFSSL_PREFIX_ABS
+exec_prefix=$WOLFSSL_EXEC_PREFIX_ABS
+eval WOLFSSL_LIBDIR_ABS=\"$libdir\"
+eval WOLFSSL_INCLUDEDIR_ABS=\"$includedir\"
+AC_SUBST([WOLFSSL_PREFIX_ABS])
+AC_SUBST([WOLFSSL_LIBDIR_ABS])
+AC_SUBST([WOLFSSL_INCLUDEDIR_ABS])
# FINAL
AC_CONFIG_FILES([stamp-h], [echo timestamp > stamp-h])
@@ -11275,6 +11324,12 @@ AC_CONFIG_FILES([Makefile
rpm/spec
wolfcrypt/test/test_paths.h
])
+AS_IF([ test "x$ENABLED_CMAKE_INSTALL" = "xyes" ],[
+AC_CONFIG_FILES([cmake/wolfssl-config.cmake:cmake/Config.cmake.in
+ cmake/wolfssl-config-version.cmake:cmake/wolfssl-config-version.cmake.in
+ cmake/wolfssl-targets.cmake:cmake/wolfssl-targets.cmake.in
+ ])
+])
AC_CONFIG_FILES([scripts/unit.test],[chmod +x scripts/unit.test])
AC_CONFIG_FILES([debian/rules],[chmod +x debian/rules])
diff --git a/debian/libwolfssl-dev.install b/debian/libwolfssl-dev.install
index 21de1f2062..4ee57d0d1f 100644
--- a/debian/libwolfssl-dev.install
+++ b/debian/libwolfssl-dev.install
@@ -2,5 +2,6 @@ usr/include/
usr/lib/*/libwolfssl.so
usr/lib/*/libwolfssl.a
usr/lib/*/pkgconfig/wolfssl.pc
+usr/lib/*/cmake/wolfssl/*
usr/bin/wolfssl-config
usr/share/doc/wolfssl/
diff --git a/doc/dox_comments/header_files/cryptocb.h b/doc/dox_comments/header_files/cryptocb.h
index 145d8c9ff5..b6a21922f3 100644
--- a/doc/dox_comments/header_files/cryptocb.h
+++ b/doc/dox_comments/header_files/cryptocb.h
@@ -180,3 +180,63 @@ void wc_CryptoCb_SetDeviceFindCb(CryptoDevCallbackFind cb);
\sa wc_CryptoCb_RegisterDevice
*/
void wc_CryptoCb_InfoString(wc_CryptoInfo* info);
+
+/*!
+ \ingroup CryptoCb
+
+ \brief Import an AES key into a CryptoCB device for hardware offload.
+
+ This function allows AES keys to be handled by an external device
+ (e.g. Secure Element or HSM). When supported, the device callback stores
+ the key internally and sets an opaque handle in aes->devCtx.
+
+ When CryptoCB AES SetKey support is enabled
+ (WOLF_CRYPTO_CB_AES_SETKEY), wolfCrypt routes AES-GCM operations
+ through the CryptoCB interface.
+
+ **TLS Builds (Default):**
+ - Key bytes ARE stored in wolfCrypt memory (devKey) for fallback
+ - GCM tables ARE generated for software fallback
+ - Provides hardware acceleration with automatic fallback
+
+ **Crypto-Only Builds (--disable-tls):**
+ - Key bytes NOT stored in wolfCrypt memory (true key isolation)
+ - GCM tables skipped (true hardware offload)
+ - Callback must handle all GCM operations (SetKey, Encrypt, Decrypt, Free)
+
+ If the callback returns success (0), full AES-GCM offload is assumed.
+ The callback must handle SetKey, Encrypt, Decrypt, and Free operations.
+
+ \param aes AES context
+ \param key Pointer to raw AES key material
+ \param keySz Size of key in bytes
+
+ \return 0 on success
+ \return CRYPTOCB_UNAVAILABLE if device does not support this operation
+ \return BAD_FUNC_ARG on invalid parameters
+
+ _Example_
+ \code
+ #include
+ #include
+
+ Aes aes;
+ byte key[32] = { /* 256-bit key */ };
+ int devId = 1;
+
+ /* Register your CryptoCB callback first */
+ wc_CryptoCb_RegisterDevice(devId, myCryptoCallback, NULL);
+
+ wc_AesInit(&aes, NULL, devId);
+ /* wc_AesGcmSetKey internally calls wc_CryptoCb_AesSetKey */
+ if (wc_CryptoCb_AesSetKey(&aes, key, sizeof(key)) == 0) {
+ /* Key successfully imported to device via callback */
+ /* aes.devCtx now contains device handle */
+ /* Full GCM offload is assumed - callback must handle all operations */
+ }
+ \endcode
+
+ \sa wc_CryptoCb_RegisterDevice
+ \sa wc_AesInit
+*/
+int wc_CryptoCb_AesSetKey(Aes* aes, const byte* key, word32 keySz);
diff --git a/doc/dox_comments/header_files/doxygen_pages.h b/doc/dox_comments/header_files/doxygen_pages.h
index 2765449ac8..58ae75852e 100644
--- a/doc/dox_comments/header_files/doxygen_pages.h
+++ b/doc/dox_comments/header_files/doxygen_pages.h
@@ -74,4 +74,27 @@
- \ref SAKKE_RSK
- \ref SAKKE_Operations
*/
+/*!
+ \page AES_CryptoCB_KeyImport AES CryptoCB Key Import
+
+ When enabled via WOLF_CRYPTO_CB_AES_SETKEY, wolfSSL invokes a CryptoCB
+ callback during AES key setup. The callback behavior determines the mode:
+
+ **If callback returns 0 (success):**
+ - Key is imported to Secure Element/HSM
+ - Key is NOT copied to wolfSSL RAM (true key isolation)
+ - GCM tables are NOT generated (full hardware offload)
+ - All subsequent AES operations route through CryptoCB
+
+ **If callback returns CRYPTOCB_UNAVAILABLE:**
+ - SE doesn't support key import
+ - Normal software AES path is used
+ - Key is copied to devKey for CryptoCB encrypt/decrypt acceleration
+
+ This mode is compatible with Secure Elements and hardware-backed
+ key storage and is intended for protecting TLS traffic keys.
+
+ \sa wc_CryptoCb_AesSetKey
+ \sa \ref Crypto Callbacks
+*/
diff --git a/doc/dox_comments/header_files/memory.h b/doc/dox_comments/header_files/memory.h
index fe18397db1..b5430758a3 100644
--- a/doc/dox_comments/header_files/memory.h
+++ b/doc/dox_comments/header_files/memory.h
@@ -376,7 +376,8 @@ int wolfSSL_is_static_memory(WOLFSSL* ssl, WOLFSSL_MEM_CONN_STATS* mem_stats);
buffers to themselves for their lifetime.
WOLFMEM_TRACK_STATS - each SSL keeps track of memory stats while running
- \return none This function does not return a value.
+ \return Returns 0 on success.
+ \return Returns a non-zero integer on failure.
\param pHint WOLFSSL_HEAP_HINT structure to use
\param buf memory to use for all operations.
@@ -396,7 +397,7 @@ int wolfSSL_is_static_memory(WOLFSSL* ssl, WOLFSSL_MEM_CONN_STATS* mem_stats);
// load in memory for use
ret = wc_LoadStaticMemory(&hint, memory, memorySz, flag, 0);
- if (ret != SSL_SUCCESS) {
+ if (ret) {
// handle error case
}
...
@@ -419,7 +420,8 @@ int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, unsigned char* buf,
into functions. This extended version allows for custom bucket sizes and distributions
instead of using the default predefined sizes.
- \return none This function does not return a value.
+ \return Returns 0 on success.
+ \return Returns a non-zero integer on failure.
\param pHint WOLFSSL_HEAP_HINT handle to initialize
\param listSz number of entries in the size and distribution lists
@@ -447,7 +449,7 @@ int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, unsigned char* buf,
ret = wc_LoadStaticMemory_ex(&hint, listSz, sizeList, distList,
memory, memorySz, flag, 0);
- if (ret != SSL_SUCCESS) {
+ if (ret) {
// handle error case
}
...
diff --git a/linuxkm/linuxkm_wc_port.h b/linuxkm/linuxkm_wc_port.h
index 00e7e45d3e..ebe0d64bc5 100644
--- a/linuxkm/linuxkm_wc_port.h
+++ b/linuxkm/linuxkm_wc_port.h
@@ -545,9 +545,10 @@
* to assure that calls to get_random_bytes() in random.c are gated out
* (they would recurse, potentially infinitely).
*/
- #if (defined(LINUXKM_LKCAPI_REGISTER_ALL) && \
- !defined(LINUXKM_LKCAPI_DONT_REGISTER_HASH_DRBG) && \
- !defined(LINUXKM_LKCAPI_DONT_REGISTER_HASH_DRBG_DEFAULT)) && \
+ #if defined(LINUXKM_LKCAPI_REGISTER_ALL) && \
+ !defined(LINUXKM_LKCAPI_DONT_REGISTER_HASH_DRBG) && \
+ !defined(LINUXKM_LKCAPI_DONT_REGISTER_HASH_DRBG_DEFAULT) && \
+ !defined(NO_LINUXKM_DRBG_GET_RANDOM_BYTES) && \
!defined(LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT)
#define LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
#endif
diff --git a/linuxkm/lkcapi_sha_glue.c b/linuxkm/lkcapi_sha_glue.c
index 1bdc56a8ac..bf2a16c929 100644
--- a/linuxkm/lkcapi_sha_glue.c
+++ b/linuxkm/lkcapi_sha_glue.c
@@ -30,6 +30,22 @@
#error SHA* WC_LINUXKM_C_FALLBACK_IN_SHIMS is not currently supported.
#endif
+#ifdef NO_LINUXKM_DRBG_GET_RANDOM_BYTES
+ #undef LINUXKM_DRBG_GET_RANDOM_BYTES
+/* setup for LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT is in linuxkm_wc_port.h */
+#elif defined(LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT) && \
+ (defined(WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS) || \
+ defined(WOLFSSL_LINUXKM_USE_GET_RANDOM_KPROBES))
+ #ifndef LINUXKM_DRBG_GET_RANDOM_BYTES
+ #define LINUXKM_DRBG_GET_RANDOM_BYTES
+ #endif
+#else
+ #ifdef LINUXKM_DRBG_GET_RANDOM_BYTES
+ #error LINUXKM_DRBG_GET_RANDOM_BYTES configured with no callback model configured.
+ #undef LINUXKM_DRBG_GET_RANDOM_BYTES
+ #endif
+#endif
+
#include
#include
@@ -94,7 +110,14 @@
* exhaustion. A caller that really needs PR can pass in seed data in its call
* to our rng_alg.generate() implementation.
*/
-#define WOLFKM_STDRNG_DRIVER ("sha2-256-drbg-nopr" WOLFKM_SHA_DRIVER_SUFFIX)
+#ifdef LINUXKM_DRBG_GET_RANDOM_BYTES
+ #define WOLFKM_STDRNG_DRIVER ("sha2-256-drbg-nopr" \
+ WOLFKM_DRIVER_SUFFIX_BASE \
+ "-with-global-replace")
+#else
+ #define WOLFKM_STDRNG_DRIVER ("sha2-256-drbg-nopr" \
+ WOLFKM_DRIVER_SUFFIX_BASE)
+#endif
#ifdef LINUXKM_LKCAPI_REGISTER_SHA_ALL
#define LINUXKM_LKCAPI_REGISTER_SHA1
@@ -388,7 +411,7 @@
#else
#if defined(LINUXKM_LKCAPI_REGISTER_ALL_KCONFIG) && defined(CONFIG_CRYPTO_DRBG) && \
!defined(LINUXKM_LKCAPI_DONT_REGISTER_HASH_DRBG)
- #error Config conflict: target kernel has CONFIG_CRYPTO_SHA3, but module is missing WOLFSSL_SHA3
+ #error Config conflict: target kernel has CONFIG_CRYPTO_DRBG, but module is missing HAVE_HASHDRBG
#endif
#undef LINUXKM_LKCAPI_REGISTER_HASH_DRBG
#endif
@@ -1257,20 +1280,6 @@ static struct rng_alg wc_linuxkm_drbg = {
};
static int wc_linuxkm_drbg_loaded = 0;
-#ifdef NO_LINUXKM_DRBG_GET_RANDOM_BYTES
- #undef LINUXKM_DRBG_GET_RANDOM_BYTES
-#elif defined(LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT) && \
- (defined(WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS) || defined(WOLFSSL_LINUXKM_USE_GET_RANDOM_KPROBES))
- #ifndef LINUXKM_DRBG_GET_RANDOM_BYTES
- #define LINUXKM_DRBG_GET_RANDOM_BYTES
- #endif
-#else
- #ifdef LINUXKM_DRBG_GET_RANDOM_BYTES
- #error LINUXKM_DRBG_GET_RANDOM_BYTES configured with no callback model configured.
- #undef LINUXKM_DRBG_GET_RANDOM_BYTES
- #endif
-#endif
-
#ifdef LINUXKM_DRBG_GET_RANDOM_BYTES
#ifndef WOLFSSL_SMALL_STACK_CACHE
diff --git a/src/include.am b/src/include.am
index fe97320637..943522b4e8 100644
--- a/src/include.am
+++ b/src/include.am
@@ -17,10 +17,16 @@ MAINTAINERCLEANFILES+= $(FIPS_FILES)
EXTRA_DIST += src/bio.c
EXTRA_DIST += src/conf.c
EXTRA_DIST += src/pk.c
+EXTRA_DIST += src/pk_rsa.c
+EXTRA_DIST += src/pk_ec.c
+EXTRA_DIST += src/ssl_api_cert.c
+EXTRA_DIST += src/ssl_api_crl_ocsp.c
+EXTRA_DIST += src/ssl_api_pk.c
EXTRA_DIST += src/ssl_asn1.c
EXTRA_DIST += src/ssl_bn.c
EXTRA_DIST += src/ssl_certman.c
EXTRA_DIST += src/ssl_crypto.c
+EXTRA_DIST += src/ssl_ech.c
EXTRA_DIST += src/ssl_load.c
EXTRA_DIST += src/ssl_misc.c
EXTRA_DIST += src/ssl_p7p12.c
diff --git a/src/internal.c b/src/internal.c
index 74f59faff9..818f6e0d5d 100644
--- a/src/internal.c
+++ b/src/internal.c
@@ -13848,6 +13848,34 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
}
x509->authInfoSet = dCert->extAuthInfoSet;
x509->authInfoCrit = dCert->extAuthInfoCrit;
+ x509->authInfoListSz = dCert->extAuthInfoListSz;
+ x509->authInfoListOverflow = dCert->extAuthInfoListOverflow;
+ if (x509->authInfoListSz > WOLFSSL_MAX_AIA_ENTRIES) {
+ x509->authInfoListSz = WOLFSSL_MAX_AIA_ENTRIES;
+ x509->authInfoListOverflow = 1;
+ }
+ if (x509->authInfoListSz > 0) {
+ int i;
+ for (i = 0; i < x509->authInfoListSz; i++) {
+ x509->authInfoList[i].method = dCert->extAuthInfoList[i].method;
+ x509->authInfoList[i].uriSz = dCert->extAuthInfoList[i].uriSz;
+ x509->authInfoList[i].uri = NULL;
+
+ if (dCert->extAuthInfoList[i].uri != NULL &&
+ dCert->source != NULL && dCert->maxIdx > 0 &&
+ x509->derCert != NULL && x509->derCert->buffer != NULL) {
+ word32 offset = (word32)
+ (dCert->extAuthInfoList[i].uri - dCert->source);
+ if (offset < (word32)dCert->maxIdx) {
+ x509->authInfoList[i].uri =
+ x509->derCert->buffer + offset;
+ }
+ else {
+ x509->authInfoList[i].uriSz = 0;
+ }
+ }
+ }
+ }
if (dCert->extAuthInfo != NULL && dCert->extAuthInfoSz > 0) {
x509->authInfo = (byte*)XMALLOC(dCert->extAuthInfoSz, x509->heap,
DYNAMIC_TYPE_X509_EXT);
diff --git a/src/pk.c b/src/pk.c
index 8f07a679c1..34f26dfcdb 100644
--- a/src/pk.c
+++ b/src/pk.c
@@ -26,21 +26,6 @@
#include
#endif
-#ifdef HAVE_ECC
- #include
- #ifdef HAVE_SELFTEST
- /* point compression types. */
- #define ECC_POINT_COMP_EVEN 0x02
- #define ECC_POINT_COMP_ODD 0x03
- #define ECC_POINT_UNCOMP 0x04
- #endif
-#endif
-#ifndef WOLFSSL_HAVE_ECC_KEY_GET_PRIV
- /* FIPS build has replaced ecc.h. */
- #define wc_ecc_key_get_priv(key) (&((key)->k))
- #define WOLFSSL_HAVE_ECC_KEY_GET_PRIV
-#endif
-
#if !defined(WOLFSSL_PK_INCLUDED)
#ifndef WOLFSSL_IGNORE_FILE_WARN
#warning pk.c does not need to be compiled separately from ssl.c
@@ -941,3909 +926,9 @@ static int wolfssl_der_length(const unsigned char* seq, int len)
#endif
-/*******************************************************************************
- * START OF RSA API
- ******************************************************************************/
-#ifndef NO_RSA
-
-/*
- * RSA METHOD
- * Could be used to hold function pointers to implementations of RSA operations.
- */
-
-#if defined(OPENSSL_EXTRA)
-/* Return a blank RSA method and set the name and flags.
- *
- * Only one implementation of RSA operations.
- * name is duplicated.
- *
- * @param [in] name Name to use in method.
- * @param [in] flags Flags to set into method.
- * @return Newly allocated RSA method on success.
- * @return NULL on failure.
- */
-WOLFSSL_RSA_METHOD *wolfSSL_RSA_meth_new(const char *name, int flags)
-{
- WOLFSSL_RSA_METHOD* meth = NULL;
- int name_len = 0;
- int err;
-
- /* Validate name is not NULL. */
- if (name == NULL)
- return NULL;
- /* Allocate an RSA METHOD to return. */
- meth = (WOLFSSL_RSA_METHOD*)XMALLOC(sizeof(WOLFSSL_RSA_METHOD), NULL,
- DYNAMIC_TYPE_OPENSSL);
- if (meth == NULL)
- return NULL;
-
- XMEMSET(meth, 0, sizeof(*meth));
- meth->flags = flags;
- meth->dynamic = 1;
-
- name_len = (int)XSTRLEN(name);
- meth->name = (char*)XMALLOC((size_t)(name_len + 1), NULL,
- DYNAMIC_TYPE_OPENSSL);
- err = (meth->name == NULL);
-
- if (!err) {
- XMEMCPY(meth->name, name, (size_t)(name_len + 1));
- }
-
- if (err) {
- /* meth->name won't be allocated on error. */
- XFREE(meth, NULL, DYNAMIC_TYPE_OPENSSL);
- meth = NULL;
- }
- return meth;
-}
-
-/* Default RSA method is one with wolfSSL name and no flags.
- *
- * @return Newly allocated wolfSSL RSA method on success.
- * @return NULL on failure.
- */
-const WOLFSSL_RSA_METHOD* wolfSSL_RSA_get_default_method(void)
-{
- static const WOLFSSL_RSA_METHOD wolfssl_rsa_meth = {
- 0, /* No flags. */
- (char*)"wolfSSL RSA",
- 0 /* Static definition. */
- };
- return &wolfssl_rsa_meth;
-}
-
-/* Dispose of RSA method and allocated data.
- *
- * @param [in] meth RSA method to free.
- */
-void wolfSSL_RSA_meth_free(WOLFSSL_RSA_METHOD *meth)
-{
- /* Free method if available and dynamically allocated. */
- if ((meth != NULL) && meth->dynamic) {
- /* Name was duplicated and must be freed. */
- XFREE(meth->name, NULL, DYNAMIC_TYPE_OPENSSL);
- /* Dispose of RSA method. */
- XFREE(meth, NULL, DYNAMIC_TYPE_OPENSSL);
- }
-}
-
-#ifndef NO_WOLFSSL_STUB
-/* Stub function for any RSA method setting function.
- *
- * Nothing is stored - not even flags or name.
- *
- * @param [in] meth RSA method.
- * @param [in] p A pointer.
- * @return 1 to indicate success.
- */
-int wolfSSL_RSA_meth_set(WOLFSSL_RSA_METHOD *meth, void* p)
-{
- WOLFSSL_STUB("RSA_METHOD is not implemented.");
-
- (void)meth;
- (void)p;
-
- return 1;
-}
-#endif /* !NO_WOLFSSL_STUB */
-#endif /* OPENSSL_EXTRA */
-
-/*
- * RSA constructor/deconstructor APIs
- */
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-/* Dispose of RSA key and allocated data.
- *
- * Cannot use rsa after this call.
- *
- * @param [in] rsa RSA key to free.
- */
-void wolfSSL_RSA_free(WOLFSSL_RSA* rsa)
-{
- int doFree = 1;
-
- WOLFSSL_ENTER("wolfSSL_RSA_free");
-
- /* Validate parameter. */
- if (rsa == NULL) {
- doFree = 0;
- }
- if (doFree) {
- int err;
-
- /* Decrement reference count. */
- wolfSSL_RefDec(&rsa->ref, &doFree, &err);
- #ifndef WOLFSSL_REFCNT_ERROR_RETURN
- (void)err;
- #endif
- }
- if (doFree) {
- void* heap = rsa->heap;
-
- /* Dispose of allocated reference counting data. */
- wolfSSL_RefFree(&rsa->ref);
-
- #ifdef HAVE_EX_DATA_CLEANUP_HOOKS
- wolfSSL_CRYPTO_cleanup_ex_data(&rsa->ex_data);
- #endif
-
- if (rsa->internal != NULL) {
- #if !defined(HAVE_FIPS) && defined(WC_RSA_BLINDING)
- /* Check if RNG is owned before freeing it. */
- if (rsa->ownRng) {
- WC_RNG* rng = ((RsaKey*)(rsa->internal))->rng;
- if ((rng != NULL) && (rng != wolfssl_get_global_rng())) {
- wc_FreeRng(rng);
- XFREE(rng, heap, DYNAMIC_TYPE_RNG);
- }
- /* RNG isn't freed by wolfCrypt RSA free. */
- }
- #endif
- /* Dispose of allocated data in wolfCrypt RSA key. */
- wc_FreeRsaKey((RsaKey*)rsa->internal);
- /* Dispose of memory for wolfCrypt RSA key. */
- XFREE(rsa->internal, heap, DYNAMIC_TYPE_RSA);
- }
-
- /* Dispose of external representation of RSA values. */
- wolfSSL_BN_clear_free(rsa->iqmp);
- wolfSSL_BN_clear_free(rsa->dmq1);
- wolfSSL_BN_clear_free(rsa->dmp1);
- wolfSSL_BN_clear_free(rsa->q);
- wolfSSL_BN_clear_free(rsa->p);
- wolfSSL_BN_clear_free(rsa->d);
- wolfSSL_BN_free(rsa->e);
- wolfSSL_BN_free(rsa->n);
-
- #if defined(OPENSSL_EXTRA)
- if (rsa->meth) {
- wolfSSL_RSA_meth_free((WOLFSSL_RSA_METHOD*)rsa->meth);
- }
- #endif
-
- /* Set back to NULLs for safety. */
- ForceZero(rsa, sizeof(*rsa));
-
- XFREE(rsa, heap, DYNAMIC_TYPE_RSA);
- (void)heap;
- }
-}
-
-/* Allocate and initialize a new RSA key.
- *
- * Not OpenSSL API.
- *
- * @param [in] heap Heap hint for dynamic memory allocation.
- * @param [in] devId Device identifier value.
- * @return RSA key on success.
- * @return NULL on failure.
- */
-WOLFSSL_RSA* wolfSSL_RSA_new_ex(void* heap, int devId)
-{
- WOLFSSL_RSA* rsa = NULL;
- RsaKey* key = NULL;
- int err = 0;
- int rsaKeyInited = 0;
-
- WOLFSSL_ENTER("wolfSSL_RSA_new");
-
- /* Allocate memory for new wolfCrypt RSA key. */
- key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA);
- if (key == NULL) {
- WOLFSSL_ERROR_MSG("wolfSSL_RSA_new malloc RsaKey failure");
- err = 1;
- }
- if (!err) {
- /* Allocate memory for new RSA key. */
- rsa = (WOLFSSL_RSA*)XMALLOC(sizeof(WOLFSSL_RSA), heap,
- DYNAMIC_TYPE_RSA);
- if (rsa == NULL) {
- WOLFSSL_ERROR_MSG("wolfSSL_RSA_new malloc WOLFSSL_RSA failure");
- err = 1;
- }
- }
- if (!err) {
- /* Clear all fields of RSA key. */
- XMEMSET(rsa, 0, sizeof(WOLFSSL_RSA));
- /* Cache heap to use for all allocations. */
- rsa->heap = heap;
- #ifdef OPENSSL_EXTRA
- /* Always have a method set. */
- rsa->meth = wolfSSL_RSA_get_default_method();
- #endif
-
- /* Initialize reference counting. */
- wolfSSL_RefInit(&rsa->ref, &err);
-#ifdef WOLFSSL_REFCNT_ERROR_RETURN
- }
- if (!err) {
-#endif
- /* Initialize wolfCrypt RSA key. */
- if (wc_InitRsaKey_ex(key, heap, devId) != 0) {
- WOLFSSL_ERROR_MSG("InitRsaKey WOLFSSL_RSA failure");
- err = 1;
- }
- else {
- rsaKeyInited = 1;
- }
- }
- #if !defined(HAVE_FIPS) && defined(WC_RSA_BLINDING)
- if (!err) {
- WC_RNG* rng;
-
- /* Create a local RNG. */
- rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), heap, DYNAMIC_TYPE_RNG);
- if ((rng != NULL) && (wc_InitRng_ex(rng, heap, devId) != 0)) {
- WOLFSSL_MSG("InitRng failure, attempting to use global RNG");
- XFREE(rng, heap, DYNAMIC_TYPE_RNG);
- rng = NULL;
- }
-
- rsa->ownRng = 1;
- if (rng == NULL) {
- /* Get the wolfSSL global RNG - not thread safe. */
- rng = wolfssl_get_global_rng();
- rsa->ownRng = 0;
- }
- if (rng == NULL) {
- /* Couldn't create global either. */
- WOLFSSL_ERROR_MSG("wolfSSL_RSA_new no WC_RNG for blinding");
- err = 1;
- }
- else {
- /* Set the local or global RNG into the wolfCrypt RSA key. */
- (void)wc_RsaSetRNG(key, rng);
- /* Won't fail as key and rng are not NULL. */
- }
- }
- #endif /* !HAVE_FIPS && WC_RSA_BLINDING */
- if (!err) {
- /* Set wolfCrypt RSA key into RSA key. */
- rsa->internal = key;
- /* Data from external RSA key has not been set into internal one. */
- rsa->inSet = 0;
- }
-
- if (err) {
- /* Dispose of any allocated data on error. */
- /* No failure after RNG allocation - no need to free RNG. */
- if (rsaKeyInited) {
- wc_FreeRsaKey(key);
- }
- XFREE(key, heap, DYNAMIC_TYPE_RSA);
- XFREE(rsa, heap, DYNAMIC_TYPE_RSA);
- /* Return NULL. */
- rsa = NULL;
- }
- return rsa;
-}
-
-/* Allocate and initialize a new RSA key.
- *
- * @return RSA key on success.
- * @return NULL on failure.
- */
-WOLFSSL_RSA* wolfSSL_RSA_new(void)
-{
- /* Call wolfSSL API to do work. */
- return wolfSSL_RSA_new_ex(NULL, INVALID_DEVID);
-}
-
-/* Increments ref count of RSA key.
- *
- * @param [in, out] rsa RSA key.
- * @return 1 on success
- * @return 0 on error
- */
-int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa)
-{
- int err = 0;
- if (rsa != NULL) {
- wolfSSL_RefInc(&rsa->ref, &err);
- }
- return !err;
-}
-
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-
-#ifdef OPENSSL_EXTRA
-
-#if defined(WOLFSSL_KEY_GEN)
-
-/* Allocate a new RSA key and make it a copy.
- *
- * Encodes to and from DER to copy.
- *
- * @param [in] rsa RSA key to duplicate.
- * @return RSA key on success.
- * @return NULL on error.
- */
-WOLFSSL_RSA* wolfSSL_RSAPublicKey_dup(WOLFSSL_RSA *rsa)
-{
- WOLFSSL_RSA* ret = NULL;
- int derSz = 0;
- byte* derBuf = NULL;
- int err;
-
- WOLFSSL_ENTER("wolfSSL_RSAPublicKey_dup");
-
- err = (rsa == NULL);
- if (!err) {
- /* Create a new RSA key to return. */
- ret = wolfSSL_RSA_new();
- if (ret == NULL) {
- WOLFSSL_ERROR_MSG("Error creating a new WOLFSSL_RSA structure");
- err = 1;
- }
- }
- if (!err) {
- /* Encode RSA public key to copy to DER - allocates DER buffer. */
- if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 1, rsa->heap)) < 0) {
- WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
- err = 1;
- }
- }
- if (!err) {
- /* Decode DER of the RSA public key into new key. */
- if (wolfSSL_RSA_LoadDer_ex(ret, derBuf, derSz,
- WOLFSSL_RSA_LOAD_PUBLIC) != 1) {
- WOLFSSL_ERROR_MSG("wolfSSL_RSA_LoadDer_ex failed");
- err = 1;
- }
- }
-
- /* Dispose of any allocated DER buffer. */
- XFREE(derBuf, rsa ? rsa->heap : NULL, DYNAMIC_TYPE_ASN1);
- if (err) {
- /* Disposes of any created RSA key - on error. */
- wolfSSL_RSA_free(ret);
- ret = NULL;
- }
- return ret;
-}
-
-/* wolfSSL_RSAPrivateKey_dup not supported */
-
-#endif /* WOLFSSL_KEY_GEN */
-
-static int wolfSSL_RSA_To_Der_ex(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey,
- void* heap);
-
-/*
- * RSA to/from bin APIs
- */
-
-/* Convert RSA public key data to internal.
- *
- * Creates new RSA key from the DER encoded RSA public key.
- *
- * @param [out] out Pointer to RSA key to return through. May be NULL.
- * @param [in, out] derBuf Pointer to start of DER encoded data.
- * @param [in] derSz Length of the data in the DER buffer.
- * @return RSA key on success.
- * @return NULL on failure.
- */
-WOLFSSL_RSA *wolfSSL_d2i_RSAPublicKey(WOLFSSL_RSA **out,
- const unsigned char **derBuf, long derSz)
-{
- WOLFSSL_RSA *rsa = NULL;
- int err = 0;
-
- WOLFSSL_ENTER("wolfSSL_d2i_RSAPublicKey");
-
- /* Validate parameters. */
- if (derBuf == NULL) {
- WOLFSSL_ERROR_MSG("Bad argument");
- err = 1;
- }
- /* Create a new RSA key to return. */
- if ((!err) && ((rsa = wolfSSL_RSA_new()) == NULL)) {
- WOLFSSL_ERROR_MSG("RSA_new failed");
- err = 1;
- }
- /* Decode RSA key from DER. */
- if ((!err) && (wolfSSL_RSA_LoadDer_ex(rsa, *derBuf, (int)derSz,
- WOLFSSL_RSA_LOAD_PUBLIC) != 1)) {
- WOLFSSL_ERROR_MSG("RSA_LoadDer failed");
- err = 1;
- }
- if ((!err) && (out != NULL)) {
- /* Return through parameter too. */
- *out = rsa;
- /* Move buffer on by the used amount. */
- *derBuf += wolfssl_der_length(*derBuf, (int)derSz);
- }
-
- if (err) {
- /* Dispose of any created RSA key. */
- wolfSSL_RSA_free(rsa);
- rsa = NULL;
- }
- return rsa;
-}
-
-/* Convert RSA private key data to internal.
- *
- * Create a new RSA key from the DER encoded RSA private key.
- *
- * @param [out] out Pointer to RSA key to return through. May be NULL.
- * @param [in, out] derBuf Pointer to start of DER encoded data.
- * @param [in] derSz Length of the data in the DER buffer.
- * @return RSA key on success.
- * @return NULL on failure.
- */
-WOLFSSL_RSA *wolfSSL_d2i_RSAPrivateKey(WOLFSSL_RSA **out,
- const unsigned char **derBuf, long derSz)
-{
- WOLFSSL_RSA *rsa = NULL;
- int err = 0;
-
- WOLFSSL_ENTER("wolfSSL_d2i_RSAPublicKey");
-
- /* Validate parameters. */
- if (derBuf == NULL) {
- WOLFSSL_ERROR_MSG("Bad argument");
- err = 1;
- }
- /* Create a new RSA key to return. */
- if ((!err) && ((rsa = wolfSSL_RSA_new()) == NULL)) {
- WOLFSSL_ERROR_MSG("RSA_new failed");
- err = 1;
- }
- /* Decode RSA key from DER. */
- if ((!err) && (wolfSSL_RSA_LoadDer_ex(rsa, *derBuf, (int)derSz,
- WOLFSSL_RSA_LOAD_PRIVATE) != 1)) {
- WOLFSSL_ERROR_MSG("RSA_LoadDer failed");
- err = 1;
- }
- if ((!err) && (out != NULL)) {
- /* Return through parameter too. */
- *out = rsa;
- /* Move buffer on by the used amount. */
- *derBuf += wolfssl_der_length(*derBuf, (int)derSz);
- }
-
- if (err) {
- /* Dispose of any created RSA key. */
- wolfSSL_RSA_free(rsa);
- rsa = NULL;
- }
- return rsa;
-}
-
-/* Converts an internal RSA structure to DER format for the private key.
- *
- * If "pp" is null then buffer size only is returned.
- * If "*pp" is null then a created buffer is set in *pp and the caller is
- * responsible for free'ing it.
- *
- * @param [in] rsa RSA key.
- * @param [in, out] pp On in, pointer to allocated buffer or NULL.
- * May be NULL.
- * On out, newly allocated buffer or pointer to byte after
- * encoding in passed in buffer.
- *
- * @return Size of DER encoding on success
- * @return BAD_FUNC_ARG when rsa is NULL.
- * @return 0 on failure.
- */
-int wolfSSL_i2d_RSAPrivateKey(WOLFSSL_RSA *rsa, unsigned char **pp)
-{
- int ret;
-
- WOLFSSL_ENTER("wolfSSL_i2d_RSAPrivateKey");
-
- /* Validate parameters. */
- if (rsa == NULL) {
- WOLFSSL_ERROR_MSG("Bad Function Arguments");
- ret = BAD_FUNC_ARG;
- }
- /* Encode the RSA key as a DER. Call allocates buffer into pp.
- * No heap hint as this gets returned to the user */
- else if ((ret = wolfSSL_RSA_To_Der_ex(rsa, pp, 0, NULL)) < 0) {
- WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
- ret = 0;
- }
-
- /* Size of DER encoding. */
- return ret;
-}
-
-/* Converts an internal RSA structure to DER format for the public key.
- *
- * If "pp" is null then buffer size only is returned.
- * If "*pp" is null then a created buffer is set in *pp and the caller is
- * responsible for free'ing it.
- *
- * @param [in] rsa RSA key.
- * @param [in, out] pp On in, pointer to allocated buffer or NULL.
- * May be NULL.
- * On out, newly allocated buffer or pointer to byte after
- * encoding in passed in buffer.
- * @return Size of DER encoding on success
- * @return BAD_FUNC_ARG when rsa is NULL.
- * @return 0 on failure.
- */
-int wolfSSL_i2d_RSAPublicKey(WOLFSSL_RSA *rsa, unsigned char **pp)
-{
- int ret;
-
- WOLFSSL_ENTER("wolfSSL_i2d_RSAPublicKey");
-
- /* check for bad functions arguments */
- if (rsa == NULL) {
- WOLFSSL_ERROR_MSG("Bad Function Arguments");
- ret = BAD_FUNC_ARG;
- }
- /* Encode the RSA key as a DER. Call allocates buffer into pp.
- * No heap hint as this gets returned to the user */
- else if ((ret = wolfSSL_RSA_To_Der_ex(rsa, pp, 1, NULL)) < 0) {
- WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
- ret = 0;
- }
-
- return ret;
-}
-
-#endif /* OPENSSL_EXTRA */
-
-/*
- * RSA to/from BIO APIs
- */
-
-/* wolfSSL_d2i_RSAPublicKey_bio not supported */
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \
- || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT)
-
-#if defined(WOLFSSL_KEY_GEN) && !defined(NO_BIO)
-
-/* Read DER data from a BIO.
- *
- * DER structures start with a constructed sequence. Use this to calculate the
- * total length of the DER data.
- *
- * @param [in] bio BIO object to read from.
- * @param [out] out Buffer holding DER encoding.
- * @return Number of bytes to DER encoding on success.
- * @return 0 on failure.
- */
-static int wolfssl_read_der_bio(WOLFSSL_BIO* bio, unsigned char** out)
-{
- int err = 0;
- unsigned char seq[MAX_SEQ_SZ];
- unsigned char* der = NULL;
- int derLen = 0;
-
- /* Read in a minimal amount to get a SEQUENCE header of any size. */
- if (wolfSSL_BIO_read(bio, seq, sizeof(seq)) != sizeof(seq)) {
- WOLFSSL_ERROR_MSG("wolfSSL_BIO_read() of sequence failure");
- err = 1;
- }
- /* Calculate complete DER encoding length. */
- if ((!err) && ((derLen = wolfssl_der_length(seq, sizeof(seq))) <= 0)) {
- WOLFSSL_ERROR_MSG("DER SEQUENCE decode failed");
- err = 1;
- }
- /* Allocate a buffer to read DER data into. */
- if ((!err) && ((der = (unsigned char*)XMALLOC((size_t)derLen, bio->heap,
- DYNAMIC_TYPE_TMP_BUFFER)) == NULL)) {
- WOLFSSL_ERROR_MSG("Malloc failure");
- err = 1;
- }
- if ((!err) && (derLen <= (int)sizeof(seq))) {
- /* Copy the previously read data into the buffer. */
- XMEMCPY(der, seq, derLen);
- }
- else if (!err) {
- /* Calculate the unread amount. */
- int len = derLen - (int)sizeof(seq);
- /* Copy the previously read data into the buffer. */
- XMEMCPY(der, seq, sizeof(seq));
- /* Read rest of DER data from BIO. */
- if (wolfSSL_BIO_read(bio, der + sizeof(seq), len) != len) {
- WOLFSSL_ERROR_MSG("wolfSSL_BIO_read() failure");
- err = 1;
- }
- }
- if (!err) {
- /* Return buffer through parameter. */
- *out = der;
- }
-
- if (err) {
- /* Dispose of any allocated buffer on error. */
- XFREE(der, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- derLen = 0;
- }
- return derLen;
-}
-
-/* Reads the RSA private key data from a BIO to the internal form.
- *
- * Creates new RSA key from the DER encoded RSA private key read from the BIO.
- *
- * @param [in] bio BIO object to read from.
- * @param [out] out Pointer to RSA key to return through. May be NULL.
- * @return RSA key on success.
- * @return NULL on failure.
- */
-WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out)
-{
- WOLFSSL_RSA* key = NULL;
- unsigned char* der = NULL;
- int derLen = 0;
- int err;
-
- WOLFSSL_ENTER("wolfSSL_d2i_RSAPrivateKey_bio");
-
- /* Validate parameters. */
- err = (bio == NULL);
- /* Read just DER encoding from BIO - buffer allocated in call. */
- if ((!err) && ((derLen = wolfssl_read_der_bio(bio, &der)) == 0)) {
- err = 1;
- }
- if (!err) {
- /* Keep der for call to deallocate. */
- const unsigned char* cder = der;
- /* Create an RSA key from the data from the BIO. */
- key = wolfSSL_d2i_RSAPrivateKey(NULL, &cder, derLen);
- err = (key == NULL);
- }
- if ((!err) && (out != NULL)) {
- /* Return the created RSA key through the parameter. */
- *out = key;
- }
-
- if (err) {
- /* Dispose of created key on error. */
- wolfSSL_RSA_free(key);
- key = NULL;
- }
- /* Dispose of allocated data. */
- XFREE(der, bio ? bio->heap : NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return key;
-}
-#endif /* defined(WOLFSSL_KEY_GEN) && !NO_BIO */
-
-#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT */
-
-/*
- * RSA DER APIs
- */
-
-#ifdef OPENSSL_EXTRA
-
-/* Create a DER encoding of key.
- *
- * Not OpenSSL API.
- *
- * @param [in] rsa RSA key.
- * @param [out] outBuf Allocated buffer containing DER encoding.
- * May be NULL.
- * @param [in] publicKey Whether to encode as public key.
- * @param [in] heap Heap hint.
- * @return Encoding size on success.
- * @return Negative on failure.
- */
-int wolfSSL_RSA_To_Der(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey,
- void* heap)
-{
- byte* p = NULL;
- int ret;
-
- if (outBuf != NULL) {
- p = *outBuf;
- }
- ret = wolfSSL_RSA_To_Der_ex(rsa, outBuf, publicKey, heap);
- if ((ret > 0) && (p != NULL)) {
- *outBuf = p;
- }
- return ret;
-}
-
-/* Create a DER encoding of key.
- *
- * Buffer allocated with heap and DYNAMIC_TYPE_TMP_BUFFER.
- *
- * @param [in] rsa RSA key.
- * @param [in, out] outBuf On in, pointer to allocated buffer or NULL.
- * May be NULL.
- * On out, newly allocated buffer or pointer to byte
- * after encoding in passed in buffer.
- * @param [in] publicKey Whether to encode as public key.
- * @param [in] heap Heap hint.
- * @return Encoding size on success.
- * @return Negative on failure.
- */
-static int wolfSSL_RSA_To_Der_ex(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey,
- void* heap)
-{
- int ret = 1;
- int derSz = 0;
- byte* derBuf = NULL;
-
- WOLFSSL_ENTER("wolfSSL_RSA_To_Der");
-
- /* Unused if memory is disabled. */
- (void)heap;
-
- /* Validate parameters. */
- if ((rsa == NULL) || ((publicKey != 0) && (publicKey != 1))) {
- WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", BAD_FUNC_ARG);
- ret = BAD_FUNC_ARG;
- }
- /* Push external RSA data into internal RSA key if not set. */
- if ((ret == 1) && (!rsa->inSet)) {
- ret = SetRsaInternal(rsa);
- }
- /* wc_RsaKeyToPublicDer encode regardless of values. */
- if ((ret == 1) && publicKey && (mp_iszero(&((RsaKey*)rsa->internal)->n) ||
- mp_iszero(&((RsaKey*)rsa->internal)->e))) {
- ret = BAD_FUNC_ARG;
- }
-
- if (ret == 1) {
- if (publicKey) {
- /* Calculate length of DER encoded RSA public key. */
- derSz = wc_RsaPublicKeyDerSize((RsaKey*)rsa->internal, 1);
- if (derSz < 0) {
- WOLFSSL_ERROR_MSG("wc_RsaPublicKeyDerSize failed");
- ret = derSz;
- }
- }
- else {
- /* Calculate length of DER encoded RSA private key. */
- derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, NULL, 0);
- if (derSz < 0) {
- WOLFSSL_ERROR_MSG("wc_RsaKeyToDer failed");
- ret = derSz;
- }
- }
- }
-
- if ((ret == 1) && (outBuf != NULL)) {
- derBuf = *outBuf;
- if (derBuf == NULL) {
- /* Allocate buffer to hold DER encoded RSA key. */
- derBuf = (byte*)XMALLOC((size_t)derSz, heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (derBuf == NULL) {
- WOLFSSL_ERROR_MSG("Memory allocation failed");
- ret = MEMORY_ERROR;
- }
- }
- }
- if ((ret == 1) && (outBuf != NULL)) {
- if (publicKey > 0) {
- /* RSA public key to DER. */
- derSz = wc_RsaKeyToPublicDer((RsaKey*)rsa->internal, derBuf,
- (word32)derSz);
- }
- else {
- /* RSA private key to DER. */
- derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, derBuf,
- (word32)derSz);
- }
- if (derSz < 0) {
- WOLFSSL_ERROR_MSG("RSA key encoding failed");
- ret = derSz;
- }
- else if ((*outBuf) != NULL) {
- derBuf = NULL;
- *outBuf += derSz;
- }
- else {
- /* Return allocated buffer. */
- *outBuf = derBuf;
- }
- }
- if (ret == 1) {
- /* Success - return DER encoding size. */
- ret = derSz;
- }
-
- if ((outBuf != NULL) && (*outBuf != derBuf)) {
- /* Not returning buffer, needs to be disposed of. */
- XFREE(derBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", ret);
- return ret;
-}
-
-#endif /* OPENSSL_EXTRA */
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-/* Load the DER encoded private RSA key.
- *
- * Not OpenSSL API.
- *
- * @param [in] rsa RSA key.
- * @param [in] derBuf Buffer holding DER encoding.
- * @param [in] derSz Length of DER encoding.
- * @return 1 on success.
- * @return -1 on failure.
- */
-int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf,
- int derSz)
-{
- /* Call implementation that handles both private and public keys. */
- return wolfSSL_RSA_LoadDer_ex(rsa, derBuf, derSz, WOLFSSL_RSA_LOAD_PRIVATE);
-}
-
-/* Load the DER encoded public or private RSA key.
- *
- * Not OpenSSL API.
- *
- * @param [in] rsa RSA key.
- * @param [in] derBuf Buffer holding DER encoding.
- * @param [in] derSz Length of DER encoding.
- * @param [in] opt Indicates public or private key.
- * (WOLFSSL_RSA_LOAD_PUBLIC or WOLFSSL_RSA_LOAD_PRIVATE)
- * @return 1 on success.
- * @return -1 on failure.
- */
-int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf,
- int derSz, int opt)
-{
- int ret = 1;
- int res;
- word32 idx = 0;
- word32 algId;
-
- WOLFSSL_ENTER("wolfSSL_RSA_LoadDer");
-
- /* Validate parameters. */
- if ((rsa == NULL) || (rsa->internal == NULL) || (derBuf == NULL) ||
- (derSz <= 0)) {
- WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- if (ret == 1) {
- rsa->pkcs8HeaderSz = 0;
- /* Check if input buffer has PKCS8 header. In the case that it does not
- * have a PKCS8 header then do not error out. */
- res = ToTraditionalInline_ex((const byte*)derBuf, &idx, (word32)derSz,
- &algId);
- if (res > 0) {
- /* Store size of PKCS#8 header for encoding. */
- WOLFSSL_MSG("Found PKCS8 header");
- rsa->pkcs8HeaderSz = (word16)idx;
- }
- /* When decoding and not PKCS#8, return will be ASN_PARSE_E. */
- else if (res != WC_NO_ERR_TRACE(ASN_PARSE_E)) {
- /* Something went wrong while decoding. */
- WOLFSSL_ERROR_MSG("Unexpected error with trying to remove PKCS#8 "
- "header");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- if (ret == 1) {
- /* Decode private or public key data. */
- if (opt == WOLFSSL_RSA_LOAD_PRIVATE) {
- res = wc_RsaPrivateKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal,
- (word32)derSz);
- }
- else {
- res = wc_RsaPublicKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal,
- (word32)derSz);
- }
- /* Check for error. */
- if (res < 0) {
- if (opt == WOLFSSL_RSA_LOAD_PRIVATE) {
- WOLFSSL_ERROR_MSG("RsaPrivateKeyDecode failed");
- }
- else {
- WOLFSSL_ERROR_MSG("RsaPublicKeyDecode failed");
- }
- WOLFSSL_ERROR_VERBOSE(res);
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- if (ret == 1) {
- /* Set external RSA key data from wolfCrypt key. */
- if (SetRsaExternal(rsa) != 1) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- else {
- rsa->inSet = 1;
- }
- }
-
- return ret;
-}
-
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
-
-#if !defined(NO_BIO) || !defined(NO_FILESYSTEM)
-/* Load DER encoded data into WOLFSSL_RSA object.
- *
- * Creates a new WOLFSSL_RSA object if one is not passed in.
- *
- * @param [in, out] rsa WOLFSSL_RSA object to load into.
- * When rsa or *rsa is NULL a new object is created.
- * When not NULL and *rsa is NULL then new object
- * returned through pointer.
- * @param [in] in DER encoded RSA key data.
- * @param [in] inSz Size of DER encoded data in bytes.
- * @param [in] opt Public or private key encoded in data. Valid values:
- * WOLFSSL_RSA_LOAD_PRIVATE, WOLFSSL_RSA_LOAD_PUBLIC.
- * @return NULL on failure.
- * @return WOLFSSL_RSA object on success.
- */
-static WOLFSSL_RSA* wolfssl_rsa_d2i(WOLFSSL_RSA** rsa, const unsigned char* in,
- long inSz, int opt)
-{
- WOLFSSL_RSA* ret = NULL;
-
- if ((rsa != NULL) && (*rsa != NULL)) {
- ret = *rsa;
- }
- else {
- ret = wolfSSL_RSA_new();
- }
- if ((ret != NULL) && (wolfSSL_RSA_LoadDer_ex(ret, in, (int)inSz, opt)
- != 1)) {
- if ((rsa == NULL) || (ret != *rsa)) {
- wolfSSL_RSA_free(ret);
- }
- ret = NULL;
- }
-
- if ((rsa != NULL) && (*rsa == NULL)) {
- *rsa = ret;
- }
- return ret;
-}
-#endif
-
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
-
-/*
- * RSA PEM APIs
- */
-
-#ifdef OPENSSL_EXTRA
-
-#ifndef NO_BIO
-#if defined(WOLFSSL_KEY_GEN)
-/* Writes PEM encoding of an RSA public key to a BIO.
- *
- * @param [in] bio BIO object to write to.
- * @param [in] rsa RSA key to write.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_PEM_write_bio_RSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa)
-{
- int ret = 1;
- int derSz = 0;
- byte* derBuf = NULL;
-
- WOLFSSL_ENTER("wolfSSL_PEM_write_bio_RSA_PUBKEY");
-
- /* Validate parameters. */
- if ((bio == NULL) || (rsa == NULL)) {
- WOLFSSL_ERROR_MSG("Bad Function Arguments");
- return 0;
- }
-
- if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 1, bio->heap)) < 0) {
- WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
- ret = 0;
- }
- if (derBuf == NULL) {
- WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed to get buffer");
- ret = 0;
- }
- if ((ret == 1) && (der_write_to_bio_as_pem(derBuf, derSz, bio,
- PUBLICKEY_TYPE) != 1)) {
- ret = 0;
- }
-
- /* Dispose of DER buffer. */
- XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
-}
-
-#endif /* WOLFSSL_KEY_GEN */
-#endif /* !NO_BIO */
-
-#if defined(WOLFSSL_KEY_GEN)
-#ifndef NO_FILESYSTEM
-
-/* Writes PEM encoding of an RSA public key to a file pointer.
- *
- * @param [in] fp File pointer to write to.
- * @param [in] rsa RSA key to write.
- * @param [in] type PEM type to write out.
- * @return 1 on success.
- * @return 0 on failure.
- */
-static int wolfssl_pem_write_rsa_public_key(XFILE fp, WOLFSSL_RSA* rsa,
- int type)
-{
- int ret = 1;
- int derSz;
- byte* derBuf = NULL;
-
- /* Validate parameters. */
- if ((fp == XBADFILE) || (rsa == NULL)) {
- WOLFSSL_ERROR_MSG("Bad Function Arguments");
- return 0;
- }
-
- if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 1, rsa->heap)) < 0) {
- WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
- ret = 0;
- }
- if (derBuf == NULL) {
- WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed to get buffer");
- ret = 0;
- }
- if ((ret == 1) && (der_write_to_file_as_pem(derBuf, derSz, fp, type,
- rsa->heap) != 1)) {
- ret = 0;
- }
-
- /* Dispose of DER buffer. */
- XFREE(derBuf, rsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
-
- return ret;
-}
-
-/* Writes PEM encoding of an RSA public key to a file pointer.
- *
- * Header/footer will contain: PUBLIC KEY
- *
- * @param [in] fp File pointer to write to.
- * @param [in] rsa RSA key to write.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_PEM_write_RSA_PUBKEY(XFILE fp, WOLFSSL_RSA* rsa)
-{
- return wolfssl_pem_write_rsa_public_key(fp, rsa, PUBLICKEY_TYPE);
-}
-
-/* Writes PEM encoding of an RSA public key to a file pointer.
- *
- * Header/footer will contain: RSA PUBLIC KEY
- *
- * @param [in] fp File pointer to write to.
- * @param [in] rsa RSA key to write.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_PEM_write_RSAPublicKey(XFILE fp, WOLFSSL_RSA* rsa)
-{
- return wolfssl_pem_write_rsa_public_key(fp, rsa, RSA_PUBLICKEY_TYPE);
-}
-#endif /* !NO_FILESYSTEM */
-#endif /* WOLFSSL_KEY_GEN */
-
-#ifndef NO_BIO
-/* Create an RSA public key by reading the PEM encoded data from the BIO.
- *
- * @param [in] bio BIO object to read from.
- * @param [out] out RSA key created.
- * @param [in] cb Password callback when PEM encrypted.
- * @param [in] pass NUL terminated string for passphrase when PEM encrypted.
- * @return RSA key on success.
- * @return NULL on failure.
- */
-WOLFSSL_RSA *wolfSSL_PEM_read_bio_RSA_PUBKEY(WOLFSSL_BIO* bio,
- WOLFSSL_RSA** out, wc_pem_password_cb* cb, void *pass)
-{
- WOLFSSL_RSA* rsa = NULL;
- DerBuffer* der = NULL;
- int keyFormat = 0;
-
- WOLFSSL_ENTER("wolfSSL_PEM_read_bio_RSA_PUBKEY");
-
- if ((bio != NULL) && (pem_read_bio_key(bio, cb, pass, PUBLICKEY_TYPE,
- &keyFormat, &der) >= 0)) {
- rsa = wolfssl_rsa_d2i(out, der->buffer, der->length,
- WOLFSSL_RSA_LOAD_PUBLIC);
- if (rsa == NULL) {
- WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_RSA");
- }
- }
-
- FreeDer(&der);
- if ((out != NULL) && (rsa != NULL)) {
- *out = rsa;
- }
- return rsa;
-}
-
-WOLFSSL_RSA *wolfSSL_d2i_RSA_PUBKEY_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out)
-{
- char* data = NULL;
- int dataSz = 0;
- int memAlloced = 0;
- WOLFSSL_RSA* rsa = NULL;
-
- WOLFSSL_ENTER("wolfSSL_d2i_RSA_PUBKEY_bio");
-
- if (bio == NULL)
- return NULL;
-
- if (wolfssl_read_bio(bio, &data, &dataSz, &memAlloced) != 0) {
- if (memAlloced)
- XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
-
- rsa = wolfssl_rsa_d2i(out, (const unsigned char*)data, dataSz,
- WOLFSSL_RSA_LOAD_PUBLIC);
- if (memAlloced)
- XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
- return rsa;
-}
-#endif /* !NO_BIO */
-
-#ifndef NO_FILESYSTEM
-/* Create an RSA public key by reading the PEM encoded data from the BIO.
- *
- * Header/footer should contain: PUBLIC KEY
- * PEM decoder supports either 'RSA PUBLIC KEY' or 'PUBLIC KEY'.
- *
- * @param [in] fp File pointer to read from.
- * @param [out] out RSA key created.
- * @param [in] cb Password callback when PEM encrypted.
- * @param [in] pass NUL terminated string for passphrase when PEM encrypted.
- * @return RSA key on success.
- * @return NULL on failure.
- */
-WOLFSSL_RSA *wolfSSL_PEM_read_RSA_PUBKEY(XFILE fp,
- WOLFSSL_RSA** out, wc_pem_password_cb* cb, void *pass)
-{
- WOLFSSL_RSA* rsa = NULL;
- DerBuffer* der = NULL;
- int keyFormat = 0;
-
- WOLFSSL_ENTER("wolfSSL_PEM_read_RSA_PUBKEY");
-
- if ((fp != XBADFILE) && (pem_read_file_key(fp, cb, pass, PUBLICKEY_TYPE,
- &keyFormat, &der) >= 0)) {
- rsa = wolfssl_rsa_d2i(out, der->buffer, der->length,
- WOLFSSL_RSA_LOAD_PUBLIC);
- if (rsa == NULL) {
- WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_RSA");
- }
- }
-
- FreeDer(&der);
- if ((out != NULL) && (rsa != NULL)) {
- *out = rsa;
- }
- return rsa;
-}
-
-/* Create an RSA public key by reading the PEM encoded data from the BIO.
- *
- * Header/footer should contain: RSA PUBLIC KEY
- * PEM decoder supports either 'RSA PUBLIC KEY' or 'PUBLIC KEY'.
- *
- * @param [in] fp File pointer to read from.
- * @param [out] rsa RSA key created.
- * @param [in] cb Password callback when PEM encrypted. May be NULL.
- * @param [in] pass NUL terminated string for passphrase when PEM encrypted.
- * May be NULL.
- * @return RSA key on success.
- * @return NULL on failure.
- */
-WOLFSSL_RSA* wolfSSL_PEM_read_RSAPublicKey(XFILE fp, WOLFSSL_RSA** rsa,
- wc_pem_password_cb* cb, void* pass)
-{
- return wolfSSL_PEM_read_RSA_PUBKEY(fp, rsa, cb, pass);
-}
-
-#endif /* NO_FILESYSTEM */
-
-#if defined(WOLFSSL_KEY_GEN) && \
- (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM))
-
-/* Writes PEM encoding of an RSA private key to newly allocated buffer.
- *
- * Buffer returned was allocated with: DYNAMIC_TYPE_KEY.
- *
- * @param [in] rsa RSA key to write.
- * @param [in] cipher Cipher to use when PEM encrypted. May be NULL.
- * @param [in] passwd Password string when PEM encrypted. May be NULL.
- * @param [in] passwdSz Length of password string when PEM encrypted.
- * @param [out] pem Allocated buffer with PEM encoding.
- * @param [out] pLen Length of PEM encoding.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_PEM_write_mem_RSAPrivateKey(WOLFSSL_RSA* rsa,
- const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz,
- unsigned char **pem, int *pLen)
-{
- int ret = 1;
- byte* derBuf = NULL;
- int derSz = 0;
-
- WOLFSSL_ENTER("wolfSSL_PEM_write_mem_RSAPrivateKey");
-
- /* Validate parameters. */
- if ((pem == NULL) || (pLen == NULL) || (rsa == NULL) ||
- (rsa->internal == NULL)) {
- WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = 0;
- }
-
- /* Set the RSA key data into the wolfCrypt RSA key if not done so. */
- if ((ret == 1) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
- ret = 0;
- }
-
- /* Encode wolfCrypt RSA key to DER - derBuf allocated in call. */
- if ((ret == 1) && ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 0,
- rsa->heap)) < 0)) {
- WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
- ret = 0;
- }
-
- if ((ret == 1) && (der_to_enc_pem_alloc(derBuf, derSz, cipher, passwd,
- passwdSz, PRIVATEKEY_TYPE, NULL, pem, pLen) != 1)) {
- WOLFSSL_ERROR_MSG("der_to_enc_pem_alloc failed");
- ret = 0;
- }
-
- return ret;
-}
-
-#ifndef NO_BIO
-/* Writes PEM encoding of an RSA private key to a BIO.
- *
- * @param [in] bio BIO object to write to.
- * @param [in] rsa RSA key to write.
- * @param [in] cipher Cipher to use when PEM encrypted.
- * @param [in] passwd Password string when PEM encrypted.
- * @param [in] len Length of password string when PEM encrypted.
- * @param [in] cb Password callback to use when PEM encrypted.
- * @param [in] arg NUL terminated string for passphrase when PEM encrypted.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa,
- const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int len,
- wc_pem_password_cb* cb, void* arg)
-{
- int ret = 1;
- byte* pem = NULL;
- int pLen = 0;
-
- (void)cb;
- (void)arg;
-
- WOLFSSL_ENTER("wolfSSL_PEM_write_bio_RSAPrivateKey");
-
- /* Validate parameters. */
- if ((bio == NULL) || (rsa == NULL) || (rsa->internal == NULL)) {
- WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = 0;
- }
-
- if (ret == 1) {
- /* Write PEM to buffer that is allocated in the call. */
- ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, cipher, passwd, len,
- &pem, &pLen);
- if (ret != 1) {
- WOLFSSL_ERROR_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed");
- }
- }
- /* Write PEM to BIO. */
- if ((ret == 1) && (wolfSSL_BIO_write(bio, pem, pLen) <= 0)) {
- WOLFSSL_ERROR_MSG("RSA private key BIO write failed");
- ret = 0;
- }
-
- /* Dispose of any allocated PEM buffer. */
- XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
- return ret;
-}
-#endif /* !NO_BIO */
-
-#ifndef NO_FILESYSTEM
-/* Writes PEM encoding of an RSA private key to a file pointer.
- *
- * TODO: Support use of the password callback and callback context.
- *
- * @param [in] fp File pointer to write to.
- * @param [in] rsa RSA key to write.
- * @param [in] cipher Cipher to use when PEM encrypted. May be NULL.
- * @param [in] passwd Password string when PEM encrypted. May be NULL.
- * @param [in] passwdSz Length of password string when PEM encrypted.
- * @param [in] cb Password callback to use when PEM encrypted. Unused.
- * @param [in] arg NUL terminated string for passphrase when PEM
- * encrypted. Unused.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_PEM_write_RSAPrivateKey(XFILE fp, WOLFSSL_RSA *rsa,
- const WOLFSSL_EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz,
- wc_pem_password_cb *cb, void *arg)
-{
- int ret = 1;
- byte* pem = NULL;
- int pLen = 0;
-
- (void)cb;
- (void)arg;
-
- WOLFSSL_ENTER("wolfSSL_PEM_write_RSAPrivateKey");
-
- /* Validate parameters. */
- if ((fp == XBADFILE) || (rsa == NULL) || (rsa->internal == NULL)) {
- WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = 0;
- }
-
- if (ret == 1) {
- /* Write PEM to buffer that is allocated in the call. */
- ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, cipher, passwd, passwdSz,
- &pem, &pLen);
- if (ret != 1) {
- WOLFSSL_ERROR_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed");
- }
- }
- /* Write PEM to file pointer. */
- if ((ret == 1) && ((int)XFWRITE(pem, 1, (size_t)pLen, fp) != pLen)) {
- WOLFSSL_ERROR_MSG("RSA private key file write failed");
- ret = 0;
- }
-
- /* Dispose of any allocated PEM buffer. */
- XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
- return ret;
-}
-#endif /* NO_FILESYSTEM */
-#endif /* WOLFSSL_KEY_GEN && WOLFSSL_PEM_TO_DER */
-
-#ifndef NO_BIO
-/* Create an RSA private key by reading the PEM encoded data from the BIO.
- *
- * @param [in] bio BIO object to read from.
- * @param [out] out RSA key created.
- * @param [in] cb Password callback when PEM encrypted.
- * @param [in] pass NUL terminated string for passphrase when PEM encrypted.
- * @return RSA key on success.
- * @return NULL on failure.
- */
-WOLFSSL_RSA* wolfSSL_PEM_read_bio_RSAPrivateKey(WOLFSSL_BIO* bio,
- WOLFSSL_RSA** out, wc_pem_password_cb* cb, void* pass)
-{
- WOLFSSL_RSA* rsa = NULL;
- DerBuffer* der = NULL;
- int keyFormat = 0;
-
- WOLFSSL_ENTER("wolfSSL_PEM_read_bio_RSAPrivateKey");
-
- if ((bio != NULL) && (pem_read_bio_key(bio, cb, pass, PRIVATEKEY_TYPE,
- &keyFormat, &der) >= 0)) {
- rsa = wolfssl_rsa_d2i(out, der->buffer, der->length,
- WOLFSSL_RSA_LOAD_PRIVATE);
- if (rsa == NULL) {
- WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_RSA");
- }
- }
-
- FreeDer(&der);
- if ((out != NULL) && (rsa != NULL)) {
- *out = rsa;
- }
- return rsa;
-}
-#endif /* !NO_BIO */
-
-/* Create an RSA private key by reading the PEM encoded data from the file
- * pointer.
- *
- * @param [in] fp File pointer to read from.
- * @param [out] out RSA key created.
- * @param [in] cb Password callback when PEM encrypted.
- * @param [in] pass NUL terminated string for passphrase when PEM encrypted.
- * @return RSA key on success.
- * @return NULL on failure.
- */
-#ifndef NO_FILESYSTEM
-WOLFSSL_RSA* wolfSSL_PEM_read_RSAPrivateKey(XFILE fp, WOLFSSL_RSA** out,
- wc_pem_password_cb* cb, void* pass)
-{
- WOLFSSL_RSA* rsa = NULL;
- DerBuffer* der = NULL;
- int keyFormat = 0;
-
- WOLFSSL_ENTER("wolfSSL_PEM_read_RSAPrivateKey");
-
- if ((fp != XBADFILE) && (pem_read_file_key(fp, cb, pass, PRIVATEKEY_TYPE,
- &keyFormat, &der) >= 0)) {
- rsa = wolfssl_rsa_d2i(out, der->buffer, der->length,
- WOLFSSL_RSA_LOAD_PRIVATE);
- if (rsa == NULL) {
- WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_RSA");
- }
- }
-
- FreeDer(&der);
- if ((out != NULL) && (rsa != NULL)) {
- *out = rsa;
- }
- return rsa;
-}
-#endif /* !NO_FILESYSTEM */
-
-/*
- * RSA print APIs
- */
-
-#if defined(XFPRINTF) && !defined(NO_FILESYSTEM) && \
- !defined(NO_STDIO_FILESYSTEM)
-/* Print an RSA key to a file pointer.
- *
- * @param [in] fp File pointer to write to.
- * @param [in] rsa RSA key to write.
- * @param [in] indent Number of spaces to prepend to each line.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_RSA_print_fp(XFILE fp, WOLFSSL_RSA* rsa, int indent)
-{
- int ret = 1;
-
- WOLFSSL_ENTER("wolfSSL_RSA_print_fp");
-
- /* Validate parameters. */
- if ((fp == XBADFILE) || (rsa == NULL)) {
- ret = 0;
- }
-
- /* Set the external data from the wolfCrypt RSA key if not done. */
- if ((ret == 1) && (!rsa->exSet)) {
- ret = SetRsaExternal(rsa);
- }
-
- /* Get the key size from modulus if available. */
- if ((ret == 1) && (rsa->n != NULL)) {
- int keySize = wolfSSL_BN_num_bits(rsa->n);
- if (keySize == 0) {
- ret = 0;
- }
- else {
- if (XFPRINTF(fp, "%*s", indent, "") < 0)
- ret = 0;
- else if (XFPRINTF(fp, "RSA Private-Key: (%d bit, 2 primes)\n",
- keySize) < 0)
- ret = 0;
- }
- }
- /* Print out any components available. */
- if ((ret == 1) && (rsa->n != NULL)) {
- ret = pk_bn_field_print_fp(fp, indent, "modulus", rsa->n);
- }
- if ((ret == 1) && (rsa->d != NULL)) {
- ret = pk_bn_field_print_fp(fp, indent, "privateExponent", rsa->d);
- }
- if ((ret == 1) && (rsa->p != NULL)) {
- ret = pk_bn_field_print_fp(fp, indent, "prime1", rsa->p);
- }
- if ((ret == 1) && (rsa->q != NULL)) {
- ret = pk_bn_field_print_fp(fp, indent, "prime2", rsa->q);
- }
- if ((ret == 1) && (rsa->dmp1 != NULL)) {
- ret = pk_bn_field_print_fp(fp, indent, "exponent1", rsa->dmp1);
- }
- if ((ret == 1) && (rsa->dmq1 != NULL)) {
- ret = pk_bn_field_print_fp(fp, indent, "exponent2", rsa->dmq1);
- }
- if ((ret == 1) && (rsa->iqmp != NULL)) {
- ret = pk_bn_field_print_fp(fp, indent, "coefficient", rsa->iqmp);
- }
-
- WOLFSSL_LEAVE("wolfSSL_RSA_print_fp", ret);
-
- return ret;
-}
-#endif /* XFPRINTF && !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */
-
-#if defined(XSNPRINTF) && !defined(NO_BIO)
-/* snprintf() must be available */
-
-/* Maximum size of a header line. */
-#define RSA_PRINT_MAX_HEADER_LINE PRINT_NUM_MAX_INDENT
-
-/* Writes the human readable form of RSA to a BIO.
- *
- * @param [in] bio BIO object to write to.
- * @param [in] rsa RSA key to write.
- * @param [in] indent Number of spaces before each line.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_RSA_print(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, int indent)
-{
- int ret = 1;
- int sz = 0;
- RsaKey* key = NULL;
- char line[RSA_PRINT_MAX_HEADER_LINE];
- int i = 0;
- mp_int *num = NULL;
- /* Header strings. */
- const char *name[] = {
- "Modulus:", "Exponent:", "PrivateExponent:", "Prime1:", "Prime2:",
- "Exponent1:", "Exponent2:", "Coefficient:"
- };
-
- WOLFSSL_ENTER("wolfSSL_RSA_print");
-
- /* Validate parameters. */
- if ((bio == NULL) || (rsa == NULL) || (indent > PRINT_NUM_MAX_INDENT)) {
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- if (ret == 1) {
- key = (RsaKey*)rsa->internal;
-
- /* Get size in bits of key for printing out. */
- sz = wolfSSL_RSA_bits(rsa);
- if (sz <= 0) {
- WOLFSSL_ERROR_MSG("Error getting RSA key size");
- ret = 0;
- }
- }
- if (ret == 1) {
- /* Print any indent spaces. */
- ret = wolfssl_print_indent(bio, line, sizeof(line), indent);
- }
- if (ret == 1) {
- /* Print header line. */
- int len = XSNPRINTF(line, sizeof(line), "\nRSA %s: (%d bit)\n",
- (!mp_iszero(&key->d)) ? "Private-Key" : "Public-Key", sz);
- if (len >= (int)sizeof(line)) {
- WOLFSSL_ERROR_MSG("Buffer overflow while formatting key preamble");
- ret = 0;
- }
- else {
- if (wolfSSL_BIO_write(bio, line, len) <= 0) {
- ret = 0;
- }
- }
- }
-
- for (i = 0; (ret == 1) && (i < RSA_INTS); i++) {
- /* Get mp_int for index. */
- switch (i) {
- case 0:
- /* Print out modulus */
- num = &key->n;
- break;
- case 1:
- num = &key->e;
- break;
- case 2:
- num = &key->d;
- break;
- case 3:
- num = &key->p;
- break;
- case 4:
- num = &key->q;
- break;
- case 5:
- num = &key->dP;
- break;
- case 6:
- num = &key->dQ;
- break;
- case 7:
- num = &key->u;
- break;
- default:
- WOLFSSL_ERROR_MSG("Bad index value");
- }
-
- if (i == 1) {
- /* Print exponent as a 32-bit value. */
- ret = wolfssl_print_value(bio, num, name[i], indent);
- }
- else if (!mp_iszero(num)) {
- /* Print name and MP integer. */
- ret = wolfssl_print_number(bio, num, name[i], indent);
- }
- }
-
- return ret;
-}
-#endif /* XSNPRINTF && !NO_BIO */
-
-#endif /* OPENSSL_EXTRA */
-
-/*
- * RSA get/set/test APIs
- */
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-/* Set RSA key data (external) from wolfCrypt RSA key (internal).
- *
- * @param [in, out] rsa RSA key.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int SetRsaExternal(WOLFSSL_RSA* rsa)
-{
- int ret = 1;
-
- WOLFSSL_ENTER("SetRsaExternal");
-
- /* Validate parameters. */
- if ((rsa == NULL) || (rsa->internal == NULL)) {
- WOLFSSL_ERROR_MSG("rsa key NULL error");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- if (ret == 1) {
- RsaKey* key = (RsaKey*)rsa->internal;
-
- /* Copy modulus. */
- ret = wolfssl_bn_set_value(&rsa->n, &key->n);
- if (ret != 1) {
- WOLFSSL_ERROR_MSG("rsa n error");
- }
- if (ret == 1) {
- /* Copy public exponent. */
- ret = wolfssl_bn_set_value(&rsa->e, &key->e);
- if (ret != 1) {
- WOLFSSL_ERROR_MSG("rsa e error");
- }
- }
-
- if (key->type == RSA_PRIVATE) {
- #ifndef WOLFSSL_RSA_PUBLIC_ONLY
- if (ret == 1) {
- /* Copy private exponent. */
- ret = wolfssl_bn_set_value(&rsa->d, &key->d);
- if (ret != 1) {
- WOLFSSL_ERROR_MSG("rsa d error");
- }
- }
- if (ret == 1) {
- /* Copy first prime. */
- ret = wolfssl_bn_set_value(&rsa->p, &key->p);
- if (ret != 1) {
- WOLFSSL_ERROR_MSG("rsa p error");
- }
- }
- if (ret == 1) {
- /* Copy second prime. */
- ret = wolfssl_bn_set_value(&rsa->q, &key->q);
- if (ret != 1) {
- WOLFSSL_ERROR_MSG("rsa q error");
- }
- }
- #if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || \
- !defined(RSA_LOW_MEM)
- if (ret == 1) {
- /* Copy d mod p-1. */
- ret = wolfssl_bn_set_value(&rsa->dmp1, &key->dP);
- if (ret != 1) {
- WOLFSSL_ERROR_MSG("rsa dP error");
- }
- }
- if (ret == 1) {
- /* Copy d mod q-1. */
- ret = wolfssl_bn_set_value(&rsa->dmq1, &key->dQ);
- if (ret != 1) {
- WOLFSSL_ERROR_MSG("rsa dq error");
- }
- }
- if (ret == 1) {
- /* Copy 1/q mod p. */
- ret = wolfssl_bn_set_value(&rsa->iqmp, &key->u);
- if (ret != 1) {
- WOLFSSL_ERROR_MSG("rsa u error");
- }
- }
- #endif
- #else
- WOLFSSL_ERROR_MSG("rsa private key not compiled in ");
- ret = 0;
- #endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
- }
- }
- if (ret == 1) {
- /* External values set. */
- rsa->exSet = 1;
- }
- else {
- /* Return 0 on failure. */
- ret = 0;
- }
-
- return ret;
-}
-#endif /* (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */
-
-#ifdef OPENSSL_EXTRA
-
-/* Set wolfCrypt RSA key data (internal) from RSA key (external).
- *
- * @param [in, out] rsa RSA key.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int SetRsaInternal(WOLFSSL_RSA* rsa)
-{
- int ret = 1;
-
- WOLFSSL_ENTER("SetRsaInternal");
-
- /* Validate parameters. */
- if ((rsa == NULL) || (rsa->internal == NULL)) {
- WOLFSSL_ERROR_MSG("rsa key NULL error");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- if (ret == 1) {
- RsaKey* key = (RsaKey*)rsa->internal;
-
- /* Copy down modulus if available. */
- if ((rsa->n != NULL) && (wolfssl_bn_get_value(rsa->n, &key->n) != 1)) {
- WOLFSSL_ERROR_MSG("rsa n key error");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- /* Copy down public exponent if available. */
- if ((ret == 1) && (rsa->e != NULL) &&
- (wolfssl_bn_get_value(rsa->e, &key->e) != 1)) {
- WOLFSSL_ERROR_MSG("rsa e key error");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- /* Enough numbers for public key */
- key->type = RSA_PUBLIC;
-
-#ifndef WOLFSSL_RSA_PUBLIC_ONLY
- /* Copy down private exponent if available. */
- if ((ret == 1) && (rsa->d != NULL)) {
- if (wolfssl_bn_get_value(rsa->d, &key->d) != 1) {
- WOLFSSL_ERROR_MSG("rsa d key error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- else {
- /* Enough numbers for private key */
- key->type = RSA_PRIVATE;
- }
- }
-
- /* Copy down first prime if available. */
- if ((ret == 1) && (rsa->p != NULL) &&
- (wolfssl_bn_get_value(rsa->p, &key->p) != 1)) {
- WOLFSSL_ERROR_MSG("rsa p key error");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- /* Copy down second prime if available. */
- if ((ret == 1) && (rsa->q != NULL) &&
- (wolfssl_bn_get_value(rsa->q, &key->q) != 1)) {
- WOLFSSL_ERROR_MSG("rsa q key error");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
-#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)
- /* Copy down d mod p-1 if available. */
- if ((ret == 1) && (rsa->dmp1 != NULL) &&
- (wolfssl_bn_get_value(rsa->dmp1, &key->dP) != 1)) {
- WOLFSSL_ERROR_MSG("rsa dP key error");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- /* Copy down d mod q-1 if available. */
- if ((ret == 1) && (rsa->dmq1 != NULL) &&
- (wolfssl_bn_get_value(rsa->dmq1, &key->dQ) != 1)) {
- WOLFSSL_ERROR_MSG("rsa dQ key error");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- /* Copy down 1/q mod p if available. */
- if ((ret == 1) && (rsa->iqmp != NULL) &&
- (wolfssl_bn_get_value(rsa->iqmp, &key->u) != 1)) {
- WOLFSSL_ERROR_MSG("rsa u key error");
- ret = WOLFSSL_FATAL_ERROR;
- }
-#endif
-#endif
-
- if (ret == 1) {
- /* All available numbers have been set down. */
- rsa->inSet = 1;
- }
- }
-
- return ret;
-}
-
-/* Set the RSA method into object.
- *
- * @param [in, out] rsa RSA key.
- * @param [in] meth RSA method.
- * @return 1 always.
- */
-int wolfSSL_RSA_set_method(WOLFSSL_RSA *rsa, WOLFSSL_RSA_METHOD *meth)
-{
- if (rsa != NULL) {
- /* Store the method into object. */
- rsa->meth = meth;
- /* Copy over flags. */
- rsa->flags = meth->flags;
- }
- /* OpenSSL always assumes it will work. */
- return 1;
-}
-
-/* Get the RSA method from the RSA object.
- *
- * @param [in] rsa RSA key.
- * @return RSA method on success.
- * @return NULL when RSA is NULL or no method set.
- */
-const WOLFSSL_RSA_METHOD* wolfSSL_RSA_get_method(const WOLFSSL_RSA *rsa)
-{
- return (rsa != NULL) ? rsa->meth : NULL;
-}
-
-/* Get the size in bytes of the RSA key.
- *
- * Return compliant with OpenSSL
- *
- * @param [in] rsa RSA key.
- * @return RSA modulus size in bytes.
- * @return 0 on error.
- */
-int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa)
-{
- int ret = 0;
-
- WOLFSSL_ENTER("wolfSSL_RSA_size");
-
- if (rsa != NULL) {
- /* Make sure we have set the RSA values into wolfCrypt RSA key. */
- if (rsa->inSet || (SetRsaInternal((WOLFSSL_RSA*)rsa) == 1)) {
- /* Get key size in bytes using wolfCrypt RSA key. */
- ret = wc_RsaEncryptSize((RsaKey*)rsa->internal);
- }
- }
-
- return ret;
-}
-
-/* Get the size in bits of the RSA key.
- *
- * Uses external modulus field.
- *
- * @param [in] rsa RSA key.
- * @return RSA modulus size in bits.
- * @return 0 on error.
- */
-int wolfSSL_RSA_bits(const WOLFSSL_RSA* rsa)
-{
- int ret = 0;
-
- WOLFSSL_ENTER("wolfSSL_RSA_bits");
-
- if (rsa != NULL) {
- /* Get number of bits in external modulus. */
- ret = wolfSSL_BN_num_bits(rsa->n);
- }
-
- return ret;
-}
-
-/* Get the BN objects that are the Chinese-Remainder Theorem (CRT) parameters.
- *
- * Only for those that are not NULL parameters.
- *
- * @param [in] rsa RSA key.
- * @param [out] dmp1 BN that is d mod (p - 1). May be NULL.
- * @param [out] dmq1 BN that is d mod (q - 1). May be NULL.
- * @param [out] iqmp BN that is 1/q mod p. May be NULL.
- */
-void wolfSSL_RSA_get0_crt_params(const WOLFSSL_RSA *rsa,
- const WOLFSSL_BIGNUM **dmp1, const WOLFSSL_BIGNUM **dmq1,
- const WOLFSSL_BIGNUM **iqmp)
-{
- WOLFSSL_ENTER("wolfSSL_RSA_get0_crt_params");
-
- /* For any parameters not NULL, return the BN from the key or NULL. */
- if (dmp1 != NULL) {
- *dmp1 = (rsa != NULL) ? rsa->dmp1 : NULL;
- }
- if (dmq1 != NULL) {
- *dmq1 = (rsa != NULL) ? rsa->dmq1 : NULL;
- }
- if (iqmp != NULL) {
- *iqmp = (rsa != NULL) ? rsa->iqmp : NULL;
- }
-}
-
-/* Set the BN objects that are the Chinese-Remainder Theorem (CRT) parameters
- * into RSA key.
- *
- * If CRT parameter is NULL then there must be one in the RSA key already.
- *
- * @param [in, out] rsa RSA key.
- * @param [in] dmp1 BN that is d mod (p - 1). May be NULL.
- * @param [in] dmq1 BN that is d mod (q - 1). May be NULL.
- * @param [in] iqmp BN that is 1/q mod p. May be NULL.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_RSA_set0_crt_params(WOLFSSL_RSA *rsa, WOLFSSL_BIGNUM *dmp1,
- WOLFSSL_BIGNUM *dmq1, WOLFSSL_BIGNUM *iqmp)
-{
- int ret = 1;
-
- WOLFSSL_ENTER("wolfSSL_RSA_set0_crt_params");
-
- /* If a param is NULL in rsa then it must be non-NULL in the
- * corresponding user input. */
- if ((rsa == NULL) || ((rsa->dmp1 == NULL) && (dmp1 == NULL)) ||
- ((rsa->dmq1 == NULL) && (dmq1 == NULL)) ||
- ((rsa->iqmp == NULL) && (iqmp == NULL))) {
- WOLFSSL_ERROR_MSG("Bad parameters");
- ret = 0;
- }
- if (ret == 1) {
- /* Replace the BNs. */
- if (dmp1 != NULL) {
- wolfSSL_BN_clear_free(rsa->dmp1);
- rsa->dmp1 = dmp1;
- }
- if (dmq1 != NULL) {
- wolfSSL_BN_clear_free(rsa->dmq1);
- rsa->dmq1 = dmq1;
- }
- if (iqmp != NULL) {
- wolfSSL_BN_clear_free(rsa->iqmp);
- rsa->iqmp = iqmp;
- }
-
- /* Set the values into the wolfCrypt RSA key. */
- if (SetRsaInternal(rsa) != 1) {
- if (dmp1 != NULL) {
- rsa->dmp1 = NULL;
- }
- if (dmq1 != NULL) {
- rsa->dmq1 = NULL;
- }
- if (iqmp != NULL) {
- rsa->iqmp = NULL;
- }
- ret = 0;
- }
- }
-
- return ret;
-}
-
-/* Get the BN objects that are the factors of the RSA key (two primes p and q).
- *
- * @param [in] rsa RSA key.
- * @param [out] p BN that is first prime. May be NULL.
- * @param [out] q BN that is second prime. May be NULL.
- */
-void wolfSSL_RSA_get0_factors(const WOLFSSL_RSA *rsa, const WOLFSSL_BIGNUM **p,
- const WOLFSSL_BIGNUM **q)
-{
- WOLFSSL_ENTER("wolfSSL_RSA_get0_factors");
-
- /* For any primes not NULL, return the BN from the key or NULL. */
- if (p != NULL) {
- *p = (rsa != NULL) ? rsa->p : NULL;
- }
- if (q != NULL) {
- *q = (rsa != NULL) ? rsa->q : NULL;
- }
-}
-
-/* Set the BN objects that are the factors of the RSA key (two primes p and q).
- *
- * If factor parameter is NULL then there must be one in the RSA key already.
- *
- * @param [in, out] rsa RSA key.
- * @param [in] p BN that is first prime. May be NULL.
- * @param [in] q BN that is second prime. May be NULL.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_RSA_set0_factors(WOLFSSL_RSA *rsa, WOLFSSL_BIGNUM *p,
- WOLFSSL_BIGNUM *q)
-{
- int ret = 1;
-
- WOLFSSL_ENTER("wolfSSL_RSA_set0_factors");
-
- /* If a param is null in r then it must be non-null in the
- * corresponding user input. */
- if (rsa == NULL || ((rsa->p == NULL) && (p == NULL)) ||
- ((rsa->q == NULL) && (q == NULL))) {
- WOLFSSL_ERROR_MSG("Bad parameters");
- ret = 0;
- }
- if (ret == 1) {
- /* Replace the BNs. */
- if (p != NULL) {
- wolfSSL_BN_clear_free(rsa->p);
- rsa->p = p;
- }
- if (q != NULL) {
- wolfSSL_BN_clear_free(rsa->q);
- rsa->q = q;
- }
-
- /* Set the values into the wolfCrypt RSA key. */
- if (SetRsaInternal(rsa) != 1) {
- if (p != NULL) {
- rsa->p = NULL;
- }
- if (q != NULL) {
- rsa->q = NULL;
- }
- ret = 0;
- }
- }
-
- return ret;
-}
-
-/* Get the BN objects for the basic key numbers of the RSA key (modulus, public
- * exponent, private exponent).
- *
- * @param [in] rsa RSA key.
- * @param [out] n BN that is the modulus. May be NULL.
- * @param [out] e BN that is the public exponent. May be NULL.
- * @param [out] d BN that is the private exponent. May be NULL.
- */
-void wolfSSL_RSA_get0_key(const WOLFSSL_RSA *rsa, const WOLFSSL_BIGNUM **n,
- const WOLFSSL_BIGNUM **e, const WOLFSSL_BIGNUM **d)
-{
- WOLFSSL_ENTER("wolfSSL_RSA_get0_key");
-
- /* For any parameters not NULL, return the BN from the key or NULL. */
- if (n != NULL) {
- *n = (rsa != NULL) ? rsa->n : NULL;
- }
- if (e != NULL) {
- *e = (rsa != NULL) ? rsa->e : NULL;
- }
- if (d != NULL) {
- *d = (rsa != NULL) ? rsa->d : NULL;
- }
-}
-
-/* Set the BN objects for the basic key numbers into the RSA key (modulus,
- * public exponent, private exponent).
- *
- * If BN parameter is NULL then there must be one in the RSA key already.
- *
- * @param [in,out] rsa RSA key.
- * @param [in] n BN that is the modulus. May be NULL.
- * @param [in] e BN that is the public exponent. May be NULL.
- * @param [in] d BN that is the private exponent. May be NULL.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_RSA_set0_key(WOLFSSL_RSA *rsa, WOLFSSL_BIGNUM *n, WOLFSSL_BIGNUM *e,
- WOLFSSL_BIGNUM *d)
-{
- int ret = 1;
-
- /* If the fields n and e in r are NULL, the corresponding input
- * parameters MUST be non-NULL for n and e. d may be
- * left NULL (in case only the public key is used).
- */
- if ((rsa == NULL) || ((rsa->n == NULL) && (n == NULL)) ||
- ((rsa->e == NULL) && (e == NULL))) {
- ret = 0;
- }
- if (ret == 1) {
- /* Replace the BNs. */
- if (n != NULL) {
- wolfSSL_BN_free(rsa->n);
- rsa->n = n;
- }
- if (e != NULL) {
- wolfSSL_BN_free(rsa->e);
- rsa->e = e;
- }
- if (d != NULL) {
- /* Private key is sensitive data. */
- wolfSSL_BN_clear_free(rsa->d);
- rsa->d = d;
- }
-
- /* Set the values into the wolfCrypt RSA key. */
- if (SetRsaInternal(rsa) != 1) {
- if (n != NULL) {
- rsa->n = NULL;
- }
- if (e != NULL) {
- rsa->e = NULL;
- }
- if (d != NULL) {
- rsa->d = NULL;
- }
- ret = 0;
- }
- }
-
- return ret;
-}
-
-/* Get the flags of the RSA key.
- *
- * @param [in] rsa RSA key.
- * @return Flags set in RSA key on success.
- * @return 0 when RSA key is NULL.
- */
-int wolfSSL_RSA_flags(const WOLFSSL_RSA *rsa)
-{
- int ret = 0;
-
- /* Get flags from the RSA key if available. */
- if (rsa != NULL) {
- ret = rsa->flags;
- }
-
- return ret;
-}
-
-/* Set the flags into the RSA key.
- *
- * @param [in, out] rsa RSA key.
- * @param [in] flags Flags to set.
- */
-void wolfSSL_RSA_set_flags(WOLFSSL_RSA *rsa, int flags)
-{
- /* Add the flags into RSA key if available. */
- if (rsa != NULL) {
- rsa->flags |= flags;
- }
-}
-
-/* Clear the flags in the RSA key.
- *
- * @param [in, out] rsa RSA key.
- * @param [in] flags Flags to clear.
- */
-void wolfSSL_RSA_clear_flags(WOLFSSL_RSA *rsa, int flags)
-{
- /* Clear the flags passed in that are on the RSA key if available. */
- if (rsa != NULL) {
- rsa->flags &= ~flags;
- }
-}
-
-/* Test the flags in the RSA key.
- *
- * @param [in] rsa RSA key.
- * @return Matching flags of RSA key on success.
- * @return 0 when RSA key is NULL.
- */
-int wolfSSL_RSA_test_flags(const WOLFSSL_RSA *rsa, int flags)
-{
- /* Return the flags passed in that are set on the RSA key if available. */
- return (rsa != NULL) ? (rsa->flags & flags) : 0;
-}
-
-/* Get the extra data, by index, associated with the RSA key.
- *
- * @param [in] rsa RSA key.
- * @param [in] idx Index of extra data.
- * @return Extra data (anonymous type) on success.
- * @return NULL on failure.
- */
-void* wolfSSL_RSA_get_ex_data(const WOLFSSL_RSA *rsa, int idx)
-{
- WOLFSSL_ENTER("wolfSSL_RSA_get_ex_data");
-
-#ifdef HAVE_EX_DATA
- return (rsa == NULL) ? NULL :
- wolfSSL_CRYPTO_get_ex_data(&rsa->ex_data, idx);
-#else
- (void)rsa;
- (void)idx;
-
- return NULL;
-#endif
-}
-
-/* Set extra data against the RSA key at an index.
- *
- * @param [in, out] rsa RSA key.
- * @param [in] idx Index set set extra data at.
- * @param [in] data Extra data of anonymous type.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_RSA_set_ex_data(WOLFSSL_RSA *rsa, int idx, void *data)
-{
- WOLFSSL_ENTER("wolfSSL_RSA_set_ex_data");
-
-#ifdef HAVE_EX_DATA
- return (rsa == NULL) ? 0 :
- wolfSSL_CRYPTO_set_ex_data(&rsa->ex_data, idx, data);
-#else
- (void)rsa;
- (void)idx;
- (void)data;
-
- return 0;
-#endif
-}
-
-#ifdef HAVE_EX_DATA_CLEANUP_HOOKS
-/* Set the extra data and cleanup callback against the RSA key at an index.
- *
- * Not OpenSSL API.
- *
- * @param [in, out] rsa RSA key.
- * @param [in] idx Index set set extra data at.
- * @param [in] data Extra data of anonymous type.
- * @param [in] freeCb Callback function to free extra data.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_RSA_set_ex_data_with_cleanup(WOLFSSL_RSA *rsa, int idx, void *data,
- wolfSSL_ex_data_cleanup_routine_t freeCb)
-{
- WOLFSSL_ENTER("wolfSSL_RSA_set_ex_data_with_cleanup");
-
- return (rsa == NULL) ? 0 :
- wolfSSL_CRYPTO_set_ex_data_with_cleanup(&rsa->ex_data, idx, data,
- freeCb);
-}
-#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */
-
-/*
- * RSA check key APIs
- */
-
-#ifdef WOLFSSL_RSA_KEY_CHECK
-/* Check that the RSA key is valid using wolfCrypt.
- *
- * @param [in] rsa RSA key.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_RSA_check_key(const WOLFSSL_RSA* rsa)
-{
- int ret = 1;
-
- WOLFSSL_ENTER("wolfSSL_RSA_check_key");
-
- /* Validate parameters. */
- if ((rsa == NULL) || (rsa->internal == NULL)) {
- ret = 0;
- }
-
- /* Constant RSA - assume internal data has been set. */
-
- /* Check wolfCrypt RSA key. */
- if ((ret == 1) && (wc_CheckRsaKey((RsaKey*)rsa->internal) != 0)) {
- ret = 0;
- }
-
- WOLFSSL_LEAVE("wolfSSL_RSA_check_key", ret);
-
- return ret;
-}
-#endif /* WOLFSSL_RSA_KEY_CHECK */
-
-/*
- * RSA generate APIs
- */
-
-/* Get a random number generator associated with the RSA key.
- *
- * If not able, then get the global if possible.
- * *tmpRng must not be an initialized RNG.
- * *tmpRng is allocated when WOLFSSL_SMALL_STACK is defined and an RNG isn't
- * associated with the wolfCrypt RSA key.
- *
- * @param [in] rsa RSA key.
- * @param [out] tmpRng Temporary random number generator.
- * @param [out] initTmpRng Temporary random number generator was initialized.
- *
- * @return A wolfCrypt RNG to use on success.
- * @return NULL on error.
- */
-WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA* rsa, WC_RNG** tmpRng, int* initTmpRng)
-{
- WC_RNG* rng = NULL;
- int err = 0;
-
- /* Check validity of parameters. */
- if ((rsa == NULL) || (initTmpRng == NULL)) {
- err = 1;
- }
- if (!err) {
- /* Haven't initialized any RNG passed through tmpRng. */
- *initTmpRng = 0;
-
- #if !defined(HAVE_FIPS) && defined(WC_RSA_BLINDING)
- /* Use wolfCrypt RSA key's RNG if available/set. */
- rng = ((RsaKey*)rsa->internal)->rng;
- #endif
- }
- if ((!err) && (rng == NULL) && (tmpRng != NULL)) {
- /* Make an RNG with tmpRng or get global. */
- rng = wolfssl_make_rng(*tmpRng, initTmpRng);
- if ((rng != NULL) && *initTmpRng) {
- *tmpRng = rng;
- }
- }
-
- return rng;
-}
-
-/* Use the wolfCrypt RSA APIs to generate a new RSA key.
- *
- * @param [in, out] rsa RSA key.
- * @param [in] bits Number of bits that the modulus must have.
- * @param [in] e A BN object holding the public exponent to use.
- * @param [in] cb Status callback. Unused.
- * @return 0 on success.
- * @return wolfSSL native error code on error.
- */
-static int wolfssl_rsa_generate_key_native(WOLFSSL_RSA* rsa, int bits,
- WOLFSSL_BIGNUM* e, void* cb)
-{
-#ifdef WOLFSSL_KEY_GEN
- int ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
- WC_RNG* tmpRng = NULL;
-#else
- WC_RNG _tmpRng[1];
- WC_RNG* tmpRng = _tmpRng;
-#endif
- int initTmpRng = 0;
- WC_RNG* rng = NULL;
- long en = 0;
-#endif
-
- (void)cb;
-
- WOLFSSL_ENTER("wolfssl_rsa_generate_key_native");
-
-#ifdef WOLFSSL_KEY_GEN
- /* Get RNG in wolfCrypt RSA key or initialize a new one (or global). */
- rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
- if (rng == NULL) {
- /* Something went wrong so return memory error. */
- ret = MEMORY_E;
- }
- if ((ret == 0) && ((en = (long)wolfSSL_BN_get_word(e)) <= 0)) {
- ret = BAD_FUNC_ARG;
- }
- if (ret == 0) {
- /* Generate an RSA key. */
- ret = wc_MakeRsaKey((RsaKey*)rsa->internal, bits, en, rng);
- if (ret != MP_OKAY) {
- WOLFSSL_ERROR_MSG("wc_MakeRsaKey failed");
- }
- }
- if (ret == 0) {
- /* Get the values from wolfCrypt RSA key into external RSA key. */
- ret = SetRsaExternal(rsa);
- if (ret == 1) {
- /* Internal matches external. */
- rsa->inSet = 1;
- /* Return success. */
- ret = 0;
- }
- else {
- /* Something went wrong so return memory error. */
- ret = MEMORY_E;
- }
- }
-
- /* Finalize RNG if initialized in WOLFSSL_RSA_GetRNG(). */
- if (initTmpRng) {
- wc_FreeRng(tmpRng);
- }
- WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
-
- return ret;
-#else
- WOLFSSL_ERROR_MSG("No Key Gen built in");
-
- (void)rsa;
- (void)e;
- (void)bits;
-
- return NOT_COMPILED_IN;
-#endif
-}
-
-/* Generate an RSA key that has the specified modulus size and public exponent.
- *
- * Note: Because of wc_MakeRsaKey an RSA key size generated can be rounded
- * down to nearest multiple of 8. For example generating a key of size
- * 2999 bits will make a key of size 374 bytes instead of 375 bytes.
- *
- * @param [in] bits Number of bits that the modulus must have i.e. 2048.
- * @param [in] e Public exponent to use i.e. 65537.
- * @param [in] cb Status callback. Unused.
- * @param [in] data Data to pass to status callback. Unused.
- * @return A new RSA key on success.
- * @return NULL on failure.
- */
-WOLFSSL_RSA* wolfSSL_RSA_generate_key(int bits, unsigned long e,
- void(*cb)(int, int, void*), void* data)
-{
- WOLFSSL_RSA* rsa = NULL;
- WOLFSSL_BIGNUM* bn = NULL;
- int err = 0;
-
- WOLFSSL_ENTER("wolfSSL_RSA_generate_key");
-
- (void)cb;
- (void)data;
-
- /* Validate bits. */
- if (bits < 0) {
- WOLFSSL_ERROR_MSG("Bad argument: bits was less than 0");
- err = 1;
- }
- /* Create a new BN to hold public exponent - for when wolfCrypt supports
- * longer values. */
- if ((!err) && ((bn = wolfSSL_BN_new()) == NULL)) {
- WOLFSSL_ERROR_MSG("Error creating big number");
- err = 1;
- }
- /* Set public exponent. */
- if ((!err) && (wolfSSL_BN_set_word(bn, e) != 1)) {
- WOLFSSL_ERROR_MSG("Error using e value");
- err = 1;
- }
-
- /* Create an RSA key object to hold generated key. */
- if ((!err) && ((rsa = wolfSSL_RSA_new()) == NULL)) {
- WOLFSSL_ERROR_MSG("memory error");
- err = 1;
- }
- while (!err) {
- int ret;
-
- /* Use wolfCrypt to generate RSA key. */
- ret = wolfssl_rsa_generate_key_native(rsa, bits, bn, NULL);
- #ifdef HAVE_FIPS
- /* Keep trying if failed to find a prime. */
- if (ret == WC_NO_ERR_TRACE(PRIME_GEN_E)) {
- continue;
- }
- #endif
- if (ret != WOLFSSL_ERROR_NONE) {
- /* Unrecoverable error in generation. */
- err = 1;
- }
- /* Done generating - unrecoverable error or success. */
- break;
- }
- if (err) {
- /* Dispose of RSA key object if generation didn't work. */
- wolfSSL_RSA_free(rsa);
- /* Returning NULL on error. */
- rsa = NULL;
- }
- /* Dispose of the temporary BN used for the public exponent. */
- wolfSSL_BN_free(bn);
-
- return rsa;
-}
-
-/* Generate an RSA key that has the specified modulus size and public exponent.
- *
- * Note: Because of wc_MakeRsaKey an RSA key size generated can be rounded
- * down to nearest multiple of 8. For example generating a key of size
- * 2999 bits will make a key of size 374 bytes instead of 375 bytes.
- *
- * @param [in] bits Number of bits that the modulus must have i.e. 2048.
- * @param [in] e Public exponent to use, i.e. 65537, as a BN.
- * @param [in] cb Status callback. Unused.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* e,
- void* cb)
-{
- int ret = 1;
-
- /* Validate parameters. */
- if ((rsa == NULL) || (rsa->internal == NULL)) {
- WOLFSSL_ERROR_MSG("bad arguments");
- ret = 0;
- }
- else {
- for (;;) {
- /* Use wolfCrypt to generate RSA key. */
- int gen_ret = wolfssl_rsa_generate_key_native(rsa, bits, e, cb);
- #ifdef HAVE_FIPS
- /* Keep trying again if public key value didn't work. */
- if (gen_ret == WC_NO_ERR_TRACE(PRIME_GEN_E)) {
- continue;
- }
- #endif
- if (gen_ret != WOLFSSL_ERROR_NONE) {
- /* Unrecoverable error in generation. */
- ret = 0;
- }
- /* Done generating - unrecoverable error or success. */
- break;
- }
- }
-
- return ret;
-}
-
-#endif /* OPENSSL_EXTRA */
-
-/*
- * RSA padding APIs
- */
-
-#ifdef WC_RSA_PSS
-
-#if defined(OPENSSL_EXTRA) && !defined(HAVE_SELFTEST) && \
- (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
-static int rsa_pss_calc_salt(int saltLen, int hashLen, int emLen)
-{
- /* Calculate the salt length to use for special cases. */
- switch (saltLen) {
- /* Negative saltLen values are treated differently. */
- case WC_RSA_PSS_SALTLEN_DIGEST:
- saltLen = hashLen;
- break;
- case WC_RSA_PSS_SALTLEN_MAX_SIGN:
- case WC_RSA_PSS_SALTLEN_MAX:
- #ifdef WOLFSSL_PSS_LONG_SALT
- saltLen = emLen - hashLen - 2;
- #else
- saltLen = hashLen;
- (void)emLen;
- #endif
- break;
- default:
- break;
- }
- if (saltLen < 0) {
- /* log invalid salt, let wolfCrypt handle error */
- WOLFSSL_ERROR_MSG("invalid saltLen");
- saltLen = -3; /* for wolfCrypt to produce error must be < -2 */
- }
- return saltLen;
-}
-#endif /* OPENSSL_EXTRA && !HAVE_SELFTEST */
-
-#if (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \
- defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX)) && \
- (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
-
-/* Add PKCS#1 PSS padding to hash.
- *
- *
- * +-----------+
- * | M |
- * +-----------+
- * |
- * V
- * Hash
- * |
- * V
- * +--------+----------+----------+
- * M' = |Padding1| mHash | salt |
- * +--------+----------+----------+
- * |
- * +--------+----------+ V
- * DB = |Padding2|maskedseed| Hash
- * +--------+----------+ |
- * | |
- * V | +--+
- * xor <--- MGF <---| |bc|
- * | | +--+
- * | | |
- * V V V
- * +-------------------+----------+--+
- * EM = | maskedDB |maskedseed|bc|
- * +-------------------+----------+--+
- * Diagram taken from https://tools.ietf.org/html/rfc3447#section-9.1
- *
- * @param [in] rsa RSA key.
- * @param [out] em Encoded message.
- * @param [in[ mHash Message hash.
- * @param [in] hashAlg Hash algorithm.
- * @param [in] mgf1Hash MGF algorithm.
- * @param [in] saltLen Length of salt to generate.
- * @return 1 on success.
- * @return 0 on failure.
- */
-
-int wolfSSL_RSA_padding_add_PKCS1_PSS_mgf1(WOLFSSL_RSA *rsa, unsigned char *em,
- const unsigned char *mHash, const WOLFSSL_EVP_MD *hashAlg,
- const WOLFSSL_EVP_MD *mgf1Hash, int saltLen)
-{
- int ret = 1;
- enum wc_HashType hashType = WC_HASH_TYPE_NONE;
- int hashLen = 0;
- int emLen = 0;
- int mgf = 0;
- int initTmpRng = 0;
- WC_RNG *rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- WC_RNG* tmpRng = NULL;
-#else
- WC_RNG _tmpRng[1];
- WC_RNG* tmpRng = _tmpRng;
-#endif
-
- WOLFSSL_ENTER("wolfSSL_RSA_padding_add_PKCS1_PSS");
-
- /* Validate parameters. */
- if ((rsa == NULL) || (em == NULL) || (mHash == NULL) || (hashAlg == NULL)) {
- ret = 0;
- }
-
- if (mgf1Hash == NULL)
- mgf1Hash = hashAlg;
-
- if (ret == 1) {
- /* Get/create an RNG. */
- rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
- if (rng == NULL) {
- WOLFSSL_ERROR_MSG("WOLFSSL_RSA_GetRNG error");
- ret = 0;
- }
- }
-
- /* TODO: use wolfCrypt RSA key to get emLen and bits? */
- /* Set the external data from the wolfCrypt RSA key if not done. */
- if ((ret == 1) && (!rsa->exSet)) {
- ret = SetRsaExternal(rsa);
- }
-
- if (ret == 1) {
- /* Get the wolfCrypt hash algorithm type. */
- hashType = EvpMd2MacType(hashAlg);
- if (hashType > WC_HASH_TYPE_MAX) {
- WOLFSSL_ERROR_MSG("EvpMd2MacType error");
- ret = 0;
- }
- }
- if (ret == 1) {
- /* Get the wolfCrypt MGF algorithm from hash algorithm. */
- mgf = wc_hash2mgf(EvpMd2MacType(mgf1Hash));
- if (mgf == WC_MGF1NONE) {
- WOLFSSL_ERROR_MSG("wc_hash2mgf error");
- ret = 0;
- }
- }
- if (ret == 1) {
- /* Get the length of the hash output. */
- hashLen = wolfSSL_EVP_MD_size(hashAlg);
- if (hashLen < 0) {
- WOLFSSL_ERROR_MSG("wolfSSL_EVP_MD_size error");
- ret = 0;
- }
- }
-
- if (ret == 1) {
- /* Get length of RSA key - encrypted message length. */
- emLen = wolfSSL_RSA_size(rsa);
- if (emLen <= 0) {
- WOLFSSL_ERROR_MSG("wolfSSL_RSA_size error");
- ret = 0;
- }
- }
-
- if (ret == 1) {
- saltLen = rsa_pss_calc_salt(saltLen, hashLen, emLen);
- }
-
- if (ret == 1) {
- /* Generate RSA PKCS#1 PSS padding for hash using wolfCrypt. */
- if (wc_RsaPad_ex(mHash, (word32)hashLen, em, (word32)emLen,
- RSA_BLOCK_TYPE_1, rng, WC_RSA_PSS_PAD, hashType, mgf, NULL, 0,
- saltLen, wolfSSL_BN_num_bits(rsa->n), NULL) != MP_OKAY) {
- WOLFSSL_ERROR_MSG("wc_RsaPad_ex error");
- ret = 0;
- }
- }
-
- /* Finalize RNG if initialized in WOLFSSL_RSA_GetRNG(). */
- if (initTmpRng) {
- wc_FreeRng(tmpRng);
- }
- WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
-
- return ret;
-}
-
-int wolfSSL_RSA_padding_add_PKCS1_PSS(WOLFSSL_RSA *rsa, unsigned char *em,
- const unsigned char *mHash, const WOLFSSL_EVP_MD *hashAlg, int saltLen)
-{
- return wolfSSL_RSA_padding_add_PKCS1_PSS_mgf1(rsa, em, mHash, hashAlg, NULL,
- saltLen);
-}
-
-/* Checks that the hash is valid for the RSA PKCS#1 PSS encoded message.
- *
- * Refer to wolfSSL_RSA_padding_add_PKCS1_PSS for a diagram.
- *
- * @param [in] rsa RSA key.
- * @param [in[ mHash Message hash.
- * @param [in] hashAlg Hash algorithm.
- * @param [in] mgf1Hash MGF algorithm.
- * @param [in] em Encoded message.
- * @param [in] saltLen Length of salt to generate.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_RSA_verify_PKCS1_PSS_mgf1(WOLFSSL_RSA *rsa,
- const unsigned char *mHash, const WOLFSSL_EVP_MD *hashAlg,
- const WOLFSSL_EVP_MD *mgf1Hash, const unsigned char *em, int saltLen)
-{
- int ret = 1;
- int hashLen = 0;
- int mgf = 0;
- int emLen = 0;
- int mPrimeLen = 0;
- enum wc_HashType hashType = WC_HASH_TYPE_NONE;
- byte *mPrime = NULL;
- byte *buf = NULL;
-
- WOLFSSL_ENTER("wolfSSL_RSA_verify_PKCS1_PSS");
-
- /* Validate parameters. */
- if ((rsa == NULL) || (mHash == NULL) || (hashAlg == NULL) || (em == NULL)) {
- ret = 0;
- }
-
- if (mgf1Hash == NULL)
- mgf1Hash = hashAlg;
-
- /* TODO: use wolfCrypt RSA key to get emLen and bits? */
- /* Set the external data from the wolfCrypt RSA key if not done. */
- if ((ret == 1) && (!rsa->exSet)) {
- ret = SetRsaExternal(rsa);
- }
-
- if (ret == 1) {
- /* Get hash length for hash algorithm. */
- hashLen = wolfSSL_EVP_MD_size(hashAlg);
- if (hashLen < 0) {
- ret = 0;
- }
- }
-
- if (ret == 1) {
- /* Get length of RSA key - encrypted message length. */
- emLen = wolfSSL_RSA_size(rsa);
- if (emLen <= 0) {
- WOLFSSL_ERROR_MSG("wolfSSL_RSA_size error");
- ret = 0;
- }
- }
-
- if (ret == 1) {
- saltLen = rsa_pss_calc_salt(saltLen, hashLen, emLen);
- }
-
- if (ret == 1) {
- /* Get the wolfCrypt hash algorithm type. */
- hashType = EvpMd2MacType(hashAlg);
- if (hashType > WC_HASH_TYPE_MAX) {
- WOLFSSL_ERROR_MSG("EvpMd2MacType error");
- ret = 0;
- }
- }
-
- if (ret == 1) {
- /* Get the wolfCrypt MGF algorithm from hash algorithm. */
- if ((mgf = wc_hash2mgf(EvpMd2MacType(mgf1Hash))) == WC_MGF1NONE) {
- WOLFSSL_ERROR_MSG("wc_hash2mgf error");
- ret = 0;
- }
- }
-
- if (ret == 1) {
- /* Allocate buffer to unpad inline with. */
- buf = (byte*)XMALLOC((size_t)emLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (buf == NULL) {
- WOLFSSL_ERROR_MSG("malloc error");
- ret = 0;
- }
- }
-
- if (ret == 1) {
- /* Copy encrypted message to temp for inline unpadding. */
- XMEMCPY(buf, em, (size_t)emLen);
-
- /* Remove and verify the PSS padding. */
- mPrimeLen = wc_RsaUnPad_ex(buf, (word32)emLen, &mPrime,
- RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD, hashType, mgf, NULL, 0, saltLen,
- wolfSSL_BN_num_bits(rsa->n), NULL);
- if (mPrimeLen < 0) {
- WOLFSSL_ERROR_MSG("wc_RsaPad_ex error");
- ret = 0;
- }
- }
-
- if (ret == 1) {
- /* Verify the hash is correct. */
- if (wc_RsaPSS_CheckPadding_ex(mHash, (word32)hashLen, mPrime,
- (word32)mPrimeLen, hashType, saltLen,
- wolfSSL_BN_num_bits(rsa->n)) != MP_OKAY) {
- WOLFSSL_ERROR_MSG("wc_RsaPSS_CheckPadding_ex error");
- ret = 0;
- }
- }
-
- /* Dispose of any allocated buffer. */
- XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
-}
-
-int wolfSSL_RSA_verify_PKCS1_PSS(WOLFSSL_RSA *rsa, const unsigned char *mHash,
- const WOLFSSL_EVP_MD *hashAlg,
- const unsigned char *em, int saltLen)
-{
- return wolfSSL_RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, hashAlg, NULL, em,
- saltLen);
-}
-#endif /* (!HAVE_FIPS || FIPS_VERSION_GT(2,0)) && \
- (OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_NGINX) */
-#endif /* WC_RSA_PSS */
-
-/*
- * RSA sign/verify APIs
- */
-
-#if defined(WC_RSA_PSS) && !defined(HAVE_SELFTEST) && \
- (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,1))
- #ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER
- #define DEF_PSS_SALT_LEN RSA_PSS_SALT_LEN_DEFAULT
- #else
- #define DEF_PSS_SALT_LEN RSA_PSS_SALT_LEN_DISCOVER
- #endif
-#else
- #define DEF_PSS_SALT_LEN 0 /* not used */
-#endif
-
-#if defined(OPENSSL_EXTRA)
-
-/* Encode the message hash.
- *
- * Used by signing and verification.
- *
- * @param [in] hashAlg Hash algorithm OID.
- * @param [in] hash Hash of message to encode for signing.
- * @param [in] hLen Length of hash of message.
- * @param [out] enc Encoded message hash.
- * @param [out] encLen Length of encoded message hash.
- * @param [in] padding Which padding scheme is being used.
- * @return 1 on success.
- * @return 0 on failure.
- */
-static int wolfssl_rsa_sig_encode(int hashAlg, const unsigned char* hash,
- unsigned int hLen, unsigned char* enc, unsigned int* encLen, int padding)
-{
- int ret = 1;
- int hType = WC_HASH_TYPE_NONE;
-
- /* Validate parameters. */
- if ((hash == NULL) || (enc == NULL) || (encLen == NULL)) {
- ret = 0;
- }
-
- if ((ret == 1) && (hashAlg != WC_NID_undef) &&
- (padding == WC_RSA_PKCS1_PADDING)) {
- /* Convert hash algorithm to hash type for PKCS#1.5 padding. */
- hType = (int)nid2oid(hashAlg, oidHashType);
- if (hType == -1) {
- ret = 0;
- }
- }
- if ((ret == 1) && (padding == WC_RSA_PKCS1_PADDING)) {
- /* PKCS#1.5 encoding. */
- word32 encSz = wc_EncodeSignature(enc, hash, hLen, hType);
- if (encSz == 0) {
- WOLFSSL_ERROR_MSG("Bad Encode Signature");
- ret = 0;
- }
- else {
- *encLen = (unsigned int)encSz;
- }
- }
- /* Other padding schemes require the hash as is. */
- if ((ret == 1) && (padding != WC_RSA_PKCS1_PADDING)) {
- XMEMCPY(enc, hash, hLen);
- *encLen = hLen;
- }
-
- return ret;
-}
-
-/* Sign the message hash using hash algorithm and RSA key.
- *
- * @param [in] hashAlg Hash algorithm OID.
- * @param [in] hash Hash of message to encode for signing.
- * @param [in] hLen Length of hash of message.
- * @param [out] enc Encoded message hash.
- * @param [out] encLen Length of encoded message hash.
- * @param [in] rsa RSA key.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_RSA_sign(int hashAlg, const unsigned char* hash, unsigned int hLen,
- unsigned char* sigRet, unsigned int* sigLen, WOLFSSL_RSA* rsa)
-{
- if (sigLen != NULL) {
- /* No size checking in this API */
- *sigLen = RSA_MAX_SIZE / CHAR_BIT;
- }
- /* flag is 1: output complete signature. */
- return wolfSSL_RSA_sign_generic_padding(hashAlg, hash, hLen, sigRet,
- sigLen, rsa, 1, WC_RSA_PKCS1_PADDING);
-}
-
-/* Sign the message hash using hash algorithm and RSA key.
- *
- * Not OpenSSL API.
- *
- * @param [in] hashAlg Hash algorithm NID.
- * @param [in] hash Hash of message to encode for signing.
- * @param [in] hLen Length of hash of message.
- * @param [out] enc Encoded message hash.
- * @param [out] encLen Length of encoded message hash.
- * @param [in] rsa RSA key.
- * @param [in] flag When 1: Output encrypted signature.
- * When 0: Output encoded hash.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_RSA_sign_ex(int hashAlg, const unsigned char* hash,
- unsigned int hLen, unsigned char* sigRet, unsigned int* sigLen,
- WOLFSSL_RSA* rsa, int flag)
-{
- int ret = 0;
-
- if ((flag == 0) || (flag == 1)) {
- if (sigLen != NULL) {
- /* No size checking in this API */
- *sigLen = RSA_MAX_SIZE / CHAR_BIT;
- }
- ret = wolfSSL_RSA_sign_generic_padding(hashAlg, hash, hLen, sigRet,
- sigLen, rsa, flag, WC_RSA_PKCS1_PADDING);
- }
-
- return ret;
-}
-
-int wolfSSL_RSA_sign_generic_padding(int hashAlg, const unsigned char* hash,
- unsigned int hLen, unsigned char* sigRet, unsigned int* sigLen,
- WOLFSSL_RSA* rsa, int flag, int padding)
-{
- return wolfSSL_RSA_sign_mgf(hashAlg, hash, hLen, sigRet, sigLen, rsa, flag,
- padding, hashAlg, DEF_PSS_SALT_LEN);
-}
-
-/**
- * Sign a message hash with the chosen message digest, padding, and RSA key.
- *
- * Not OpenSSL API.
- *
- * @param [in] hashAlg Hash NID
- * @param [in] hash Message hash to sign.
- * @param [in] mLen Length of message hash to sign.
- * @param [out] sigRet Output buffer.
- * @param [in, out] sigLen On Input: length of sigRet buffer.
- * On Output: length of data written to sigRet.
- * @param [in] rsa RSA key used to sign the input.
- * @param [in] flag 1: Output the signature.
- * 0: Output the value that the unpadded signature
- * should be compared to.
- * @param [in] padding Padding to use. Only RSA_PKCS1_PSS_PADDING and
- * WC_RSA_PKCS1_PADDING are currently supported for
- * signing.
- * @param [in] mgf1Hash MGF1 Hash NID
- * @param [in] saltLen Length of RSA PSS salt
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_RSA_sign_mgf(int hashAlg, const unsigned char* hash,
- unsigned int hLen, unsigned char* sigRet, unsigned int* sigLen,
- WOLFSSL_RSA* rsa, int flag, int padding, int mgf1Hash, int saltLen)
-{
- int ret = 1;
- word32 outLen = 0;
- int signSz = 0;
- WC_RNG* rng = NULL;
- int initTmpRng = 0;
-#ifdef WOLFSSL_SMALL_STACK
- WC_RNG* tmpRng = NULL;
- byte* encodedSig = NULL;
-#else
- WC_RNG _tmpRng[1];
- WC_RNG* tmpRng = _tmpRng;
- byte encodedSig[MAX_ENCODED_SIG_SZ];
-#endif
- unsigned int encSz = 0;
-
- WOLFSSL_ENTER("wolfSSL_RSA_sign_mgf");
-
- if (flag == 0) {
- /* Only encode message. */
- return wolfssl_rsa_sig_encode(hashAlg, hash, hLen, sigRet, sigLen,
- padding);
- }
-
- /* Validate parameters. */
- if ((hash == NULL) || (sigRet == NULL) || sigLen == NULL || rsa == NULL) {
- WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = 0;
- }
-
- /* Set wolfCrypt RSA key data from external if not already done. */
- if ((ret == 1) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
- ret = 0;
- }
-
- if (ret == 1) {
- /* Get the maximum signature length. */
- outLen = (word32)wolfSSL_BN_num_bytes(rsa->n);
- /* Check not an error return. */
- if (outLen == 0) {
- WOLFSSL_ERROR_MSG("Bad RSA size");
- ret = 0;
- }
- /* Check signature buffer is big enough. */
- else if (outLen > *sigLen) {
- WOLFSSL_ERROR_MSG("Output buffer too small");
- ret = 0;
- }
- }
-
-#ifdef WOLFSSL_SMALL_STACK
- if (ret == 1) {
- /* Allocate encoded signature buffer if doing PKCS#1 padding. */
- encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
- DYNAMIC_TYPE_SIGNATURE);
- if (encodedSig == NULL) {
- ret = 0;
- }
- }
-#endif
-
- if (ret == 1) {
- /* Get/create an RNG. */
- rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
- if (rng == NULL) {
- WOLFSSL_ERROR_MSG("WOLFSSL_RSA_GetRNG error");
- ret = 0;
- }
- }
-
- /* Either encodes with PKCS#1.5 or copies hash into encodedSig. */
- if ((ret == 1) && (wolfssl_rsa_sig_encode(hashAlg, hash, hLen, encodedSig,
- &encSz, padding) == 0)) {
- WOLFSSL_ERROR_MSG("Bad Encode Signature");
- ret = 0;
- }
-
- if (ret == 1) {
- switch (padding) {
- #if defined(WC_RSA_NO_PADDING) || defined(WC_RSA_DIRECT)
- case WC_RSA_NO_PAD:
- if ((signSz = wc_RsaDirect(encodedSig, encSz, sigRet, &outLen,
- (RsaKey*)rsa->internal, RSA_PRIVATE_ENCRYPT, rng)) <= 0) {
- WOLFSSL_ERROR_MSG("Bad RSA Sign no pad");
- ret = 0;
- }
- break;
- #endif
- #if defined(WC_RSA_PSS) && !defined(HAVE_SELFTEST) && \
- (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,1))
- case WC_RSA_PKCS1_PSS_PADDING:
- {
- RsaKey* key = (RsaKey*)rsa->internal;
- enum wc_HashType mgf1, hType;
- hType = wc_OidGetHash((int)nid2oid(hashAlg, oidHashType));
- if (mgf1Hash == WC_NID_undef)
- mgf1Hash = hashAlg;
- mgf1 = wc_OidGetHash((int)nid2oid(mgf1Hash, oidHashType));
- /* handle compat layer salt special cases */
- saltLen = rsa_pss_calc_salt(saltLen, wc_HashGetDigestSize(hType),
- wolfSSL_RSA_size(rsa));
-
- /* Create RSA PSS signature. */
- if ((signSz = wc_RsaPSS_Sign_ex(encodedSig, encSz, sigRet, outLen,
- hType, wc_hash2mgf(mgf1), saltLen, key, rng)) <= 0) {
- WOLFSSL_ERROR_MSG("Bad RSA PSS Sign");
- ret = 0;
- }
- break;
- }
- #endif
- #ifndef WC_NO_RSA_OAEP
- case WC_RSA_PKCS1_OAEP_PADDING:
- /* Not a signature padding scheme. */
- WOLFSSL_ERROR_MSG("RSA_PKCS1_OAEP_PADDING not supported for "
- "signing");
- ret = 0;
- break;
- #endif
- case WC_RSA_PKCS1_PADDING:
- {
- /* Sign (private encrypt) PKCS#1 encoded signature. */
- if ((signSz = wc_RsaSSL_Sign(encodedSig, encSz, sigRet, outLen,
- (RsaKey*)rsa->internal, rng)) <= 0) {
- WOLFSSL_ERROR_MSG("Bad PKCS1 RSA Sign");
- ret = 0;
- }
- break;
- }
- default:
- WOLFSSL_ERROR_MSG("Unsupported padding");
- (void)mgf1Hash;
- (void)saltLen;
- ret = 0;
- break;
- }
- }
-
- if (ret == 1) {
- /* Return the size of signature generated. */
- *sigLen = (unsigned int)signSz;
- }
-
- /* Finalize RNG if initialized in WOLFSSL_RSA_GetRNG(). */
- if (initTmpRng) {
- wc_FreeRng(tmpRng);
- }
- WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
- WC_FREE_VAR_EX(encodedSig, NULL, DYNAMIC_TYPE_SIGNATURE);
-
- WOLFSSL_LEAVE("wolfSSL_RSA_sign_mgf", ret);
- return ret;
-}
-
-/**
- * Verify a message hash with the chosen message digest, padding, and RSA key.
- *
- * @param [in] hashAlg Hash NID
- * @param [in] hash Message hash.
- * @param [in] mLen Length of message hash.
- * @param [in] sigRet Signature data.
- * @param [in] sigLen Length of signature data.
- * @param [in] rsa RSA key used to sign the input
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_RSA_verify(int hashAlg, const unsigned char* hash,
- unsigned int hLen, const unsigned char* sig, unsigned int sigLen,
- WOLFSSL_RSA* rsa)
-{
- return wolfSSL_RSA_verify_ex(hashAlg, hash, hLen, sig, sigLen, rsa,
- WC_RSA_PKCS1_PADDING);
-}
-
-int wolfSSL_RSA_verify_ex(int hashAlg, const unsigned char* hash,
- unsigned int hLen, const unsigned char* sig, unsigned int sigLen,
- WOLFSSL_RSA* rsa, int padding)
-{
- return wolfSSL_RSA_verify_mgf(hashAlg, hash, hLen, sig, sigLen, rsa,
- padding, hashAlg, DEF_PSS_SALT_LEN);
-}
-
-/**
- * Verify a message hash with the chosen message digest, padding, and RSA key.
- *
- * Not OpenSSL API.
- *
- * @param [in] hashAlg Hash NID
- * @param [in] hash Message hash.
- * @param [in] mLen Length of message hash.
- * @param [in] sigRet Signature data.
- * @param [in] sigLen Length of signature data.
- * @param [in] rsa RSA key used to sign the input
- * @param [in] padding Padding to use. Only RSA_PKCS1_PSS_PADDING and
- * WC_RSA_PKCS1_PADDING are currently supported for
- * signing.
- * @param [in] mgf1Hash MGF1 Hash NID
- * @param [in] saltLen Length of RSA PSS salt
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_RSA_verify_mgf(int hashAlg, const unsigned char* hash,
- unsigned int hLen, const unsigned char* sig, unsigned int sigLen,
- WOLFSSL_RSA* rsa, int padding, int mgf1Hash, int saltLen)
-{
- int ret = 1;
-#ifdef WOLFSSL_SMALL_STACK
- unsigned char* encodedSig = NULL;
-#else
- unsigned char encodedSig[MAX_ENCODED_SIG_SZ];
-#endif
- unsigned char* sigDec = NULL;
- unsigned int len = MAX_ENCODED_SIG_SZ;
- int verLen = 0;
-#if (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 1)) && !defined(HAVE_SELFTEST)
- enum wc_HashType hType = WC_HASH_TYPE_NONE;
-#endif
-
- WOLFSSL_ENTER("wolfSSL_RSA_verify_mgf");
-
- /* Validate parameters. */
- if ((hash == NULL) || (sig == NULL) || (rsa == NULL)) {
- WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = 0;
- }
-
- if (ret == 1) {
- /* Allocate memory for decrypted signature. */
- sigDec = (unsigned char *)XMALLOC(sigLen, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (sigDec == NULL) {
- WOLFSSL_ERROR_MSG("Memory allocation failure");
- ret = 0;
- }
- }
- if (ret == 1 && padding == WC_RSA_PKCS1_PSS_PADDING) {
- #if defined(WC_RSA_PSS) && !defined(HAVE_SELFTEST) && \
- (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,1))
- RsaKey* key = (RsaKey*)rsa->internal;
- enum wc_HashType mgf1;
- hType = wc_OidGetHash((int)nid2oid(hashAlg, oidHashType));
- if (mgf1Hash == WC_NID_undef)
- mgf1Hash = hashAlg;
- mgf1 = wc_OidGetHash((int)nid2oid(mgf1Hash, oidHashType));
-
- /* handle compat layer salt special cases */
- saltLen = rsa_pss_calc_salt(saltLen, wc_HashGetDigestSize(hType),
- wolfSSL_RSA_size(rsa));
-
- verLen = wc_RsaPSS_Verify_ex((byte*)sig, sigLen, sigDec, sigLen,
- hType, wc_hash2mgf(mgf1), saltLen, key);
- if (verLen > 0) {
- /* Check PSS padding is valid. */
- if (wc_RsaPSS_CheckPadding_ex(hash, hLen, sigDec, (word32)verLen,
- hType, saltLen, mp_count_bits(&key->n)) != 0) {
- WOLFSSL_ERROR_MSG("wc_RsaPSS_CheckPadding_ex error");
- ret = WOLFSSL_FAILURE;
- }
- else {
- /* Success! Free resources and return early */
- XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return WOLFSSL_SUCCESS;
- }
- }
- else {
- WOLFSSL_ERROR_MSG("wc_RsaPSS_Verify_ex failed!");
- ret = WOLFSSL_FAILURE;
- }
- #else
- (void)mgf1Hash;
- (void)saltLen;
- WOLFSSL_ERROR_MSG("RSA PSS not compiled in!");
- ret = WOLFSSL_FAILURE;
- #endif
- }
-
-#ifdef WOLFSSL_SMALL_STACK
- if (ret == 1) {
- /* Allocate memory for encoded signature. */
- encodedSig = (unsigned char *)XMALLOC(len, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (encodedSig == NULL) {
- WOLFSSL_ERROR_MSG("Memory allocation failure");
- ret = 0;
- }
- }
-#endif
- if (ret == 1) {
- /* Make encoded signature to compare with decrypted signature. */
- if (wolfssl_rsa_sig_encode(hashAlg, hash, hLen, encodedSig, &len,
- padding) <= 0) {
- WOLFSSL_ERROR_MSG("Message Digest Error");
- ret = 0;
- }
- }
- if (ret == 1) {
- /* Decrypt signature */
- #if (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 1)) && \
- !defined(HAVE_SELFTEST)
- hType = wc_OidGetHash((int)nid2oid(hashAlg, oidHashType));
- if ((verLen = wc_RsaSSL_Verify_ex2(sig, sigLen, (unsigned char *)sigDec,
- sigLen, (RsaKey*)rsa->internal, padding, hType)) <= 0) {
- WOLFSSL_ERROR_MSG("RSA Decrypt error");
- ret = 0;
- }
- #else
- verLen = wc_RsaSSL_Verify(sig, sigLen, (unsigned char *)sigDec, sigLen,
- (RsaKey*)rsa->internal);
- if (verLen < 0) {
- ret = 0;
- }
- #endif
- }
- if (ret == 1) {
- /* Compare decrypted signature to encoded signature. */
- if (((int)len != verLen) ||
- (XMEMCMP(encodedSig, sigDec, (size_t)verLen) != 0)) {
- WOLFSSL_ERROR_MSG("wolfSSL_RSA_verify_ex failed");
- ret = 0;
- }
- }
-
- /* Dispose of any allocated data. */
- WC_FREE_VAR_EX(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
- WOLFSSL_LEAVE("wolfSSL_RSA_verify_mgf", ret);
- return ret;
-}
-
-/*
- * RSA public/private encrypt/decrypt APIs
- */
-
-/* Encrypt with the RSA public key.
- *
- * Return compliant with OpenSSL.
- *
- * @param [in] len Length of data to encrypt.
- * @param [in] from Data to encrypt.
- * @param [out] to Encrypted data.
- * @param [in] rsa RSA key.
- * @param [in] padding Type of padding to place around plaintext.
- * @return Size of encrypted data on success.
- * @return -1 on failure.
- */
-int wolfSSL_RSA_public_encrypt(int len, const unsigned char* from,
- unsigned char* to, WOLFSSL_RSA* rsa, int padding)
-{
- int ret = 0;
- int initTmpRng = 0;
- WC_RNG *rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- WC_RNG* tmpRng = NULL;
-#else
- WC_RNG _tmpRng[1];
- WC_RNG* tmpRng = _tmpRng;
-#endif
-#if !defined(HAVE_FIPS)
- int mgf = WC_MGF1NONE;
- enum wc_HashType hash = WC_HASH_TYPE_NONE;
- int pad_type = WC_RSA_NO_PAD;
-#endif
- int outLen = 0;
-
- WOLFSSL_ENTER("wolfSSL_RSA_public_encrypt");
-
- /* Validate parameters. */
- if ((len < 0) || (rsa == NULL) || (rsa->internal == NULL) ||
- (from == NULL)) {
- WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- if (ret == 0) {
- #if !defined(HAVE_FIPS)
- /* Convert to wolfCrypt padding, hash and MGF. */
- switch (padding) {
- case WC_RSA_PKCS1_PADDING:
- pad_type = WC_RSA_PKCSV15_PAD;
- break;
- case WC_RSA_PKCS1_OAEP_PADDING:
- pad_type = WC_RSA_OAEP_PAD;
- hash = WC_HASH_TYPE_SHA;
- mgf = WC_MGF1SHA1;
- break;
- case WC_RSA_NO_PAD:
- pad_type = WC_RSA_NO_PAD;
- break;
- default:
- WOLFSSL_ERROR_MSG("RSA_public_encrypt doesn't support padding "
- "scheme");
- ret = WOLFSSL_FATAL_ERROR;
- }
- #else
- /* Check for supported padding schemes in FIPS. */
- /* TODO: Do we support more schemes in later versions of FIPS? */
- if (padding != WC_RSA_PKCS1_PADDING) {
- WOLFSSL_ERROR_MSG("RSA_public_encrypt pad type not supported in "
- "FIPS");
- ret = WOLFSSL_FATAL_ERROR;
- }
- #endif
- }
-
- /* Set wolfCrypt RSA key data from external if not already done. */
- if ((ret == 0) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- if (ret == 0) {
- /* Calculate maximum length of encrypted data. */
- outLen = wolfSSL_RSA_size(rsa);
- if (outLen == 0) {
- WOLFSSL_ERROR_MSG("Bad RSA size");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
-
- if (ret == 0) {
- /* Get an RNG. */
- rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
- if (rng == NULL) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
-
- if (ret == 0) {
- /* Use wolfCrypt to public-encrypt with RSA key. */
- #if !defined(HAVE_FIPS)
- ret = wc_RsaPublicEncrypt_ex(from, (word32)len, to, (word32)outLen,
- (RsaKey*)rsa->internal, rng, pad_type, hash, mgf, NULL, 0);
- #else
- ret = wc_RsaPublicEncrypt(from, (word32)len, to, (word32)outLen,
- (RsaKey*)rsa->internal, rng);
- #endif
- }
-
- /* Finalize RNG if initialized in WOLFSSL_RSA_GetRNG(). */
- if (initTmpRng) {
- wc_FreeRng(tmpRng);
- }
- WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
-
- /* wolfCrypt error means return -1. */
- if (ret <= 0) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- WOLFSSL_LEAVE("wolfSSL_RSA_public_encrypt", ret);
- return ret;
-}
-
-/* Decrypt with the RSA public key.
- *
- * Return compliant with OpenSSL.
- *
- * @param [in] len Length of encrypted data.
- * @param [in] from Encrypted data.
- * @param [out] to Decrypted data.
- * @param [in] rsa RSA key.
- * @param [in] padding Type of padding to around plaintext to remove.
- * @return Size of decrypted data on success.
- * @return -1 on failure.
- */
-int wolfSSL_RSA_private_decrypt(int len, const unsigned char* from,
- unsigned char* to, WOLFSSL_RSA* rsa, int padding)
-{
- int ret = 0;
-#if !defined(HAVE_FIPS)
- int mgf = WC_MGF1NONE;
- enum wc_HashType hash = WC_HASH_TYPE_NONE;
- int pad_type = WC_RSA_NO_PAD;
-#endif
- int outLen = 0;
-
- WOLFSSL_ENTER("wolfSSL_RSA_private_decrypt");
-
- /* Validate parameters. */
- if ((len < 0) || (rsa == NULL) || (rsa->internal == NULL) ||
- (from == NULL)) {
- WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- if (ret == 0) {
- #if !defined(HAVE_FIPS)
- switch (padding) {
- case WC_RSA_PKCS1_PADDING:
- pad_type = WC_RSA_PKCSV15_PAD;
- break;
- case WC_RSA_PKCS1_OAEP_PADDING:
- pad_type = WC_RSA_OAEP_PAD;
- hash = WC_HASH_TYPE_SHA;
- mgf = WC_MGF1SHA1;
- break;
- case WC_RSA_NO_PAD:
- pad_type = WC_RSA_NO_PAD;
- break;
- default:
- WOLFSSL_ERROR_MSG("RSA_private_decrypt unsupported padding");
- ret = WOLFSSL_FATAL_ERROR;
- }
- #else
- /* Check for supported padding schemes in FIPS. */
- /* TODO: Do we support more schemes in later versions of FIPS? */
- if (padding != WC_RSA_PKCS1_PADDING) {
- WOLFSSL_ERROR_MSG("RSA_public_encrypt pad type not supported in "
- "FIPS");
- ret = WOLFSSL_FATAL_ERROR;
- }
- #endif
- }
-
- /* Set wolfCrypt RSA key data from external if not already done. */
- if ((ret == 0) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- if (ret == 0) {
- /* Calculate maximum length of decrypted data. */
- outLen = wolfSSL_RSA_size(rsa);
- if (outLen == 0) {
- WOLFSSL_ERROR_MSG("Bad RSA size");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
-
- if (ret == 0) {
- /* Use wolfCrypt to private-decrypt with RSA key.
- * Size of 'to' buffer must be size of RSA key */
- #if !defined(HAVE_FIPS)
- ret = wc_RsaPrivateDecrypt_ex(from, (word32)len, to, (word32)outLen,
- (RsaKey*)rsa->internal, pad_type, hash, mgf, NULL, 0);
- #else
- ret = wc_RsaPrivateDecrypt(from, (word32)len, to, (word32)outLen,
- (RsaKey*)rsa->internal);
- #endif
- }
-
- /* wolfCrypt error means return -1. */
- if (ret <= 0) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- WOLFSSL_LEAVE("wolfSSL_RSA_private_decrypt", ret);
- return ret;
-}
-
-/* Decrypt with the RSA public key.
- *
- * @param [in] len Length of encrypted data.
- * @param [in] from Encrypted data.
- * @param [out] to Decrypted data.
- * @param [in] rsa RSA key.
- * @param [in] padding Type of padding to around plaintext to remove.
- * @return Size of decrypted data on success.
- * @return -1 on failure.
- */
-int wolfSSL_RSA_public_decrypt(int len, const unsigned char* from,
- unsigned char* to, WOLFSSL_RSA* rsa, int padding)
-{
- int ret = 0;
-#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
- int pad_type = WC_RSA_NO_PAD;
-#endif
- int outLen = 0;
-
- WOLFSSL_ENTER("wolfSSL_RSA_public_decrypt");
-
- /* Validate parameters. */
- if ((len < 0) || (rsa == NULL) || (rsa->internal == NULL) ||
- (from == NULL)) {
- WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- if (ret == 0) {
- #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
- switch (padding) {
- case WC_RSA_PKCS1_PADDING:
- pad_type = WC_RSA_PKCSV15_PAD;
- break;
- case WC_RSA_NO_PAD:
- pad_type = WC_RSA_NO_PAD;
- break;
- /* TODO: RSA_X931_PADDING not supported */
- default:
- WOLFSSL_ERROR_MSG("RSA_public_decrypt unsupported padding");
- ret = WOLFSSL_FATAL_ERROR;
- }
- #else
- if (padding != WC_RSA_PKCS1_PADDING) {
- WOLFSSL_ERROR_MSG("RSA_public_decrypt pad type not supported in "
- "FIPS");
- ret = WOLFSSL_FATAL_ERROR;
- }
- #endif
- }
-
- /* Set wolfCrypt RSA key data from external if not already done. */
- if ((ret == 0) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- if (ret == 0) {
- /* Calculate maximum length of encrypted data. */
- outLen = wolfSSL_RSA_size(rsa);
- if (outLen == 0) {
- WOLFSSL_ERROR_MSG("Bad RSA size");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
-
- if (ret == 0) {
- /* Use wolfCrypt to public-decrypt with RSA key. */
- #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
- /* Size of 'to' buffer must be size of RSA key. */
- ret = wc_RsaSSL_Verify_ex(from, (word32)len, to, (word32)outLen,
- (RsaKey*)rsa->internal, pad_type);
- #else
- /* For FIPS v1/v2 only PKCSV15 padding is supported */
- ret = wc_RsaSSL_Verify(from, (word32)len, to, (word32)outLen,
- (RsaKey*)rsa->internal);
- #endif
- }
-
- /* wolfCrypt error means return -1. */
- if (ret <= 0) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- WOLFSSL_LEAVE("wolfSSL_RSA_public_decrypt", ret);
- return ret;
-}
-
-/* Encrypt with the RSA private key.
- *
- * Calls wc_RsaSSL_Sign.
- *
- * @param [in] len Length of data to encrypt.
- * @param [in] from Data to encrypt.
- * @param [out] to Encrypted data.
- * @param [in] rsa RSA key.
- * @param [in] padding Type of padding to place around plaintext.
- * @return Size of encrypted data on success.
- * @return -1 on failure.
- */
-int wolfSSL_RSA_private_encrypt(int len, const unsigned char* from,
- unsigned char* to, WOLFSSL_RSA* rsa, int padding)
-{
- int ret = 0;
- int initTmpRng = 0;
- WC_RNG *rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- WC_RNG* tmpRng = NULL;
-#else
- WC_RNG _tmpRng[1];
- WC_RNG* tmpRng = _tmpRng;
-#endif
-
- WOLFSSL_ENTER("wolfSSL_RSA_private_encrypt");
-
- /* Validate parameters. */
- if ((len < 0) || (rsa == NULL) || (rsa->internal == NULL) ||
- (from == NULL)) {
- WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- if (ret == 0) {
- switch (padding) {
- case WC_RSA_PKCS1_PADDING:
- #ifdef WC_RSA_NO_PADDING
- case WC_RSA_NO_PAD:
- #endif
- break;
- /* TODO: RSA_X931_PADDING not supported */
- default:
- WOLFSSL_ERROR_MSG("RSA_private_encrypt unsupported padding");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
-
- /* Set wolfCrypt RSA key data from external if not already done. */
- if ((ret == 0) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- if (ret == 0) {
- /* Get an RNG. */
- rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
- if (rng == NULL) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
-
- if (ret == 0) {
- /* Use wolfCrypt to private-encrypt with RSA key.
- * Size of output buffer must be size of RSA key. */
- if (padding == WC_RSA_PKCS1_PADDING) {
- ret = wc_RsaSSL_Sign(from, (word32)len, to,
- (word32)wolfSSL_RSA_size(rsa), (RsaKey*)rsa->internal, rng);
- }
- #ifdef WC_RSA_NO_PADDING
- else if (padding == WC_RSA_NO_PAD) {
- word32 outLen = (word32)wolfSSL_RSA_size(rsa);
- ret = wc_RsaFunction(from, (word32)len, to, &outLen,
- RSA_PRIVATE_ENCRYPT, (RsaKey*)rsa->internal, rng);
- if (ret == 0)
- ret = (int)outLen;
- }
- #endif
- }
-
- /* Finalize RNG if initialized in WOLFSSL_RSA_GetRNG(). */
- if (initTmpRng) {
- wc_FreeRng(tmpRng);
- }
- WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
-
- /* wolfCrypt error means return -1. */
- if (ret <= 0) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- WOLFSSL_LEAVE("wolfSSL_RSA_private_encrypt", ret);
- return ret;
-}
-
-/*
- * RSA misc operation APIs
- */
-
-/* Calculate d mod p-1 and q-1 into BNs.
- *
- * Not OpenSSL API.
- *
- * @param [in, out] rsa RSA key.
- * @return 1 on success.
- * @return -1 on failure.
- */
-int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
-{
- int ret = 1;
- int err;
- mp_int* t = NULL;
- WC_DECLARE_VAR(tmp, mp_int, 1, 0);
-
- WOLFSSL_ENTER("wolfSSL_RsaGenAdd");
-
- /* Validate parameters. */
- if ((rsa == NULL) || (rsa->p == NULL) || (rsa->q == NULL) ||
- (rsa->d == NULL) || (rsa->dmp1 == NULL) || (rsa->dmq1 == NULL)) {
- WOLFSSL_ERROR_MSG("rsa no init error");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
-#ifdef WOLFSSL_SMALL_STACK
- if (ret == 1) {
- tmp = (mp_int *)XMALLOC(sizeof(*tmp), rsa->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (tmp == NULL) {
- WOLFSSL_ERROR_MSG("Memory allocation failure");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
-#endif
-
- if (ret == 1) {
- /* Initialize temp MP integer. */
- if (mp_init(tmp) != MP_OKAY) {
- WOLFSSL_ERROR_MSG("mp_init error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
-
- if (ret == 1) {
- t = tmp;
-
- /* Sub 1 from p into temp. */
- err = mp_sub_d((mp_int*)rsa->p->internal, 1, tmp);
- if (err != MP_OKAY) {
- WOLFSSL_ERROR_MSG("mp_sub_d error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- if (ret == 1) {
- /* Calculate d mod (p - 1) into dmp1 MP integer of BN. */
- err = mp_mod((mp_int*)rsa->d->internal, tmp,
- (mp_int*)rsa->dmp1->internal);
- if (err != MP_OKAY) {
- WOLFSSL_ERROR_MSG("mp_mod error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- if (ret == 1) {
- /* Sub 1 from q into temp. */
- err = mp_sub_d((mp_int*)rsa->q->internal, 1, tmp);
- if (err != MP_OKAY) {
- WOLFSSL_ERROR_MSG("mp_sub_d error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- if (ret == 1) {
- /* Calculate d mod (q - 1) into dmq1 MP integer of BN. */
- err = mp_mod((mp_int*)rsa->d->internal, tmp,
- (mp_int*)rsa->dmq1->internal);
- if (err != MP_OKAY) {
- WOLFSSL_ERROR_MSG("mp_mod error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
-
- mp_clear(t);
-
-#ifdef WOLFSSL_SMALL_STACK
- if (rsa != NULL) {
- XFREE(tmp, rsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
-#endif
-
- return ret;
-}
-
-
-#ifndef NO_WOLFSSL_STUB
-/* Enable blinding for RSA key operations.
- *
- * Blinding is a compile time option in wolfCrypt.
- *
- * @param [in] rsa RSA key. Unused.
- * @param [in] bnCtx BN context to use for blinding. Unused.
- * @return 1 always.
- */
-int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bnCtx)
-{
- WOLFSSL_STUB("RSA_blinding_on");
- WOLFSSL_ENTER("wolfSSL_RSA_blinding_on");
-
- (void)rsa;
- (void)bnCtx;
-
- return 1; /* on by default */
-}
-#endif
-
-#endif /* OPENSSL_EXTRA */
-
-#endif /* !NO_RSA */
-
-/*******************************************************************************
- * END OF RSA API
- ******************************************************************************/
+#define WOLFSSL_PK_RSA_INCLUDED
+#include "src/pk_rsa.c"
/*******************************************************************************
@@ -5393,7 +1478,7 @@ int wolfSSL_i2d_DSA_SIG(const WOLFSSL_DSA_SIG *sig, byte **out)
}
/**
- * Same as wolfSSL_DSA_SIG_new but also initializes the internal bignums as well.
+ * Same as wolfSSL_DSA_SIG_new but also initializes the internal bignums.
* @return New WOLFSSL_DSA_SIG with r and s created as well
*/
static WOLFSSL_DSA_SIG* wolfSSL_DSA_SIG_new_bn(void)
@@ -6226,7 +2311,8 @@ WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSA_PUBKEY(WOLFSSL_BIO* bio,WOLFSSL_DSA** dsa,
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
/* return 1 if success, -1 if error */
-int wolfSSL_DSA_LoadDer(WOLFSSL_DSA* dsa, const unsigned char* derBuf, int derSz)
+int wolfSSL_DSA_LoadDer(WOLFSSL_DSA* dsa, const unsigned char* derBuf,
+ int derSz)
{
word32 idx = 0;
int ret;
@@ -6330,7 +2416,7 @@ WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, WOLFSSL_DSA **x,
* cb is for a call back when encountering encrypted PEM files
* if cb == NULL and u != NULL then u = null terminated password string
*/
- WOLFSSL_MSG("Not yet supporting call back or password for encrypted PEM");
+ WOLFSSL_MSG("Not supporting callback or password for encrypted PEM");
}
if (PemToDer(buf, (long)bufSz, DSA_PARAM_TYPE, &pDer, NULL, NULL,
@@ -8950,5511 +5036,9 @@ int wolfSSL_DH_compute_key_padded(unsigned char* key,
******************************************************************************/
-/*******************************************************************************
- * START OF EC API
- ******************************************************************************/
+#define WOLFSSL_PK_EC_INCLUDED
+#include "src/pk_ec.c"
-#ifdef HAVE_ECC
-
-#if defined(OPENSSL_EXTRA)
-
-/* Start EC_curve */
-
-/* Get the NIST name for the numeric ID.
- *
- * @param [in] nid Numeric ID of an EC curve.
- * @return String representing NIST name of EC curve on success.
- * @return NULL on error.
- */
-const char* wolfSSL_EC_curve_nid2nist(int nid)
-{
- const char* name = NULL;
- const WOLF_EC_NIST_NAME* nist_name;
-
- /* Attempt to find the curve info matching the NID passed in. */
- for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
- if (nist_name->nid == nid) {
- /* NID found - return name. */
- name = nist_name->name;
- break;
- }
- }
-
- return name;
-}
-
-/* Get the numeric ID for the NIST name.
- *
- * @param [in] name NIST name of EC curve.
- * @return NID matching NIST name on success.
- * @return 0 on error.
- */
-int wolfSSL_EC_curve_nist2nid(const char* name)
-{
- int nid = 0;
- const WOLF_EC_NIST_NAME* nist_name;
-
- /* Attempt to find the curve info matching the NIST name passed in. */
- for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
- if (XSTRCMP(nist_name->name, name) == 0) {
- /* Name found - return NID. */
- nid = nist_name->nid;
- break;
- }
- }
-
- return nid;
-}
-
-#endif /* OPENSSL_EXTRA */
-
-/* End EC_curve */
-
-/* Start EC_METHOD */
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-/* Get the EC method of the EC group object.
- *
- * wolfSSL doesn't use method tables. Implementation used is dependent upon
- * the NID.
- *
- * @param [in] group EC group object.
- * @return EC method.
- */
-const WOLFSSL_EC_METHOD* wolfSSL_EC_GROUP_method_of(
- const WOLFSSL_EC_GROUP *group)
-{
- /* No method table used so just return the same object. */
- return group;
-}
-
-/* Get field type for method.
- *
- * Only prime fields are supported.
- *
- * @param [in] meth EC method.
- * @return X9.63 prime field NID on success.
- * @return 0 on error.
- */
-int wolfSSL_EC_METHOD_get_field_type(const WOLFSSL_EC_METHOD *meth)
-{
- int nid = 0;
-
- if (meth != NULL) {
- /* Only field type supported by code base. */
- nid = WC_NID_X9_62_prime_field;
- }
-
- return nid;
-}
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-
-/* End EC_METHOD */
-
-/* Start EC_GROUP */
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-/* Converts ECC curve enum values in ecc_curve_id to the associated OpenSSL NID
- * value.
- *
- * @param [in] n ECC curve id.
- * @return ECC curve NID (OpenSSL compatible value).
- */
-int EccEnumToNID(int n)
-{
- WOLFSSL_ENTER("EccEnumToNID");
-
- switch(n) {
- case ECC_SECP192R1:
- return WC_NID_X9_62_prime192v1;
- case ECC_PRIME192V2:
- return WC_NID_X9_62_prime192v2;
- case ECC_PRIME192V3:
- return WC_NID_X9_62_prime192v3;
- case ECC_PRIME239V1:
- return WC_NID_X9_62_prime239v1;
- case ECC_PRIME239V2:
- return WC_NID_X9_62_prime239v2;
- case ECC_PRIME239V3:
- return WC_NID_X9_62_prime239v3;
- case ECC_SECP256R1:
- return WC_NID_X9_62_prime256v1;
- case ECC_SECP112R1:
- return WC_NID_secp112r1;
- case ECC_SECP112R2:
- return WC_NID_secp112r2;
- case ECC_SECP128R1:
- return WC_NID_secp128r1;
- case ECC_SECP128R2:
- return WC_NID_secp128r2;
- case ECC_SECP160R1:
- return WC_NID_secp160r1;
- case ECC_SECP160R2:
- return WC_NID_secp160r2;
- case ECC_SECP224R1:
- return WC_NID_secp224r1;
- case ECC_SECP384R1:
- return WC_NID_secp384r1;
- case ECC_SECP521R1:
- return WC_NID_secp521r1;
- case ECC_SECP160K1:
- return WC_NID_secp160k1;
- case ECC_SECP192K1:
- return WC_NID_secp192k1;
- case ECC_SECP224K1:
- return WC_NID_secp224k1;
- case ECC_SECP256K1:
- return WC_NID_secp256k1;
- case ECC_BRAINPOOLP160R1:
- return WC_NID_brainpoolP160r1;
- case ECC_BRAINPOOLP192R1:
- return WC_NID_brainpoolP192r1;
- case ECC_BRAINPOOLP224R1:
- return WC_NID_brainpoolP224r1;
- case ECC_BRAINPOOLP256R1:
- return WC_NID_brainpoolP256r1;
- case ECC_BRAINPOOLP320R1:
- return WC_NID_brainpoolP320r1;
- case ECC_BRAINPOOLP384R1:
- return WC_NID_brainpoolP384r1;
- case ECC_BRAINPOOLP512R1:
- return WC_NID_brainpoolP512r1;
- #ifdef WOLFSSL_SM2
- case ECC_SM2P256V1:
- return WC_NID_sm2;
- #endif
- default:
- WOLFSSL_MSG("NID not found");
- return WOLFSSL_FATAL_ERROR;
- }
-}
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
-/* Converts OpenSSL NID of EC curve to the enum value in ecc_curve_id
- *
- * Used by ecc_sets[].
- *
- * @param [in] n OpenSSL NID of EC curve.
- * @return wolfCrypt EC curve id.
- * @return -1 on error.
- */
-int NIDToEccEnum(int nid)
-{
- int id;
-
- WOLFSSL_ENTER("NIDToEccEnum");
-
- switch (nid) {
- case WC_NID_X9_62_prime192v1:
- id = ECC_SECP192R1;
- break;
- case WC_NID_X9_62_prime192v2:
- id = ECC_PRIME192V2;
- break;
- case WC_NID_X9_62_prime192v3:
- id = ECC_PRIME192V3;
- break;
- case WC_NID_X9_62_prime239v1:
- id = ECC_PRIME239V1;
- break;
- case WC_NID_X9_62_prime239v2:
- id = ECC_PRIME239V2;
- break;
- case WC_NID_X9_62_prime239v3:
- id = ECC_PRIME239V3;
- break;
- case WC_NID_X9_62_prime256v1:
- id = ECC_SECP256R1;
- break;
- case WC_NID_secp112r1:
- id = ECC_SECP112R1;
- break;
- case WC_NID_secp112r2:
- id = ECC_SECP112R2;
- break;
- case WC_NID_secp128r1:
- id = ECC_SECP128R1;
- break;
- case WC_NID_secp128r2:
- id = ECC_SECP128R2;
- break;
- case WC_NID_secp160r1:
- id = ECC_SECP160R1;
- break;
- case WC_NID_secp160r2:
- id = ECC_SECP160R2;
- break;
- case WC_NID_secp224r1:
- id = ECC_SECP224R1;
- break;
- case WC_NID_secp384r1:
- id = ECC_SECP384R1;
- break;
- case WC_NID_secp521r1:
- id = ECC_SECP521R1;
- break;
- case WC_NID_secp160k1:
- id = ECC_SECP160K1;
- break;
- case WC_NID_secp192k1:
- id = ECC_SECP192K1;
- break;
- case WC_NID_secp224k1:
- id = ECC_SECP224K1;
- break;
- case WC_NID_secp256k1:
- id = ECC_SECP256K1;
- break;
- case WC_NID_brainpoolP160r1:
- id = ECC_BRAINPOOLP160R1;
- break;
- case WC_NID_brainpoolP192r1:
- id = ECC_BRAINPOOLP192R1;
- break;
- case WC_NID_brainpoolP224r1:
- id = ECC_BRAINPOOLP224R1;
- break;
- case WC_NID_brainpoolP256r1:
- id = ECC_BRAINPOOLP256R1;
- break;
- case WC_NID_brainpoolP320r1:
- id = ECC_BRAINPOOLP320R1;
- break;
- case WC_NID_brainpoolP384r1:
- id = ECC_BRAINPOOLP384R1;
- break;
- case WC_NID_brainpoolP512r1:
- id = ECC_BRAINPOOLP512R1;
- break;
- default:
- WOLFSSL_MSG("NID not found");
- /* -1 on error. */
- id = WOLFSSL_FATAL_ERROR;
- }
-
- return id;
-}
-
-/* Set the fields of the EC group based on numeric ID.
- *
- * @param [in, out] group EC group.
- * @param [in] nid Numeric ID of an EC curve.
- */
-static void ec_group_set_nid(WOLFSSL_EC_GROUP* group, int nid)
-{
- int eccEnum;
- int realNid;
-
- /* Convert ecc_curve_id enum to NID. */
- if ((realNid = EccEnumToNID(nid)) != -1) {
- /* ecc_curve_id enum passed in - have real NID value set. */
- eccEnum = nid;
- }
- else {
- /* NID passed in is OpenSSL type. */
- realNid = nid;
- /* Convert NID to ecc_curve_id enum. */
- eccEnum = NIDToEccEnum(nid);
- }
-
- /* Set the numeric ID of the curve */
- group->curve_nid = realNid;
- /* Initialize index to -1 (i.e. wolfCrypt doesn't support curve). */
- group->curve_idx = -1;
-
- /* Find index and OID sum for curve if wolfCrypt supports it. */
- if (eccEnum != -1) {
- int i;
-
- /* Find id and set the internal curve idx and OID sum. */
- for (i = 0; ecc_sets[i].size != 0; i++) {
- if (ecc_sets[i].id == eccEnum) {
- /* Found id in wolfCrypt supported EC curves. */
- group->curve_idx = i;
- group->curve_oid = (int)ecc_sets[i].oidSum;
- break;
- }
- }
- }
-}
-
-/* Create a new EC group with the numeric ID for an EC curve.
- *
- * @param [in] nid Numeric ID of an EC curve.
- * @return New, allocated EC group on success.
- * @return NULL on error.
- */
-WOLFSSL_EC_GROUP* wolfSSL_EC_GROUP_new_by_curve_name(int nid)
-{
- int err = 0;
- WOLFSSL_EC_GROUP* group;
-
- WOLFSSL_ENTER("wolfSSL_EC_GROUP_new_by_curve_name");
-
- /* Allocate EC group. */
- group = (WOLFSSL_EC_GROUP*)XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL,
- DYNAMIC_TYPE_ECC);
- if (group == NULL) {
- WOLFSSL_MSG("wolfSSL_EC_GROUP_new_by_curve_name malloc failure");
- err = 1;
- }
-
- if (!err) {
- /* Reset all fields. */
- XMEMSET(group, 0, sizeof(WOLFSSL_EC_GROUP));
-
- /* Set the fields of group based on the numeric ID. */
- ec_group_set_nid(group, nid);
- }
-
- return group;
-}
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-/* Dispose of the EC group.
- *
- * Cannot use group after this call.
- *
- * @param [in] group EC group to free.
- */
-void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group)
-{
- WOLFSSL_ENTER("wolfSSL_EC_GROUP_free");
-
- /* Dispose of EC group. */
- XFREE(group, NULL, DYNAMIC_TYPE_ECC);
-}
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-
-#ifdef OPENSSL_EXTRA
-#ifndef NO_BIO
-
-/* Creates an EC group from the DER encoding.
- *
- * Only named curves supported.
- *
- * @param [out] group Reference to EC group object.
- * @param [in] in Buffer holding DER encoding of curve.
- * @param [in] inSz Length of data in buffer.
- * @return EC group on success.
- * @return NULL on error.
- */
-static WOLFSSL_EC_GROUP* wolfssl_ec_group_d2i(WOLFSSL_EC_GROUP** group,
- const unsigned char** in_pp, long inSz)
-{
- int err = 0;
- WOLFSSL_EC_GROUP* ret = NULL;
- word32 idx = 0;
- word32 oid = 0;
- int id = 0;
- const unsigned char* in;
-
- if (in_pp == NULL || *in_pp == NULL)
- return NULL;
-
- in = *in_pp;
-
- /* Use the group passed in. */
- if ((group != NULL) && (*group != NULL)) {
- ret = *group;
- }
-
- /* Only support named curves. */
- if (in[0] != ASN_OBJECT_ID) {
- WOLFSSL_ERROR_MSG("Invalid or unsupported encoding");
- err = 1;
- }
- /* Decode the OBJECT ID - expecting an EC curve OID. */
- if ((!err) && (GetObjectId(in, &idx, &oid, oidCurveType, (word32)inSz) !=
- 0)) {
- err = 1;
- }
- if (!err) {
- /* Get the internal ID for OID. */
- id = wc_ecc_get_oid(oid, NULL, NULL);
- if (id < 0) {
- err = 1;
- }
- }
- if (!err) {
- /* Get the NID for the internal ID. */
- int nid = EccEnumToNID(id);
- if (ret == NULL) {
- /* Create a new EC group with the numeric ID. */
- ret = wolfSSL_EC_GROUP_new_by_curve_name(nid);
- if (ret == NULL) {
- err = 1;
- }
- }
- else {
- ec_group_set_nid(ret, nid);
- }
- }
- if ((!err) && (group != NULL)) {
- /* Return the EC group through reference. */
- *group = ret;
- }
-
- if (err) {
- if ((ret != NULL) && (ret != *group)) {
- wolfSSL_EC_GROUP_free(ret);
- }
- ret = NULL;
- }
- else {
- *in_pp += idx;
- }
- return ret;
-}
-
-/* Creates a new EC group from the PEM encoding in the BIO.
- *
- * @param [in] bio BIO to read PEM encoding from.
- * @param [out] group Reference to EC group object.
- * @param [in] cb Password callback when PEM encrypted.
- * @param [in] pass NUL terminated string for passphrase when PEM encrypted.
- * @return EC group on success.
- * @return NULL on error.
- */
-WOLFSSL_EC_GROUP* wolfSSL_PEM_read_bio_ECPKParameters(WOLFSSL_BIO* bio,
- WOLFSSL_EC_GROUP** group, wc_pem_password_cb* cb, void* pass)
-{
- int err = 0;
- WOLFSSL_EC_GROUP* ret = NULL;
- DerBuffer* der = NULL;
- int keyFormat = 0;
-
- if (bio == NULL) {
- err = 1;
- }
-
- /* Read parameters from BIO and convert PEM to DER. */
- if ((!err) && (pem_read_bio_key(bio, cb, pass, ECC_PARAM_TYPE,
- &keyFormat, &der) < 0)) {
- err = 1;
- }
- if (!err) {
- /* Create EC group from DER encoding. */
- const byte** p = (const byte**)&der->buffer;
- ret = wolfssl_ec_group_d2i(group, p, der->length);
- if (ret == NULL) {
- WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_EC_GROUP");
- }
- }
-
- /* Dispose of any allocated data. */
- FreeDer(&der);
- return ret;
-}
-
-WOLFSSL_EC_GROUP *wolfSSL_d2i_ECPKParameters(WOLFSSL_EC_GROUP **out,
- const unsigned char **in, long len)
-{
- return wolfssl_ec_group_d2i(out, in, len);
-}
-
-int wolfSSL_i2d_ECPKParameters(const WOLFSSL_EC_GROUP* grp, unsigned char** pp)
-{
- unsigned char* out = NULL;
- int len = 0;
- int idx;
- const byte* oid = NULL;
- word32 oidSz = 0;
-
- if (grp == NULL || !wc_ecc_is_valid_idx(grp->curve_idx) ||
- grp->curve_idx < 0)
- return WOLFSSL_FATAL_ERROR;
-
- /* Get the actual DER encoding of the OID. ecc_sets[grp->curve_idx].oid
- * is just the numerical representation. */
- if (wc_ecc_get_oid((word32)grp->curve_oid, &oid, &oidSz) < 0)
- return WOLFSSL_FATAL_ERROR;
-
- len = SetObjectId((int)oidSz, NULL) + (int)oidSz;
-
- if (pp == NULL)
- return len;
-
- if (*pp == NULL) {
- out = (unsigned char*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_ASN1);
- if (out == NULL)
- return WOLFSSL_FATAL_ERROR;
- }
- else {
- out = *pp;
- }
-
- idx = SetObjectId((int)oidSz, out);
- XMEMCPY(out + idx, oid, oidSz);
- if (*pp == NULL)
- *pp = out;
- else
- *pp += len;
-
- return len;
-}
-#endif /* !NO_BIO */
-
-#if defined(OPENSSL_ALL) && !defined(NO_CERTS)
-/* Copy an EC group.
- *
- * Only used by wolfSSL_EC_KEY_dup at this time.
- *
- * @param [in, out] dst Destination EC group.
- * @param [in] src Source EC group.
- * @return 0 on success.
- */
-static int wolfssl_ec_group_copy(WOLFSSL_EC_GROUP* dst,
- const WOLFSSL_EC_GROUP* src)
-{
- /* Copy the fields. */
- dst->curve_idx = src->curve_idx;
- dst->curve_nid = src->curve_nid;
- dst->curve_oid = src->curve_oid;
-
- return 0;
-}
-#endif /* OPENSSL_ALL && !NO_CERTS */
-
-/* Copies ecc_key into new WOLFSSL_EC_GROUP object
- *
- * @param [in] src EC group to duplicate.
- *
- * @return EC group on success.
- * @return NULL on error.
- */
-WOLFSSL_EC_GROUP* wolfSSL_EC_GROUP_dup(const WOLFSSL_EC_GROUP *src)
-{
- WOLFSSL_EC_GROUP* newGroup = NULL;
-
- if (src != NULL) {
- /* Create new group base on NID in original EC group. */
- newGroup = wolfSSL_EC_GROUP_new_by_curve_name(src->curve_nid);
- }
-
- return newGroup;
-}
-
-/* Compare two EC groups.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in] a First EC group.
- * @param [in] b Second EC group.
- * @param [in] ctx Big number context to use when comparing fields. Unused.
- *
- * @return 0 if equal.
- * @return 1 if not equal.
- * @return -1 on error.
- */
-int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b,
- WOLFSSL_BN_CTX *ctx)
-{
- int ret;
-
- /* No BN operations performed. */
- (void)ctx;
-
- WOLFSSL_ENTER("wolfSSL_EC_GROUP_cmp");
-
- /* Validate parameters. */
- if ((a == NULL) || (b == NULL)) {
- WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments");
- /* Return error value. */
- ret = WOLFSSL_FATAL_ERROR;
- }
- /* Compare NID and wolfSSL curve index. */
- else {
- /* 0 when same, 1 when not. */
- ret = ((a->curve_nid == b->curve_nid) &&
- (a->curve_idx == b->curve_idx)) ? 0 : 1;
- }
-
- return ret;
-}
-
-#ifndef NO_WOLFSSL_STUB
-/* Set the ASN.1 flag that indicate encoding of curve.
- *
- * Stub function - flag not used elsewhere.
- * Always encoded as named curve.
- *
- * @param [in] group EC group to modify.
- * @param [in] flag ASN.1 flag to set. Valid values:
- * OPENSSL_EC_EXPLICIT_CURVE, OPENSSL_EC_NAMED_CURVE
- */
-void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag)
-{
- (void)group;
- (void)flag;
-
- WOLFSSL_ENTER("wolfSSL_EC_GROUP_set_asn1_flag");
- WOLFSSL_STUB("EC_GROUP_set_asn1_flag");
-}
-#endif
-
-/* Get the curve NID of the group.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in] group EC group.
- * @return Curve NID on success.
- * @return 0 on error.
- */
-int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group)
-{
- int nid = 0;
- WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_curve_name");
-
- if (group == NULL) {
- WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments");
- }
- else {
- nid = group->curve_nid;
- }
-
- return nid;
-}
-
-/* Get the degree (curve size in bits) of the EC group.
- *
- * Return code compliant with OpenSSL.
- *
- * @return Degree of the curve on success.
- * @return 0 on error.
- */
-int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group)
-{
- int degree = 0;
-
- WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_degree");
-
- if (group == NULL) {
- WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments");
- }
- else {
- switch (group->curve_nid) {
- case WC_NID_secp112r1:
- case WC_NID_secp112r2:
- degree = 112;
- break;
- case WC_NID_secp128r1:
- case WC_NID_secp128r2:
- degree = 128;
- break;
- case WC_NID_secp160k1:
- case WC_NID_secp160r1:
- case WC_NID_secp160r2:
- case WC_NID_brainpoolP160r1:
- degree = 160;
- break;
- case WC_NID_secp192k1:
- case WC_NID_brainpoolP192r1:
- case WC_NID_X9_62_prime192v1:
- case WC_NID_X9_62_prime192v2:
- case WC_NID_X9_62_prime192v3:
- degree = 192;
- break;
- case WC_NID_secp224k1:
- case WC_NID_secp224r1:
- case WC_NID_brainpoolP224r1:
- degree = 224;
- break;
- case WC_NID_X9_62_prime239v1:
- case WC_NID_X9_62_prime239v2:
- case WC_NID_X9_62_prime239v3:
- degree = 239;
- break;
- case WC_NID_secp256k1:
- case WC_NID_brainpoolP256r1:
- case WC_NID_X9_62_prime256v1:
- degree = 256;
- break;
- case WC_NID_brainpoolP320r1:
- degree = 320;
- break;
- case WC_NID_secp384r1:
- case WC_NID_brainpoolP384r1:
- degree = 384;
- break;
- case WC_NID_brainpoolP512r1:
- degree = 512;
- break;
- case WC_NID_secp521r1:
- degree = 521;
- break;
- }
- }
-
- return degree;
-}
-#endif /* OPENSSL_EXTRA */
-
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
-/* Get the length of the order in bits of the EC group.
- *
- * TODO: consider switch statement or calculating directly from hex string
- * array instead of using mp_int.
- *
- * @param [in] group EC group.
- * @return Length of order in bits on success.
- * @return 0 on error.
- */
-int wolfSSL_EC_GROUP_order_bits(const WOLFSSL_EC_GROUP *group)
-{
- int ret = 0;
- WC_DECLARE_VAR(order, mp_int, 1, 0);
-
- /* Validate parameter. */
- if ((group == NULL) || (group->curve_idx < 0)) {
- WOLFSSL_MSG("wolfSSL_EC_GROUP_order_bits NULL error");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
-#ifdef WOLFSSL_SMALL_STACK
- if (ret == 0) {
- /* Allocate memory for mp_int that will hold order value. */
- order = (mp_int *)XMALLOC(sizeof(*order), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (order == NULL) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
-#endif
-
- if (ret == 0) {
- /* Initialize mp_int. */
- ret = mp_init(order);
- }
-
- if (ret == 0) {
- /* Read hex string of order from wolfCrypt array of curves. */
- ret = mp_read_radix(order, ecc_sets[group->curve_idx].order,
- MP_RADIX_HEX);
- if (ret == 0) {
- /* Get bits of order. */
- ret = mp_count_bits(order);
- }
- /* Clear and free mp_int. */
- mp_clear(order);
- }
-
- WC_FREE_VAR_EX(order, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
- /* Convert error code to length of 0. */
- if (ret < 0) {
- ret = 0;
- }
-
- return ret;
-}
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
-
-#if defined(OPENSSL_EXTRA)
-/* Get the order of the group as a BN.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in] group EC group.
- * @param [in, out] order BN to hold order value.
- * @param [in] ctx Context to use for BN operations. Unused.
- * @return 1 on success.
- * @return 0 on error.
- */
-int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group,
- WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx)
-{
- int ret = 1;
- mp_int* mp = NULL;
-
- /* No BN operations performed - done with mp_int in BN. */
- (void)ctx;
-
- /* Validate parameters. */
- if ((group == NULL) || (order == NULL) || (order->internal == NULL)) {
- WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error");
- ret = 0;
- }
-
- if (ret == 1 &&
- (group->curve_idx < 0 || !wc_ecc_is_valid_idx(group->curve_idx))) {
- WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order Bad group idx");
- ret = 0;
- }
-
- if (ret == 1) {
- mp = (mp_int*)order->internal;
- }
- /* Initialize */
- if ((ret == 1) && (mp_init(mp) != MP_OKAY)) {
- WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure");
- ret = 0;
- }
- /* Read hex string of order from wolfCrypt array of curves. */
- if ((ret == 1) && (mp_read_radix(mp, ecc_sets[group->curve_idx].order,
- MP_RADIX_HEX) != MP_OKAY)) {
- WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_read order failure");
- /* Zero out any partial value but don't free. */
- mp_zero(mp);
- ret = 0;
- }
-
- return ret;
-}
-
-#endif /* OPENSSL_EXTRA */
-
-/* End EC_GROUP */
-
-/* Start EC_POINT */
-
-#if defined(OPENSSL_EXTRA)
-
-/* Set data of EC point into internal, wolfCrypt EC point object.
- *
- * EC_POINT Openssl -> WolfSSL
- *
- * @param [in, out] p EC point to update.
- * @return 1 on success.
- * @return -1 on failure.
- */
-static int ec_point_internal_set(WOLFSSL_EC_POINT *p)
-{
- int ret = 1;
-
- WOLFSSL_ENTER("ec_point_internal_set");
-
- /* Validate parameter. */
- if ((p == NULL) || (p->internal == NULL)) {
- WOLFSSL_MSG("ECPoint NULL error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- else {
- /* Get internal point as a wolfCrypt EC point. */
- ecc_point* point = (ecc_point*)p->internal;
-
- /* Set X ordinate if available. */
- if ((p->X != NULL) && (wolfssl_bn_get_value(p->X, point->x) != 1)) {
- WOLFSSL_MSG("ecc point X error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- /* Set Y ordinate if available. */
- if ((ret == 1) && (p->Y != NULL) && (wolfssl_bn_get_value(p->Y,
- point->y) != 1)) {
- WOLFSSL_MSG("ecc point Y error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- /* Set Z ordinate if available. */
- if ((ret == 1) && (p->Z != NULL) && (wolfssl_bn_get_value(p->Z,
- point->z) != 1)) {
- WOLFSSL_MSG("ecc point Z error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- /* Internal values set when operations succeeded. */
- p->inSet = (ret == 1);
- }
-
- return ret;
-}
-
-/* Set data of internal, wolfCrypt EC point object into EC point.
- *
- * EC_POINT WolfSSL -> OpenSSL
- *
- * @param [in, out] p EC point to update.
- * @return 1 on success.
- * @return -1 on failure.
- */
-static int ec_point_external_set(WOLFSSL_EC_POINT *p)
-{
- int ret = 1;
-
- WOLFSSL_ENTER("ec_point_external_set");
-
- /* Validate parameter. */
- if ((p == NULL) || (p->internal == NULL)) {
- WOLFSSL_MSG("ECPoint NULL error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- else {
- /* Get internal point as a wolfCrypt EC point. */
- ecc_point* point = (ecc_point*)p->internal;
-
- /* Set X ordinate. */
- if (wolfssl_bn_set_value(&p->X, point->x) != 1) {
- WOLFSSL_MSG("ecc point X error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- /* Set Y ordinate. */
- if ((ret == 1) && (wolfssl_bn_set_value(&p->Y, point->y) != 1)) {
- WOLFSSL_MSG("ecc point Y error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- /* Set Z ordinate. */
- if ((ret == 1) && (wolfssl_bn_set_value(&p->Z, point->z) != 1)) {
- WOLFSSL_MSG("ecc point Z error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- /* External values set when operations succeeded. */
- p->exSet = (ret == 1);
- }
-
- return ret;
-}
-
-/* Setup internals of EC point.
- *
- * Assumes point is not NULL.
- *
- * @param [in, out] point EC point to update.
- * @return 1 on success.
- * @return 0 on failure.
- */
-static int ec_point_setup(const WOLFSSL_EC_POINT *point) {
- int ret = 1;
-
- /* Check if internal values need setting. */
- if (!point->inSet) {
- WOLFSSL_MSG("No ECPoint internal set, do it");
-
- /* Forcing to non-constant type to update internals. */
- if (ec_point_internal_set((WOLFSSL_EC_POINT *)point) != 1) {
- WOLFSSL_MSG("ec_point_internal_set failed");
- ret = 0;
- }
- }
-
- return ret;
-}
-
-/* Create a new EC point from the group.
- *
- * @param [in] group EC group.
- * @return EC point on success.
- * @return NULL on error.
- */
-WOLFSSL_EC_POINT* wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP* group)
-{
- int err = 0;
- WOLFSSL_EC_POINT* point = NULL;
-
- WOLFSSL_ENTER("wolfSSL_EC_POINT_new");
-
- /* Validate parameter. */
- if (group == NULL) {
- WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error");
- err = 1;
- }
-
- if (!err) {
- /* Allocate memory for new EC point. */
- point = (WOLFSSL_EC_POINT*)XMALLOC(sizeof(WOLFSSL_EC_POINT), NULL,
- DYNAMIC_TYPE_ECC);
- if (point == NULL) {
- WOLFSSL_MSG("wolfSSL_EC_POINT_new malloc ecc point failure");
- err = 1;
- }
- }
- if (!err) {
- /* Clear fields of EC point. */
- XMEMSET(point, 0, sizeof(WOLFSSL_EC_POINT));
-
- /* Allocate internal EC point. */
- point->internal = wc_ecc_new_point();
- if (point->internal == NULL) {
- WOLFSSL_MSG("ecc_new_point failure");
- err = 1;
- }
- }
-
- if (err) {
- XFREE(point, NULL, DYNAMIC_TYPE_ECC);
- point = NULL;
- }
- return point;
-}
-
-#endif /* OPENSSL_EXTRA */
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-/* Dispose of the EC point.
- *
- * Cannot use point after this call.
- *
- * @param [in, out] point EC point to free.
- */
-void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *point)
-{
- WOLFSSL_ENTER("wolfSSL_EC_POINT_free");
-
- if (point != NULL) {
- if (point->internal != NULL) {
- wc_ecc_del_point((ecc_point*)point->internal);
- point->internal = NULL;
- }
-
- /* Free ordinates. */
- wolfSSL_BN_free(point->X);
- wolfSSL_BN_free(point->Y);
- wolfSSL_BN_free(point->Z);
- /* Clear fields. */
- point->X = NULL;
- point->Y = NULL;
- point->Z = NULL;
- point->inSet = 0;
- point->exSet = 0;
-
- /* Dispose of EC point. */
- XFREE(point, NULL, DYNAMIC_TYPE_ECC);
- }
-}
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-
-#ifdef OPENSSL_EXTRA
-
-/* Clear and dispose of the EC point.
- *
- * Cannot use point after this call.
- *
- * @param [in, out] point EC point to free.
- */
-void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *point)
-{
- WOLFSSL_ENTER("wolfSSL_EC_POINT_clear_free");
-
- if (point != NULL) {
- if (point->internal != NULL) {
- /* Force internal point to be zeros. */
- #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
- wc_ecc_forcezero_point((ecc_point*)point->internal);
- #else
- ecc_point* p = (ecc_point*)point->internal;
- mp_forcezero(p->x);
- mp_forcezero(p->y);
- mp_forcezero(p->z);
- #endif
- wc_ecc_del_point((ecc_point*)point->internal);
- point->internal = NULL;
- }
-
- /* Clear the ordinates before freeing. */
- wolfSSL_BN_clear_free(point->X);
- wolfSSL_BN_clear_free(point->Y);
- wolfSSL_BN_clear_free(point->Z);
- /* Clear fields. */
- point->X = NULL;
- point->Y = NULL;
- point->Z = NULL;
- point->inSet = 0;
- point->exSet = 0;
-
- /* Dispose of EC point. */
- XFREE(point, NULL, DYNAMIC_TYPE_ECC);
- }
-}
-
-/* Print out the internals of EC point in debug and when logging callback set.
- *
- * Not an OpenSSL API.
- *
- * TODO: Use WOLFSSL_MSG_EX()?
- *
- * @param [in] msg Message to prepend.
- * @param [in] point EC point to print.
- */
-void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *point)
-{
-#if defined(DEBUG_WOLFSSL)
- char *num;
-
- WOLFSSL_ENTER("wolfSSL_EC_POINT_dump");
-
- /* Only print when debugging on. */
- if (WOLFSSL_IS_DEBUG_ON()) {
- if (point == NULL) {
- /* No point passed in so just put out "NULL". */
- WOLFSSL_MSG_EX("%s = NULL\n", msg);
- }
- else {
- /* Put out message and status of internal/external data set. */
- WOLFSSL_MSG_EX("%s:\n\tinSet=%d, exSet=%d\n", msg, point->inSet,
- point->exSet);
- /* Get x-ordinate as a hex string and print. */
- num = wolfSSL_BN_bn2hex(point->X);
- WOLFSSL_MSG_EX("\tX = %s\n", num);
- XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL);
- /* Get x-ordinate as a hex string and print. */
- num = wolfSSL_BN_bn2hex(point->Y);
- WOLFSSL_MSG_EX("\tY = %s\n", num);
- XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL);
- /* Get z-ordinate as a hex string and print. */
- num = wolfSSL_BN_bn2hex(point->Z);
- WOLFSSL_MSG_EX("\tZ = %s\n", num);
- XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- }
-#else
- (void)msg;
- (void)point;
-#endif
-}
-
-/* Convert EC point to hex string that as either uncompressed or compressed.
- *
- * ECC point compression types were not included in selftest ecc.h
- *
- * @param [in] group EC group for point.
- * @param [in] point EC point to encode.
- * @param [in] form Format of encoding. Valid values:
- * POINT_CONVERSION_UNCOMPRESSED, POINT_CONVERSION_COMPRESSED
- * @param [in] ctx Context to use for BN operations. Unused.
- * @return Allocated hex string on success.
- * @return NULL on error.
- */
-char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group,
- const WOLFSSL_EC_POINT* point, int form, WOLFSSL_BN_CTX* ctx)
-{
- static const char* hexDigit = "0123456789ABCDEF";
- char* hex = NULL;
- int i;
- int sz = 0;
- int len = 0;
- int err = 0;
-
- /* No BN operations performed. */
- (void)ctx;
-
- /* Validate parameters. */
- if ((group == NULL) || (point == NULL)) {
- err = 1;
- }
- /* Get curve id expects a positive index. */
- if ((!err) && (group->curve_idx < 0)) {
- err = 1;
- }
-
- if (!err) {
- /* Get curve id to look up ordinate size. */
- int id = wc_ecc_get_curve_id(group->curve_idx);
- /* Get size of ordinate. */
- if ((sz = wc_ecc_get_curve_size_from_id(id)) < 0) {
- err = 1;
- }
- }
- if (!err) {
- /* [] */
- len = sz + 1;
- if (form == WC_POINT_CONVERSION_UNCOMPRESSED) {
- /* Include y ordinate when uncompressed. */
- len += sz;
- }
-
- /* Hex string: allocate 2 bytes to represent each byte plus 1 for '\0'.
- */
- hex = (char*)XMALLOC((size_t)(2 * len + 1), NULL, DYNAMIC_TYPE_ECC);
- if (hex == NULL) {
- err = 1;
- }
- }
- if (!err) {
- /* Make bytes all zeros to allow for ordinate values less than max size.
- */
- XMEMSET(hex, 0, (size_t)(2 * len + 1));
-
- /* Calculate offset as leading zeros not encoded. */
- i = sz - mp_unsigned_bin_size((mp_int*)point->X->internal) + 1;
- /* Put in x-ordinate after format byte. */
- if (mp_to_unsigned_bin((mp_int*)point->X->internal, (byte*)(hex + i)) <
- 0) {
- err = 1;
- }
- }
- if (!err) {
- if (form == WC_POINT_CONVERSION_COMPRESSED) {
- /* Compressed format byte value dependent on whether y-ordinate is
- * odd.
- */
- hex[0] = mp_isodd((mp_int*)point->Y->internal) ?
- ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN;
- /* No y-ordinate. */
- }
- else {
- /* Put in uncompressed format byte. */
- hex[0] = ECC_POINT_UNCOMP;
- /* Calculate offset as leading zeros not encoded. */
- i = 1 + 2 * sz - mp_unsigned_bin_size((mp_int*)point->Y->internal);
- /* Put in y-ordinate after x-ordinate. */
- if (mp_to_unsigned_bin((mp_int*)point->Y->internal,
- (byte*)(hex + i)) < 0) {
- err = 1;
- }
- }
- }
- if (!err) {
- /* Convert binary encoding to hex string. */
- /* Start at end so as not to overwrite. */
- for (i = len-1; i >= 0; i--) {
- /* Get byte value and store has hex string. */
- byte b = (byte)hex[i];
- hex[i * 2 + 1] = hexDigit[b & 0xf];
- hex[i * 2 ] = hexDigit[b >> 4];
- }
- /* Memset put trailing zero or '\0' on end of string. */
- }
-
- if (err && (hex != NULL)) {
- /* Dispose of allocated data not being returned. */
- XFREE(hex, NULL, DYNAMIC_TYPE_ECC);
- hex = NULL;
- }
- /* Return hex string encoding. */
- return hex;
-}
-
-static size_t hex_to_bytes(const char *hex, unsigned char *output, size_t sz)
-{
- word32 i;
- for (i = 0; i < sz; i++) {
- signed char ch1, ch2;
- ch1 = HexCharToByte(hex[i * 2]);
- ch2 = HexCharToByte(hex[i * 2 + 1]);
- if ((ch1 < 0) || (ch2 < 0)) {
- WOLFSSL_MSG("hex_to_bytes: syntax error");
- return 0;
- }
- output[i] = (unsigned char)((ch1 << 4) + ch2);
- }
- return sz;
-}
-
-WOLFSSL_EC_POINT* wolfSSL_EC_POINT_hex2point(const WOLFSSL_EC_GROUP *group,
- const char *hex, WOLFSSL_EC_POINT*p, WOLFSSL_BN_CTX *ctx)
-{
- /* for uncompressed mode */
- size_t str_sz;
- WOLFSSL_BIGNUM *Gx = NULL;
- WOLFSSL_BIGNUM *Gy = NULL;
- char strGx[MAX_ECC_BYTES * 2 + 1];
-
- /* for compressed mode */
- int key_sz;
- byte *octGx = (byte *)strGx; /* octGx[MAX_ECC_BYTES] */
-
- int p_alloc = 0;
- int ret;
-
- WOLFSSL_ENTER("wolfSSL_EC_POINT_hex2point");
-
- if (group == NULL || hex == NULL || ctx == NULL)
- return NULL;
-
- if (p == NULL) {
- if ((p = wolfSSL_EC_POINT_new(group)) == NULL) {
- WOLFSSL_MSG("wolfSSL_EC_POINT_new");
- goto err;
- }
- p_alloc = 1;
- }
-
- key_sz = (wolfSSL_EC_GROUP_get_degree(group) + 7) / 8;
- if (hex[0] == '0' && hex[1] == '4') { /* uncompressed mode */
- str_sz = (size_t)key_sz * 2;
-
- XMEMSET(strGx, 0x0, str_sz + 1);
- XMEMCPY(strGx, hex + 2, str_sz);
-
- if (wolfSSL_BN_hex2bn(&Gx, strGx) == 0)
- goto err;
-
- if (wolfSSL_BN_hex2bn(&Gy, hex + 2 + str_sz) == 0)
- goto err;
-
- ret = wolfSSL_EC_POINT_set_affine_coordinates_GFp
- (group, p, Gx, Gy, ctx);
-
- if (ret != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp");
- goto err;
- }
- }
- else if (hex[0] == '0' && (hex[1] == '2' || hex[1] == '3')) {
- size_t sz = XSTRLEN(hex + 2) / 2;
- /* compressed mode */
- octGx[0] = ECC_POINT_COMP_ODD;
- if (hex_to_bytes(hex + 2, octGx + 1, sz) != sz) {
- goto err;
- }
- if (wolfSSL_ECPoint_d2i(octGx, (word32)key_sz + 1, group, p)
- != WOLFSSL_SUCCESS) {
- goto err;
- }
- }
- else
- goto err;
-
- wolfSSL_BN_free(Gx);
- wolfSSL_BN_free(Gy);
- return p;
-
-err:
- wolfSSL_BN_free(Gx);
- wolfSSL_BN_free(Gy);
- if (p_alloc) {
- wolfSSL_EC_POINT_free(p);
- }
- return NULL;
-
-}
-
-/* Encode the EC point as an uncompressed point in DER.
- *
- * Return code compliant with OpenSSL.
- * Not OpenSSL API.
- *
- * @param [in] group EC group point belongs to.
- * @param [in] point EC point to encode.
- * @param [out] out Buffer to encode into. May be NULL.
- * @param [in, out] len On in, length of buffer in bytes.
- * On out, length of encoding in bytes.
- * @return 1 on success.
- * @return 0 on error.
- */
-int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group,
- const WOLFSSL_EC_POINT *point, unsigned char *out, unsigned int *len)
-{
- int res = 1;
-
- WOLFSSL_ENTER("wolfSSL_ECPoint_i2d");
-
- /* Validate parameters. */
- if ((group == NULL) || (point == NULL) || (len == NULL)) {
- WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error");
- res = 0;
- }
-
- /* Ensure points internals are set up. */
- if ((res == 1) && (ec_point_setup(point) != 1)) {
- res = 0;
- }
-
- /* Dump the point if encoding. */
- if ((res == 1) && (out != NULL)) {
- wolfSSL_EC_POINT_dump("i2d p", point);
- }
-
- if (res == 1) {
- /* DER encode point in uncompressed format. */
- int ret = wc_ecc_export_point_der(group->curve_idx,
- (ecc_point*)point->internal, out, len);
- /* Check return. When out is NULL, return will be length only error. */
- if ((ret != MP_OKAY) && ((out != NULL) ||
- (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)))) {
- WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed");
- res = 0;
- }
- }
-
- return res;
-}
-
-/* Decode the uncompressed point in DER into EC point.
- *
- * Return code compliant with OpenSSL.
- * Not OpenSSL API.
- *
- * @param [in] in Buffer containing DER encoded point.
- * @param [in] len Length of data in bytes.
- * @param [in] group EC group associated with point.
- * @param [in, out] point EC point to set data into.
- * @return 1 on success.
- * @return 0 on error.
- */
-int wolfSSL_ECPoint_d2i(const unsigned char *in, unsigned int len,
- const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *point)
-{
- int ret = 1;
- WOLFSSL_BIGNUM* x = NULL;
- WOLFSSL_BIGNUM* y = NULL;
-
- WOLFSSL_ENTER("wolfSSL_ECPoint_d2i");
-
- /* Validate parameters. */
- if ((in == NULL) || (group == NULL) || (point == NULL) ||
- (point->internal == NULL)) {
- WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error");
- ret = 0;
- }
-
- if (ret == 1) {
- #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
- /* Import point into internal EC point. */
- if (wc_ecc_import_point_der_ex(in, len, group->curve_idx,
- (ecc_point*)point->internal, 0) != MP_OKAY) {
- WOLFSSL_MSG("wc_ecc_import_point_der_ex failed");
- ret = 0;
- }
- #else
- /* ECC_POINT_UNCOMP is not defined CAVP self test so use magic number */
- if (in[0] == 0x04) {
- /* Import point into internal EC point. */
- if (wc_ecc_import_point_der((unsigned char *)in, len,
- group->curve_idx, (ecc_point*)point->internal) != MP_OKAY) {
- WOLFSSL_MSG("wc_ecc_import_point_der failed");
- ret = 0;
- }
- }
- else {
- WOLFSSL_MSG("Only uncompressed points supported with "
- "HAVE_SELFTEST");
- ret = 0;
- }
- #endif
- }
-
- if (ret == 1)
- point->inSet = 1;
-
- /* Set new external point. */
- if (ret == 1 && ec_point_external_set(point) != 1) {
- WOLFSSL_MSG("ec_point_external_set failed");
- ret = 0;
- }
-
- if (ret == 1 && !wolfSSL_BN_is_one(point->Z)) {
-#if !defined(WOLFSSL_SP_MATH) && !defined(WOLF_CRYPTO_CB_ONLY_ECC)
- x = wolfSSL_BN_new();
- y = wolfSSL_BN_new();
- if (x == NULL || y == NULL)
- ret = 0;
-
- if (ret == 1 && wolfSSL_EC_POINT_get_affine_coordinates_GFp(group,
- point, x, y, NULL) != 1) {
- WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp failed");
- ret = 0;
- }
-
- /* wolfSSL_EC_POINT_set_affine_coordinates_GFp check that the point is
- * on the curve. */
- if (ret == 1 && wolfSSL_EC_POINT_set_affine_coordinates_GFp(group,
- point, x, y, NULL) != 1) {
- WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp failed");
- ret = 0;
- }
-#else
- WOLFSSL_MSG("Importing non-affine point. This may cause issues in math "
- "operations later on.");
-#endif
- }
-
- if (ret == 1) {
- /* Dump new point. */
- wolfSSL_EC_POINT_dump("d2i p", point);
- }
-
- wolfSSL_BN_free(x);
- wolfSSL_BN_free(y);
-
- return ret;
-}
-
-/* Encode point as octet string.
- *
- * HYBRID not supported.
- *
- * @param [in] group EC group that point belongs to.
- * @param [in] point EC point to encode.
- * @param [in] form Format of encoding. Valid values:
- * POINT_CONVERSION_UNCOMPRESSED,POINT_CONVERSION_COMPRESSED
- * @param [out] buf Buffer to write encoding into.
- * @param [in] len Length of buffer.
- * @param [in] ctx Context to use for BN operations. Unused.
- * @return Length of encoded data on success.
- * @return 0 on error.
- */
-size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group,
- const WOLFSSL_EC_POINT *point, int form, byte *buf, size_t len,
- WOLFSSL_BN_CTX *ctx)
-{
- int err = 0;
- word32 enc_len = (word32)len;
-#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
- int compressed = ((form == WC_POINT_CONVERSION_COMPRESSED) ? 1 : 0);
-#endif /* !HAVE_SELFTEST */
-
- WOLFSSL_ENTER("wolfSSL_EC_POINT_point2oct");
-
- /* No BN operations performed. */
- (void)ctx;
-
- /* Validate parameters. */
- if ((group == NULL) || (point == NULL)) {
- err = 1;
- }
-
- /* Ensure points internals are set up. */
- if ((!err) && (ec_point_setup(point) != 1)) {
- err = 1;
- }
-
- /* Special case when point is infinity. */
- if ((!err) && wolfSSL_EC_POINT_is_at_infinity(group, point)) {
- /* Encoding is a single octet: 0x00. */
- enc_len = 1;
- if (buf != NULL) {
- /* Check whether buffer has space. */
- if (len < 1) {
- wolfSSL_ECerr(WOLFSSL_EC_F_EC_GFP_SIMPLE_POINT2OCT, BUFFER_E);
- err = 1;
- }
- else {
- /* Put in encoding of infinity. */
- buf[0] = 0x00;
- }
- }
- }
- /* Not infinity. */
- else if (!err) {
- /* Validate format. */
- if (form != WC_POINT_CONVERSION_UNCOMPRESSED
- #ifndef HAVE_SELFTEST
- && form != WC_POINT_CONVERSION_COMPRESSED
- #endif /* !HAVE_SELFTEST */
- ) {
- WOLFSSL_MSG("Unsupported point form");
- err = 1;
- }
-
- if (!err) {
- int ret;
-
- #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
- /* Encode as compressed or uncompressed. */
- ret = wc_ecc_export_point_der_ex(group->curve_idx,
- (ecc_point*)point->internal, buf, &enc_len, compressed);
- #else
- /* Encode uncompressed point in DER format. */
- ret = wc_ecc_export_point_der(group->curve_idx,
- (ecc_point*)point->internal, buf, &enc_len);
- #endif /* !HAVE_SELFTEST */
- /* Check return. When buf is NULL, return will be length only
- * error.
- */
- if (ret != ((buf != NULL) ? MP_OKAY : WC_NO_ERR_TRACE(LENGTH_ONLY_E))) {
- err = 1;
- }
- }
- }
-
-#if defined(DEBUG_WOLFSSL)
- if (!err) {
- wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_point2oct point", point);
- WOLFSSL_MSG("\twolfSSL_EC_POINT_point2oct output:");
- WOLFSSL_BUFFER(buf, enc_len);
- }
-#endif
-
- /* On error, return encoding length of 0. */
- if (err) {
- enc_len = 0;
- }
- return (size_t)enc_len;
-}
-
-
-/* Convert octet string to EC point.
- *
- * @param [in] group EC group.
- * @param [in, out] point EC point to set data into.
- * @param [in] buf Buffer holding octet string.
- * @param [in] len Length of data in buffer in bytes.
- * @param [in] ctx Context to use for BN operations. Unused.
- */
-int wolfSSL_EC_POINT_oct2point(const WOLFSSL_EC_GROUP *group,
- WOLFSSL_EC_POINT *point, const unsigned char *buf, size_t len,
- WOLFSSL_BN_CTX *ctx)
-{
- int ret;
-
- WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point");
-
- /* No BN operations performed. */
- (void)ctx;
-
- /* Validate parameters. */
- if ((group == NULL) || (point == NULL)) {
- ret = 0;
- }
- else {
- /* Decode DER encoding into EC point. */
- ret = wolfSSL_ECPoint_d2i((unsigned char*)buf, (unsigned int)len, group,
- point);
- }
-
- return ret;
-}
-
-/* Convert an EC point to a single BN.
- *
- * @param [in] group EC group.
- * @param [in] point EC point.
- * @param [in] form Format of encoding. Valid values:
- * WC_POINT_CONVERSION_UNCOMPRESSED,
- * WC_POINT_CONVERSION_COMPRESSED.
- * @param [in, out] bn BN to hold point value.
- * When NULL a new BN is allocated otherwise this is
- * returned on success.
- * @param [in] ctx Context to use for BN operations. Unused.
- * @return BN object with point as a value on success.
- * @return NULL on error.
- */
-WOLFSSL_BIGNUM *wolfSSL_EC_POINT_point2bn(const WOLFSSL_EC_GROUP* group,
- const WOLFSSL_EC_POINT* point, int form, WOLFSSL_BIGNUM* bn,
- WOLFSSL_BN_CTX* ctx)
-{
- int err = 0;
- size_t len = 0;
- byte *buf = NULL;
- WOLFSSL_BIGNUM *ret = NULL;
-
- WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point");
-
- /* Validate parameters. */
- if ((group == NULL) || (point == NULL)) {
- err = 1;
- }
-
- /* Calculate length of octet encoding. */
- if ((!err) && ((len = wolfSSL_EC_POINT_point2oct(group, point, form, NULL,
- 0, ctx)) == 0)) {
- err = 1;
- }
- /* Allocate buffer to hold octet encoding. */
- if ((!err) && ((buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER)) ==
- NULL)) {
- WOLFSSL_MSG("malloc failed");
- err = 1;
- }
- /* Encode EC point as an octet string. */
- if ((!err) && (wolfSSL_EC_POINT_point2oct(group, point, form, buf, len,
- ctx) != len)) {
- err = 1;
- }
- /* Load BN with octet string data. */
- if (!err) {
- ret = wolfSSL_BN_bin2bn(buf, (int)len, bn);
- }
-
- /* Dispose of any allocated data. */
- XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
- return ret;
-}
-
-#if defined(USE_ECC_B_PARAM) && !defined(HAVE_SELFTEST) && \
- (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
-/* Check if EC point is on the the curve defined by the EC group.
- *
- * @param [in] group EC group defining curve.
- * @param [in] point EC point to check.
- * @param [in] ctx Context to use for BN operations. Unused.
- * @return 1 when point is on curve.
- * @return 0 when point is not on curve or error.
- */
-int wolfSSL_EC_POINT_is_on_curve(const WOLFSSL_EC_GROUP *group,
- const WOLFSSL_EC_POINT *point, WOLFSSL_BN_CTX *ctx)
-{
- int err = 0;
-
- WOLFSSL_ENTER("wolfSSL_EC_POINT_is_on_curve");
-
- /* No BN operations performed. */
- (void)ctx;
-
- /* Validate parameters. */
- if ((group == NULL) || (point == NULL)) {
- WOLFSSL_MSG("Invalid arguments");
- err = 1;
- }
-
- /* Ensure internal EC point set. */
- if ((!err) && (!point->inSet) && ec_point_internal_set(
- (WOLFSSL_EC_POINT*)point) != 1) {
- WOLFSSL_MSG("ec_point_internal_set error");
- err = 1;
- }
-
- /* Check point is on curve from group. */
- if ((!err) && (wc_ecc_point_is_on_curve((ecc_point*)point->internal,
- group->curve_idx) != MP_OKAY)) {
- err = 1;
- }
-
- /* Return boolean of on curve. No error means on curve. */
- return !err;
-}
-#endif /* USE_ECC_B_PARAM && !HAVE_SELFTEST && !(FIPS_VERSION <= 2) */
-
-#if !defined(WOLFSSL_SP_MATH) && !defined(WOLF_CRYPTO_CB_ONLY_ECC)
-/* Convert Jacobian ordinates to affine.
- *
- * @param [in] group EC group.
- * @param [in] point EC point to get coordinates from.
- * @return 1 on success.
- * @return 0 on error.
- */
-int ec_point_convert_to_affine(const WOLFSSL_EC_GROUP *group,
- WOLFSSL_EC_POINT *point)
-{
- int err = 0;
- mp_digit mp = 0;
- WC_DECLARE_VAR(modulus, mp_int, 1, 0);
-
- /* Allocate memory for curve's prime modulus. */
- WC_ALLOC_VAR_EX(modulus, mp_int, 1, NULL, DYNAMIC_TYPE_BIGINT, err=1);
- /* Initialize the MP integer. */
- if ((!err) && (mp_init(modulus) != MP_OKAY)) {
- WOLFSSL_MSG("mp_init failed");
- err = 1;
- }
-
- if (!err) {
- /* Get the modulus from the hex string in the EC curve set. */
- if (mp_read_radix(modulus, ecc_sets[group->curve_idx].prime,
- MP_RADIX_HEX) != MP_OKAY) {
- WOLFSSL_MSG("mp_read_radix failed");
- err = 1;
- }
- /* Get Montgomery multiplier for the modulus as ordinates in
- * Montgomery form.
- */
- if ((!err) && (mp_montgomery_setup(modulus, &mp) != MP_OKAY)) {
- WOLFSSL_MSG("mp_montgomery_setup failed");
- err = 1;
- }
- /* Map internal EC point from Jacobian to affine. */
- if ((!err) && (ecc_map((ecc_point*)point->internal, modulus, mp) !=
- MP_OKAY)) {
- WOLFSSL_MSG("ecc_map failed");
- err = 1;
- }
- /* Set new ordinates into external EC point. */
- if ((!err) && (ec_point_external_set((WOLFSSL_EC_POINT *)point) != 1)) {
- WOLFSSL_MSG("ec_point_external_set failed");
- err = 1;
- }
-
- point->exSet = !err;
- mp_clear(modulus);
- }
-
- WC_FREE_VAR_EX(modulus, NULL, DYNAMIC_TYPE_BIGINT);
-
- return err;
-}
-
-/* Get the affine coordinates of the EC point on a Prime curve.
- *
- * When z-ordinate is not one then coordinates are Jacobian and need to be
- * converted to affine before storing in BNs.
- *
- * Return code compliant with OpenSSL.
- *
- * TODO: OpenSSL doesn't change point when Jacobian. Do the same?
- *
- * @param [in] group EC group.
- * @param [in] point EC point to get coordinates from.
- * @param [in, out] x BN to hold x-ordinate.
- * @param [in, out] y BN to hold y-ordinate.
- * @param [in] ctx Context to use for BN operations. Unused.
- * @return 1 on success.
- * @return 0 on error.
- */
-int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP* group,
- const WOLFSSL_EC_POINT* point, WOLFSSL_BIGNUM* x, WOLFSSL_BIGNUM* y,
- WOLFSSL_BN_CTX* ctx)
-{
- int ret = 1;
-
- /* BN operations don't need context. */
- (void)ctx;
-
- WOLFSSL_ENTER("wolfSSL_EC_POINT_get_affine_coordinates_GFp");
-
- /* Validate parameters. */
- if ((group == NULL) || (point == NULL) || (point->internal == NULL) ||
- (x == NULL) || (y == NULL)) {
- WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp NULL error");
- ret = 0;
- }
- /* Don't return point at infinity. */
- if ((ret == 1) && wolfSSL_EC_POINT_is_at_infinity(group, point)) {
- ret = 0;
- }
-
- /* Ensure internal EC point has values of external EC point. */
- if ((ret == 1) && (ec_point_setup(point) != 1)) {
- ret = 0;
- }
-
- /* Check whether ordinates are in Jacobian form. */
- if ((ret == 1) && (!wolfSSL_BN_is_one(point->Z))) {
- /* Convert from Jacobian to affine. */
- if (ec_point_convert_to_affine(group, (WOLFSSL_EC_POINT*)point) == 1) {
- ret = 0;
- }
- }
-
- /* Copy the externally set x and y ordinates. */
- if ((ret == 1) && (wolfSSL_BN_copy(x, point->X) == NULL)) {
- ret = 0;
- }
- if ((ret == 1) && (wolfSSL_BN_copy(y, point->Y) == NULL)) {
- ret = 0;
- }
-
- return ret;
-}
-#endif /* !WOLFSSL_SP_MATH && !WOLF_CRYPTO_CB_ONLY_ECC */
-
-/* Sets the affine coordinates that belong on a prime curve.
- *
- * @param [in] group EC group.
- * @param [in, out] point EC point to set coordinates into.
- * @param [in] x BN holding x-ordinate.
- * @param [in] y BN holding y-ordinate.
- * @param [in] ctx Context to use for BN operations. Unused.
- * @return 1 on success.
- * @return 0 on error.
- */
-int wolfSSL_EC_POINT_set_affine_coordinates_GFp(const WOLFSSL_EC_GROUP* group,
- WOLFSSL_EC_POINT* point, const WOLFSSL_BIGNUM* x, const WOLFSSL_BIGNUM* y,
- WOLFSSL_BN_CTX* ctx)
-{
- int ret = 1;
-
- /* BN operations don't need context. */
- (void)ctx;
-
- WOLFSSL_ENTER("wolfSSL_EC_POINT_set_affine_coordinates_GFp");
-
- /* Validate parameters. */
- if ((group == NULL) || (point == NULL) || (point->internal == NULL) ||
- (x == NULL) || (y == NULL)) {
- WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp NULL error");
- ret = 0;
- }
-
- /* Ensure we have a object for x-ordinate. */
- if ((ret == 1) && (point->X == NULL) &&
- ((point->X = wolfSSL_BN_new()) == NULL)) {
- WOLFSSL_MSG("wolfSSL_BN_new failed");
- ret = 0;
- }
- /* Ensure we have a object for y-ordinate. */
- if ((ret == 1) && (point->Y == NULL) &&
- ((point->Y = wolfSSL_BN_new()) == NULL)) {
- WOLFSSL_MSG("wolfSSL_BN_new failed");
- ret = 0;
- }
- /* Ensure we have a object for z-ordinate. */
- if ((ret == 1) && (point->Z == NULL) &&
- ((point->Z = wolfSSL_BN_new()) == NULL)) {
- WOLFSSL_MSG("wolfSSL_BN_new failed");
- ret = 0;
- }
-
- /* Copy the x-ordinate. */
- if ((ret == 1) && ((wolfSSL_BN_copy(point->X, x)) == NULL)) {
- WOLFSSL_MSG("wolfSSL_BN_copy failed");
- ret = 0;
- }
- /* Copy the y-ordinate. */
- if ((ret == 1) && ((wolfSSL_BN_copy(point->Y, y)) == NULL)) {
- WOLFSSL_MSG("wolfSSL_BN_copy failed");
- ret = 0;
- }
- /* z-ordinate is one for affine coordinates. */
- if ((ret == 1) && ((wolfSSL_BN_one(point->Z)) == 0)) {
- WOLFSSL_MSG("wolfSSL_BN_one failed");
- ret = 0;
- }
-
- /* Copy the new point data to internal object. */
- if ((ret == 1) && (ec_point_internal_set((WOLFSSL_EC_POINT *)point) != 1)) {
- WOLFSSL_MSG("ec_point_internal_set failed");
- ret = 0;
- }
-
-#if defined(USE_ECC_B_PARAM) && !defined(HAVE_SELFTEST) && \
- (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
- /* Check that the point is valid. */
- if ((ret == 1) && (wolfSSL_EC_POINT_is_on_curve(group,
- (WOLFSSL_EC_POINT *)point, ctx) != 1)) {
- WOLFSSL_MSG("EC_POINT_is_on_curve failed");
- ret = 0;
- }
-#endif
-
- return ret;
-}
-
-#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \
- !defined(HAVE_SELFTEST) && !defined(WOLFSSL_SP_MATH) && \
- !defined(WOLF_CRYPTO_CB_ONLY_ECC)
-/* Add two points on the same together.
- *
- * @param [in] curveIdx Index of curve in ecc_set.
- * @param [out] r Result point.
- * @param [in] p1 First point to add.
- * @param [in] p2 Second point to add.
- * @return 1 on success.
- * @return 0 on error.
- */
-static int wolfssl_ec_point_add(int curveIdx, ecc_point* r, ecc_point* p1,
- ecc_point* p2)
-{
- int ret = 1;
-#ifdef WOLFSSL_SMALL_STACK
- mp_int* a = NULL;
- mp_int* prime = NULL;
- mp_int* mu = NULL;
-#else
- mp_int a[1];
- mp_int prime[1];
- mp_int mu[1];
-#endif
- mp_digit mp = 0;
- ecc_point* montP1 = NULL;
- ecc_point* montP2 = NULL;
-
-#ifdef WOLFSSL_SMALL_STACK
- if (ret == 1) {
- /* Allocate memory for curve parameter: a. */
- a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
- if (a == NULL) {
- WOLFSSL_MSG("Failed to allocate memory for mp_int a");
- ret = 0;
- }
- }
- if (ret == 1) {
- /* Allocate memory for curve parameter: prime. */
- prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
- if (prime == NULL) {
- WOLFSSL_MSG("Failed to allocate memory for mp_int prime");
- ret = 0;
- }
- }
- if (ret == 1) {
- /* Allocate memory for mu (Montgomery normalizer). */
- mu = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
- if (mu == NULL) {
- WOLFSSL_MSG("Failed to allocate memory for mp_int mu");
- ret = 0;
- }
- }
- if (ret == 1) {
- /* Zero out all MP int data in case initialization fails. */
- XMEMSET(a, 0, sizeof(mp_int));
- XMEMSET(prime, 0, sizeof(mp_int));
- XMEMSET(mu, 0, sizeof(mp_int));
- }
-#endif
-
- /* Initialize the MP ints. */
- if ((ret == 1) && (mp_init_multi(prime, a, mu, NULL, NULL, NULL) !=
- MP_OKAY)) {
- WOLFSSL_MSG("mp_init_multi error");
- ret = 0;
- }
-
- /* Read the curve parameter: a. */
- if ((ret == 1) && (mp_read_radix(a, ecc_sets[curveIdx].Af, MP_RADIX_HEX) !=
- MP_OKAY)) {
- WOLFSSL_MSG("mp_read_radix a error");
- ret = 0;
- }
-
- /* Read the curve parameter: prime. */
- if ((ret == 1) && (mp_read_radix(prime, ecc_sets[curveIdx].prime,
- MP_RADIX_HEX) != MP_OKAY)) {
- WOLFSSL_MSG("mp_read_radix prime error");
- ret = 0;
- }
-
- /* Calculate the Montgomery product. */
- if ((ret == 1) && (mp_montgomery_setup(prime, &mp) != MP_OKAY)) {
- WOLFSSL_MSG("mp_montgomery_setup nqm error");
- ret = 0;
- }
-
- /* TODO: use the heap filed of one of the points? */
- /* Allocate new points to hold the Montgomery form values. */
- if ((ret == 1) && (((montP1 = wc_ecc_new_point_h(NULL)) == NULL) ||
- ((montP2 = wc_ecc_new_point_h(NULL)) == NULL))) {
- WOLFSSL_MSG("wc_ecc_new_point_h nqm error");
- ret = 0;
- }
-
- /* Calculate the Montgomery normalizer. */
- if ((ret == 1) && (mp_montgomery_calc_normalization(mu, prime) !=
- MP_OKAY)) {
- WOLFSSL_MSG("mp_montgomery_calc_normalization error");
- ret = 0;
- }
-
- /* Convert to Montgomery form. */
- if ((ret == 1) && (mp_cmp_d(mu, 1) == MP_EQ)) {
- /* Copy the points if the normalizer is 1. */
- if ((wc_ecc_copy_point(p1, montP1) != MP_OKAY) ||
- (wc_ecc_copy_point(p2, montP2) != MP_OKAY)) {
- WOLFSSL_MSG("wc_ecc_copy_point error");
- ret = 0;
- }
- }
- else if (ret == 1) {
- /* Multiply each ordinate by the Montgomery normalizer. */
- if ((mp_mulmod(p1->x, mu, prime, montP1->x) != MP_OKAY) ||
- (mp_mulmod(p1->y, mu, prime, montP1->y) != MP_OKAY) ||
- (mp_mulmod(p1->z, mu, prime, montP1->z) != MP_OKAY)) {
- WOLFSSL_MSG("mp_mulmod error");
- ret = 0;
- }
- /* Multiply each ordinate by the Montgomery normalizer. */
- if ((mp_mulmod(p2->x, mu, prime, montP2->x) != MP_OKAY) ||
- (mp_mulmod(p2->y, mu, prime, montP2->y) != MP_OKAY) ||
- (mp_mulmod(p2->z, mu, prime, montP2->z) != MP_OKAY)) {
- WOLFSSL_MSG("mp_mulmod error");
- ret = 0;
- }
- }
-
- /* Perform point addition with internal EC point objects - Jacobian form
- * result.
- */
- if ((ret == 1) && (ecc_projective_add_point(montP1, montP2, r, a, prime,
- mp) != MP_OKAY)) {
- WOLFSSL_MSG("ecc_projective_add_point error");
- ret = 0;
- }
-
- /* Map point back to affine coordinates. Converts from Montogomery form. */
- if ((ret == 1) && (ecc_map(r, prime, mp) != MP_OKAY)) {
- WOLFSSL_MSG("ecc_map error");
- ret = 0;
- }
-
- /* Dispose of allocated memory. */
- mp_clear(a);
- mp_clear(prime);
- mp_clear(mu);
- wc_ecc_del_point_h(montP1, NULL);
- wc_ecc_del_point_h(montP2, NULL);
- WC_FREE_VAR_EX(a, NULL, DYNAMIC_TYPE_BIGINT);
- WC_FREE_VAR_EX(prime, NULL, DYNAMIC_TYPE_BIGINT);
- WC_FREE_VAR_EX(mu, NULL, DYNAMIC_TYPE_BIGINT);
- return ret;
-}
-
-/* Add two points on the same curve together.
- *
- * @param [in] group EC group.
- * @param [out] r EC point that is result of point addition.
- * @param [in] p1 First EC point to add.
- * @param [in] p2 Second EC point to add.
- * @param [in] ctx Context to use for BN operations. Unused.
- * @return 1 on success.
- * @return 0 on error.
- */
-int wolfSSL_EC_POINT_add(const WOLFSSL_EC_GROUP* group, WOLFSSL_EC_POINT* r,
- const WOLFSSL_EC_POINT* p1, const WOLFSSL_EC_POINT* p2, WOLFSSL_BN_CTX* ctx)
-{
- int ret = 1;
-
- /* No BN operations performed. */
- (void)ctx;
-
- /* Validate parameters. */
- if ((group == NULL) || (r == NULL) || (p1 == NULL) || (p2 == NULL)) {
- WOLFSSL_MSG("wolfSSL_EC_POINT_add error");
- ret = 0;
- }
-
- /* Ensure the internal objects of the EC points are setup. */
- if ((ret == 1) && ((ec_point_setup(r) != 1) || (ec_point_setup(p1) != 1) ||
- (ec_point_setup(p2) != 1))) {
- WOLFSSL_MSG("ec_point_setup error");
- ret = 0;
- }
-
-#ifdef DEBUG_WOLFSSL
- if (ret == 1) {
- int nid = wolfSSL_EC_GROUP_get_curve_name(group);
- const char* curve = wolfSSL_OBJ_nid2ln(nid);
- const char* nistName = wolfSSL_EC_curve_nid2nist(nid);
- wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_add p1", p1);
- wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_add p2", p2);
- if (curve != NULL)
- WOLFSSL_MSG_EX("curve name: %s", curve);
- if (nistName != NULL)
- WOLFSSL_MSG_EX("nist curve name: %s", nistName);
- }
-#endif
-
- if (ret == 1) {
- /* Add points using wolfCrypt objects. */
- ret = wolfssl_ec_point_add(group->curve_idx, (ecc_point*)r->internal,
- (ecc_point*)p1->internal, (ecc_point*)p2->internal);
- }
-
- /* Copy internal EC point values out to external EC point. */
- if ((ret == 1) && (ec_point_external_set(r) != 1)) {
- WOLFSSL_MSG("ec_point_external_set error");
- ret = 0;
- }
-
-#ifdef DEBUG_WOLFSSL
- if (ret == 1) {
- wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_add result", r);
- }
-#endif
-
- return ret;
-}
-
-/* Sum the scalar multiplications of the base point and n, and q and m.
- *
- * r = base point * n + q * m
- *
- * @param [out] r EC point that is result of operation.
- * @param [in] b Base point of curve.
- * @param [in] n Scalar to multiply by base point.
- * @param [in] q EC point to be scalar multiplied.
- * @param [in] m Scalar to multiply q by.
- * @param [in] a Parameter A of curve.
- * @param [in] prime Prime (modulus) of curve.
- * @return 1 on success.
- * @return 0 on error.
- */
-static int ec_mul2add(ecc_point* r, ecc_point* b, mp_int* n, ecc_point* q,
- mp_int* m, mp_int* a, mp_int* prime)
-{
- int ret = 1;
-#if defined(ECC_SHAMIR) && !defined(WOLFSSL_KCAPI_ECC)
- if (ecc_mul2add(b, n, q, m, r, a, prime, NULL) != MP_OKAY) {
- WOLFSSL_MSG("ecc_mul2add error");
- ret = 0;
- }
-#else
- ecc_point* tmp = NULL;
- mp_digit mp = 0;
-
- /* Calculate Montgomery product. */
- if (mp_montgomery_setup(prime, &mp) != MP_OKAY) {
- WOLFSSL_MSG("mp_montgomery_setup nqm error");
- ret = 0;
- }
- /* Create temporary point to hold: q * m */
- if ((ret == 1) && ((tmp = wc_ecc_new_point()) == NULL)) {
- WOLFSSL_MSG("wolfSSL_EC_POINT_new nqm error");
- ret = 0;
- }
- /* r = base point * n */
- if ((ret == 1) && (wc_ecc_mulmod(n, b, r, a, prime, 0) !=
- MP_OKAY)) {
- WOLFSSL_MSG("wc_ecc_mulmod nqm error");
- ret = 0;
- }
- /* tmp = q * m */
- if ((ret == 1) && (wc_ecc_mulmod(m, q, tmp, a, prime, 0) != MP_OKAY)) {
- WOLFSSL_MSG("wc_ecc_mulmod nqm error");
- ret = 0;
- }
- /* r = r + tmp */
- if ((ret == 1) && (ecc_projective_add_point(tmp, r, r, a, prime, mp) !=
- MP_OKAY)) {
- WOLFSSL_MSG("wc_ecc_mulmod nqm error");
- ret = 0;
- }
- /* Map point back to affine coordinates. Converts from Montogomery
- * form. */
- if ((ret == 1) && (ecc_map(r, prime, mp) != MP_OKAY)) {
- WOLFSSL_MSG("ecc_map nqm error");
- ret = 0;
- }
-
- /* Dispose of allocated temporary point. */
- wc_ecc_del_point(tmp);
-#endif
-
- return ret;
-}
-
-/* Sum the scalar multiplications of the base point and n, and q and m.
- *
- * r = base point * n + q * m
- *
- * @param [in] curveIdx Index of curve in ecc_set.
- * @param [out] r EC point that is result of operation.
- * @param [in] n Scalar to multiply by base point. May be NULL.
- * @param [in] q EC point to be scalar multiplied. May be NULL.
- * @param [in] m Scalar to multiply q by. May be NULL.
- * @return 1 on success.
- * @return 0 on error.
- */
-static int wolfssl_ec_point_mul(int curveIdx, ecc_point* r, mp_int* n,
- ecc_point* q, mp_int* m)
-{
- int ret = 1;
-#ifdef WOLFSSL_SMALL_STACK
- mp_int* a = NULL;
- mp_int* prime = NULL;
-#else
- mp_int a[1], prime[1];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
- /* Allocate MP integer for curve parameter: a. */
- a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
- if (a == NULL) {
- ret = 0;
- }
- if (ret == 1) {
- /* Allocate MP integer for curve parameter: prime. */
- prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
- if (prime == NULL) {
- ret = 0;
- }
- }
-#endif
-
- /* Initialize the MP ints. */
- if ((ret == 1) && (mp_init_multi(prime, a, NULL, NULL, NULL, NULL) !=
- MP_OKAY)) {
- WOLFSSL_MSG("mp_init_multi error");
- ret = 0;
- }
-
- /* Read the curve parameter: prime. */
- if ((ret == 1) && (mp_read_radix(prime, ecc_sets[curveIdx].prime,
- MP_RADIX_HEX) != MP_OKAY)) {
- WOLFSSL_MSG("mp_read_radix prime error");
- ret = 0;
- }
-
- /* Read the curve parameter: a. */
- if ((ret == 1) && (mp_read_radix(a, ecc_sets[curveIdx].Af,
- MP_RADIX_HEX) != MP_OKAY)) {
- WOLFSSL_MSG("mp_read_radix a error");
- ret = 0;
- }
-
- if ((ret == 1) && (n != NULL)) {
- /* Get generator - base point. */
- #if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)
- if ((ret == 1) && (wc_ecc_get_generator(r, curveIdx) != MP_OKAY)) {
- WOLFSSL_MSG("wc_ecc_get_generator error");
- ret = 0;
- }
- #else
- /* wc_ecc_get_generator is not defined in the FIPS v2 module. */
- /* Read generator (base point) x-ordinate. */
- if ((ret == 1) && (mp_read_radix(r->x, ecc_sets[curveIdx].Gx,
- MP_RADIX_HEX) != MP_OKAY)) {
- WOLFSSL_MSG("mp_read_radix Gx error");
- ret = 0;
- }
- /* Read generator (base point) y-ordinate. */
- if ((ret == 1) && (mp_read_radix(r->y, ecc_sets[curveIdx].Gy,
- MP_RADIX_HEX) != MP_OKAY)) {
- WOLFSSL_MSG("mp_read_radix Gy error");
- ret = 0;
- }
- /* z-ordinate is one as point is affine. */
- if ((ret == 1) && (mp_set(r->z, 1) != MP_OKAY)) {
- WOLFSSL_MSG("mp_set Gz error");
- ret = 0;
- }
- #endif /* NOPT_FIPS_VERSION == 2 */
- }
-
- if ((ret == 1) && (n != NULL) && (q != NULL) && (m != NULL)) {
- /* r = base point * n + q * m */
- ret = ec_mul2add(r, r, n, q, m, a, prime);
- }
- /* Not all values present, see if we are only doing base point * n. */
- else if ((ret == 1) && (n != NULL)) {
- /* r = base point * n */
- if (wc_ecc_mulmod(n, r, r, a, prime, 1) != MP_OKAY) {
- WOLFSSL_MSG("wc_ecc_mulmod gn error");
- ret = 0;
- }
- }
- /* Not all values present, see if we are only doing q * m. */
- else if ((ret == 1) && (q != NULL) && (m != NULL)) {
- /* r = q * m */
- if (wc_ecc_mulmod(m, q, r, a, prime, 1) != MP_OKAY) {
- WOLFSSL_MSG("wc_ecc_mulmod qm error");
- ret = 0;
- }
- }
- /* No values to use. */
- else if (ret == 1) {
- /* Set result to infinity as no values passed in. */
- mp_zero(r->x);
- mp_zero(r->y);
- mp_zero(r->z);
- }
-
- mp_clear(a);
- mp_clear(prime);
- WC_FREE_VAR_EX(a, NULL, DYNAMIC_TYPE_BIGINT);
- WC_FREE_VAR_EX(prime, NULL, DYNAMIC_TYPE_BIGINT);
- return ret;
-}
-
-/* Sum the scalar multiplications of the base point and n, and q and m.
- *
- * r = base point * n + q * m
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in] group EC group.
- * @param [out] r EC point that is result of operation.
- * @param [in] n Scalar to multiply by base point. May be NULL.
- * @param [in] q EC point to be scalar multiplied. May be NULL.
- * @param [in] m Scalar to multiply q by. May be NULL.
- * @param [in] ctx Context to use for BN operations. Unused.
- * @return 1 on success.
- * @return 0 on error.
- */
-int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r,
- const WOLFSSL_BIGNUM *n, const WOLFSSL_EC_POINT *q, const WOLFSSL_BIGNUM *m,
- WOLFSSL_BN_CTX *ctx)
-{
- int ret = 1;
-
- /* No BN operations performed. */
- (void)ctx;
-
- WOLFSSL_ENTER("wolfSSL_EC_POINT_mul");
-
- /* Validate parameters. */
- if ((group == NULL) || (r == NULL)) {
- WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error");
- ret = 0;
- }
-
- /* Ensure the internal representation of the EC point q is setup. */
- if ((ret == 1) && (q != NULL) && (ec_point_setup(q) != 1)) {
- WOLFSSL_MSG("ec_point_setup error");
- ret = 0;
- }
-
-#ifdef DEBUG_WOLFSSL
- if (ret == 1) {
- int nid = wolfSSL_EC_GROUP_get_curve_name(group);
- const char* curve = wolfSSL_OBJ_nid2ln(nid);
- const char* nistName = wolfSSL_EC_curve_nid2nist(nid);
- char* num;
- wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_mul input q", q);
- num = wolfSSL_BN_bn2hex(n);
- WOLFSSL_MSG_EX("\tn = %s", num);
- XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL);
- num = wolfSSL_BN_bn2hex(m);
- WOLFSSL_MSG_EX("\tm = %s", num);
- XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL);
- if (curve != NULL)
- WOLFSSL_MSG_EX("curve name: %s", curve);
- if (nistName != NULL)
- WOLFSSL_MSG_EX("nist curve name: %s", nistName);
- }
-#endif
-
- if (ret == 1) {
- mp_int* ni = (n != NULL) ? (mp_int*)n->internal : NULL;
- ecc_point* qi = (q != NULL) ? (ecc_point*)q->internal : NULL;
- mp_int* mi = (m != NULL) ? (mp_int*)m->internal : NULL;
-
- /* Perform multiplication with wolfCrypt objects. */
- ret = wolfssl_ec_point_mul(group->curve_idx, (ecc_point*)r->internal,
- ni, qi, mi);
- }
-
- /* Only on success is the internal point guaranteed to be set. */
- if (r != NULL) {
- r->inSet = (ret == 1);
- }
- /* Copy internal EC point values out to external EC point. */
- if ((ret == 1) && (ec_point_external_set(r) != 1)) {
- WOLFSSL_MSG("ec_point_external_set error");
- ret = 0;
- }
-
-#ifdef DEBUG_WOLFSSL
- if (ret == 1) {
- wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_mul result", r);
- }
-#endif
-
- return ret;
-}
-#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_ATECC608A && !HAVE_SELFTEST &&
- * !WOLFSSL_SP_MATH */
-
-/* Invert the point on the curve.
- * (x, y) -> (x, -y) = (x, (prime - y) % prime)
- *
- * @param [in] curveIdx Index of curve in ecc_set.
- * @param [in, out] point EC point to invert.
- * @return 1 on success.
- * @return 0 on error.
- */
-static int wolfssl_ec_point_invert(int curveIdx, ecc_point* point)
-{
- int ret = 1;
- WC_DECLARE_VAR(prime, mp_int, 1, 0);
-
- /* Allocate memory for an MP int to hold the prime of the curve. */
- WC_ALLOC_VAR_EX(prime, mp_int, 1, NULL, DYNAMIC_TYPE_BIGINT, ret=0);
-
- /* Initialize MP int. */
- if ((ret == 1) && (mp_init(prime) != MP_OKAY)) {
- WOLFSSL_MSG("mp_init_multi error");
- ret = 0;
- }
-
- /* Read the curve parameter: prime. */
- if ((ret == 1) && (mp_read_radix(prime, ecc_sets[curveIdx].prime,
- MP_RADIX_HEX) != MP_OKAY)) {
- WOLFSSL_MSG("mp_read_radix prime error");
- ret = 0;
- }
-
- /* y = (prime - y) mod prime. */
- if ((ret == 1) && (!mp_iszero(point->y)) && (mp_sub(prime, point->y,
- point->y) != MP_OKAY)) {
- WOLFSSL_MSG("mp_sub error");
- ret = 0;
- }
-
- /* Dispose of memory associated with MP. */
- mp_free(prime);
- WC_FREE_VAR_EX(prime, NULL, DYNAMIC_TYPE_BIGINT);
- return ret;
-}
-
-/* Invert the point on the curve.
- * (x, y) -> (x, -y) = (x, (prime - y) % prime)
- *
- * @param [in] group EC group.
- * @param [in, out] point EC point to invert.
- * @param [in] ctx Context to use for BN operations. Unused.
- * @return 1 on success.
- * @return 0 on error.
- */
-int wolfSSL_EC_POINT_invert(const WOLFSSL_EC_GROUP *group,
- WOLFSSL_EC_POINT *point, WOLFSSL_BN_CTX *ctx)
-{
- int ret = 1;
-
- /* No BN operations performed. */
- (void)ctx;
-
- WOLFSSL_ENTER("wolfSSL_EC_POINT_invert");
-
- /* Validate parameters. */
- if ((group == NULL) || (point == NULL) || (point->internal == NULL)) {
- ret = 0;
- }
-
- /* Ensure internal representation of point is setup. */
- if ((ret == 1) && (ec_point_setup(point) != 1)) {
- ret = 0;
- }
-
-#ifdef DEBUG_WOLFSSL
- if (ret == 1) {
- int nid = wolfSSL_EC_GROUP_get_curve_name(group);
- const char* curve = wolfSSL_OBJ_nid2ln(nid);
- const char* nistName = wolfSSL_EC_curve_nid2nist(nid);
- wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_invert input", point);
- if (curve != NULL)
- WOLFSSL_MSG_EX("curve name: %s", curve);
- if (nistName != NULL)
- WOLFSSL_MSG_EX("nist curve name: %s", nistName);
-
- }
-#endif
-
- if (ret == 1 && !wolfSSL_BN_is_one(point->Z)) {
-#if !defined(WOLFSSL_SP_MATH) && !defined(WOLF_CRYPTO_CB_ONLY_ECC)
- if (ec_point_convert_to_affine(group, point) != 0)
- ret = 0;
-#else
- WOLFSSL_MSG("wolfSSL_EC_POINT_invert called on non-affine point");
- ret = 0;
-#endif
- }
-
- if (ret == 1) {
- /* Perform inversion using wolfCrypt objects. */
- ret = wolfssl_ec_point_invert(group->curve_idx,
- (ecc_point*)point->internal);
- }
-
- /* Set the external EC point representation based on internal. */
- if ((ret == 1) && (ec_point_external_set(point) != 1)) {
- WOLFSSL_MSG("ec_point_external_set error");
- ret = 0;
- }
-
-#ifdef DEBUG_WOLFSSL
- if (ret == 1) {
- wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_invert result", point);
- }
-#endif
-
- return ret;
-}
-
-#ifdef WOLFSSL_EC_POINT_CMP_JACOBIAN
-/* Compare two points on a the same curve.
- *
- * (Ax, Ay, Az) => (Ax / (Az ^ 2), Ay / (Az ^ 3))
- * (Bx, By, Bz) => (Bx / (Bz ^ 2), By / (Bz ^ 3))
- * When equal:
- * (Ax / (Az ^ 2), Ay / (Az ^ 3)) = (Bx / (Bz ^ 2), By / (Bz ^ 3))
- * => (Ax * (Bz ^ 2), Ay * (Bz ^ 3)) = (Bx * (Az ^ 2), By * (Az ^ 3))
- *
- * @param [in] group EC group.
- * @param [in] a EC point to compare.
- * @param [in] b EC point to compare.
- * @return 0 when equal.
- * @return 1 when different.
- * @return -1 on error.
- */
-static int ec_point_cmp_jacobian(const WOLFSSL_EC_GROUP* group,
- const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b, WOLFSSL_BN_CTX *ctx)
-{
- int ret = 0;
- BIGNUM* at = BN_new();
- BIGNUM* bt = BN_new();
- BIGNUM* az = BN_new();
- BIGNUM* bz = BN_new();
- BIGNUM* mod = BN_new();
-
- /* Check that the big numbers were allocated. */
- if ((at == NULL) || (bt == NULL) || (az == NULL) || (bz == NULL) ||
- (mod == NULL)) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- /* Get the modulus for the curve. */
- if ((ret == 0) &&
- (BN_hex2bn(&mod, ecc_sets[group->curve_idx].prime) != 1)) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- if (ret == 0) {
- /* bt = Bx * (Az ^ 2). When Az is one then just copy. */
- if (BN_is_one(a->Z)) {
- if (BN_copy(bt, b->X) == NULL) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- /* az = Az ^ 2 */
- else if ((BN_mod_mul(az, a->Z, a->Z, mod, ctx) != 1)) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- /* bt = Bx * az = Bx * (Az ^ 2) */
- else if (BN_mod_mul(bt, b->X, az, mod, ctx) != 1) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- if (ret == 0) {
- /* at = Ax * (Bz ^ 2). When Bz is one then just copy. */
- if (BN_is_one(b->Z)) {
- if (BN_copy(at, a->X) == NULL) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- /* bz = Bz ^ 2 */
- else if (BN_mod_mul(bz, b->Z, b->Z, mod, ctx) != 1) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- /* at = Ax * bz = Ax * (Bz ^ 2) */
- else if (BN_mod_mul(at, a->X, bz, mod, ctx) != 1) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- /* Compare x-ordinates. */
- if ((ret == 0) && (BN_cmp(at, bt) != 0)) {
- ret = 1;
- }
- if (ret == 0) {
- /* bt = By * (Az ^ 3). When Az is one then just copy. */
- if (BN_is_one(a->Z)) {
- if (BN_copy(bt, b->Y) == NULL) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- /* az = az * Az = Az ^ 3 */
- else if ((BN_mod_mul(az, az, a->Z, mod, ctx) != 1)) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- /* bt = By * az = By * (Az ^ 3) */
- else if (BN_mod_mul(bt, b->Y, az, mod, ctx) != 1) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- if (ret == 0) {
- /* at = Ay * (Bz ^ 3). When Bz is one then just copy. */
- if (BN_is_one(b->Z)) {
- if (BN_copy(at, a->Y) == NULL) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- /* bz = bz * Bz = Bz ^ 3 */
- else if (BN_mod_mul(bz, bz, b->Z, mod, ctx) != 1) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- /* at = Ay * bz = Ay * (Bz ^ 3) */
- else if (BN_mod_mul(at, a->Y, bz, mod, ctx) != 1) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
- /* Compare y-ordinates. */
- if ((ret == 0) && (BN_cmp(at, bt) != 0)) {
- ret = 1;
- }
-
- BN_free(mod);
- BN_free(bz);
- BN_free(az);
- BN_free(bt);
- BN_free(at);
- return ret;
-}
-#endif
-
-/* Compare two points on a the same curve.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in] group EC group.
- * @param [in] a EC point to compare.
- * @param [in] b EC point to compare.
- * @param [in] ctx Context to use for BN operations. Unused.
- * @return 0 when equal.
- * @return 1 when different.
- * @return -1 on error.
- */
-int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group,
- const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b, WOLFSSL_BN_CTX *ctx)
-{
- int ret = 0;
-
- WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp");
-
- /* Validate parameters. */
- if ((group == NULL) || (a == NULL) || (a->internal == NULL) ||
- (b == NULL) || (b->internal == NULL)) {
- WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments");
- ret = WOLFSSL_FATAL_ERROR;
- }
- if (ret != -1) {
- #ifdef WOLFSSL_EC_POINT_CMP_JACOBIAN
- /* If same Z ordinate then no need to convert to affine. */
- if (BN_cmp(a->Z, b->Z) == 0) {
- /* Compare */
- ret = ((BN_cmp(a->X, b->X) != 0) || (BN_cmp(a->Y, b->Y) != 0));
- }
- else {
- ret = ec_point_cmp_jacobian(group, a, b, ctx);
- }
- #else
- /* No BN operations performed. */
- (void)ctx;
-
- ret = (wc_ecc_cmp_point((ecc_point*)a->internal,
- (ecc_point*)b->internal) != MP_EQ);
- #endif
- }
-
- return ret;
-}
-
-/* Copy EC point.
- *
- * @param [out] dest EC point to copy into.
- * @param [in] src EC point to copy.
- * @return 1 on success.
- * @return 0 on error.
- */
-int wolfSSL_EC_POINT_copy(WOLFSSL_EC_POINT *dest, const WOLFSSL_EC_POINT *src)
-{
- int ret = 1;
-
- WOLFSSL_ENTER("wolfSSL_EC_POINT_copy");
-
- /* Validate parameters. */
- if ((dest == NULL) || (src == NULL)) {
- ret = 0;
- }
-
- /* Ensure internal EC point of src is setup. */
- if ((ret == 1) && (ec_point_setup(src) != 1)) {
- ret = 0;
- }
-
- /* Copy internal EC points. */
- if ((ret == 1) && (wc_ecc_copy_point((ecc_point*)src->internal,
- (ecc_point*)dest->internal) != MP_OKAY)) {
- ret = 0;
- }
-
- if (ret == 1) {
- /* Destinatation internal point is set. */
- dest->inSet = 1;
-
- /* Set the external EC point of dest based on internal. */
- if (ec_point_external_set(dest) != 1) {
- ret = 0;
- }
- }
-
- return ret;
-}
-
-/* Checks whether point is at infinity.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in] group EC group.
- * @param [in] point EC point to check.
- * @return 1 when at infinity.
- * @return 0 when not at infinity.
- */
-int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group,
- const WOLFSSL_EC_POINT *point)
-{
- int ret = 1;
-
- WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity");
-
- /* Validate parameters. */
- if ((group == NULL) || (point == NULL) || (point->internal == NULL)) {
- WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error");
- ret = 0;
- }
-
- /* Ensure internal EC point is setup. */
- if ((ret == 1) && (ec_point_setup(point) != 1)) {
- ret = 0;
- }
- if (ret == 1) {
- #ifndef WOLF_CRYPTO_CB_ONLY_ECC
- /* Check for infinity. */
- ret = wc_ecc_point_is_at_infinity((ecc_point*)point->internal);
- if (ret < 0) {
- WOLFSSL_MSG("ecc_point_is_at_infinity failure");
- /* Error return is 0 by OpenSSL. */
- ret = 0;
- }
- #else
- WOLFSSL_MSG("ecc_point_is_at_infinitiy compiled out");
- ret = 0;
- #endif
- }
-
- return ret;
-}
-
-#endif /* OPENSSL_EXTRA */
-
-/* End EC_POINT */
-
-/* Start EC_KEY */
-
-#ifdef OPENSSL_EXTRA
-
-/*
- * EC key constructor/deconstructor APIs
- */
-
-/* Allocate a new EC key.
- *
- * Not OpenSSL API.
- *
- * @param [in] heap Heap hint for dynamic memory allocation.
- * @param [in] devId Device identifier value.
- * @return New, allocated EC key on success.
- * @return NULL on error.
- */
-WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_ex(void* heap, int devId)
-{
- WOLFSSL_EC_KEY *key = NULL;
- int err = 0;
-
- WOLFSSL_ENTER("wolfSSL_EC_KEY_new");
-
- /* Allocate memory for EC key. */
- key = (WOLFSSL_EC_KEY*)XMALLOC(sizeof(WOLFSSL_EC_KEY), heap,
- DYNAMIC_TYPE_ECC);
- if (key == NULL) {
- WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_KEY failure");
- err = 1;
- }
- if (!err) {
- /* Reset all fields to 0. */
- XMEMSET(key, 0, sizeof(WOLFSSL_EC_KEY));
- /* Cache heap hint. */
- key->heap = heap;
- /* Initialize fields to defaults. */
- key->form = WC_POINT_CONVERSION_UNCOMPRESSED;
-
- /* Initialize reference count. */
- wolfSSL_RefInit(&key->ref, &err);
-#ifdef WOLFSSL_REFCNT_ERROR_RETURN
- }
- if (!err) {
-#endif
- /* Allocate memory for internal EC key representation. */
- key->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), heap,
- DYNAMIC_TYPE_ECC);
- if (key->internal == NULL) {
- WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc ecc key failure");
- err = 1;
- }
- }
- if (!err) {
- /* Initialize wolfCrypt EC key. */
- if (wc_ecc_init_ex((ecc_key*)key->internal, heap, devId) != 0) {
- WOLFSSL_MSG("wolfSSL_EC_KEY_new init ecc key failure");
- err = 1;
- }
- }
-
- if (!err) {
- /* Group unknown at creation */
- key->group = wolfSSL_EC_GROUP_new_by_curve_name(WC_NID_undef);
- if (key->group == NULL) {
- WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure");
- err = 1;
- }
- }
-
- if (!err) {
- /* Allocate a point as public key. */
- key->pub_key = wolfSSL_EC_POINT_new(key->group);
- if (key->pub_key == NULL) {
- WOLFSSL_MSG("wolfSSL_EC_POINT_new failure");
- err = 1;
- }
- }
-
- if (!err) {
- /* Allocate a BN as private key. */
- key->priv_key = wolfSSL_BN_new();
- if (key->priv_key == NULL) {
- WOLFSSL_MSG("wolfSSL_BN_new failure");
- err = 1;
- }
- }
-
- if (err) {
- /* Dispose of EC key on error. */
- wolfSSL_EC_KEY_free(key);
- key = NULL;
- }
- /* Return new EC key object. */
- return key;
-}
-
-/* Allocate a new EC key.
- *
- * @return New, allocated EC key on success.
- * @return NULL on error.
- */
-WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void)
-{
- return wolfSSL_EC_KEY_new_ex(NULL, INVALID_DEVID);
-}
-
-/* Create new EC key with the group having the specified numeric ID.
- *
- * @param [in] nid Numeric ID.
- * @return New, allocated EC key on success.
- * @return NULL on error.
- */
-WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid)
-{
- WOLFSSL_EC_KEY *key;
- int err = 0;
-
- WOLFSSL_ENTER("wolfSSL_EC_KEY_new_by_curve_name");
-
- /* Allocate empty, EC key. */
- key = wolfSSL_EC_KEY_new();
- if (key == NULL) {
- WOLFSSL_MSG("wolfSSL_EC_KEY_new failure");
- err = 1;
- }
-
- if (!err) {
- /* Set group to be nid. */
- ec_group_set_nid(key->group, nid);
- if (key->group->curve_idx == -1) {
- wolfSSL_EC_KEY_free(key);
- key = NULL;
- }
- }
-
- /* Return the new EC key object. */
- return key;
-}
-
-/* Dispose of the EC key and allocated data.
- *
- * Cannot use key after this call.
- *
- * @param [in] key EC key to free.
- */
-void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key)
-{
- int doFree = 0;
- int err;
-
- (void)err;
-
- WOLFSSL_ENTER("wolfSSL_EC_KEY_free");
-
- if (key != NULL) {
- void* heap = key->heap;
-
- /* Decrement reference count. */
- wolfSSL_RefDec(&key->ref, &doFree, &err);
- if (doFree) {
- /* Dispose of allocated reference counting data. */
- wolfSSL_RefFree(&key->ref);
-
- /* Dispose of private key. */
- wolfSSL_BN_free(key->priv_key);
- wolfSSL_EC_POINT_free(key->pub_key);
- wolfSSL_EC_GROUP_free(key->group);
- if (key->internal != NULL) {
- /* Dispose of wolfCrypt representation of EC key. */
- wc_ecc_free((ecc_key*)key->internal);
- XFREE(key->internal, heap, DYNAMIC_TYPE_ECC);
- }
-
- /* Set back to NULLs for safety. */
- ForceZero(key, sizeof(*key));
-
- /* Dispose of the memory associated with the EC key. */
- XFREE(key, heap, DYNAMIC_TYPE_ECC);
- (void)heap;
- }
- }
-}
-
-/* Increments ref count of EC key.
- *
- * @param [in, out] key EC key.
- * @return 1 on success
- * @return 0 on error
- */
-int wolfSSL_EC_KEY_up_ref(WOLFSSL_EC_KEY* key)
-{
- int err = 1;
-
- if (key != NULL) {
- wolfSSL_RefInc(&key->ref, &err);
- }
-
- return !err;
-}
-
-#ifndef NO_CERTS
-
-#if defined(OPENSSL_ALL)
-/* Copy the internal, wolfCrypt EC key.
- *
- * @param [in, out] dst Destination wolfCrypt EC key.
- * @param [in] src Source wolfCrypt EC key.
- * @return 0 on success.
- * @return Negative on error.
- */
-static int wolfssl_ec_key_int_copy(ecc_key* dst, const ecc_key* src)
-{
- int ret;
-
- /* Copy public key. */
-#if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)
- ret = wc_ecc_copy_point(&src->pubkey, &dst->pubkey);
-#else
- ret = wc_ecc_copy_point((ecc_point*)&src->pubkey, &dst->pubkey);
-#endif
- if (ret != MP_OKAY) {
- WOLFSSL_MSG("wc_ecc_copy_point error");
- }
-
- if (ret == 0) {
- /* Copy private key. */
- ret = mp_copy(wc_ecc_key_get_priv((ecc_key*)src),
- wc_ecc_key_get_priv(dst));
- if (ret != MP_OKAY) {
- WOLFSSL_MSG("mp_copy error");
- }
- }
-
- if (ret == 0) {
- /* Copy domain parameters. */
- if (src->dp) {
- ret = wc_ecc_set_curve(dst, 0, src->dp->id);
- if (ret != 0) {
- WOLFSSL_MSG("wc_ecc_set_curve error");
- }
- }
- }
-
- if (ret == 0) {
- /* Copy the other components. */
- dst->type = src->type;
- dst->idx = src->idx;
- dst->state = src->state;
- dst->flags = src->flags;
- }
-
- return ret;
-}
-
-/* Copies ecc_key into new WOLFSSL_EC_KEY object
- *
- * Copies the internal representation as well.
- *
- * @param [in] src EC key to duplicate.
- *
- * @return EC key on success.
- * @return NULL on error.
- */
-WOLFSSL_EC_KEY *wolfSSL_EC_KEY_dup(const WOLFSSL_EC_KEY *src)
-{
- int err = 0;
- WOLFSSL_EC_KEY* newKey = NULL;
-
- WOLFSSL_ENTER("wolfSSL_EC_KEY_dup");
-
- /* Validate EC key. */
- if ((src == NULL) || (src->internal == NULL) || (src->group == NULL) ||
- (src->pub_key == NULL) || (src->priv_key == NULL)) {
- WOLFSSL_MSG("src NULL error");
- err = 1;
- }
-
- if (!err) {
- /* Create a new, empty key. */
- newKey = wolfSSL_EC_KEY_new();
- if (newKey == NULL) {
- WOLFSSL_MSG("wolfSSL_EC_KEY_new error");
- err = 1;
- }
- }
-
- if (!err) {
- /* Copy internal EC key. */
- if (wolfssl_ec_key_int_copy((ecc_key*)newKey->internal,
- (ecc_key*)src->internal) != 0) {
- WOLFSSL_MSG("Copying internal EC key error");
- err = 1;
- }
- }
- if (!err) {
- /* Internal key set. */
- newKey->inSet = 1;
-
- /* Copy group */
- err = wolfssl_ec_group_copy(newKey->group, src->group);
- }
- /* Copy public key. */
- if ((!err) && (wolfSSL_EC_POINT_copy(newKey->pub_key, src->pub_key) != 1)) {
- WOLFSSL_MSG("Copying EC public key error");
- err = 1;
- }
-
- if (!err) {
- /* Set header size of private key in PKCS#8 format.*/
- newKey->pkcs8HeaderSz = src->pkcs8HeaderSz;
-
- /* Copy private key. */
- if (wolfSSL_BN_copy(newKey->priv_key, src->priv_key) == NULL) {
- WOLFSSL_MSG("Copying EC private key error");
- err = 1;
- }
- }
-
- if (err) {
- /* Dispose of EC key on error. */
- wolfSSL_EC_KEY_free(newKey);
- newKey = NULL;
- }
- /* Return the new EC key. */
- return newKey;
-}
-
-#endif /* OPENSSL_ALL */
-
-#endif /* !NO_CERTS */
-
-/*
- * EC key to/from bin/octet APIs
- */
-
-/* Create an EC key from the octet encoded public key.
- *
- * Behaviour checked against OpenSSL.
- *
- * @param [out] key Reference to EC key. Must pass in a valid object with
- * group set.
- * @param [in, out] in On in, reference to buffer that contains data.
- * On out, reference to buffer after public key data.
- * @param [in] len Length of data in the buffer. Must be length of the
- * encoded public key.
- * @return Allocated EC key on success.
- * @return NULL on error.
- */
-WOLFSSL_EC_KEY *wolfSSL_o2i_ECPublicKey(WOLFSSL_EC_KEY **key,
- const unsigned char **in, long len)
-{
- int err = 0;
- WOLFSSL_EC_KEY* ret = NULL;
-
- WOLFSSL_ENTER("wolfSSL_o2i_ECPublicKey");
-
- /* Validate parameters: EC group needed to perform import. */
- if ((key == NULL) || (*key == NULL) || ((*key)->group == NULL) ||
- (in == NULL) || (*in == NULL) || (len <= 0)) {
- WOLFSSL_MSG("wolfSSL_o2i_ECPublicKey Bad arguments");
- err = 1;
- }
-
- if (!err) {
- /* Return the EC key object passed in. */
- ret = *key;
-
- /* Import point into public key field. */
- if (wolfSSL_EC_POINT_oct2point(ret->group, ret->pub_key, *in,
- (size_t)len, NULL) != 1) {
- WOLFSSL_MSG("wolfSSL_EC_POINT_oct2point error");
- ret = NULL;
- err = 1;
- }
- }
- if (!err) {
- /* Assumed length passed in is all the data. */
- *in += len;
- }
-
- return ret;
-}
-
-/* Puts the encoded public key into out.
- *
- * Passing in NULL for out returns length only.
- * Passing in NULL for *out has buffer allocated, encoded into and passed back.
- * Passing non-NULL for *out has it encoded into and pointer moved past.
- *
- * @param [in] key EC key to encode.
- * @param [in, out] out Reference to buffer to encode into. May be NULL or
- * point to NULL.
- * @return Length of encoding in bytes on success.
- * @return 0 on error.
- */
-int wolfSSL_i2o_ECPublicKey(const WOLFSSL_EC_KEY *key, unsigned char **out)
-{
- int ret = 1;
- size_t len = 0;
- int form = WC_POINT_CONVERSION_UNCOMPRESSED;
-
- WOLFSSL_ENTER("wolfSSL_i2o_ECPublicKey");
-
- /* Validate parameters. */
- if (key == NULL) {
- WOLFSSL_MSG("wolfSSL_i2o_ECPublicKey Bad arguments");
- ret = 0;
- }
-
- /* Ensure the external key data is set from the internal EC key. */
- if ((ret == 1) && (!key->exSet) && (SetECKeyExternal((WOLFSSL_EC_KEY*)
- key) != 1)) {
- WOLFSSL_MSG("SetECKeyExternal failure");
- ret = 0;
- }
-
- if (ret == 1) {
- #ifdef HAVE_COMP_KEY
- /* Default to compressed form if not set */
- form = (key->form == WC_POINT_CONVERSION_UNCOMPRESSED) ?
- WC_POINT_CONVERSION_UNCOMPRESSED :
- WC_POINT_CONVERSION_COMPRESSED;
- #endif
-
- /* Calculate length of point encoding. */
- len = wolfSSL_EC_POINT_point2oct(key->group, key->pub_key, form, NULL,
- 0, NULL);
- }
- /* Encode if length calculated and pointer supplied to update. */
- if ((ret == 1) && (len != 0) && (out != NULL)) {
- unsigned char *tmp = NULL;
-
- /* Allocate buffer for encoding if no buffer supplied. */
- if (*out == NULL) {
- tmp = (unsigned char*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
- if (tmp == NULL) {
- WOLFSSL_MSG("malloc failed");
- ret = 0;
- }
- }
- else {
- /* Get buffer to encode into. */
- tmp = *out;
- }
-
- /* Encode public key into buffer. */
- if ((ret == 1) && (wolfSSL_EC_POINT_point2oct(key->group, key->pub_key,
- form, tmp, len, NULL) == 0)) {
- ret = 0;
- }
-
- if (ret == 1) {
- /* Return buffer if allocated. */
- if (*out == NULL) {
- *out = tmp;
- }
- else {
- /* Step over encoded data if not allocated. */
- *out += len;
- }
- }
- else if (*out == NULL) {
- /* Dispose of allocated buffer. */
- XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
- }
- }
-
- if (ret == 1) {
- /* Return length on success. */
- ret = (int)len;
- }
- return ret;
-}
-
-#ifdef HAVE_ECC_KEY_IMPORT
-/* Create a EC key from the DER encoded private key.
- *
- * @param [out] key Reference to EC key.
- * @param [in, out] in On in, reference to buffer that contains DER data.
- * On out, reference to buffer after private key data.
- * @param [in] long Length of data in the buffer. May be larger than the
- * length of the encoded private key.
- * @return Allocated EC key on success.
- * @return NULL on error.
- */
-WOLFSSL_EC_KEY* wolfSSL_d2i_ECPrivateKey(WOLFSSL_EC_KEY** key,
- const unsigned char** in, long len)
-{
- int err = 0;
- word32 idx = 0;
- WOLFSSL_EC_KEY* ret = NULL;
-
- WOLFSSL_ENTER("wolfSSL_d2i_ECPrivateKey");
-
- /* Validate parameters. */
- if ((in == NULL) || (*in == NULL) || (len <= 0)) {
- WOLFSSL_MSG("wolfSSL_d2i_ECPrivateKey Bad arguments");
- err = 1;
- }
-
- /* Create a new, empty EC key. */
- if ((!err) && ((ret = wolfSSL_EC_KEY_new()) == NULL)) {
- WOLFSSL_MSG("wolfSSL_EC_KEY_new error");
- err = 1;
- }
-
- /* Decode the private key DER data into internal EC key. */
- if ((!err) && (wc_EccPrivateKeyDecode(*in, &idx, (ecc_key*)ret->internal,
- (word32)len) != 0)) {
- WOLFSSL_MSG("wc_EccPrivateKeyDecode error");
- err = 1;
- }
-
- if (!err) {
- /* Internal EC key setup. */
- ret->inSet = 1;
-
- /* Set the EC key from the internal values. */
- if (SetECKeyExternal(ret) != 1) {
- WOLFSSL_MSG("SetECKeyExternal error");
- err = 1;
- }
- }
-
- if (!err) {
- /* Move buffer on to next byte after data used. */
- *in += idx;
- if (key) {
- /* Return new EC key through reference. */
- *key = ret;
- }
- }
-
- if (err && (ret != NULL)) {
- /* Dispose of allocated EC key. */
- wolfSSL_EC_KEY_free(ret);
- ret = NULL;
- }
- return ret;
-}
-#endif /* HAVE_ECC_KEY_IMPORT */
-
-/* Enecode the private key of the EC key into the buffer as DER.
- *
- * @param [in] key EC key to encode.
- * @param [in, out] out On in, reference to buffer to place DER encoding into.
- * On out, reference to buffer after the encoding.
- * May be NULL.
- * @return Length of DER encoding on success.
- * @return 0 on error.
- */
-int wolfSSL_i2d_ECPrivateKey(const WOLFSSL_EC_KEY *key, unsigned char **out)
-{
- int err = 0;
- word32 len = 0;
-
- WOLFSSL_ENTER("wolfSSL_i2d_ECPrivateKey");
-
- /* Validate parameters. */
- if (key == NULL) {
- WOLFSSL_MSG("wolfSSL_i2d_ECPrivateKey Bad arguments");
- err = 1;
- }
-
- /* Update the internal EC key if not set. */
- if ((!err) && (!key->inSet) && (SetECKeyInternal((WOLFSSL_EC_KEY*)key) !=
- 1)) {
- WOLFSSL_MSG("SetECKeyInternal error");
- err = 1;
- }
-
- /* Calculate the length of the private key DER encoding using internal EC
- * key. */
- if ((!err) && ((int)(len = (word32)wc_EccKeyDerSize((ecc_key*)key->internal,
- 0)) <= 0)) {
- WOLFSSL_MSG("wc_EccKeyDerSize error");
- err = 1;
- }
-
- /* Only return length when out is NULL. */
- if ((!err) && (out != NULL)) {
- unsigned char* buf = NULL;
-
- /* Must have a buffer to encode into. */
- if (*out == NULL) {
- /* Allocate a new buffer of appropriate length. */
- buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (buf == NULL) {
- /* Error and return 0. */
- err = 1;
- len = 0;
- }
- else {
- /* Return the allocated buffer. */
- *out = buf;
- }
- }
- /* Encode the internal EC key as a private key in DER format. */
- if ((!err) && wc_EccPrivateKeyToDer((ecc_key*)key->internal, *out,
- len) < 0) {
- WOLFSSL_MSG("wc_EccPrivateKeyToDer error");
- err = 1;
- }
- else if (buf != *out) {
- /* Move the reference to byte past encoded private key. */
- *out += len;
- }
-
- /* Dispose of any allocated buffer on error. */
- if (err && (*out == buf)) {
- XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- *out = NULL;
- }
- }
-
- return (int)len;
-}
-
-/* Load private key into EC key from DER encoding.
- *
- * Not an OpenSSL compatibility API.
- *
- * @param [in, out] key EC key to put private key values into.
- * @param [in] derBuf Buffer holding DER encoding.
- * @param [in] derSz Size of DER encoding in bytes.
- * @return 1 on success.
- * @return -1 on error.
- */
-int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
- int derSz)
-{
- return wolfSSL_EC_KEY_LoadDer_ex(key, derBuf, derSz,
- WOLFSSL_EC_KEY_LOAD_PRIVATE);
-}
-
-/* Load private/public key into EC key from DER encoding.
- *
- * Not an OpenSSL compatibility API.
- *
- * @param [in, out] key EC key to put private/public key values into.
- * @param [in] derBuf Buffer holding DER encoding.
- * @param [in] derSz Size of DER encoding in bytes.
- * @param [in] opt Key type option. Valid values:
- * WOLFSSL_EC_KEY_LOAD_PRIVATE,
- * WOLFSSL_EC_KEY_LOAD_PUBLIC.
- * @return 1 on success.
- * @return -1 on error.
- */
-int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
- int derSz, int opt)
-{
- int res = 1;
- int ret;
- word32 idx = 0;
- word32 algId;
-
- WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer");
-
- /* Validate parameters. */
- if ((key == NULL) || (key->internal == NULL) || (derBuf == NULL) ||
- (derSz <= 0)) {
- WOLFSSL_MSG("Bad function arguments");
- res = WOLFSSL_FATAL_ERROR;
- }
- if ((res == 1) && (opt != WOLFSSL_EC_KEY_LOAD_PRIVATE) &&
- (opt != WOLFSSL_EC_KEY_LOAD_PUBLIC)) {
- res = WOLFSSL_FATAL_ERROR;
- }
-
- if (res == 1) {
- /* Assume no PKCS#8 header. */
- key->pkcs8HeaderSz = 0;
-
- /* Check if input buffer has PKCS8 header. In the case that it does not
- * have a PKCS8 header then do not error out.
- */
- if ((ret = ToTraditionalInline_ex((const byte*)derBuf, &idx,
- (word32)derSz, &algId)) > 0) {
- WOLFSSL_MSG("Found PKCS8 header");
- key->pkcs8HeaderSz = (word16)idx;
- res = 1;
- }
- /* Error out on parsing error. */
- else if (ret != WC_NO_ERR_TRACE(ASN_PARSE_E)) {
- WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header");
- res = WOLFSSL_FATAL_ERROR;
- }
- }
-
- if (res == 1) {
- /* Load into internal EC key based on key type option. */
- if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) {
- ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal,
- (word32)derSz);
- }
- else {
- ret = wc_EccPublicKeyDecode(derBuf, &idx, (ecc_key*)key->internal,
- (word32)derSz);
- if (ret < 0) {
- ecc_key *tmp = (ecc_key*)XMALLOC(sizeof(ecc_key),
- ((ecc_key*)key->internal)->heap, DYNAMIC_TYPE_ECC);
- if (tmp == NULL) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- else {
- /* We now try again as x.963 [point type][x][opt y]. */
- ret = wc_ecc_init_ex(tmp, ((ecc_key*)key->internal)->heap,
- INVALID_DEVID);
- if (ret == 0) {
- ret = wc_ecc_import_x963(derBuf, (word32)derSz, tmp);
- if (ret == 0) {
- /* Take ownership of new key - set tmp to the old
- * key which will then be freed below. */
- ecc_key *old = (ecc_key *)key->internal;
- key->internal = tmp;
- tmp = old;
-
- idx = (word32)derSz;
- }
- wc_ecc_free(tmp);
- }
- XFREE(tmp, ((ecc_key*)key->internal)->heap,
- DYNAMIC_TYPE_ECC);
- }
- }
- }
- if (ret < 0) {
- /* Error returned from wolfSSL. */
- if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) {
- WOLFSSL_MSG("wc_EccPrivateKeyDecode failed");
- }
- else {
- WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
- }
- res = WOLFSSL_FATAL_ERROR;
- }
-
- /* Internal key updated - update whether it is a valid key. */
- key->inSet = (res == 1);
- }
-
- /* Set the external EC key based on value in internal. */
- if ((res == 1) && (SetECKeyExternal(key) != 1)) {
- WOLFSSL_MSG("SetECKeyExternal failed");
- res = WOLFSSL_FATAL_ERROR;
- }
-
- return res;
-}
-
-
-#ifndef NO_BIO
-
-WOLFSSL_EC_KEY *wolfSSL_d2i_EC_PUBKEY_bio(WOLFSSL_BIO *bio,
- WOLFSSL_EC_KEY **out)
-{
- char* data = NULL;
- int dataSz = 0;
- int memAlloced = 0;
- WOLFSSL_EC_KEY* ec = NULL;
- int err = 0;
-
- WOLFSSL_ENTER("wolfSSL_d2i_EC_PUBKEY_bio");
-
- if (bio == NULL)
- return NULL;
-
- if (err == 0 && wolfssl_read_bio(bio, &data, &dataSz, &memAlloced) != 0) {
- WOLFSSL_ERROR_MSG("wolfssl_read_bio failed");
- err = 1;
- }
-
- if (err == 0 && (ec = wolfSSL_EC_KEY_new()) == NULL) {
- WOLFSSL_ERROR_MSG("wolfSSL_EC_KEY_new failed");
- err = 1;
- }
-
- /* Load the EC key with the public key from the DER encoding. */
- if (err == 0 && wolfSSL_EC_KEY_LoadDer_ex(ec, (const unsigned char*)data,
- dataSz, WOLFSSL_EC_KEY_LOAD_PUBLIC) != 1) {
- WOLFSSL_ERROR_MSG("wolfSSL_EC_KEY_LoadDer_ex failed");
- err = 1;
- }
-
- if (memAlloced)
- XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (err) { /* on error */
- wolfSSL_EC_KEY_free(ec);
- ec = NULL;
- }
- else { /* on success */
- if (out != NULL)
- *out = ec;
- }
-
- return ec;
-}
-
-#endif /* !NO_BIO */
-
-/*
- * EC key PEM APIs
- */
-
-#ifdef HAVE_ECC_KEY_EXPORT
-#if defined(WOLFSSL_KEY_GEN) && (!defined(NO_FILESYSTEM) || !defined(NO_BIO))
-/* Encode the EC public key as DER.
- *
- * @param [in] key EC key to encode.
- * @param [out] der Pointer through which buffer is returned.
- * @param [in] heap Heap hint.
- * @return Size of encoding on success.
- * @return 0 on error.
- */
-static int wolfssl_ec_key_to_pubkey_der(WOLFSSL_EC_KEY* key,
- unsigned char** der, void* heap)
-{
- int sz;
- unsigned char* buf = NULL;
-
- (void)heap;
-
- /* Calculate encoded size to allocate. */
- sz = wc_EccPublicKeyDerSize((ecc_key*)key->internal, 1);
- if (sz <= 0) {
- WOLFSSL_MSG("wc_EccPublicKeyDerSize failed");
- sz = 0;
- }
- if (sz > 0) {
- /* Allocate memory to hold encoding. */
- buf = (byte*)XMALLOC((size_t)sz, heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (buf == NULL) {
- WOLFSSL_MSG("malloc failed");
- sz = 0;
- }
- }
- if (sz > 0) {
- /* Encode public key to DER using wolfSSL. */
- sz = wc_EccPublicKeyToDer((ecc_key*)key->internal, buf, (word32)sz, 1);
- if (sz < 0) {
- WOLFSSL_MSG("wc_EccPublicKeyToDer failed");
- sz = 0;
- }
- }
-
- /* Return buffer on success. */
- if (sz > 0) {
- *der = buf;
- }
- else {
- /* Dispose of any dynamically allocated data not returned. */
- XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
-
- return sz;
-}
-#endif
-
-#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_KEY_GEN)
-/*
- * Return code compliant with OpenSSL.
- *
- * @param [in] fp File pointer to write PEM encoding to.
- * @param [in] key EC key to encode and write.
- * @return 1 on success.
- * @return 0 on error.
- */
-int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY* key)
-{
- int ret = 1;
- unsigned char* derBuf = NULL;
- int derSz = 0;
-
- WOLFSSL_ENTER("wolfSSL_PEM_write_EC_PUBKEY");
-
- /* Validate parameters. */
- if ((fp == XBADFILE) || (key == NULL)) {
- WOLFSSL_MSG("Bad argument.");
- return 0;
- }
-
- /* Encode public key in EC key as DER. */
- derSz = wolfssl_ec_key_to_pubkey_der(key, &derBuf, key->heap);
- if (derSz == 0) {
- ret = 0;
- }
-
- /* Write out to file the PEM encoding of the DER. */
- if ((ret == 1) && (der_write_to_file_as_pem(derBuf, derSz, fp,
- ECC_PUBLICKEY_TYPE, key->heap) != 1)) {
- ret = 0;
- }
-
- /* Dispose of any dynamically allocated data. */
- XFREE(derBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-
- WOLFSSL_LEAVE("wolfSSL_PEM_write_EC_PUBKEY", ret);
-
- return ret;
-}
-#endif
-#endif
-
-#ifndef NO_BIO
-/* Read a PEM encoded EC public key from a BIO.
- *
- * @param [in] bio BIO to read EC public key from.
- * @param [out] out Pointer to return EC key object through. May be NULL.
- * @param [in] cb Password callback when PEM encrypted.
- * @param [in] pass NUL terminated string for passphrase when PEM
- * encrypted.
- * @return New EC key object on success.
- * @return NULL on error.
- */
-WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_EC_PUBKEY(WOLFSSL_BIO* bio,
- WOLFSSL_EC_KEY** out, wc_pem_password_cb* cb, void *pass)
-{
- int err = 0;
- WOLFSSL_EC_KEY* ec = NULL;
- DerBuffer* der = NULL;
- int keyFormat = 0;
-
- WOLFSSL_ENTER("wolfSSL_PEM_read_bio_EC_PUBKEY");
-
- /* Validate parameters. */
- if (bio == NULL) {
- err = 1;
- }
-
- if (!err) {
- /* Create an empty EC key. */
- ec = wolfSSL_EC_KEY_new();
- if (ec == NULL) {
- err = 1;
- }
- }
- /* Read a PEM key in to a new DER buffer. */
- if ((!err) && (pem_read_bio_key(bio, cb, pass, ECC_PUBLICKEY_TYPE,
- &keyFormat, &der) <= 0)) {
- err = 1;
- }
- /* Load the EC key with the public key from the DER encoding. */
- if ((!err) && (wolfSSL_EC_KEY_LoadDer_ex(ec, der->buffer, (int)der->length,
- WOLFSSL_EC_KEY_LOAD_PUBLIC) != 1)) {
- WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_EC_KEY");
- err = 1;
- }
-
- /* Dispose of dynamically allocated data not needed anymore. */
- FreeDer(&der);
- if (err) {
- wolfSSL_EC_KEY_free(ec);
- ec = NULL;
- }
-
- /* Return EC key through out if required. */
- if ((out != NULL) && (ec != NULL)) {
- *out = ec;
- }
- return ec;
-}
-
-/* Read a PEM encoded EC private key from a BIO.
- *
- * @param [in] bio BIO to read EC private key from.
- * @param [out] out Pointer to return EC key object through. May be NULL.
- * @param [in] cb Password callback when PEM encrypted.
- * @param [in] pass NUL terminated string for passphrase when PEM
- * encrypted.
- * @return New EC key object on success.
- * @return NULL on error.
- */
-WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_ECPrivateKey(WOLFSSL_BIO* bio,
- WOLFSSL_EC_KEY** out, wc_pem_password_cb* cb, void *pass)
-{
- int err = 0;
- WOLFSSL_EC_KEY* ec = NULL;
- DerBuffer* der = NULL;
- int keyFormat = 0;
-
- WOLFSSL_ENTER("wolfSSL_PEM_read_bio_ECPrivateKey");
-
- /* Validate parameters. */
- if (bio == NULL) {
- err = 1;
- }
-
- if (!err) {
- /* Create an empty EC key. */
- ec = wolfSSL_EC_KEY_new();
- if (ec == NULL) {
- err = 1;
- }
- }
- /* Read a PEM key in to a new DER buffer.
- * To check ENC EC PRIVATE KEY, it uses PRIVATEKEY_TYPE to call
- * pem_read_bio_key(), and then check key format if it is EC.
- */
- if ((!err) && (pem_read_bio_key(bio, cb, pass, PRIVATEKEY_TYPE,
- &keyFormat, &der) <= 0)) {
- err = 1;
- }
- if (keyFormat != ECDSAk) {
- WOLFSSL_ERROR_MSG("Error not EC key format");
- err = 1;
- }
- /* Load the EC key with the private key from the DER encoding. */
- if ((!err) && (wolfSSL_EC_KEY_LoadDer_ex(ec, der->buffer, (int)der->length,
- WOLFSSL_EC_KEY_LOAD_PRIVATE) != 1)) {
- WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_EC_KEY");
- err = 1;
- }
-
- /* Dispose of dynamically allocated data not needed anymore. */
- FreeDer(&der);
- if (err) {
- wolfSSL_EC_KEY_free(ec);
- ec = NULL;
- }
-
- /* Return EC key through out if required. */
- if ((out != NULL) && (ec != NULL)) {
- *out = ec;
- }
- return ec;
-}
-#endif /* !NO_BIO */
-
-#if defined(WOLFSSL_KEY_GEN) && defined(HAVE_ECC_KEY_EXPORT)
-#ifndef NO_BIO
-/* Write out the EC public key as PEM to the BIO.
- *
- * @param [in] bio BIO to write PEM encoding to.
- * @param [in] ec EC public key to encode.
- * @return 1 on success.
- * @return 0 on error.
- */
-int wolfSSL_PEM_write_bio_EC_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec)
-{
- int ret = 1;
- unsigned char* derBuf = NULL;
- int derSz = 0;
-
- WOLFSSL_ENTER("wolfSSL_PEM_write_bio_EC_PUBKEY");
-
- /* Validate parameters. */
- if ((bio == NULL) || (ec == NULL)) {
- WOLFSSL_MSG("Bad Function Arguments");
- return 0;
- }
-
- /* Encode public key in EC key as DER. */
- derSz = wolfssl_ec_key_to_pubkey_der(ec, &derBuf, ec->heap);
- if (derSz == 0) {
- ret = 0;
- }
-
- /* Write out to BIO the PEM encoding of the EC public key. */
- if ((ret == 1) && (der_write_to_bio_as_pem(derBuf, derSz, bio,
- ECC_PUBLICKEY_TYPE) != 1)) {
- ret = 0;
- }
-
- /* Dispose of any dynamically allocated data. */
- XFREE(derBuf, ec->heap, DYNAMIC_TYPE_TMP_BUFFER);
-
- return ret;
-}
-
-/* Write out the EC private key as PEM to the BIO.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in] bio BIO to write PEM encoding to.
- * @param [in] ec EC private key to encode.
- * @param [in] cipher Cipher to use when PEM encrypted. May be NULL.
- * @param [in] passwd Password string when PEM encrypted. May be NULL.
- * @param [in] passwdSz Length of password string when PEM encrypted.
- * @param [in] cb Password callback when PEM encrypted. Unused.
- * @param [in] pass NUL terminated string for passphrase when PEM
- * encrypted. Unused.
- * @return 1 on success.
- * @return 0 on error.
- */
-int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec,
- const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz,
- wc_pem_password_cb* cb, void* arg)
-{
- int ret = 1;
- unsigned char* pem = NULL;
- int pLen = 0;
-
- (void)cb;
- (void)arg;
-
- /* Validate parameters. */
- if ((bio == NULL) || (ec == NULL)) {
- ret = 0;
- }
-
- /* Write EC private key to PEM. */
- if ((ret == 1) && (wolfSSL_PEM_write_mem_ECPrivateKey(ec, cipher, passwd,
- passwdSz, &pem, &pLen) != 1)) {
- ret = 0;
- }
- /* Write PEM to BIO. */
- if ((ret == 1) && (wolfSSL_BIO_write(bio, pem, pLen) != pLen)) {
- WOLFSSL_ERROR_MSG("EC private key BIO write failed");
- ret = 0;
- }
-
- XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
-
- return ret;
-}
-
-#endif /* !NO_BIO */
-
-/* Encode the EC private key as PEM into buffer.
- *
- * Return code compliant with OpenSSL.
- * Not an OpenSSL API.
- *
- * @param [in] ec EC private key to encode.
- * @param [in] cipher Cipher to use when PEM encrypted. May be NULL.
- * @param [in] passwd Password string when PEM encrypted. May be NULL.
- * @param [in] passwdSz Length of password string when PEM encrypted.
- * @param [out] pem Newly allocated buffer holding PEM encoding.
- * @param [out] pLen Length of PEM encoding in bytes.
- * @return 1 on success.
- * @return 0 on error.
- */
-int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ec,
- const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz,
- unsigned char **pem, int *pLen)
-{
-#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
- int ret = 1;
- byte* derBuf = NULL;
- word32 der_max_len = 0;
- int derSz = 0;
-
- WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey");
-
- /* Validate parameters. */
- if ((pem == NULL) || (pLen == NULL) || (ec == NULL) ||
- (ec->internal == NULL)) {
- WOLFSSL_MSG("Bad function arguments");
- ret = 0;
- }
-
- /* Ensure internal EC key is set from external. */
- if ((ret == 1) && (ec->inSet == 0)) {
- WOLFSSL_MSG("No ECC internal set, do it");
-
- if (SetECKeyInternal(ec) != 1) {
- WOLFSSL_MSG("SetECKeyInternal failed");
- ret = 0;
- }
- }
-
- if (ret == 1) {
- /* Calculate maximum size of DER encoding.
- * 4 > size of pub, priv + ASN.1 additional information */
- der_max_len = 4 * (word32)wc_ecc_size((ecc_key*)ec->internal) +
- WC_AES_BLOCK_SIZE;
-
- /* Allocate buffer big enough to hold encoding. */
- derBuf = (byte*)XMALLOC((size_t)der_max_len, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (derBuf == NULL) {
- WOLFSSL_MSG("malloc failed");
- ret = 0;
- }
- }
-
- if (ret == 1) {
- /* Encode EC private key as DER. */
- derSz = wc_EccKeyToDer((ecc_key*)ec->internal, derBuf, der_max_len);
- if (derSz < 0) {
- WOLFSSL_MSG("wc_EccKeyToDer failed");
- XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
- ret = 0;
- }
- }
-
- /* Convert DER to PEM - possibly encrypting. */
- if ((ret == 1) && (der_to_enc_pem_alloc(derBuf, derSz, cipher, passwd,
- passwdSz, ECC_PRIVATEKEY_TYPE, NULL, pem, pLen) != 1)) {
- WOLFSSL_ERROR_MSG("der_to_enc_pem_alloc failed");
- ret = 0;
- }
-
- return ret;
-#else
- (void)ec;
- (void)cipher;
- (void)passwd;
- (void)passwdSz;
- (void)pem;
- (void)pLen;
- return 0;
-#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
-}
-
-#ifndef NO_FILESYSTEM
-/* Write out the EC private key as PEM to file.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in] fp File pointer to write PEM encoding to.
- * @param [in] ec EC private key to encode.
- * @param [in] cipher Cipher to use when PEM encrypted. May be NULL.
- * @param [in] passwd Password string when PEM encrypted. May be NULL.
- * @param [in] passwdSz Length of password string when PEM encrypted.
- * @param [in] cb Password callback when PEM encrypted. Unused.
- * @param [in] pass NUL terminated string for passphrase when PEM
- * encrypted. Unused.
- * @return 1 on success.
- * @return 0 on error.
- */
-int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *ec,
- const WOLFSSL_EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz,
- wc_pem_password_cb *cb, void *pass)
-{
- int ret = 1;
- byte *pem = NULL;
- int pLen = 0;
-
- (void)cb;
- (void)pass;
-
- WOLFSSL_MSG("wolfSSL_PEM_write_ECPrivateKey");
-
- /* Validate parameters. */
- if ((fp == XBADFILE) || (ec == NULL) || (ec->internal == NULL)) {
- WOLFSSL_MSG("Bad function arguments");
- ret = 0;
- }
-
- /* Write EC private key to PEM. */
- if ((ret == 1) && (wolfSSL_PEM_write_mem_ECPrivateKey(ec, cipher, passwd,
- passwdSz, &pem, &pLen) != 1)) {
- WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed");
- ret = 0;
- }
-
- /* Write out to file the PEM encoding of the EC private key. */
- if ((ret == 1) && ((int)XFWRITE(pem, 1, (size_t)pLen, fp) != pLen)) {
- WOLFSSL_MSG("ECC private key file write failed");
- ret = 0;
- }
-
- /* Dispose of any dynamically allocated data. */
- XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
-
- return ret;
-}
-
-#endif /* NO_FILESYSTEM */
-#endif /* WOLFSSL_KEY_GEN && HAVE_ECC_KEY_EXPORT */
-
-/*
- * EC key print APIs
- */
-
-#ifndef NO_CERTS
-
-#if defined(XFPRINTF) && !defined(NO_FILESYSTEM) && \
- !defined(NO_STDIO_FILESYSTEM)
-/* Print the EC key to a file pointer as text.
- *
- * @param [in] fp File pointer.
- * @param [in] key EC key to print.
- * @param [in] indent Number of spaces to place before each line printed.
- * @return 1 on success.
- * @return 0 on failure.
- */
-int wolfSSL_EC_KEY_print_fp(XFILE fp, WOLFSSL_EC_KEY* key, int indent)
-{
- int ret = 1;
- int bits = 0;
- int priv = 0;
-
- WOLFSSL_ENTER("wolfSSL_EC_KEY_print_fp");
-
- /* Validate parameters. */
- if ((fp == XBADFILE) || (key == NULL) || (key->group == NULL) ||
- (indent < 0)) {
- ret = 0;
- }
-
- if (ret == 1) {
- /* Get EC groups order size in bits. */
- bits = wolfSSL_EC_GROUP_order_bits(key->group);
- if (bits <= 0) {
- WOLFSSL_MSG("Failed to get group order bits.");
- ret = 0;
- }
- }
- if (ret == 1) {
- const char* keyType;
-
- /* Determine whether this is a private or public key. */
- if ((key->priv_key != NULL) && (!wolfSSL_BN_is_zero(key->priv_key))) {
- keyType = "Private-Key";
- priv = 1;
- }
- else {
- keyType = "Public-Key";
- }
-
- /* Print key header. */
- if (XFPRINTF(fp, "%*s%s: (%d bit)\n", indent, "", keyType, bits) < 0) {
- ret = 0;
- }
- }
- if ((ret == 1) && priv) {
- /* Print the private key BN. */
- ret = pk_bn_field_print_fp(fp, indent, "priv", key->priv_key);
- }
- /* Check for public key data in EC key. */
- if ((ret == 1) && (key->pub_key != NULL) && (key->pub_key->exSet)) {
- /* Get the public key point as one BN. */
- WOLFSSL_BIGNUM* pubBn = wolfSSL_EC_POINT_point2bn(key->group,
- key->pub_key, WC_POINT_CONVERSION_UNCOMPRESSED, NULL, NULL);
- if (pubBn == NULL) {
- WOLFSSL_MSG("wolfSSL_EC_POINT_point2bn failed.");
- ret = 0;
- }
- else {
- /* Print the public key in a BN. */
- ret = pk_bn_field_print_fp(fp, indent, "pub", pubBn);
- wolfSSL_BN_free(pubBn);
- }
- }
- if (ret == 1) {
- /* Get the NID of the group. */
- int nid = wolfSSL_EC_GROUP_get_curve_name(key->group);
- if (nid > 0) {
- /* Convert the NID into a long name and NIST name. */
- const char* curve = wolfSSL_OBJ_nid2ln(nid);
- const char* nistName = wolfSSL_EC_curve_nid2nist(nid);
-
- /* Print OID name if known. */
- if ((curve != NULL) &&
- (XFPRINTF(fp, "%*sASN1 OID: %s\n", indent, "", curve) < 0)) {
- ret = 0;
- }
- /* Print NIST curve name if known. */
- if ((nistName != NULL) &&
- (XFPRINTF(fp, "%*sNIST CURVE: %s\n", indent, "",
- nistName) < 0)) {
- ret = 0;
- }
- }
- }
-
-
- WOLFSSL_LEAVE("wolfSSL_EC_KEY_print_fp", ret);
-
- return ret;
-}
-#endif /* XFPRINTF && !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */
-
-#endif /* !NO_CERTS */
-
-/*
- * EC_KEY get/set/test APIs
- */
-
-/* Set data of internal, wolfCrypt EC key object into EC key.
- *
- * EC_KEY wolfSSL -> OpenSSL
- *
- * @param [in, out] p EC key to update.
- * @return 1 on success.
- * @return -1 on failure.
- */
-int SetECKeyExternal(WOLFSSL_EC_KEY* eckey)
-{
- int ret = 1;
-
- WOLFSSL_ENTER("SetECKeyExternal");
-
- /* Validate parameter. */
- if ((eckey == NULL) || (eckey->internal == NULL)) {
- WOLFSSL_MSG("ec key NULL error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- else {
- ecc_key* key = (ecc_key*)eckey->internal;
-
- /* Set group (OID, nid and idx) from wolfCrypt EC key. */
- eckey->group->curve_oid = (int)key->dp->oidSum;
- eckey->group->curve_nid = EccEnumToNID(key->dp->id);
- eckey->group->curve_idx = key->idx;
-
- if (eckey->pub_key->internal != NULL) {
- /* Copy internal public point from internal key's public point. */
- if (wc_ecc_copy_point(&key->pubkey,
- (ecc_point*)eckey->pub_key->internal) != MP_OKAY) {
- WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- /* Set external public key from internal wolfCrypt, public key. */
- if ((ret == 1) && (ec_point_external_set(eckey->pub_key) != 1)) {
- WOLFSSL_MSG("SetECKeyExternal ec_point_external_set failed");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
-
- /* set the external privkey */
- if ((ret == 1) && (key->type == ECC_PRIVATEKEY) &&
- (wolfssl_bn_set_value(&eckey->priv_key,
- wc_ecc_key_get_priv(key)) != 1)) {
- WOLFSSL_MSG("ec priv key error");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- /* External values set when operations succeeded. */
- eckey->exSet = (ret == 1);
- }
-
- return ret;
-}
-
-/* Set data of EC key into internal, wolfCrypt EC key object.
- *
- * EC_KEY Openssl -> WolfSSL
- *
- * @param [in, out] p EC key to update.
- * @return 1 on success.
- * @return -1 on failure.
- */
-int SetECKeyInternal(WOLFSSL_EC_KEY* eckey)
-{
- int ret = 1;
-
- WOLFSSL_ENTER("SetECKeyInternal");
-
- /* Validate parameter. */
- if ((eckey == NULL) || (eckey->internal == NULL) ||
- (eckey->group == NULL)) {
- WOLFSSL_MSG("ec key NULL error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- else {
- ecc_key* key = (ecc_key*)eckey->internal;
- int pubSet = 0;
-
- /* Validate group. */
- if ((eckey->group->curve_idx < 0) ||
- (wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) {
- WOLFSSL_MSG("invalid curve idx");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- if (ret == 1) {
- /* Set group (idx of curve and corresponding domain parameters). */
- key->idx = eckey->group->curve_idx;
- key->dp = &ecc_sets[key->idx];
- pubSet = (eckey->pub_key != NULL);
- }
- /* Set public key (point). */
- if ((ret == 1) && pubSet) {
- if (ec_point_internal_set(eckey->pub_key) != 1) {
- WOLFSSL_MSG("ec key pub error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- /* Copy public point to key. */
- if ((ret == 1) && (wc_ecc_copy_point(
- (ecc_point*)eckey->pub_key->internal, &key->pubkey) !=
- MP_OKAY)) {
- WOLFSSL_MSG("wc_ecc_copy_point error");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- if (ret == 1) {
- /* Set that the internal key is a public key */
- key->type = ECC_PUBLICKEY;
- }
- }
-
- /* set privkey */
- if ((ret == 1) && (eckey->priv_key != NULL)) {
- if (wolfssl_bn_get_value(eckey->priv_key,
- wc_ecc_key_get_priv(key)) != 1) {
- WOLFSSL_MSG("ec key priv error");
- ret = WOLFSSL_FATAL_ERROR;
- }
- /* private key */
- if ((ret == 1) && (!mp_iszero(wc_ecc_key_get_priv(key)))) {
- if (pubSet) {
- key->type = ECC_PRIVATEKEY;
- }
- else {
- key->type = ECC_PRIVATEKEY_ONLY;
- }
- }
- }
-
- /* Internal values set when operations succeeded. */
- eckey->inSet = (ret == 1);
- }
-
- return ret;
-}
-
-/* Get point conversion format of EC key.
- *
- * @param [in] key EC key.
- * @return Point conversion format on success.
- * @return -1 on error.
- */
-wc_point_conversion_form_t wolfSSL_EC_KEY_get_conv_form(
- const WOLFSSL_EC_KEY* key)
-{
- if (key == NULL)
- return WOLFSSL_FATAL_ERROR;
- return key->form;
-}
-
-/* Set point conversion format into EC key.
- *
- * @param [in, out] key EC key to set format into.
- * @param [in] form Point conversion format. Valid values:
- * WC_POINT_CONVERSION_UNCOMPRESSED,
- * WC_POINT_CONVERSION_COMPRESSED (when HAVE_COMP_KEY)
- */
-void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *key, int form)
-{
- if (key == NULL) {
- WOLFSSL_MSG("Key passed in NULL");
- }
- else if (form == WC_POINT_CONVERSION_UNCOMPRESSED
-#ifdef HAVE_COMP_KEY
- || form == WC_POINT_CONVERSION_COMPRESSED
-#endif
- ) {
- key->form = (unsigned char)form;
- }
- else {
- WOLFSSL_MSG("Incorrect form or HAVE_COMP_KEY not compiled in");
- }
-}
-
-/* Get the EC group object that is in EC key.
- *
- * @param [in] key EC key.
- * @return EC group object on success.
- * @return NULL when key is NULL.
- */
-const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key)
-{
- WOLFSSL_EC_GROUP* group = NULL;
-
- WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_group");
-
- if (key != NULL) {
- group = key->group;
- }
-
- return group;
-}
-
-/* Set the group in WOLFSSL_EC_KEY
- *
- * @param [in, out] key EC key to update.
- * @param [in] group EC group to copy.
- * @return 1 on success
- * @return 0 on failure.
- */
-int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group)
-{
- int ret = 1;
-
- WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group");
-
- /* Validate parameters. */
- if ((key == NULL) || (group == NULL)) {
- ret = 0;
- }
-
- if (ret == 1) {
- /* Dispose of the current group. */
- if (key->group != NULL) {
- wolfSSL_EC_GROUP_free(key->group);
- }
- /* Duplicate the passed in group into EC key. */
- key->group = wolfSSL_EC_GROUP_dup(group);
- if (key->group == NULL) {
- ret = 0;
- }
- }
-
- return ret;
-}
-
-/* Get the BN object that is the private key in the EC key.
- *
- * @param [in] key EC key.
- * @return BN object on success.
- * @return NULL when key is NULL or private key is not set.
- */
-WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key)
-{
- WOLFSSL_BIGNUM* priv_key = NULL;
-
- WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key");
-
- /* Validate parameter. */
- if (key == NULL) {
- WOLFSSL_MSG("wolfSSL_EC_KEY_get0_private_key Bad arguments");
- }
- /* Only return private key if it is not 0. */
- else if (!wolfSSL_BN_is_zero(key->priv_key)) {
- priv_key = key->priv_key;
- }
-
- return priv_key;
-}
-
-/* Sets the private key value into EC key.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in, out] key EC key to set.
- * @param [in] priv_key Private key value in a BN.
- * @return 1 on success
- * @return 0 on failure.
- */
-int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key,
- const WOLFSSL_BIGNUM *priv_key)
-{
- int ret = 1;
-
- WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key");
-
- /* Validate parameters. */
- if ((key == NULL) || (priv_key == NULL)) {
- WOLFSSL_MSG("Bad arguments");
- ret = 0;
- }
-
- /* Check for obvious invalid values. */
- if (wolfSSL_BN_is_negative(priv_key) || wolfSSL_BN_is_zero(priv_key) ||
- wolfSSL_BN_is_one(priv_key)) {
- WOLFSSL_MSG("Invalid private key value");
- ret = 0;
- }
-
- if (ret == 1) {
- /* Free key if previously set. */
- if (key->priv_key != NULL) {
- wolfSSL_BN_free(key->priv_key);
- }
-
- /* Duplicate the BN passed in. */
- key->priv_key = wolfSSL_BN_dup(priv_key);
- if (key->priv_key == NULL) {
- WOLFSSL_MSG("key ecc priv key NULL");
- ret = 0;
- }
- }
- /* Set the external values into internal EC key. */
- if ((ret == 1) && (SetECKeyInternal(key) != 1)) {
- WOLFSSL_MSG("SetECKeyInternal failed");
- /* Dispose of new private key on error. */
- wolfSSL_BN_free(key->priv_key);
- key->priv_key = NULL;
- ret = 0;
- }
-
- return ret;
-}
-
-/* Get the public key EC point object that is in EC key.
- *
- * @param [in] key EC key.
- * @return EC point object that is the public key on success.
- * @return NULL when key is NULL.
- */
-WOLFSSL_EC_POINT* wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key)
-{
- WOLFSSL_EC_POINT* pub_key = NULL;
-
- WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_public_key");
-
- if (key != NULL) {
- pub_key = key->pub_key;
- }
-
- return pub_key;
-}
-
-/*
- * Return code compliant with OpenSSL.
- *
- * @param [in, out] key EC key.
- * @param [in] pub Public key as an EC point.
- * @return 1 on success
- * @return 0 on failure.
- */
-int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key,
- const WOLFSSL_EC_POINT *pub)
-{
- int ret = 1;
- ecc_point *pub_p = NULL;
- ecc_point *key_p = NULL;
-
- WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key");
-
- /* Validate parameters. */
- if ((key == NULL) || (key->internal == NULL) || (pub == NULL) ||
- (pub->internal == NULL)) {
- WOLFSSL_MSG("wolfSSL_EC_KEY_set_public_key Bad arguments");
- ret = 0;
- }
-
- /* Ensure the internal EC key is set. */
- if ((ret == 1) && (key->inSet == 0) && (SetECKeyInternal(key) != 1)) {
- WOLFSSL_MSG("SetECKeyInternal failed");
- ret = 0;
- }
-
- /* Ensure the internal EC point of pub is setup. */
- if ((ret == 1) && (ec_point_setup(pub) != 1)) {
- ret = 0;
- }
-
- if (ret == 1) {
- /* Get the internal point of pub and the public key in key. */
- pub_p = (ecc_point*)pub->internal;
- key_p = (ecc_point*)key->pub_key->internal;
-
- /* Create new point if required. */
- if (key_p == NULL) {
- key_p = wc_ecc_new_point();
- key->pub_key->internal = (void*)key_p;
- }
- /* Check point available. */
- if (key_p == NULL) {
- WOLFSSL_MSG("key ecc point NULL");
- ret = 0;
- }
- }
-
- /* Copy the internal pub point into internal key point. */
- if ((ret == 1) && (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY)) {
- WOLFSSL_MSG("ecc_copy_point failure");
- ret = 0;
- }
-
- /* Copy the internal point data into external. */
- if ((ret == 1) && (ec_point_external_set(key->pub_key) != 1)) {
- WOLFSSL_MSG("SetECKeyInternal failed");
- ret = 0;
- }
-
- /* Copy the internal key into external. */
- if ((ret == 1) && (SetECKeyInternal(key) != 1)) {
- WOLFSSL_MSG("SetECKeyInternal failed");
- ret = 0;
- }
-
- if (ret == 1) {
- /* Dump out the point and the key's public key for debug. */
- wolfSSL_EC_POINT_dump("pub", pub);
- wolfSSL_EC_POINT_dump("key->pub_key", key->pub_key);
- }
-
- return ret;
-}
-
-#ifndef NO_WOLFSSL_STUB
-/* Set the ASN.1 encoding flag against the EC key.
- *
- * No implementation as only named curves supported for encoding.
- *
- * @param [in, out] key EC key.
- * @param [in] flag ASN.1 flag to set. Valid values:
- * OPENSSL_EC_EXPLICIT_CURVE, OPENSSL_EC_NAMED_CURVE
- */
-void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag)
-{
- (void)key;
- (void)asn1_flag;
-
- WOLFSSL_ENTER("wolfSSL_EC_KEY_set_asn1_flag");
- WOLFSSL_STUB("EC_KEY_set_asn1_flag");
-}
-#endif
-
-/*
- * EC key generate key APIs
- */
-
-/* Generate an EC key.
- *
- * Uses the internal curve index set in the EC key or the default.
- *
- * @param [in, out] key EC key.
- * @return 1 on success
- * @return 0 on failure.
- */
-int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key)
-{
- int res = 1;
- int initTmpRng = 0;
- WC_RNG* rng = NULL;
- WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
-
- WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key");
-
- /* Validate parameters. */
- if ((key == NULL) || (key->internal == NULL) || (key->group == NULL)) {
- WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key Bad arguments");
- res = 0;
- }
- if (res == 1) {
- /* Check if we know which internal curve index to use. */
- if (key->group->curve_idx < 0) {
- /* Generate key using the default curve. */
-#if FIPS_VERSION3_GE(6,0,0)
- key->group->curve_idx = ECC_SECP256R1; /* FIPS default to 256 */
-#else
- key->group->curve_idx = ECC_CURVE_DEF;
-#endif
- }
-
- /* Create a random number generator. */
- rng = wolfssl_make_rng(tmpRng, &initTmpRng);
- if (rng == NULL) {
- WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to make RNG");
- res = 0;
- }
- }
- if (res == 1) {
- /* NIDToEccEnum returns -1 for invalid NID so if key->group->curve_nid
- * is 0 then pass ECC_CURVE_DEF as arg */
- int eccEnum = key->group->curve_nid ?
-#if FIPS_VERSION3_GE(6,0,0)
- NIDToEccEnum(key->group->curve_nid) : ECC_SECP256R1;
-#else
- NIDToEccEnum(key->group->curve_nid) : ECC_CURVE_DEF;
-#endif
- /* Get the internal EC key. */
- ecc_key* ecKey = (ecc_key*)key->internal;
- /* Make the key using internal API. */
- int ret = 0;
-
-#if FIPS_VERSION3_GE(6,0,0)
- /* In the case of FIPS only allow key generation with approved curves */
- if (eccEnum != ECC_SECP256R1 && eccEnum != ECC_SECP224R1 &&
- eccEnum != ECC_SECP384R1 && eccEnum != ECC_SECP521R1) {
- WOLFSSL_MSG("Unsupported curve selected in FIPS mode");
- res = 0;
- }
- if (res == 1) {
-#endif
- ret = wc_ecc_make_key_ex(rng, 0, ecKey, eccEnum);
-#if FIPS_VERSION3_GE(6,0,0)
- }
-#endif
-
- #if defined(WOLFSSL_ASYNC_CRYPT)
- /* Wait on asynchronouse operation. */
- ret = wc_AsyncWait(ret, &ecKey->asyncDev, WC_ASYNC_FLAG_NONE);
- #endif
- if (ret != 0) {
- WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed");
- res = 0;
- }
- }
-
- /* Dispose of local random number generator if initialized. */
- if (initTmpRng) {
- wc_FreeRng(rng);
- WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG);
- }
-
- /* Set the external key from new internal key values. */
- if ((res == 1) && (SetECKeyExternal(key) != 1)) {
- WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed");
- res = 0;
- }
-
- return res;
-}
-
-/*
- * EC key check key APIs
- */
-
-/* Check that the EC key is valid.
- *
- * @param [in] key EC key.
- * @return 1 on valid.
- * @return 0 on invalid or error.
- */
-int wolfSSL_EC_KEY_check_key(const WOLFSSL_EC_KEY *key)
-{
- int ret = 1;
-
- WOLFSSL_ENTER("wolfSSL_EC_KEY_check_key");
-
- /* Validate parameter. */
- if ((key == NULL) || (key->internal == NULL)) {
- WOLFSSL_MSG("Bad parameter");
- ret = 0;
- }
-
- /* Set the external EC key values into internal if not already. */
- if ((ret == 1) && (key->inSet == 0) && (SetECKeyInternal(
- (WOLFSSL_EC_KEY*)key) != 1)) {
- WOLFSSL_MSG("SetECKeyInternal failed");
- ret = 0;
- }
-
- if (ret == 1) {
- /* Have internal EC implementation check key. */
- ret = wc_ecc_check_key((ecc_key*)key->internal) == 0;
- }
-
- return ret;
-}
-
-/* End EC_KEY */
-
-#if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)
-/* Get the supported, built-in EC curves
- *
- * @param [in, out] curves Pre-allocated list to put supported curves into.
- * @param [in] len Maximum number of items to place in list.
- * @return Number of built-in EC curves when curves is NULL or len is 0.
- * @return Number of items placed in list otherwise.
- */
-size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *curves,
- size_t len)
-{
- size_t i;
- size_t cnt;
-#ifdef HAVE_SELFTEST
- /* Defined in ecc.h when available. */
- size_t ecc_sets_count;
-
- /* Count the pre-defined curves since global not available. */
- for (i = 0; ecc_sets[i].size != 0 && ecc_sets[i].name != NULL; i++) {
- /* Do nothing. */
- }
- ecc_sets_count = i;
-#endif
-
- /* Assume we are going to return total count. */
- cnt = ecc_sets_count;
- /* Check we have a list that can hold data. */
- if ((curves != NULL) && (len != 0)) {
- /* Limit count to length of list. */
- if (cnt > len) {
- cnt = len;
- }
-
- /* Put in built-in EC curve nid and short name. */
- for (i = 0; i < cnt; i++) {
- curves[i].nid = EccEnumToNID(ecc_sets[i].id);
- curves[i].comment = wolfSSL_OBJ_nid2sn(curves[i].nid);
- }
- }
-
- return cnt;
-}
-#endif /* !HAVE_FIPS || FIPS_VERSION_GT(2,0) */
-
-/* Start ECDSA_SIG */
-
-/* Allocate a new ECDSA signature object.
- *
- * @return New, allocated ECDSA signature object on success.
- * @return NULL on error.
- */
-WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void)
-{
- int err = 0;
- WOLFSSL_ECDSA_SIG *sig;
-
- WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_new");
-
- /* Allocate memory for ECDSA signature object. */
- sig = (WOLFSSL_ECDSA_SIG*)XMALLOC(sizeof(WOLFSSL_ECDSA_SIG), NULL,
- DYNAMIC_TYPE_ECC);
- if (sig == NULL) {
- WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA signature failure");
- err = 1;
- }
-
- if (!err) {
- /* Set s to NULL in case of error. */
- sig->s = NULL;
- /* Allocate BN into r. */
- sig->r = wolfSSL_BN_new();
- if (sig->r == NULL) {
- WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA r failure");
- err = 1;
- }
- }
- if (!err) {
- /* Allocate BN into s. */
- sig->s = wolfSSL_BN_new();
- if (sig->s == NULL) {
- WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA s failure");
- err = 1;
- }
- }
-
- if (err && (sig != NULL)) {
- /* Dispose of allocated memory. */
- wolfSSL_ECDSA_SIG_free(sig);
- sig = NULL;
- }
- return sig;
-}
-
-/* Dispose of ECDSA signature object.
- *
- * Cannot use object after this call.
- *
- * @param [in] sig ECDSA signature object to free.
- */
-void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig)
-{
- WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free");
-
- if (sig != NULL) {
- /* Dispose of BNs allocated for r and s. */
- wolfSSL_BN_free(sig->r);
- wolfSSL_BN_free(sig->s);
-
- /* Dispose of memory associated with ECDSA signature object. */
- XFREE(sig, NULL, DYNAMIC_TYPE_ECC);
- }
-}
-
-/* Create an ECDSA signature from the DER encoding.
- *
- * @param [in, out] sig Reference to ECDSA signature object. May be NULL.
- * @param [in, out] pp On in, reference to buffer containing DER encoding.
- * On out, reference to buffer after signature data.
- * @param [in] len Length of the data in the buffer. May be more than
- * the length of the signature.
- * @return ECDSA signature object on success.
- * @return NULL on error.
- */
-WOLFSSL_ECDSA_SIG* wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG** sig,
- const unsigned char** pp, long len)
-{
- int err = 0;
- /* ECDSA signature object to return. */
- WOLFSSL_ECDSA_SIG *s = NULL;
-
- /* Validate parameter. */
- if (pp == NULL) {
- err = 1;
- }
- if (!err) {
- if (sig != NULL) {
- /* Use the ECDSA signature object passed in. */
- s = *sig;
- }
- if (s == NULL) {
- /* No ECDSA signature object passed in - create a new one. */
- s = wolfSSL_ECDSA_SIG_new();
- if (s == NULL) {
- err = 1;
- }
- }
- }
- if (!err) {
- /* DecodeECC_DSA_Sig calls mp_init, so free these. */
- mp_free((mp_int*)s->r->internal);
- mp_free((mp_int*)s->s->internal);
-
- /* Decode the signature into internal r and s fields. */
- if (DecodeECC_DSA_Sig(*pp, (word32)len, (mp_int*)s->r->internal,
- (mp_int*)s->s->internal) != MP_OKAY) {
- err = 1;
- }
- }
-
- if (!err) {
- /* Move pointer passed signature data successfully decoded. */
- *pp += wolfssl_der_length(*pp, (int)len);
- if (sig != NULL) {
- /* Update reference to ECDSA signature object. */
- *sig = s;
- }
- }
-
- /* Dispose of newly allocated object on error. */
- if (err) {
- if ((s != NULL) && ((sig == NULL) || (*sig != s))) {
- wolfSSL_ECDSA_SIG_free(s);
- }
- /* Return NULL for object on error. */
- s = NULL;
- }
- return s;
-}
-
-/* Encode the ECDSA signature as DER.
- *
- * @param [in] sig ECDSA signature object.
- * @param [in, out] pp On in, reference to buffer in which to place encoding.
- * On out, reference to buffer after encoding.
- * May be NULL or point to NULL in which case no encoding
- * is done.
- * @return Length of encoding on success.
- * @return 0 on error.
- */
-int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp)
-{
- word32 len = 0;
- int update_p = 1;
-
- /* Validate parameter. */
- if (sig != NULL) {
- /* ASN.1: SEQ + INT + INT
- * ASN.1 Integer must be a positive value - prepend zero if number has
- * top bit set.
- */
- /* Get total length of r including any prepended zero. */
- word32 rLen = (word32)(mp_leading_bit((mp_int*)sig->r->internal) +
- mp_unsigned_bin_size((mp_int*)sig->r->internal));
- /* Get total length of s including any prepended zero. */
- word32 sLen = (word32)(mp_leading_bit((mp_int*)sig->s->internal) +
- mp_unsigned_bin_size((mp_int*)sig->s->internal));
- /* Calculate length of data in sequence. */
- len = (word32)1 + ASN_LEN_SIZE(rLen) + rLen +
- (word32)1 + ASN_LEN_SIZE(sLen) + sLen;
- /* Add in the length of the SEQUENCE. */
- len += (word32)1 + ASN_LEN_SIZE(len);
-
- #ifdef WOLFSSL_I2D_ECDSA_SIG_ALLOC
- if ((pp != NULL) && (*pp == NULL)) {
- *pp = (unsigned char *)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
- if (*pp != NULL) {
- WOLFSSL_MSG("malloc error");
- return 0;
- }
- update_p = 0;
- }
- #endif
-
- /* Encode only if there is a buffer to encode into. */
- if ((pp != NULL) && (*pp != NULL)) {
- /* Encode using the internal representations of r and s. */
- if (StoreECC_DSA_Sig(*pp, &len, (mp_int*)sig->r->internal,
- (mp_int*)sig->s->internal) != MP_OKAY) {
- /* No bytes encoded. */
- len = 0;
- }
- else if (update_p) {
- /* Update pointer to after encoding. */
- *pp += len;
- }
- }
- }
-
- return (int)len;
-}
-
-/* Get the pointer to the fields of the ECDSA signature.
- *
- * r and s untouched when sig is NULL.
- *
- * @param [in] sig ECDSA signature object.
- * @param [out] r R field of ECDSA signature as a BN. May be NULL.
- * @param [out] s S field of ECDSA signature as a BN. May be NULL.
- */
-void wolfSSL_ECDSA_SIG_get0(const WOLFSSL_ECDSA_SIG* sig,
- const WOLFSSL_BIGNUM** r, const WOLFSSL_BIGNUM** s)
-{
- /* Validate parameter. */
- if (sig != NULL) {
- /* Return the r BN when pointer to return through. */
- if (r != NULL) {
- *r = sig->r;
- }
- /* Return the s BN when pointer to return through. */
- if (s != NULL) {
- *s = sig->s;
- }
- }
-}
-
-/* Set the pointers to the fields of the ECDSA signature.
- *
- * @param [in, out] sig ECDSA signature object to update.
- * @param [in] r R field of ECDSA signature as a BN.
- * @param [in] s S field of ECDSA signature as a BN.
- * @return 1 on success.
- * @return 0 on error.
- */
-int wolfSSL_ECDSA_SIG_set0(WOLFSSL_ECDSA_SIG* sig, WOLFSSL_BIGNUM* r,
- WOLFSSL_BIGNUM* s)
-{
- int ret = 1;
-
- /* Validate parameters. */
- if ((sig == NULL) || (r == NULL) || (s == NULL)) {
- ret = 0;
- }
-
- if (ret == 1) {
- /* Dispose of old BN objects. */
- wolfSSL_BN_free(sig->r);
- wolfSSL_BN_free(sig->s);
-
- /* Assign new BN objects. */
- sig->r = r;
- sig->s = s;
- }
-
- return ret;
-}
-
-/* End ECDSA_SIG */
-
-/* Start ECDSA */
-
-/* Calculate maximum size of the DER encoded ECDSA signature for the curve.
- *
- * @param [in] key EC key.
- * @return Size of DER encoded signature on success.
- * @return 0 on error.
- */
-int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key)
-{
- int err = 0;
- int len = 0;
- const WOLFSSL_EC_GROUP *group = NULL;
- int bits = 0;
-
- /* Validate parameter. */
- if (key == NULL) {
- err = 1;
- }
-
- /* Get group from key to get order bits. */
- if ((!err) && ((group = wolfSSL_EC_KEY_get0_group(key)) == NULL)) {
- err = 1;
- }
- /* Get order bits of group. */
- if ((!err) && ((bits = wolfSSL_EC_GROUP_order_bits(group)) == 0)) {
- /* Group is not set. */
- err = 1;
- }
-
- if (!err) {
- /* r and s are mod order. */
- int bytes = (bits + 7) / 8; /* Bytes needed to hold bits. */
- len = SIG_HEADER_SZ + /* 2*ASN_TAG + 2*LEN(ENUM) */
- ECC_MAX_PAD_SZ + /* possible leading zeroes in r and s */
- bytes + bytes; /* max r and s in bytes */
- }
-
- return len;
-}
-
-/* Create ECDSA signature by signing digest with key.
- *
- * @param [in] dgst Digest to sign.
- * @param [in] dLen Length of digest in bytes.
- * @param [in] key EC key to sign with.
- * @return ECDSA signature object on success.
- * @return NULL on error.
- */
-WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *dgst, int dLen,
- WOLFSSL_EC_KEY *key)
-{
- int err = 0;
- WOLFSSL_ECDSA_SIG *sig = NULL;
- WC_DECLARE_VAR(out, byte, ECC_BUFSIZE, 0);
- unsigned int outLen = ECC_BUFSIZE;
-
- WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign");
-
- /* Validate parameters. */
- if ((dgst == NULL) || (key == NULL) || (key->internal == NULL)) {
- WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad arguments");
- err = 1;
- }
-
- /* Ensure internal EC key is set from external. */
- if ((!err) && (key->inSet == 0)) {
- WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it");
-
- if (SetECKeyInternal(key) != 1) {
- WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed");
- err = 1;
- }
- }
-
-#ifdef WOLFSSL_SMALL_STACK
- if (!err) {
- /* Allocate buffer to hold encoded signature. */
- out = (byte*)XMALLOC(outLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (out == NULL) {
- err = 1;
- }
- }
-#endif
-
- /* Sign the digest with the key to create encoded ECDSA signature. */
- if ((!err) && (wolfSSL_ECDSA_sign(0, dgst, dLen, out, &outLen, key) != 1)) {
- err = 1;
- }
-
- if (!err) {
- const byte* p = out;
- /* Decode the ECDSA signature into a new object. */
- sig = wolfSSL_d2i_ECDSA_SIG(NULL, &p, outLen);
- }
-
- WC_FREE_VAR_EX(out, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
- return sig;
-}
-
-/* Verify ECDSA signature in the object using digest and key.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [in] dgst Digest to verify.
- * @param [in] dLen Length of the digest in bytes.
- * @param [in] sig ECDSA signature object.
- * @param [in] key EC key containing public key.
- * @return 1 when signature is valid.
- * @return 0 when signature is invalid.
- * @return -1 on error.
- */
-int wolfSSL_ECDSA_do_verify(const unsigned char *dgst, int dLen,
- const WOLFSSL_ECDSA_SIG *sig, WOLFSSL_EC_KEY *key)
-{
- int ret = 1;
- int verified = 0;
-#ifdef WOLF_CRYPTO_CB_ONLY_ECC
- byte signature[ECC_MAX_SIG_SIZE];
- int signatureLen;
- byte* p = signature;
-#endif
-
- WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify");
-
- /* Validate parameters. */
- if ((dgst == NULL) || (sig == NULL) || (key == NULL) ||
- (key->internal == NULL)) {
- WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- /* Ensure internal EC key is set from external. */
- if ((ret == 1) && (key->inSet == 0)) {
- WOLFSSL_MSG("No EC key internal set, do it");
-
- if (SetECKeyInternal(key) != 1) {
- WOLFSSL_MSG("SetECKeyInternal failed");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
-
- if (ret == 1) {
-#ifndef WOLF_CRYPTO_CB_ONLY_ECC
- /* Verify hash using digest, r and s as MP ints and internal EC key. */
- if (wc_ecc_verify_hash_ex((mp_int*)sig->r->internal,
- (mp_int*)sig->s->internal, dgst, (word32)dLen, &verified,
- (ecc_key *)key->internal) != MP_OKAY) {
- WOLFSSL_MSG("wc_ecc_verify_hash failed");
- ret = WOLFSSL_FATAL_ERROR;
- }
- else if (verified == 0) {
- WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected");
- ret = 0;
- }
-#else
- signatureLen = i2d_ECDSA_SIG(sig, &p);
- if (signatureLen > 0) {
- /* verify hash. expects to call wc_CryptoCb_EccVerify internally */
- ret = wc_ecc_verify_hash(signature, signatureLen, dgst,
- (word32)dLen, &verified, (ecc_key*)key->internal);
- if (ret != MP_OKAY) {
- WOLFSSL_MSG("wc_ecc_verify_hash failed");
- ret = WOLFSSL_FATAL_ERROR;
- }
- else if (verified == 0) {
- WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected");
- ret = 0;
- }
- }
-#endif /* WOLF_CRYPTO_CB_ONLY_ECC */
- }
-
- return ret;
-}
-
-/* Sign the digest with the key to produce a DER encode signature.
- *
- * @param [in] type Digest algorithm used to create digest. Unused.
- * @param [in] digest Digest of the message to sign.
- * @param [in] digestSz Size of the digest in bytes.
- * @param [out] sig Buffer to hold signature.
- * @param [in, out] sigSz On in, size of buffer in bytes.
- * On out, size of signatre in bytes.
- * @param [in] key EC key containing private key.
- * @return 1 on success.
- * @return 0 on error.
- */
-int wolfSSL_ECDSA_sign(int type, const unsigned char *digest, int digestSz,
- unsigned char *sig, unsigned int *sigSz, WOLFSSL_EC_KEY *key)
-{
- int ret = 1;
- WC_RNG* rng = NULL;
- WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
- int initTmpRng = 0;
-
- WOLFSSL_ENTER("wolfSSL_ECDSA_sign");
-
- /* Digest algorithm not used in DER encoding. */
- (void)type;
-
- /* Validate parameters. */
- if (key == NULL) {
- ret = 0;
- }
-
- if (ret == 1) {
- /* Make an RNG - create local or get global. */
- rng = wolfssl_make_rng(tmpRng, &initTmpRng);
- if (rng == NULL) {
- ret = 0;
- }
- }
- /* Sign the digest with the key using the RNG and put signature into buffer
- * update sigSz to be actual length.
- */
- if ((ret == 1) && (wc_ecc_sign_hash(digest, (word32)digestSz, sig, sigSz,
- rng, (ecc_key*)key->internal) != 0)) {
- ret = 0;
- }
-
- if (initTmpRng) {
- wc_FreeRng(rng);
- WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG);
- }
-
- return ret;
-}
-
-/* Verify the signature with the digest and key.
- *
- * @param [in] type Digest algorithm used to create digest. Unused.
- * @param [in] digest Digest of the message to verify.
- * @param [in] digestSz Size of the digest in bytes.
- * @param [in] sig Buffer holding signature.
- * @param [in] sigSz Size of signature data in bytes.
- * @param [in] key EC key containing public key.
- * @return 1 when signature is valid.
- * @return 0 when signature is invalid or error.
- */
-int wolfSSL_ECDSA_verify(int type, const unsigned char *digest, int digestSz,
- const unsigned char *sig, int sigSz, WOLFSSL_EC_KEY *key)
-{
- int ret = 1;
- int verify = 0;
-
- WOLFSSL_ENTER("wolfSSL_ECDSA_verify");
-
- /* Digest algorithm not used in DER encoding. */
- (void)type;
-
- /* Validate parameters. */
- if (key == NULL) {
- ret = 0;
- }
-
- /* Verify signature using digest and key. */
- if ((ret == 1) && (wc_ecc_verify_hash(sig, (word32)sigSz, digest,
- (word32)digestSz, &verify, (ecc_key*)key->internal) != 0)) {
- ret = 0;
- }
- /* When no error, verification may still have failed - check now. */
- if ((ret == 1) && (verify != 1)) {
- WOLFSSL_MSG("wolfSSL_ECDSA_verify failed");
- ret = 0;
- }
-
- return ret;
-}
-
-/* End ECDSA */
-
-/* Start ECDH */
-
-#ifndef WOLF_CRYPTO_CB_ONLY_ECC
-/* Compute the shared secret (key) using ECDH.
- *
- * KDF not supported.
- *
- * Return code compliant with OpenSSL.
- *
- * @param [out] out Buffer to hold key.
- * @param [in] outLen Length of buffer in bytes.
- * @param [in] pubKey Public key as an EC point.
- * @param [in] privKey EC key holding a private key.
- * @param [in] kdf Key derivation function to apply to secret.
- * @return Length of computed key on success
- * @return 0 on error.
- */
-int wolfSSL_ECDH_compute_key(void *out, size_t outLen,
- const WOLFSSL_EC_POINT *pubKey, WOLFSSL_EC_KEY *privKey,
- void *(*kdf) (const void *in, size_t inlen, void *out, size_t *outLen))
-{
- int err = 0;
- word32 len = 0;
- ecc_key* key = NULL;
-#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \
- (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0))
- int setGlobalRNG = 0;
-#endif
-
- /* TODO: support using the KDF. */
- (void)kdf;
-
- WOLFSSL_ENTER("wolfSSL_ECDH_compute_key");
-
- /* Validate parameters. */
- if ((out == NULL) || (pubKey == NULL) || (pubKey->internal == NULL) ||
- (privKey == NULL) || (privKey->internal == NULL)) {
- WOLFSSL_MSG("Bad function arguments");
- err = 1;
- }
-
- /* Ensure internal EC key is set from external. */
- if ((!err) && (privKey->inSet == 0)) {
- WOLFSSL_MSG("No EC key internal set, do it");
-
- if (SetECKeyInternal(privKey) != 1) {
- WOLFSSL_MSG("SetECKeyInternal failed");
- err = 1;
- }
- }
-
- if (!err) {
- int ret;
-
- /* Get the internal key. */
- key = (ecc_key*)privKey->internal;
- /* Set length into variable of type suitable for wolfSSL API. */
- len = (word32)outLen;
-
- #if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \
- (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0))
- /* An RNG is needed. */
- if (key->rng == NULL) {
- key->rng = wolfssl_make_global_rng();
- /* RNG set and needs to be unset. */
- setGlobalRNG = 1;
- }
- #endif
-
- PRIVATE_KEY_UNLOCK();
- /* Create secret using wolfSSL. */
- ret = wc_ecc_shared_secret_ex(key, (ecc_point*)pubKey->internal,
- (byte *)out, &len);
- PRIVATE_KEY_LOCK();
- if (ret != MP_OKAY) {
- WOLFSSL_MSG("wc_ecc_shared_secret failed");
- err = 1;
- }
- }
-
-#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \
- (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0))
- /* Remove global from key. */
- if (setGlobalRNG) {
- key->rng = NULL;
- }
-#endif
-
- if (err) {
- /* Make returned value zero. */
- len = 0;
- }
- return (int)len;
-}
-#endif /* WOLF_CRYPTO_CB_ONLY_ECC */
-
-/* End ECDH */
-
-#ifndef NO_WOLFSSL_STUB
-const WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_OpenSSL(void)
-{
- WOLFSSL_STUB("wolfSSL_EC_KEY_OpenSSL");
-
- return NULL;
-}
-
-WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_METHOD_new(
- const WOLFSSL_EC_KEY_METHOD *meth)
-{
- WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_new");
-
- (void)meth;
-
- return NULL;
-}
-
-void wolfSSL_EC_KEY_METHOD_free(WOLFSSL_EC_KEY_METHOD *meth)
-{
- WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_free");
-
- (void)meth;
-}
-
-void wolfSSL_EC_KEY_METHOD_set_init(WOLFSSL_EC_KEY_METHOD *meth,
- void* a1, void* a2, void* a3, void* a4, void* a5, void* a6)
-{
- WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_set_init");
-
- (void)meth;
- (void)a1;
- (void)a2;
- (void)a3;
- (void)a4;
- (void)a5;
- (void)a6;
-}
-
-void wolfSSL_EC_KEY_METHOD_set_sign(WOLFSSL_EC_KEY_METHOD *meth,
- void* a1, void* a2, void* a3)
-{
- WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_set_sign");
-
- (void)meth;
- (void)a1;
- (void)a2;
- (void)a3;
-}
-
-const WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_get_method(
- const WOLFSSL_EC_KEY *key)
-{
- WOLFSSL_STUB("wolfSSL_EC_KEY_get_method");
-
- (void)key;
-
- return NULL;
-}
-
-int wolfSSL_EC_KEY_set_method(WOLFSSL_EC_KEY *key,
- const WOLFSSL_EC_KEY_METHOD *meth)
-{
- WOLFSSL_STUB("wolfSSL_EC_KEY_set_method");
-
- (void)key;
- (void)meth;
-
- return 0;
-}
-
-#endif /* !NO_WOLFSSL_STUB */
-
-#endif /* OPENSSL_EXTRA */
-
-#endif /* HAVE_ECC */
-
-/*******************************************************************************
- * END OF EC API
- ******************************************************************************/
/*******************************************************************************
* START OF EC25519 API
@@ -16529,7 +7113,8 @@ static int pem_write_mem_pkcs8privatekey(byte** pem, int* pemSz,
if (res == 1) {
/* Guestimate key size and PEM size. */
- if (pkcs8_encode(pkey, NULL, &keySz) != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) {
+ if (pkcs8_encode(pkey, NULL, &keySz) !=
+ WC_NO_ERR_TRACE(LENGTH_ONLY_E)) {
res = 0;
}
}
diff --git a/src/pk_ec.c b/src/pk_ec.c
new file mode 100644
index 0000000000..7502030e24
--- /dev/null
+++ b/src/pk_ec.c
@@ -0,0 +1,5558 @@
+/* pk_ec.c
+ *
+ * Copyright (C) 2006-2025 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#include
+
+#include
+#ifndef WC_NO_RNG
+ #include
+#endif
+
+#ifdef HAVE_ECC
+ #include
+ #ifdef HAVE_SELFTEST
+ /* point compression types. */
+ #define ECC_POINT_COMP_EVEN 0x02
+ #define ECC_POINT_COMP_ODD 0x03
+ #define ECC_POINT_UNCOMP 0x04
+ #endif
+#endif
+#ifndef WOLFSSL_HAVE_ECC_KEY_GET_PRIV
+ /* FIPS build has replaced ecc.h. */
+ #define wc_ecc_key_get_priv(key) (&((key)->k))
+ #define WOLFSSL_HAVE_ECC_KEY_GET_PRIV
+#endif
+
+#if !defined(WOLFSSL_PK_EC_INCLUDED)
+ #ifndef WOLFSSL_IGNORE_FILE_WARN
+ #warning pk_ec.c does not need to be compiled separately from ssl.c
+ #endif
+#else
+
+/*******************************************************************************
+ * START OF EC API
+ ******************************************************************************/
+
+#ifdef HAVE_ECC
+
+#if defined(OPENSSL_EXTRA)
+
+/* Start EC_curve */
+
+/* Get the NIST name for the numeric ID.
+ *
+ * @param [in] nid Numeric ID of an EC curve.
+ * @return String representing NIST name of EC curve on success.
+ * @return NULL on error.
+ */
+const char* wolfSSL_EC_curve_nid2nist(int nid)
+{
+ const char* name = NULL;
+ const WOLF_EC_NIST_NAME* nist_name;
+
+ /* Attempt to find the curve info matching the NID passed in. */
+ for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
+ if (nist_name->nid == nid) {
+ /* NID found - return name. */
+ name = nist_name->name;
+ break;
+ }
+ }
+
+ return name;
+}
+
+/* Get the numeric ID for the NIST name.
+ *
+ * @param [in] name NIST name of EC curve.
+ * @return NID matching NIST name on success.
+ * @return 0 on error.
+ */
+int wolfSSL_EC_curve_nist2nid(const char* name)
+{
+ int nid = 0;
+ const WOLF_EC_NIST_NAME* nist_name;
+
+ /* Attempt to find the curve info matching the NIST name passed in. */
+ for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
+ if (XSTRCMP(nist_name->name, name) == 0) {
+ /* Name found - return NID. */
+ nid = nist_name->nid;
+ break;
+ }
+ }
+
+ return nid;
+}
+
+#endif /* OPENSSL_EXTRA */
+
+/* End EC_curve */
+
+/* Start EC_METHOD */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* Get the EC method of the EC group object.
+ *
+ * wolfSSL doesn't use method tables. Implementation used is dependent upon
+ * the NID.
+ *
+ * @param [in] group EC group object.
+ * @return EC method.
+ */
+const WOLFSSL_EC_METHOD* wolfSSL_EC_GROUP_method_of(
+ const WOLFSSL_EC_GROUP *group)
+{
+ /* No method table used so just return the same object. */
+ return group;
+}
+
+/* Get field type for method.
+ *
+ * Only prime fields are supported.
+ *
+ * @param [in] meth EC method.
+ * @return X9.63 prime field NID on success.
+ * @return 0 on error.
+ */
+int wolfSSL_EC_METHOD_get_field_type(const WOLFSSL_EC_METHOD *meth)
+{
+ int nid = 0;
+
+ if (meth != NULL) {
+ /* Only field type supported by code base. */
+ nid = WC_NID_X9_62_prime_field;
+ }
+
+ return nid;
+}
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+/* End EC_METHOD */
+
+/* Start EC_GROUP */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* Converts ECC curve enum values in ecc_curve_id to the associated OpenSSL NID
+ * value.
+ *
+ * @param [in] n ECC curve id.
+ * @return ECC curve NID (OpenSSL compatible value).
+ */
+int EccEnumToNID(int n)
+{
+ WOLFSSL_ENTER("EccEnumToNID");
+
+ switch(n) {
+ case ECC_SECP192R1:
+ return WC_NID_X9_62_prime192v1;
+ case ECC_PRIME192V2:
+ return WC_NID_X9_62_prime192v2;
+ case ECC_PRIME192V3:
+ return WC_NID_X9_62_prime192v3;
+ case ECC_PRIME239V1:
+ return WC_NID_X9_62_prime239v1;
+ case ECC_PRIME239V2:
+ return WC_NID_X9_62_prime239v2;
+ case ECC_PRIME239V3:
+ return WC_NID_X9_62_prime239v3;
+ case ECC_SECP256R1:
+ return WC_NID_X9_62_prime256v1;
+ case ECC_SECP112R1:
+ return WC_NID_secp112r1;
+ case ECC_SECP112R2:
+ return WC_NID_secp112r2;
+ case ECC_SECP128R1:
+ return WC_NID_secp128r1;
+ case ECC_SECP128R2:
+ return WC_NID_secp128r2;
+ case ECC_SECP160R1:
+ return WC_NID_secp160r1;
+ case ECC_SECP160R2:
+ return WC_NID_secp160r2;
+ case ECC_SECP224R1:
+ return WC_NID_secp224r1;
+ case ECC_SECP384R1:
+ return WC_NID_secp384r1;
+ case ECC_SECP521R1:
+ return WC_NID_secp521r1;
+ case ECC_SECP160K1:
+ return WC_NID_secp160k1;
+ case ECC_SECP192K1:
+ return WC_NID_secp192k1;
+ case ECC_SECP224K1:
+ return WC_NID_secp224k1;
+ case ECC_SECP256K1:
+ return WC_NID_secp256k1;
+ case ECC_BRAINPOOLP160R1:
+ return WC_NID_brainpoolP160r1;
+ case ECC_BRAINPOOLP192R1:
+ return WC_NID_brainpoolP192r1;
+ case ECC_BRAINPOOLP224R1:
+ return WC_NID_brainpoolP224r1;
+ case ECC_BRAINPOOLP256R1:
+ return WC_NID_brainpoolP256r1;
+ case ECC_BRAINPOOLP320R1:
+ return WC_NID_brainpoolP320r1;
+ case ECC_BRAINPOOLP384R1:
+ return WC_NID_brainpoolP384r1;
+ case ECC_BRAINPOOLP512R1:
+ return WC_NID_brainpoolP512r1;
+ #ifdef WOLFSSL_SM2
+ case ECC_SM2P256V1:
+ return WC_NID_sm2;
+ #endif
+ default:
+ WOLFSSL_MSG("NID not found");
+ return WOLFSSL_FATAL_ERROR;
+ }
+}
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+/* Converts OpenSSL NID of EC curve to the enum value in ecc_curve_id
+ *
+ * Used by ecc_sets[].
+ *
+ * @param [in] n OpenSSL NID of EC curve.
+ * @return wolfCrypt EC curve id.
+ * @return -1 on error.
+ */
+int NIDToEccEnum(int nid)
+{
+ int id;
+
+ WOLFSSL_ENTER("NIDToEccEnum");
+
+ switch (nid) {
+ case WC_NID_X9_62_prime192v1:
+ id = ECC_SECP192R1;
+ break;
+ case WC_NID_X9_62_prime192v2:
+ id = ECC_PRIME192V2;
+ break;
+ case WC_NID_X9_62_prime192v3:
+ id = ECC_PRIME192V3;
+ break;
+ case WC_NID_X9_62_prime239v1:
+ id = ECC_PRIME239V1;
+ break;
+ case WC_NID_X9_62_prime239v2:
+ id = ECC_PRIME239V2;
+ break;
+ case WC_NID_X9_62_prime239v3:
+ id = ECC_PRIME239V3;
+ break;
+ case WC_NID_X9_62_prime256v1:
+ id = ECC_SECP256R1;
+ break;
+ case WC_NID_secp112r1:
+ id = ECC_SECP112R1;
+ break;
+ case WC_NID_secp112r2:
+ id = ECC_SECP112R2;
+ break;
+ case WC_NID_secp128r1:
+ id = ECC_SECP128R1;
+ break;
+ case WC_NID_secp128r2:
+ id = ECC_SECP128R2;
+ break;
+ case WC_NID_secp160r1:
+ id = ECC_SECP160R1;
+ break;
+ case WC_NID_secp160r2:
+ id = ECC_SECP160R2;
+ break;
+ case WC_NID_secp224r1:
+ id = ECC_SECP224R1;
+ break;
+ case WC_NID_secp384r1:
+ id = ECC_SECP384R1;
+ break;
+ case WC_NID_secp521r1:
+ id = ECC_SECP521R1;
+ break;
+ case WC_NID_secp160k1:
+ id = ECC_SECP160K1;
+ break;
+ case WC_NID_secp192k1:
+ id = ECC_SECP192K1;
+ break;
+ case WC_NID_secp224k1:
+ id = ECC_SECP224K1;
+ break;
+ case WC_NID_secp256k1:
+ id = ECC_SECP256K1;
+ break;
+ case WC_NID_brainpoolP160r1:
+ id = ECC_BRAINPOOLP160R1;
+ break;
+ case WC_NID_brainpoolP192r1:
+ id = ECC_BRAINPOOLP192R1;
+ break;
+ case WC_NID_brainpoolP224r1:
+ id = ECC_BRAINPOOLP224R1;
+ break;
+ case WC_NID_brainpoolP256r1:
+ id = ECC_BRAINPOOLP256R1;
+ break;
+ case WC_NID_brainpoolP320r1:
+ id = ECC_BRAINPOOLP320R1;
+ break;
+ case WC_NID_brainpoolP384r1:
+ id = ECC_BRAINPOOLP384R1;
+ break;
+ case WC_NID_brainpoolP512r1:
+ id = ECC_BRAINPOOLP512R1;
+ break;
+ default:
+ WOLFSSL_MSG("NID not found");
+ /* -1 on error. */
+ id = WOLFSSL_FATAL_ERROR;
+ }
+
+ return id;
+}
+
+/* Set the fields of the EC group based on numeric ID.
+ *
+ * @param [in, out] group EC group.
+ * @param [in] nid Numeric ID of an EC curve.
+ */
+static void ec_group_set_nid(WOLFSSL_EC_GROUP* group, int nid)
+{
+ int eccEnum;
+ int realNid;
+
+ /* Convert ecc_curve_id enum to NID. */
+ if ((realNid = EccEnumToNID(nid)) != -1) {
+ /* ecc_curve_id enum passed in - have real NID value set. */
+ eccEnum = nid;
+ }
+ else {
+ /* NID passed in is OpenSSL type. */
+ realNid = nid;
+ /* Convert NID to ecc_curve_id enum. */
+ eccEnum = NIDToEccEnum(nid);
+ }
+
+ /* Set the numeric ID of the curve */
+ group->curve_nid = realNid;
+ /* Initialize index to -1 (i.e. wolfCrypt doesn't support curve). */
+ group->curve_idx = -1;
+
+ /* Find index and OID sum for curve if wolfCrypt supports it. */
+ if (eccEnum != -1) {
+ int i;
+
+ /* Find id and set the internal curve idx and OID sum. */
+ for (i = 0; ecc_sets[i].size != 0; i++) {
+ if (ecc_sets[i].id == eccEnum) {
+ /* Found id in wolfCrypt supported EC curves. */
+ group->curve_idx = i;
+ group->curve_oid = (int)ecc_sets[i].oidSum;
+ break;
+ }
+ }
+ }
+}
+
+/* Create a new EC group with the numeric ID for an EC curve.
+ *
+ * @param [in] nid Numeric ID of an EC curve.
+ * @return New, allocated EC group on success.
+ * @return NULL on error.
+ */
+WOLFSSL_EC_GROUP* wolfSSL_EC_GROUP_new_by_curve_name(int nid)
+{
+ int err = 0;
+ WOLFSSL_EC_GROUP* group;
+
+ WOLFSSL_ENTER("wolfSSL_EC_GROUP_new_by_curve_name");
+
+ /* Allocate EC group. */
+ group = (WOLFSSL_EC_GROUP*)XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL,
+ DYNAMIC_TYPE_ECC);
+ if (group == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_new_by_curve_name malloc failure");
+ err = 1;
+ }
+
+ if (!err) {
+ /* Reset all fields. */
+ XMEMSET(group, 0, sizeof(WOLFSSL_EC_GROUP));
+
+ /* Set the fields of group based on the numeric ID. */
+ ec_group_set_nid(group, nid);
+ }
+
+ return group;
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* Dispose of the EC group.
+ *
+ * Cannot use group after this call.
+ *
+ * @param [in] group EC group to free.
+ */
+void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group)
+{
+ WOLFSSL_ENTER("wolfSSL_EC_GROUP_free");
+
+ /* Dispose of EC group. */
+ XFREE(group, NULL, DYNAMIC_TYPE_ECC);
+}
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+#ifdef OPENSSL_EXTRA
+#ifndef NO_BIO
+
+/* Creates an EC group from the DER encoding.
+ *
+ * Only named curves supported.
+ *
+ * @param [out] group Reference to EC group object.
+ * @param [in] in Buffer holding DER encoding of curve.
+ * @param [in] inSz Length of data in buffer.
+ * @return EC group on success.
+ * @return NULL on error.
+ */
+static WOLFSSL_EC_GROUP* wolfssl_ec_group_d2i(WOLFSSL_EC_GROUP** group,
+ const unsigned char** in_pp, long inSz)
+{
+ int err = 0;
+ WOLFSSL_EC_GROUP* ret = NULL;
+ word32 idx = 0;
+ word32 oid = 0;
+ int id = 0;
+ const unsigned char* in;
+
+ if (in_pp == NULL || *in_pp == NULL)
+ return NULL;
+
+ in = *in_pp;
+
+ /* Use the group passed in. */
+ if ((group != NULL) && (*group != NULL)) {
+ ret = *group;
+ }
+
+ /* Only support named curves. */
+ if (in[0] != ASN_OBJECT_ID) {
+ WOLFSSL_ERROR_MSG("Invalid or unsupported encoding");
+ err = 1;
+ }
+ /* Decode the OBJECT ID - expecting an EC curve OID. */
+ if ((!err) && (GetObjectId(in, &idx, &oid, oidCurveType, (word32)inSz) !=
+ 0)) {
+ err = 1;
+ }
+ if (!err) {
+ /* Get the internal ID for OID. */
+ id = wc_ecc_get_oid(oid, NULL, NULL);
+ if (id < 0) {
+ err = 1;
+ }
+ }
+ if (!err) {
+ /* Get the NID for the internal ID. */
+ int nid = EccEnumToNID(id);
+ if (ret == NULL) {
+ /* Create a new EC group with the numeric ID. */
+ ret = wolfSSL_EC_GROUP_new_by_curve_name(nid);
+ if (ret == NULL) {
+ err = 1;
+ }
+ }
+ else {
+ ec_group_set_nid(ret, nid);
+ }
+ }
+ if ((!err) && (group != NULL)) {
+ /* Return the EC group through reference. */
+ *group = ret;
+ }
+
+ if (err) {
+ if ((ret != NULL) && (ret != *group)) {
+ wolfSSL_EC_GROUP_free(ret);
+ }
+ ret = NULL;
+ }
+ else {
+ *in_pp += idx;
+ }
+ return ret;
+}
+
+/* Creates a new EC group from the PEM encoding in the BIO.
+ *
+ * @param [in] bio BIO to read PEM encoding from.
+ * @param [out] group Reference to EC group object.
+ * @param [in] cb Password callback when PEM encrypted.
+ * @param [in] pass NUL terminated string for passphrase when PEM encrypted.
+ * @return EC group on success.
+ * @return NULL on error.
+ */
+WOLFSSL_EC_GROUP* wolfSSL_PEM_read_bio_ECPKParameters(WOLFSSL_BIO* bio,
+ WOLFSSL_EC_GROUP** group, wc_pem_password_cb* cb, void* pass)
+{
+ int err = 0;
+ WOLFSSL_EC_GROUP* ret = NULL;
+ DerBuffer* der = NULL;
+ int keyFormat = 0;
+
+ if (bio == NULL) {
+ err = 1;
+ }
+
+ /* Read parameters from BIO and convert PEM to DER. */
+ if ((!err) && (pem_read_bio_key(bio, cb, pass, ECC_PARAM_TYPE,
+ &keyFormat, &der) < 0)) {
+ err = 1;
+ }
+ if (!err) {
+ /* Create EC group from DER encoding. */
+ const byte** p = (const byte**)&der->buffer;
+ ret = wolfssl_ec_group_d2i(group, p, der->length);
+ if (ret == NULL) {
+ WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_EC_GROUP");
+ }
+ }
+
+ /* Dispose of any allocated data. */
+ FreeDer(&der);
+ return ret;
+}
+
+WOLFSSL_EC_GROUP *wolfSSL_d2i_ECPKParameters(WOLFSSL_EC_GROUP **out,
+ const unsigned char **in, long len)
+{
+ return wolfssl_ec_group_d2i(out, in, len);
+}
+
+int wolfSSL_i2d_ECPKParameters(const WOLFSSL_EC_GROUP* grp, unsigned char** pp)
+{
+ unsigned char* out = NULL;
+ int len = 0;
+ int idx;
+ const byte* oid = NULL;
+ word32 oidSz = 0;
+
+ if (grp == NULL || !wc_ecc_is_valid_idx(grp->curve_idx) ||
+ grp->curve_idx < 0)
+ return WOLFSSL_FATAL_ERROR;
+
+ /* Get the actual DER encoding of the OID. ecc_sets[grp->curve_idx].oid
+ * is just the numerical representation. */
+ if (wc_ecc_get_oid((word32)grp->curve_oid, &oid, &oidSz) < 0)
+ return WOLFSSL_FATAL_ERROR;
+
+ len = SetObjectId((int)oidSz, NULL) + (int)oidSz;
+
+ if (pp == NULL)
+ return len;
+
+ if (*pp == NULL) {
+ out = (unsigned char*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_ASN1);
+ if (out == NULL)
+ return WOLFSSL_FATAL_ERROR;
+ }
+ else {
+ out = *pp;
+ }
+
+ idx = SetObjectId((int)oidSz, out);
+ XMEMCPY(out + idx, oid, oidSz);
+ if (*pp == NULL)
+ *pp = out;
+ else
+ *pp += len;
+
+ return len;
+}
+#endif /* !NO_BIO */
+
+#if defined(OPENSSL_ALL) && !defined(NO_CERTS)
+/* Copy an EC group.
+ *
+ * Only used by wolfSSL_EC_KEY_dup at this time.
+ *
+ * @param [in, out] dst Destination EC group.
+ * @param [in] src Source EC group.
+ * @return 0 on success.
+ */
+static int wolfssl_ec_group_copy(WOLFSSL_EC_GROUP* dst,
+ const WOLFSSL_EC_GROUP* src)
+{
+ /* Copy the fields. */
+ dst->curve_idx = src->curve_idx;
+ dst->curve_nid = src->curve_nid;
+ dst->curve_oid = src->curve_oid;
+
+ return 0;
+}
+#endif /* OPENSSL_ALL && !NO_CERTS */
+
+/* Copies ecc_key into new WOLFSSL_EC_GROUP object
+ *
+ * @param [in] src EC group to duplicate.
+ *
+ * @return EC group on success.
+ * @return NULL on error.
+ */
+WOLFSSL_EC_GROUP* wolfSSL_EC_GROUP_dup(const WOLFSSL_EC_GROUP *src)
+{
+ WOLFSSL_EC_GROUP* newGroup = NULL;
+
+ if (src != NULL) {
+ /* Create new group base on NID in original EC group. */
+ newGroup = wolfSSL_EC_GROUP_new_by_curve_name(src->curve_nid);
+ }
+
+ return newGroup;
+}
+
+/* Compare two EC groups.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] a First EC group.
+ * @param [in] b Second EC group.
+ * @param [in] ctx Big number context to use when comparing fields. Unused.
+ *
+ * @return 0 if equal.
+ * @return 1 if not equal.
+ * @return -1 on error.
+ */
+int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b,
+ WOLFSSL_BN_CTX *ctx)
+{
+ int ret;
+
+ /* No BN operations performed. */
+ (void)ctx;
+
+ WOLFSSL_ENTER("wolfSSL_EC_GROUP_cmp");
+
+ /* Validate parameters. */
+ if ((a == NULL) || (b == NULL)) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments");
+ /* Return error value. */
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ /* Compare NID and wolfSSL curve index. */
+ else {
+ /* 0 when same, 1 when not. */
+ ret = ((a->curve_nid == b->curve_nid) &&
+ (a->curve_idx == b->curve_idx)) ? 0 : 1;
+ }
+
+ return ret;
+}
+
+#ifndef NO_WOLFSSL_STUB
+/* Set the ASN.1 flag that indicate encoding of curve.
+ *
+ * Stub function - flag not used elsewhere.
+ * Always encoded as named curve.
+ *
+ * @param [in] group EC group to modify.
+ * @param [in] flag ASN.1 flag to set. Valid values:
+ * OPENSSL_EC_EXPLICIT_CURVE, OPENSSL_EC_NAMED_CURVE
+ */
+void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag)
+{
+ (void)group;
+ (void)flag;
+
+ WOLFSSL_ENTER("wolfSSL_EC_GROUP_set_asn1_flag");
+ WOLFSSL_STUB("EC_GROUP_set_asn1_flag");
+}
+#endif
+
+/* Get the curve NID of the group.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] group EC group.
+ * @return Curve NID on success.
+ * @return 0 on error.
+ */
+int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group)
+{
+ int nid = 0;
+ WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_curve_name");
+
+ if (group == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments");
+ }
+ else {
+ nid = group->curve_nid;
+ }
+
+ return nid;
+}
+
+/* Get the degree (curve size in bits) of the EC group.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @return Degree of the curve on success.
+ * @return 0 on error.
+ */
+int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group)
+{
+ int degree = 0;
+
+ WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_degree");
+
+ if (group == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments");
+ }
+ else {
+ switch (group->curve_nid) {
+ case WC_NID_secp112r1:
+ case WC_NID_secp112r2:
+ degree = 112;
+ break;
+ case WC_NID_secp128r1:
+ case WC_NID_secp128r2:
+ degree = 128;
+ break;
+ case WC_NID_secp160k1:
+ case WC_NID_secp160r1:
+ case WC_NID_secp160r2:
+ case WC_NID_brainpoolP160r1:
+ degree = 160;
+ break;
+ case WC_NID_secp192k1:
+ case WC_NID_brainpoolP192r1:
+ case WC_NID_X9_62_prime192v1:
+ case WC_NID_X9_62_prime192v2:
+ case WC_NID_X9_62_prime192v3:
+ degree = 192;
+ break;
+ case WC_NID_secp224k1:
+ case WC_NID_secp224r1:
+ case WC_NID_brainpoolP224r1:
+ degree = 224;
+ break;
+ case WC_NID_X9_62_prime239v1:
+ case WC_NID_X9_62_prime239v2:
+ case WC_NID_X9_62_prime239v3:
+ degree = 239;
+ break;
+ case WC_NID_secp256k1:
+ case WC_NID_brainpoolP256r1:
+ case WC_NID_X9_62_prime256v1:
+ degree = 256;
+ break;
+ case WC_NID_brainpoolP320r1:
+ degree = 320;
+ break;
+ case WC_NID_secp384r1:
+ case WC_NID_brainpoolP384r1:
+ degree = 384;
+ break;
+ case WC_NID_brainpoolP512r1:
+ degree = 512;
+ break;
+ case WC_NID_secp521r1:
+ degree = 521;
+ break;
+ }
+ }
+
+ return degree;
+}
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+/* Get the length of the order in bits of the EC group.
+ *
+ * TODO: consider switch statement or calculating directly from hex string
+ * array instead of using mp_int.
+ *
+ * @param [in] group EC group.
+ * @return Length of order in bits on success.
+ * @return 0 on error.
+ */
+int wolfSSL_EC_GROUP_order_bits(const WOLFSSL_EC_GROUP *group)
+{
+ int ret = 0;
+ WC_DECLARE_VAR(order, mp_int, 1, 0);
+
+ /* Validate parameter. */
+ if ((group == NULL) || (group->curve_idx < 0)) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_order_bits NULL error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ if (ret == 0) {
+ /* Allocate memory for mp_int that will hold order value. */
+ order = (mp_int *)XMALLOC(sizeof(*order), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (order == NULL) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+#endif
+
+ if (ret == 0) {
+ /* Initialize mp_int. */
+ ret = mp_init(order);
+ }
+
+ if (ret == 0) {
+ /* Read hex string of order from wolfCrypt array of curves. */
+ ret = mp_read_radix(order, ecc_sets[group->curve_idx].order,
+ MP_RADIX_HEX);
+ if (ret == 0) {
+ /* Get bits of order. */
+ ret = mp_count_bits(order);
+ }
+ /* Clear and free mp_int. */
+ mp_clear(order);
+ }
+
+ WC_FREE_VAR_EX(order, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ /* Convert error code to length of 0. */
+ if (ret < 0) {
+ ret = 0;
+ }
+
+ return ret;
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+
+#if defined(OPENSSL_EXTRA)
+/* Get the order of the group as a BN.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] group EC group.
+ * @param [in, out] order BN to hold order value.
+ * @param [in] ctx Context to use for BN operations. Unused.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group,
+ WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx)
+{
+ int ret = 1;
+ mp_int* mp = NULL;
+
+ /* No BN operations performed - done with mp_int in BN. */
+ (void)ctx;
+
+ /* Validate parameters. */
+ if ((group == NULL) || (order == NULL) || (order->internal == NULL)) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error");
+ ret = 0;
+ }
+
+ if (ret == 1 &&
+ (group->curve_idx < 0 || !wc_ecc_is_valid_idx(group->curve_idx))) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order Bad group idx");
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ mp = (mp_int*)order->internal;
+ }
+ /* Initialize */
+ if ((ret == 1) && (mp_init(mp) != MP_OKAY)) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure");
+ ret = 0;
+ }
+ /* Read hex string of order from wolfCrypt array of curves. */
+ if ((ret == 1) && (mp_read_radix(mp, ecc_sets[group->curve_idx].order,
+ MP_RADIX_HEX) != MP_OKAY)) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_read order failure");
+ /* Zero out any partial value but don't free. */
+ mp_zero(mp);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+#endif /* OPENSSL_EXTRA */
+
+/* End EC_GROUP */
+
+/* Start EC_POINT */
+
+#if defined(OPENSSL_EXTRA)
+
+/* Set data of EC point into internal, wolfCrypt EC point object.
+ *
+ * EC_POINT Openssl -> WolfSSL
+ *
+ * @param [in, out] p EC point to update.
+ * @return 1 on success.
+ * @return -1 on failure.
+ */
+static int ec_point_internal_set(WOLFSSL_EC_POINT *p)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("ec_point_internal_set");
+
+ /* Validate parameter. */
+ if ((p == NULL) || (p->internal == NULL)) {
+ WOLFSSL_MSG("ECPoint NULL error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ else {
+ /* Get internal point as a wolfCrypt EC point. */
+ ecc_point* point = (ecc_point*)p->internal;
+
+ /* Set X ordinate if available. */
+ if ((p->X != NULL) && (wolfssl_bn_get_value(p->X, point->x) != 1)) {
+ WOLFSSL_MSG("ecc point X error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ /* Set Y ordinate if available. */
+ if ((ret == 1) && (p->Y != NULL) && (wolfssl_bn_get_value(p->Y,
+ point->y) != 1)) {
+ WOLFSSL_MSG("ecc point Y error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ /* Set Z ordinate if available. */
+ if ((ret == 1) && (p->Z != NULL) && (wolfssl_bn_get_value(p->Z,
+ point->z) != 1)) {
+ WOLFSSL_MSG("ecc point Z error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ /* Internal values set when operations succeeded. */
+ p->inSet = (ret == 1);
+ }
+
+ return ret;
+}
+
+/* Set data of internal, wolfCrypt EC point object into EC point.
+ *
+ * EC_POINT WolfSSL -> OpenSSL
+ *
+ * @param [in, out] p EC point to update.
+ * @return 1 on success.
+ * @return -1 on failure.
+ */
+static int ec_point_external_set(WOLFSSL_EC_POINT *p)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("ec_point_external_set");
+
+ /* Validate parameter. */
+ if ((p == NULL) || (p->internal == NULL)) {
+ WOLFSSL_MSG("ECPoint NULL error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ else {
+ /* Get internal point as a wolfCrypt EC point. */
+ ecc_point* point = (ecc_point*)p->internal;
+
+ /* Set X ordinate. */
+ if (wolfssl_bn_set_value(&p->X, point->x) != 1) {
+ WOLFSSL_MSG("ecc point X error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ /* Set Y ordinate. */
+ if ((ret == 1) && (wolfssl_bn_set_value(&p->Y, point->y) != 1)) {
+ WOLFSSL_MSG("ecc point Y error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ /* Set Z ordinate. */
+ if ((ret == 1) && (wolfssl_bn_set_value(&p->Z, point->z) != 1)) {
+ WOLFSSL_MSG("ecc point Z error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ /* External values set when operations succeeded. */
+ p->exSet = (ret == 1);
+ }
+
+ return ret;
+}
+
+/* Setup internals of EC point.
+ *
+ * Assumes point is not NULL.
+ *
+ * @param [in, out] point EC point to update.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+static int ec_point_setup(const WOLFSSL_EC_POINT *point) {
+ int ret = 1;
+
+ /* Check if internal values need setting. */
+ if (!point->inSet) {
+ WOLFSSL_MSG("No ECPoint internal set, do it");
+
+ /* Forcing to non-constant type to update internals. */
+ if (ec_point_internal_set((WOLFSSL_EC_POINT *)point) != 1) {
+ WOLFSSL_MSG("ec_point_internal_set failed");
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+/* Create a new EC point from the group.
+ *
+ * @param [in] group EC group.
+ * @return EC point on success.
+ * @return NULL on error.
+ */
+WOLFSSL_EC_POINT* wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP* group)
+{
+ int err = 0;
+ WOLFSSL_EC_POINT* point = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_new");
+
+ /* Validate parameter. */
+ if (group == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error");
+ err = 1;
+ }
+
+ if (!err) {
+ /* Allocate memory for new EC point. */
+ point = (WOLFSSL_EC_POINT*)XMALLOC(sizeof(WOLFSSL_EC_POINT), NULL,
+ DYNAMIC_TYPE_ECC);
+ if (point == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_new malloc ecc point failure");
+ err = 1;
+ }
+ }
+ if (!err) {
+ /* Clear fields of EC point. */
+ XMEMSET(point, 0, sizeof(WOLFSSL_EC_POINT));
+
+ /* Allocate internal EC point. */
+ point->internal = wc_ecc_new_point();
+ if (point->internal == NULL) {
+ WOLFSSL_MSG("ecc_new_point failure");
+ err = 1;
+ }
+ }
+
+ if (err) {
+ XFREE(point, NULL, DYNAMIC_TYPE_ECC);
+ point = NULL;
+ }
+ return point;
+}
+
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* Dispose of the EC point.
+ *
+ * Cannot use point after this call.
+ *
+ * @param [in, out] point EC point to free.
+ */
+void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *point)
+{
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_free");
+
+ if (point != NULL) {
+ if (point->internal != NULL) {
+ wc_ecc_del_point((ecc_point*)point->internal);
+ point->internal = NULL;
+ }
+
+ /* Free ordinates. */
+ wolfSSL_BN_free(point->X);
+ wolfSSL_BN_free(point->Y);
+ wolfSSL_BN_free(point->Z);
+ /* Clear fields. */
+ point->X = NULL;
+ point->Y = NULL;
+ point->Z = NULL;
+ point->inSet = 0;
+ point->exSet = 0;
+
+ /* Dispose of EC point. */
+ XFREE(point, NULL, DYNAMIC_TYPE_ECC);
+ }
+}
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+#ifdef OPENSSL_EXTRA
+
+/* Clear and dispose of the EC point.
+ *
+ * Cannot use point after this call.
+ *
+ * @param [in, out] point EC point to free.
+ */
+void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *point)
+{
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_clear_free");
+
+ if (point != NULL) {
+ if (point->internal != NULL) {
+ /* Force internal point to be zeros. */
+ #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+ wc_ecc_forcezero_point((ecc_point*)point->internal);
+ #else
+ ecc_point* p = (ecc_point*)point->internal;
+ mp_forcezero(p->x);
+ mp_forcezero(p->y);
+ mp_forcezero(p->z);
+ #endif
+ wc_ecc_del_point((ecc_point*)point->internal);
+ point->internal = NULL;
+ }
+
+ /* Clear the ordinates before freeing. */
+ wolfSSL_BN_clear_free(point->X);
+ wolfSSL_BN_clear_free(point->Y);
+ wolfSSL_BN_clear_free(point->Z);
+ /* Clear fields. */
+ point->X = NULL;
+ point->Y = NULL;
+ point->Z = NULL;
+ point->inSet = 0;
+ point->exSet = 0;
+
+ /* Dispose of EC point. */
+ XFREE(point, NULL, DYNAMIC_TYPE_ECC);
+ }
+}
+
+/* Print out the internals of EC point in debug and when logging callback set.
+ *
+ * Not an OpenSSL API.
+ *
+ * TODO: Use WOLFSSL_MSG_EX()?
+ *
+ * @param [in] msg Message to prepend.
+ * @param [in] point EC point to print.
+ */
+void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *point)
+{
+#if defined(DEBUG_WOLFSSL)
+ char *num;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_dump");
+
+ /* Only print when debugging on. */
+ if (WOLFSSL_IS_DEBUG_ON()) {
+ if (point == NULL) {
+ /* No point passed in so just put out "NULL". */
+ WOLFSSL_MSG_EX("%s = NULL\n", msg);
+ }
+ else {
+ /* Put out message and status of internal/external data set. */
+ WOLFSSL_MSG_EX("%s:\n\tinSet=%d, exSet=%d\n", msg, point->inSet,
+ point->exSet);
+ /* Get x-ordinate as a hex string and print. */
+ num = wolfSSL_BN_bn2hex(point->X);
+ WOLFSSL_MSG_EX("\tX = %s\n", num);
+ XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL);
+ /* Get x-ordinate as a hex string and print. */
+ num = wolfSSL_BN_bn2hex(point->Y);
+ WOLFSSL_MSG_EX("\tY = %s\n", num);
+ XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL);
+ /* Get z-ordinate as a hex string and print. */
+ num = wolfSSL_BN_bn2hex(point->Z);
+ WOLFSSL_MSG_EX("\tZ = %s\n", num);
+ XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+ }
+#else
+ (void)msg;
+ (void)point;
+#endif
+}
+
+/* Convert EC point to hex string that as either uncompressed or compressed.
+ *
+ * ECC point compression types were not included in selftest ecc.h
+ *
+ * @param [in] group EC group for point.
+ * @param [in] point EC point to encode.
+ * @param [in] form Format of encoding. Valid values:
+ * POINT_CONVERSION_UNCOMPRESSED, POINT_CONVERSION_COMPRESSED
+ * @param [in] ctx Context to use for BN operations. Unused.
+ * @return Allocated hex string on success.
+ * @return NULL on error.
+ */
+char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group,
+ const WOLFSSL_EC_POINT* point, int form, WOLFSSL_BN_CTX* ctx)
+{
+ static const char* hexDigit = "0123456789ABCDEF";
+ char* hex = NULL;
+ int i;
+ int sz = 0;
+ int len = 0;
+ int err = 0;
+
+ /* No BN operations performed. */
+ (void)ctx;
+
+ /* Validate parameters. */
+ if ((group == NULL) || (point == NULL)) {
+ err = 1;
+ }
+ /* Get curve id expects a positive index. */
+ if ((!err) && (group->curve_idx < 0)) {
+ err = 1;
+ }
+
+ if (!err) {
+ /* Get curve id to look up ordinate size. */
+ int id = wc_ecc_get_curve_id(group->curve_idx);
+ /* Get size of ordinate. */
+ if ((sz = wc_ecc_get_curve_size_from_id(id)) < 0) {
+ err = 1;
+ }
+ }
+ if (!err) {
+ /* [] */
+ len = sz + 1;
+ if (form == WC_POINT_CONVERSION_UNCOMPRESSED) {
+ /* Include y ordinate when uncompressed. */
+ len += sz;
+ }
+
+ /* Hex string: allocate 2 bytes to represent each byte plus 1 for '\0'.
+ */
+ hex = (char*)XMALLOC((size_t)(2 * len + 1), NULL, DYNAMIC_TYPE_ECC);
+ if (hex == NULL) {
+ err = 1;
+ }
+ }
+ if (!err) {
+ /* Make bytes all zeros to allow for ordinate values less than max size.
+ */
+ XMEMSET(hex, 0, (size_t)(2 * len + 1));
+
+ /* Calculate offset as leading zeros not encoded. */
+ i = sz - mp_unsigned_bin_size((mp_int*)point->X->internal) + 1;
+ /* Put in x-ordinate after format byte. */
+ if (mp_to_unsigned_bin((mp_int*)point->X->internal, (byte*)(hex + i)) <
+ 0) {
+ err = 1;
+ }
+ }
+ if (!err) {
+ if (form == WC_POINT_CONVERSION_COMPRESSED) {
+ /* Compressed format byte value dependent on whether y-ordinate is
+ * odd.
+ */
+ hex[0] = mp_isodd((mp_int*)point->Y->internal) ?
+ ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN;
+ /* No y-ordinate. */
+ }
+ else {
+ /* Put in uncompressed format byte. */
+ hex[0] = ECC_POINT_UNCOMP;
+ /* Calculate offset as leading zeros not encoded. */
+ i = 1 + 2 * sz - mp_unsigned_bin_size((mp_int*)point->Y->internal);
+ /* Put in y-ordinate after x-ordinate. */
+ if (mp_to_unsigned_bin((mp_int*)point->Y->internal,
+ (byte*)(hex + i)) < 0) {
+ err = 1;
+ }
+ }
+ }
+ if (!err) {
+ /* Convert binary encoding to hex string. */
+ /* Start at end so as not to overwrite. */
+ for (i = len-1; i >= 0; i--) {
+ /* Get byte value and store has hex string. */
+ byte b = (byte)hex[i];
+ hex[i * 2 + 1] = hexDigit[b & 0xf];
+ hex[i * 2 ] = hexDigit[b >> 4];
+ }
+ /* Memset put trailing zero or '\0' on end of string. */
+ }
+
+ if (err && (hex != NULL)) {
+ /* Dispose of allocated data not being returned. */
+ XFREE(hex, NULL, DYNAMIC_TYPE_ECC);
+ hex = NULL;
+ }
+ /* Return hex string encoding. */
+ return hex;
+}
+
+static size_t hex_to_bytes(const char *hex, unsigned char *output, size_t sz)
+{
+ word32 i;
+ for (i = 0; i < sz; i++) {
+ signed char ch1, ch2;
+ ch1 = HexCharToByte(hex[i * 2]);
+ ch2 = HexCharToByte(hex[i * 2 + 1]);
+ if ((ch1 < 0) || (ch2 < 0)) {
+ WOLFSSL_MSG("hex_to_bytes: syntax error");
+ return 0;
+ }
+ output[i] = (unsigned char)((ch1 << 4) + ch2);
+ }
+ return sz;
+}
+
+WOLFSSL_EC_POINT* wolfSSL_EC_POINT_hex2point(const WOLFSSL_EC_GROUP *group,
+ const char *hex, WOLFSSL_EC_POINT*p, WOLFSSL_BN_CTX *ctx)
+{
+ /* for uncompressed mode */
+ size_t str_sz;
+ WOLFSSL_BIGNUM *Gx = NULL;
+ WOLFSSL_BIGNUM *Gy = NULL;
+ char strGx[MAX_ECC_BYTES * 2 + 1];
+
+ /* for compressed mode */
+ int key_sz;
+ byte *octGx = (byte *)strGx; /* octGx[MAX_ECC_BYTES] */
+
+ int p_alloc = 0;
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_hex2point");
+
+ if (group == NULL || hex == NULL || ctx == NULL)
+ return NULL;
+
+ if (p == NULL) {
+ if ((p = wolfSSL_EC_POINT_new(group)) == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_new");
+ goto err;
+ }
+ p_alloc = 1;
+ }
+
+ key_sz = (wolfSSL_EC_GROUP_get_degree(group) + 7) / 8;
+ if (hex[0] == '0' && hex[1] == '4') { /* uncompressed mode */
+ str_sz = (size_t)key_sz * 2;
+
+ XMEMSET(strGx, 0x0, str_sz + 1);
+ XMEMCPY(strGx, hex + 2, str_sz);
+
+ if (wolfSSL_BN_hex2bn(&Gx, strGx) == 0)
+ goto err;
+
+ if (wolfSSL_BN_hex2bn(&Gy, hex + 2 + str_sz) == 0)
+ goto err;
+
+ ret = wolfSSL_EC_POINT_set_affine_coordinates_GFp
+ (group, p, Gx, Gy, ctx);
+
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp");
+ goto err;
+ }
+ }
+ else if (hex[0] == '0' && (hex[1] == '2' || hex[1] == '3')) {
+ size_t sz = XSTRLEN(hex + 2) / 2;
+ /* compressed mode */
+ octGx[0] = ECC_POINT_COMP_ODD;
+ if (hex_to_bytes(hex + 2, octGx + 1, sz) != sz) {
+ goto err;
+ }
+ if (wolfSSL_ECPoint_d2i(octGx, (word32)key_sz + 1, group, p)
+ != WOLFSSL_SUCCESS) {
+ goto err;
+ }
+ }
+ else
+ goto err;
+
+ wolfSSL_BN_free(Gx);
+ wolfSSL_BN_free(Gy);
+ return p;
+
+err:
+ wolfSSL_BN_free(Gx);
+ wolfSSL_BN_free(Gy);
+ if (p_alloc) {
+ wolfSSL_EC_POINT_free(p);
+ }
+ return NULL;
+
+}
+
+/* Encode the EC point as an uncompressed point in DER.
+ *
+ * Return code compliant with OpenSSL.
+ * Not OpenSSL API.
+ *
+ * @param [in] group EC group point belongs to.
+ * @param [in] point EC point to encode.
+ * @param [out] out Buffer to encode into. May be NULL.
+ * @param [in, out] len On in, length of buffer in bytes.
+ * On out, length of encoding in bytes.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group,
+ const WOLFSSL_EC_POINT *point, unsigned char *out, unsigned int *len)
+{
+ int res = 1;
+
+ WOLFSSL_ENTER("wolfSSL_ECPoint_i2d");
+
+ /* Validate parameters. */
+ if ((group == NULL) || (point == NULL) || (len == NULL)) {
+ WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error");
+ res = 0;
+ }
+
+ /* Ensure points internals are set up. */
+ if ((res == 1) && (ec_point_setup(point) != 1)) {
+ res = 0;
+ }
+
+ /* Dump the point if encoding. */
+ if ((res == 1) && (out != NULL)) {
+ wolfSSL_EC_POINT_dump("i2d p", point);
+ }
+
+ if (res == 1) {
+ /* DER encode point in uncompressed format. */
+ int ret = wc_ecc_export_point_der(group->curve_idx,
+ (ecc_point*)point->internal, out, len);
+ /* Check return. When out is NULL, return will be length only error. */
+ if ((ret != MP_OKAY) && ((out != NULL) ||
+ (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)))) {
+ WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed");
+ res = 0;
+ }
+ }
+
+ return res;
+}
+
+/* Decode the uncompressed point in DER into EC point.
+ *
+ * Return code compliant with OpenSSL.
+ * Not OpenSSL API.
+ *
+ * @param [in] in Buffer containing DER encoded point.
+ * @param [in] len Length of data in bytes.
+ * @param [in] group EC group associated with point.
+ * @param [in, out] point EC point to set data into.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int wolfSSL_ECPoint_d2i(const unsigned char *in, unsigned int len,
+ const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *point)
+{
+ int ret = 1;
+ WOLFSSL_BIGNUM* x = NULL;
+ WOLFSSL_BIGNUM* y = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_ECPoint_d2i");
+
+ /* Validate parameters. */
+ if ((in == NULL) || (group == NULL) || (point == NULL) ||
+ (point->internal == NULL)) {
+ WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error");
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+ /* Import point into internal EC point. */
+ if (wc_ecc_import_point_der_ex(in, len, group->curve_idx,
+ (ecc_point*)point->internal, 0) != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_import_point_der_ex failed");
+ ret = 0;
+ }
+ #else
+ /* ECC_POINT_UNCOMP is not defined CAVP self test so use magic number */
+ if (in[0] == 0x04) {
+ /* Import point into internal EC point. */
+ if (wc_ecc_import_point_der((unsigned char *)in, len,
+ group->curve_idx, (ecc_point*)point->internal) != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_import_point_der failed");
+ ret = 0;
+ }
+ }
+ else {
+ WOLFSSL_MSG("Only uncompressed points supported with "
+ "HAVE_SELFTEST");
+ ret = 0;
+ }
+ #endif
+ }
+
+ if (ret == 1)
+ point->inSet = 1;
+
+ /* Set new external point. */
+ if (ret == 1 && ec_point_external_set(point) != 1) {
+ WOLFSSL_MSG("ec_point_external_set failed");
+ ret = 0;
+ }
+
+ if (ret == 1 && !wolfSSL_BN_is_one(point->Z)) {
+#if !defined(WOLFSSL_SP_MATH) && !defined(WOLF_CRYPTO_CB_ONLY_ECC)
+ x = wolfSSL_BN_new();
+ y = wolfSSL_BN_new();
+ if (x == NULL || y == NULL)
+ ret = 0;
+
+ if (ret == 1 && wolfSSL_EC_POINT_get_affine_coordinates_GFp(group,
+ point, x, y, NULL) != 1) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp failed");
+ ret = 0;
+ }
+
+ /* wolfSSL_EC_POINT_set_affine_coordinates_GFp check that the point is
+ * on the curve. */
+ if (ret == 1 && wolfSSL_EC_POINT_set_affine_coordinates_GFp(group,
+ point, x, y, NULL) != 1) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp failed");
+ ret = 0;
+ }
+#else
+ WOLFSSL_MSG("Importing non-affine point. This may cause issues in math "
+ "operations later on.");
+#endif
+ }
+
+ if (ret == 1) {
+ /* Dump new point. */
+ wolfSSL_EC_POINT_dump("d2i p", point);
+ }
+
+ wolfSSL_BN_free(x);
+ wolfSSL_BN_free(y);
+
+ return ret;
+}
+
+/* Encode point as octet string.
+ *
+ * HYBRID not supported.
+ *
+ * @param [in] group EC group that point belongs to.
+ * @param [in] point EC point to encode.
+ * @param [in] form Format of encoding. Valid values:
+ * POINT_CONVERSION_UNCOMPRESSED,POINT_CONVERSION_COMPRESSED
+ * @param [out] buf Buffer to write encoding into.
+ * @param [in] len Length of buffer.
+ * @param [in] ctx Context to use for BN operations. Unused.
+ * @return Length of encoded data on success.
+ * @return 0 on error.
+ */
+size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group,
+ const WOLFSSL_EC_POINT *point, int form, byte *buf, size_t len,
+ WOLFSSL_BN_CTX *ctx)
+{
+ int err = 0;
+ word32 enc_len = (word32)len;
+#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+ int compressed = ((form == WC_POINT_CONVERSION_COMPRESSED) ? 1 : 0);
+#endif /* !HAVE_SELFTEST */
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_point2oct");
+
+ /* No BN operations performed. */
+ (void)ctx;
+
+ /* Validate parameters. */
+ if ((group == NULL) || (point == NULL)) {
+ err = 1;
+ }
+
+ /* Ensure points internals are set up. */
+ if ((!err) && (ec_point_setup(point) != 1)) {
+ err = 1;
+ }
+
+ /* Special case when point is infinity. */
+ if ((!err) && wolfSSL_EC_POINT_is_at_infinity(group, point)) {
+ /* Encoding is a single octet: 0x00. */
+ enc_len = 1;
+ if (buf != NULL) {
+ /* Check whether buffer has space. */
+ if (len < 1) {
+ wolfSSL_ECerr(WOLFSSL_EC_F_EC_GFP_SIMPLE_POINT2OCT, BUFFER_E);
+ err = 1;
+ }
+ else {
+ /* Put in encoding of infinity. */
+ buf[0] = 0x00;
+ }
+ }
+ }
+ /* Not infinity. */
+ else if (!err) {
+ /* Validate format. */
+ if (form != WC_POINT_CONVERSION_UNCOMPRESSED
+ #ifndef HAVE_SELFTEST
+ && form != WC_POINT_CONVERSION_COMPRESSED
+ #endif /* !HAVE_SELFTEST */
+ ) {
+ WOLFSSL_MSG("Unsupported point form");
+ err = 1;
+ }
+
+ if (!err) {
+ int ret;
+
+ #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+ /* Encode as compressed or uncompressed. */
+ ret = wc_ecc_export_point_der_ex(group->curve_idx,
+ (ecc_point*)point->internal, buf, &enc_len, compressed);
+ #else
+ /* Encode uncompressed point in DER format. */
+ ret = wc_ecc_export_point_der(group->curve_idx,
+ (ecc_point*)point->internal, buf, &enc_len);
+ #endif /* !HAVE_SELFTEST */
+ /* Check return. When buf is NULL, return will be length only
+ * error.
+ */
+ if (ret != ((buf != NULL) ? MP_OKAY :
+ WC_NO_ERR_TRACE(LENGTH_ONLY_E))) {
+ err = 1;
+ }
+ }
+ }
+
+#if defined(DEBUG_WOLFSSL)
+ if (!err) {
+ wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_point2oct point", point);
+ WOLFSSL_MSG("\twolfSSL_EC_POINT_point2oct output:");
+ WOLFSSL_BUFFER(buf, enc_len);
+ }
+#endif
+
+ /* On error, return encoding length of 0. */
+ if (err) {
+ enc_len = 0;
+ }
+ return (size_t)enc_len;
+}
+
+
+/* Convert octet string to EC point.
+ *
+ * @param [in] group EC group.
+ * @param [in, out] point EC point to set data into.
+ * @param [in] buf Buffer holding octet string.
+ * @param [in] len Length of data in buffer in bytes.
+ * @param [in] ctx Context to use for BN operations. Unused.
+ */
+int wolfSSL_EC_POINT_oct2point(const WOLFSSL_EC_GROUP *group,
+ WOLFSSL_EC_POINT *point, const unsigned char *buf, size_t len,
+ WOLFSSL_BN_CTX *ctx)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point");
+
+ /* No BN operations performed. */
+ (void)ctx;
+
+ /* Validate parameters. */
+ if ((group == NULL) || (point == NULL)) {
+ ret = 0;
+ }
+ else {
+ /* Decode DER encoding into EC point. */
+ ret = wolfSSL_ECPoint_d2i((unsigned char*)buf, (unsigned int)len, group,
+ point);
+ }
+
+ return ret;
+}
+
+/* Convert an EC point to a single BN.
+ *
+ * @param [in] group EC group.
+ * @param [in] point EC point.
+ * @param [in] form Format of encoding. Valid values:
+ * WC_POINT_CONVERSION_UNCOMPRESSED,
+ * WC_POINT_CONVERSION_COMPRESSED.
+ * @param [in, out] bn BN to hold point value.
+ * When NULL a new BN is allocated otherwise this is
+ * returned on success.
+ * @param [in] ctx Context to use for BN operations. Unused.
+ * @return BN object with point as a value on success.
+ * @return NULL on error.
+ */
+WOLFSSL_BIGNUM *wolfSSL_EC_POINT_point2bn(const WOLFSSL_EC_GROUP* group,
+ const WOLFSSL_EC_POINT* point, int form, WOLFSSL_BIGNUM* bn,
+ WOLFSSL_BN_CTX* ctx)
+{
+ int err = 0;
+ size_t len = 0;
+ byte *buf = NULL;
+ WOLFSSL_BIGNUM *ret = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point");
+
+ /* Validate parameters. */
+ if ((group == NULL) || (point == NULL)) {
+ err = 1;
+ }
+
+ /* Calculate length of octet encoding. */
+ if ((!err) && ((len = wolfSSL_EC_POINT_point2oct(group, point, form, NULL,
+ 0, ctx)) == 0)) {
+ err = 1;
+ }
+ /* Allocate buffer to hold octet encoding. */
+ if ((!err) && ((buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER)) ==
+ NULL)) {
+ WOLFSSL_MSG("malloc failed");
+ err = 1;
+ }
+ /* Encode EC point as an octet string. */
+ if ((!err) && (wolfSSL_EC_POINT_point2oct(group, point, form, buf, len,
+ ctx) != len)) {
+ err = 1;
+ }
+ /* Load BN with octet string data. */
+ if (!err) {
+ ret = wolfSSL_BN_bin2bn(buf, (int)len, bn);
+ }
+
+ /* Dispose of any allocated data. */
+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return ret;
+}
+
+#if defined(USE_ECC_B_PARAM) && !defined(HAVE_SELFTEST) && \
+ (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+/* Check if EC point is on the the curve defined by the EC group.
+ *
+ * @param [in] group EC group defining curve.
+ * @param [in] point EC point to check.
+ * @param [in] ctx Context to use for BN operations. Unused.
+ * @return 1 when point is on curve.
+ * @return 0 when point is not on curve or error.
+ */
+int wolfSSL_EC_POINT_is_on_curve(const WOLFSSL_EC_GROUP *group,
+ const WOLFSSL_EC_POINT *point, WOLFSSL_BN_CTX *ctx)
+{
+ int err = 0;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_is_on_curve");
+
+ /* No BN operations performed. */
+ (void)ctx;
+
+ /* Validate parameters. */
+ if ((group == NULL) || (point == NULL)) {
+ WOLFSSL_MSG("Invalid arguments");
+ err = 1;
+ }
+
+ /* Ensure internal EC point set. */
+ if ((!err) && (!point->inSet) && ec_point_internal_set(
+ (WOLFSSL_EC_POINT*)point) != 1) {
+ WOLFSSL_MSG("ec_point_internal_set error");
+ err = 1;
+ }
+
+ /* Check point is on curve from group. */
+ if ((!err) && (wc_ecc_point_is_on_curve((ecc_point*)point->internal,
+ group->curve_idx) != MP_OKAY)) {
+ err = 1;
+ }
+
+ /* Return boolean of on curve. No error means on curve. */
+ return !err;
+}
+#endif /* USE_ECC_B_PARAM && !HAVE_SELFTEST && !(FIPS_VERSION <= 2) */
+
+#if !defined(WOLFSSL_SP_MATH) && !defined(WOLF_CRYPTO_CB_ONLY_ECC)
+/* Convert Jacobian ordinates to affine.
+ *
+ * @param [in] group EC group.
+ * @param [in] point EC point to get coordinates from.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int ec_point_convert_to_affine(const WOLFSSL_EC_GROUP *group,
+ WOLFSSL_EC_POINT *point)
+{
+ int err = 0;
+ mp_digit mp = 0;
+ WC_DECLARE_VAR(modulus, mp_int, 1, 0);
+
+ /* Allocate memory for curve's prime modulus. */
+ WC_ALLOC_VAR_EX(modulus, mp_int, 1, NULL, DYNAMIC_TYPE_BIGINT, err=1);
+ /* Initialize the MP integer. */
+ if ((!err) && (mp_init(modulus) != MP_OKAY)) {
+ WOLFSSL_MSG("mp_init failed");
+ err = 1;
+ }
+
+ if (!err) {
+ /* Get the modulus from the hex string in the EC curve set. */
+ if (mp_read_radix(modulus, ecc_sets[group->curve_idx].prime,
+ MP_RADIX_HEX) != MP_OKAY) {
+ WOLFSSL_MSG("mp_read_radix failed");
+ err = 1;
+ }
+ /* Get Montgomery multiplier for the modulus as ordinates in
+ * Montgomery form.
+ */
+ if ((!err) && (mp_montgomery_setup(modulus, &mp) != MP_OKAY)) {
+ WOLFSSL_MSG("mp_montgomery_setup failed");
+ err = 1;
+ }
+ /* Map internal EC point from Jacobian to affine. */
+ if ((!err) && (ecc_map((ecc_point*)point->internal, modulus, mp) !=
+ MP_OKAY)) {
+ WOLFSSL_MSG("ecc_map failed");
+ err = 1;
+ }
+ /* Set new ordinates into external EC point. */
+ if ((!err) && (ec_point_external_set((WOLFSSL_EC_POINT *)point) != 1)) {
+ WOLFSSL_MSG("ec_point_external_set failed");
+ err = 1;
+ }
+
+ point->exSet = !err;
+ mp_clear(modulus);
+ }
+
+ WC_FREE_VAR_EX(modulus, NULL, DYNAMIC_TYPE_BIGINT);
+
+ return err;
+}
+
+/* Get the affine coordinates of the EC point on a Prime curve.
+ *
+ * When z-ordinate is not one then coordinates are Jacobian and need to be
+ * converted to affine before storing in BNs.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * TODO: OpenSSL doesn't change point when Jacobian. Do the same?
+ *
+ * @param [in] group EC group.
+ * @param [in] point EC point to get coordinates from.
+ * @param [in, out] x BN to hold x-ordinate.
+ * @param [in, out] y BN to hold y-ordinate.
+ * @param [in] ctx Context to use for BN operations. Unused.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP* group,
+ const WOLFSSL_EC_POINT* point, WOLFSSL_BIGNUM* x, WOLFSSL_BIGNUM* y,
+ WOLFSSL_BN_CTX* ctx)
+{
+ int ret = 1;
+
+ /* BN operations don't need context. */
+ (void)ctx;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_get_affine_coordinates_GFp");
+
+ /* Validate parameters. */
+ if ((group == NULL) || (point == NULL) || (point->internal == NULL) ||
+ (x == NULL) || (y == NULL)) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp NULL error");
+ ret = 0;
+ }
+ /* Don't return point at infinity. */
+ if ((ret == 1) && wolfSSL_EC_POINT_is_at_infinity(group, point)) {
+ ret = 0;
+ }
+
+ /* Ensure internal EC point has values of external EC point. */
+ if ((ret == 1) && (ec_point_setup(point) != 1)) {
+ ret = 0;
+ }
+
+ /* Check whether ordinates are in Jacobian form. */
+ if ((ret == 1) && (!wolfSSL_BN_is_one(point->Z))) {
+ /* Convert from Jacobian to affine. */
+ if (ec_point_convert_to_affine(group, (WOLFSSL_EC_POINT*)point) == 1) {
+ ret = 0;
+ }
+ }
+
+ /* Copy the externally set x and y ordinates. */
+ if ((ret == 1) && (wolfSSL_BN_copy(x, point->X) == NULL)) {
+ ret = 0;
+ }
+ if ((ret == 1) && (wolfSSL_BN_copy(y, point->Y) == NULL)) {
+ ret = 0;
+ }
+
+ return ret;
+}
+#endif /* !WOLFSSL_SP_MATH && !WOLF_CRYPTO_CB_ONLY_ECC */
+
+/* Sets the affine coordinates that belong on a prime curve.
+ *
+ * @param [in] group EC group.
+ * @param [in, out] point EC point to set coordinates into.
+ * @param [in] x BN holding x-ordinate.
+ * @param [in] y BN holding y-ordinate.
+ * @param [in] ctx Context to use for BN operations. Unused.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int wolfSSL_EC_POINT_set_affine_coordinates_GFp(const WOLFSSL_EC_GROUP* group,
+ WOLFSSL_EC_POINT* point, const WOLFSSL_BIGNUM* x, const WOLFSSL_BIGNUM* y,
+ WOLFSSL_BN_CTX* ctx)
+{
+ int ret = 1;
+
+ /* BN operations don't need context. */
+ (void)ctx;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_set_affine_coordinates_GFp");
+
+ /* Validate parameters. */
+ if ((group == NULL) || (point == NULL) || (point->internal == NULL) ||
+ (x == NULL) || (y == NULL)) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp NULL error");
+ ret = 0;
+ }
+
+ /* Ensure we have a object for x-ordinate. */
+ if ((ret == 1) && (point->X == NULL) &&
+ ((point->X = wolfSSL_BN_new()) == NULL)) {
+ WOLFSSL_MSG("wolfSSL_BN_new failed");
+ ret = 0;
+ }
+ /* Ensure we have a object for y-ordinate. */
+ if ((ret == 1) && (point->Y == NULL) &&
+ ((point->Y = wolfSSL_BN_new()) == NULL)) {
+ WOLFSSL_MSG("wolfSSL_BN_new failed");
+ ret = 0;
+ }
+ /* Ensure we have a object for z-ordinate. */
+ if ((ret == 1) && (point->Z == NULL) &&
+ ((point->Z = wolfSSL_BN_new()) == NULL)) {
+ WOLFSSL_MSG("wolfSSL_BN_new failed");
+ ret = 0;
+ }
+
+ /* Copy the x-ordinate. */
+ if ((ret == 1) && ((wolfSSL_BN_copy(point->X, x)) == NULL)) {
+ WOLFSSL_MSG("wolfSSL_BN_copy failed");
+ ret = 0;
+ }
+ /* Copy the y-ordinate. */
+ if ((ret == 1) && ((wolfSSL_BN_copy(point->Y, y)) == NULL)) {
+ WOLFSSL_MSG("wolfSSL_BN_copy failed");
+ ret = 0;
+ }
+ /* z-ordinate is one for affine coordinates. */
+ if ((ret == 1) && ((wolfSSL_BN_one(point->Z)) == 0)) {
+ WOLFSSL_MSG("wolfSSL_BN_one failed");
+ ret = 0;
+ }
+
+ /* Copy the new point data to internal object. */
+ if ((ret == 1) && (ec_point_internal_set((WOLFSSL_EC_POINT *)point) != 1)) {
+ WOLFSSL_MSG("ec_point_internal_set failed");
+ ret = 0;
+ }
+
+#if defined(USE_ECC_B_PARAM) && !defined(HAVE_SELFTEST) && \
+ (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+ /* Check that the point is valid. */
+ if ((ret == 1) && (wolfSSL_EC_POINT_is_on_curve(group,
+ (WOLFSSL_EC_POINT *)point, ctx) != 1)) {
+ WOLFSSL_MSG("EC_POINT_is_on_curve failed");
+ ret = 0;
+ }
+#endif
+
+ return ret;
+}
+
+#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \
+ !defined(HAVE_SELFTEST) && !defined(WOLFSSL_SP_MATH) && \
+ !defined(WOLF_CRYPTO_CB_ONLY_ECC)
+/* Add two points on the same together.
+ *
+ * @param [in] curveIdx Index of curve in ecc_set.
+ * @param [out] r Result point.
+ * @param [in] p1 First point to add.
+ * @param [in] p2 Second point to add.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+static int wolfssl_ec_point_add(int curveIdx, ecc_point* r, ecc_point* p1,
+ ecc_point* p2)
+{
+ int ret = 1;
+#ifdef WOLFSSL_SMALL_STACK
+ mp_int* a = NULL;
+ mp_int* prime = NULL;
+ mp_int* mu = NULL;
+#else
+ mp_int a[1];
+ mp_int prime[1];
+ mp_int mu[1];
+#endif
+ mp_digit mp = 0;
+ ecc_point* montP1 = NULL;
+ ecc_point* montP2 = NULL;
+
+#ifdef WOLFSSL_SMALL_STACK
+ if (ret == 1) {
+ /* Allocate memory for curve parameter: a. */
+ a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+ if (a == NULL) {
+ WOLFSSL_MSG("Failed to allocate memory for mp_int a");
+ ret = 0;
+ }
+ }
+ if (ret == 1) {
+ /* Allocate memory for curve parameter: prime. */
+ prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+ if (prime == NULL) {
+ WOLFSSL_MSG("Failed to allocate memory for mp_int prime");
+ ret = 0;
+ }
+ }
+ if (ret == 1) {
+ /* Allocate memory for mu (Montgomery normalizer). */
+ mu = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+ if (mu == NULL) {
+ WOLFSSL_MSG("Failed to allocate memory for mp_int mu");
+ ret = 0;
+ }
+ }
+ if (ret == 1) {
+ /* Zero out all MP int data in case initialization fails. */
+ XMEMSET(a, 0, sizeof(mp_int));
+ XMEMSET(prime, 0, sizeof(mp_int));
+ XMEMSET(mu, 0, sizeof(mp_int));
+ }
+#endif
+
+ /* Initialize the MP ints. */
+ if ((ret == 1) && (mp_init_multi(prime, a, mu, NULL, NULL, NULL) !=
+ MP_OKAY)) {
+ WOLFSSL_MSG("mp_init_multi error");
+ ret = 0;
+ }
+
+ /* Read the curve parameter: a. */
+ if ((ret == 1) && (mp_read_radix(a, ecc_sets[curveIdx].Af, MP_RADIX_HEX) !=
+ MP_OKAY)) {
+ WOLFSSL_MSG("mp_read_radix a error");
+ ret = 0;
+ }
+
+ /* Read the curve parameter: prime. */
+ if ((ret == 1) && (mp_read_radix(prime, ecc_sets[curveIdx].prime,
+ MP_RADIX_HEX) != MP_OKAY)) {
+ WOLFSSL_MSG("mp_read_radix prime error");
+ ret = 0;
+ }
+
+ /* Calculate the Montgomery product. */
+ if ((ret == 1) && (mp_montgomery_setup(prime, &mp) != MP_OKAY)) {
+ WOLFSSL_MSG("mp_montgomery_setup nqm error");
+ ret = 0;
+ }
+
+ /* TODO: use the heap filed of one of the points? */
+ /* Allocate new points to hold the Montgomery form values. */
+ if ((ret == 1) && (((montP1 = wc_ecc_new_point_h(NULL)) == NULL) ||
+ ((montP2 = wc_ecc_new_point_h(NULL)) == NULL))) {
+ WOLFSSL_MSG("wc_ecc_new_point_h nqm error");
+ ret = 0;
+ }
+
+ /* Calculate the Montgomery normalizer. */
+ if ((ret == 1) && (mp_montgomery_calc_normalization(mu, prime) !=
+ MP_OKAY)) {
+ WOLFSSL_MSG("mp_montgomery_calc_normalization error");
+ ret = 0;
+ }
+
+ /* Convert to Montgomery form. */
+ if ((ret == 1) && (mp_cmp_d(mu, 1) == MP_EQ)) {
+ /* Copy the points if the normalizer is 1. */
+ if ((wc_ecc_copy_point(p1, montP1) != MP_OKAY) ||
+ (wc_ecc_copy_point(p2, montP2) != MP_OKAY)) {
+ WOLFSSL_MSG("wc_ecc_copy_point error");
+ ret = 0;
+ }
+ }
+ else if (ret == 1) {
+ /* Multiply each ordinate by the Montgomery normalizer. */
+ if ((mp_mulmod(p1->x, mu, prime, montP1->x) != MP_OKAY) ||
+ (mp_mulmod(p1->y, mu, prime, montP1->y) != MP_OKAY) ||
+ (mp_mulmod(p1->z, mu, prime, montP1->z) != MP_OKAY)) {
+ WOLFSSL_MSG("mp_mulmod error");
+ ret = 0;
+ }
+ /* Multiply each ordinate by the Montgomery normalizer. */
+ if ((mp_mulmod(p2->x, mu, prime, montP2->x) != MP_OKAY) ||
+ (mp_mulmod(p2->y, mu, prime, montP2->y) != MP_OKAY) ||
+ (mp_mulmod(p2->z, mu, prime, montP2->z) != MP_OKAY)) {
+ WOLFSSL_MSG("mp_mulmod error");
+ ret = 0;
+ }
+ }
+
+ /* Perform point addition with internal EC point objects - Jacobian form
+ * result.
+ */
+ if ((ret == 1) && (ecc_projective_add_point(montP1, montP2, r, a, prime,
+ mp) != MP_OKAY)) {
+ WOLFSSL_MSG("ecc_projective_add_point error");
+ ret = 0;
+ }
+
+ /* Map point back to affine coordinates. Converts from Montogomery form. */
+ if ((ret == 1) && (ecc_map(r, prime, mp) != MP_OKAY)) {
+ WOLFSSL_MSG("ecc_map error");
+ ret = 0;
+ }
+
+ /* Dispose of allocated memory. */
+ mp_clear(a);
+ mp_clear(prime);
+ mp_clear(mu);
+ wc_ecc_del_point_h(montP1, NULL);
+ wc_ecc_del_point_h(montP2, NULL);
+ WC_FREE_VAR_EX(a, NULL, DYNAMIC_TYPE_BIGINT);
+ WC_FREE_VAR_EX(prime, NULL, DYNAMIC_TYPE_BIGINT);
+ WC_FREE_VAR_EX(mu, NULL, DYNAMIC_TYPE_BIGINT);
+ return ret;
+}
+
+/* Add two points on the same curve together.
+ *
+ * @param [in] group EC group.
+ * @param [out] r EC point that is result of point addition.
+ * @param [in] p1 First EC point to add.
+ * @param [in] p2 Second EC point to add.
+ * @param [in] ctx Context to use for BN operations. Unused.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int wolfSSL_EC_POINT_add(const WOLFSSL_EC_GROUP* group, WOLFSSL_EC_POINT* r,
+ const WOLFSSL_EC_POINT* p1, const WOLFSSL_EC_POINT* p2, WOLFSSL_BN_CTX* ctx)
+{
+ int ret = 1;
+
+ /* No BN operations performed. */
+ (void)ctx;
+
+ /* Validate parameters. */
+ if ((group == NULL) || (r == NULL) || (p1 == NULL) || (p2 == NULL)) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_add error");
+ ret = 0;
+ }
+
+ /* Ensure the internal objects of the EC points are setup. */
+ if ((ret == 1) && ((ec_point_setup(r) != 1) || (ec_point_setup(p1) != 1) ||
+ (ec_point_setup(p2) != 1))) {
+ WOLFSSL_MSG("ec_point_setup error");
+ ret = 0;
+ }
+
+#ifdef DEBUG_WOLFSSL
+ if (ret == 1) {
+ int nid = wolfSSL_EC_GROUP_get_curve_name(group);
+ const char* curve = wolfSSL_OBJ_nid2ln(nid);
+ const char* nistName = wolfSSL_EC_curve_nid2nist(nid);
+ wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_add p1", p1);
+ wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_add p2", p2);
+ if (curve != NULL)
+ WOLFSSL_MSG_EX("curve name: %s", curve);
+ if (nistName != NULL)
+ WOLFSSL_MSG_EX("nist curve name: %s", nistName);
+ }
+#endif
+
+ if (ret == 1) {
+ /* Add points using wolfCrypt objects. */
+ ret = wolfssl_ec_point_add(group->curve_idx, (ecc_point*)r->internal,
+ (ecc_point*)p1->internal, (ecc_point*)p2->internal);
+ }
+
+ /* Copy internal EC point values out to external EC point. */
+ if ((ret == 1) && (ec_point_external_set(r) != 1)) {
+ WOLFSSL_MSG("ec_point_external_set error");
+ ret = 0;
+ }
+
+#ifdef DEBUG_WOLFSSL
+ if (ret == 1) {
+ wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_add result", r);
+ }
+#endif
+
+ return ret;
+}
+
+/* Sum the scalar multiplications of the base point and n, and q and m.
+ *
+ * r = base point * n + q * m
+ *
+ * @param [out] r EC point that is result of operation.
+ * @param [in] b Base point of curve.
+ * @param [in] n Scalar to multiply by base point.
+ * @param [in] q EC point to be scalar multiplied.
+ * @param [in] m Scalar to multiply q by.
+ * @param [in] a Parameter A of curve.
+ * @param [in] prime Prime (modulus) of curve.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+static int ec_mul2add(ecc_point* r, ecc_point* b, mp_int* n, ecc_point* q,
+ mp_int* m, mp_int* a, mp_int* prime)
+{
+ int ret = 1;
+#if defined(ECC_SHAMIR) && !defined(WOLFSSL_KCAPI_ECC)
+ if (ecc_mul2add(b, n, q, m, r, a, prime, NULL) != MP_OKAY) {
+ WOLFSSL_MSG("ecc_mul2add error");
+ ret = 0;
+ }
+#else
+ ecc_point* tmp = NULL;
+ mp_digit mp = 0;
+
+ /* Calculate Montgomery product. */
+ if (mp_montgomery_setup(prime, &mp) != MP_OKAY) {
+ WOLFSSL_MSG("mp_montgomery_setup nqm error");
+ ret = 0;
+ }
+ /* Create temporary point to hold: q * m */
+ if ((ret == 1) && ((tmp = wc_ecc_new_point()) == NULL)) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_new nqm error");
+ ret = 0;
+ }
+ /* r = base point * n */
+ if ((ret == 1) && (wc_ecc_mulmod(n, b, r, a, prime, 0) !=
+ MP_OKAY)) {
+ WOLFSSL_MSG("wc_ecc_mulmod nqm error");
+ ret = 0;
+ }
+ /* tmp = q * m */
+ if ((ret == 1) && (wc_ecc_mulmod(m, q, tmp, a, prime, 0) != MP_OKAY)) {
+ WOLFSSL_MSG("wc_ecc_mulmod nqm error");
+ ret = 0;
+ }
+ /* r = r + tmp */
+ if ((ret == 1) && (ecc_projective_add_point(tmp, r, r, a, prime, mp) !=
+ MP_OKAY)) {
+ WOLFSSL_MSG("wc_ecc_mulmod nqm error");
+ ret = 0;
+ }
+ /* Map point back to affine coordinates. Converts from Montogomery
+ * form. */
+ if ((ret == 1) && (ecc_map(r, prime, mp) != MP_OKAY)) {
+ WOLFSSL_MSG("ecc_map nqm error");
+ ret = 0;
+ }
+
+ /* Dispose of allocated temporary point. */
+ wc_ecc_del_point(tmp);
+#endif
+
+ return ret;
+}
+
+/* Sum the scalar multiplications of the base point and n, and q and m.
+ *
+ * r = base point * n + q * m
+ *
+ * @param [in] curveIdx Index of curve in ecc_set.
+ * @param [out] r EC point that is result of operation.
+ * @param [in] n Scalar to multiply by base point. May be NULL.
+ * @param [in] q EC point to be scalar multiplied. May be NULL.
+ * @param [in] m Scalar to multiply q by. May be NULL.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+static int wolfssl_ec_point_mul(int curveIdx, ecc_point* r, mp_int* n,
+ ecc_point* q, mp_int* m)
+{
+ int ret = 1;
+#ifdef WOLFSSL_SMALL_STACK
+ mp_int* a = NULL;
+ mp_int* prime = NULL;
+#else
+ mp_int a[1], prime[1];
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+ /* Allocate MP integer for curve parameter: a. */
+ a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+ if (a == NULL) {
+ ret = 0;
+ }
+ if (ret == 1) {
+ /* Allocate MP integer for curve parameter: prime. */
+ prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
+ if (prime == NULL) {
+ ret = 0;
+ }
+ }
+#endif
+
+ /* Initialize the MP ints. */
+ if ((ret == 1) && (mp_init_multi(prime, a, NULL, NULL, NULL, NULL) !=
+ MP_OKAY)) {
+ WOLFSSL_MSG("mp_init_multi error");
+ ret = 0;
+ }
+
+ /* Read the curve parameter: prime. */
+ if ((ret == 1) && (mp_read_radix(prime, ecc_sets[curveIdx].prime,
+ MP_RADIX_HEX) != MP_OKAY)) {
+ WOLFSSL_MSG("mp_read_radix prime error");
+ ret = 0;
+ }
+
+ /* Read the curve parameter: a. */
+ if ((ret == 1) && (mp_read_radix(a, ecc_sets[curveIdx].Af,
+ MP_RADIX_HEX) != MP_OKAY)) {
+ WOLFSSL_MSG("mp_read_radix a error");
+ ret = 0;
+ }
+
+ if ((ret == 1) && (n != NULL)) {
+ /* Get generator - base point. */
+ #if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)
+ if ((ret == 1) && (wc_ecc_get_generator(r, curveIdx) != MP_OKAY)) {
+ WOLFSSL_MSG("wc_ecc_get_generator error");
+ ret = 0;
+ }
+ #else
+ /* wc_ecc_get_generator is not defined in the FIPS v2 module. */
+ /* Read generator (base point) x-ordinate. */
+ if ((ret == 1) && (mp_read_radix(r->x, ecc_sets[curveIdx].Gx,
+ MP_RADIX_HEX) != MP_OKAY)) {
+ WOLFSSL_MSG("mp_read_radix Gx error");
+ ret = 0;
+ }
+ /* Read generator (base point) y-ordinate. */
+ if ((ret == 1) && (mp_read_radix(r->y, ecc_sets[curveIdx].Gy,
+ MP_RADIX_HEX) != MP_OKAY)) {
+ WOLFSSL_MSG("mp_read_radix Gy error");
+ ret = 0;
+ }
+ /* z-ordinate is one as point is affine. */
+ if ((ret == 1) && (mp_set(r->z, 1) != MP_OKAY)) {
+ WOLFSSL_MSG("mp_set Gz error");
+ ret = 0;
+ }
+ #endif /* NOPT_FIPS_VERSION == 2 */
+ }
+
+ if ((ret == 1) && (n != NULL) && (q != NULL) && (m != NULL)) {
+ /* r = base point * n + q * m */
+ ret = ec_mul2add(r, r, n, q, m, a, prime);
+ }
+ /* Not all values present, see if we are only doing base point * n. */
+ else if ((ret == 1) && (n != NULL)) {
+ /* r = base point * n */
+ if (wc_ecc_mulmod(n, r, r, a, prime, 1) != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_mulmod gn error");
+ ret = 0;
+ }
+ }
+ /* Not all values present, see if we are only doing q * m. */
+ else if ((ret == 1) && (q != NULL) && (m != NULL)) {
+ /* r = q * m */
+ if (wc_ecc_mulmod(m, q, r, a, prime, 1) != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_mulmod qm error");
+ ret = 0;
+ }
+ }
+ /* No values to use. */
+ else if (ret == 1) {
+ /* Set result to infinity as no values passed in. */
+ mp_zero(r->x);
+ mp_zero(r->y);
+ mp_zero(r->z);
+ }
+
+ mp_clear(a);
+ mp_clear(prime);
+ WC_FREE_VAR_EX(a, NULL, DYNAMIC_TYPE_BIGINT);
+ WC_FREE_VAR_EX(prime, NULL, DYNAMIC_TYPE_BIGINT);
+ return ret;
+}
+
+/* Sum the scalar multiplications of the base point and n, and q and m.
+ *
+ * r = base point * n + q * m
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] group EC group.
+ * @param [out] r EC point that is result of operation.
+ * @param [in] n Scalar to multiply by base point. May be NULL.
+ * @param [in] q EC point to be scalar multiplied. May be NULL.
+ * @param [in] m Scalar to multiply q by. May be NULL.
+ * @param [in] ctx Context to use for BN operations. Unused.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r,
+ const WOLFSSL_BIGNUM *n, const WOLFSSL_EC_POINT *q, const WOLFSSL_BIGNUM *m,
+ WOLFSSL_BN_CTX *ctx)
+{
+ int ret = 1;
+
+ /* No BN operations performed. */
+ (void)ctx;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_mul");
+
+ /* Validate parameters. */
+ if ((group == NULL) || (r == NULL)) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error");
+ ret = 0;
+ }
+
+ /* Ensure the internal representation of the EC point q is setup. */
+ if ((ret == 1) && (q != NULL) && (ec_point_setup(q) != 1)) {
+ WOLFSSL_MSG("ec_point_setup error");
+ ret = 0;
+ }
+
+#ifdef DEBUG_WOLFSSL
+ if (ret == 1) {
+ int nid = wolfSSL_EC_GROUP_get_curve_name(group);
+ const char* curve = wolfSSL_OBJ_nid2ln(nid);
+ const char* nistName = wolfSSL_EC_curve_nid2nist(nid);
+ char* num;
+ wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_mul input q", q);
+ num = wolfSSL_BN_bn2hex(n);
+ WOLFSSL_MSG_EX("\tn = %s", num);
+ XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL);
+ num = wolfSSL_BN_bn2hex(m);
+ WOLFSSL_MSG_EX("\tm = %s", num);
+ XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (curve != NULL)
+ WOLFSSL_MSG_EX("curve name: %s", curve);
+ if (nistName != NULL)
+ WOLFSSL_MSG_EX("nist curve name: %s", nistName);
+ }
+#endif
+
+ if (ret == 1) {
+ mp_int* ni = (n != NULL) ? (mp_int*)n->internal : NULL;
+ ecc_point* qi = (q != NULL) ? (ecc_point*)q->internal : NULL;
+ mp_int* mi = (m != NULL) ? (mp_int*)m->internal : NULL;
+
+ /* Perform multiplication with wolfCrypt objects. */
+ ret = wolfssl_ec_point_mul(group->curve_idx, (ecc_point*)r->internal,
+ ni, qi, mi);
+ }
+
+ /* Only on success is the internal point guaranteed to be set. */
+ if (r != NULL) {
+ r->inSet = (ret == 1);
+ }
+ /* Copy internal EC point values out to external EC point. */
+ if ((ret == 1) && (ec_point_external_set(r) != 1)) {
+ WOLFSSL_MSG("ec_point_external_set error");
+ ret = 0;
+ }
+
+#ifdef DEBUG_WOLFSSL
+ if (ret == 1) {
+ wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_mul result", r);
+ }
+#endif
+
+ return ret;
+}
+#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_ATECC608A && !HAVE_SELFTEST &&
+ * !WOLFSSL_SP_MATH */
+
+/* Invert the point on the curve.
+ * (x, y) -> (x, -y) = (x, (prime - y) % prime)
+ *
+ * @param [in] curveIdx Index of curve in ecc_set.
+ * @param [in, out] point EC point to invert.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+static int wolfssl_ec_point_invert(int curveIdx, ecc_point* point)
+{
+ int ret = 1;
+ WC_DECLARE_VAR(prime, mp_int, 1, 0);
+
+ /* Allocate memory for an MP int to hold the prime of the curve. */
+ WC_ALLOC_VAR_EX(prime, mp_int, 1, NULL, DYNAMIC_TYPE_BIGINT, ret=0);
+
+ /* Initialize MP int. */
+ if ((ret == 1) && (mp_init(prime) != MP_OKAY)) {
+ WOLFSSL_MSG("mp_init_multi error");
+ ret = 0;
+ }
+
+ /* Read the curve parameter: prime. */
+ if ((ret == 1) && (mp_read_radix(prime, ecc_sets[curveIdx].prime,
+ MP_RADIX_HEX) != MP_OKAY)) {
+ WOLFSSL_MSG("mp_read_radix prime error");
+ ret = 0;
+ }
+
+ /* y = (prime - y) mod prime. */
+ if ((ret == 1) && (!mp_iszero(point->y)) && (mp_sub(prime, point->y,
+ point->y) != MP_OKAY)) {
+ WOLFSSL_MSG("mp_sub error");
+ ret = 0;
+ }
+
+ /* Dispose of memory associated with MP. */
+ mp_free(prime);
+ WC_FREE_VAR_EX(prime, NULL, DYNAMIC_TYPE_BIGINT);
+ return ret;
+}
+
+/* Invert the point on the curve.
+ * (x, y) -> (x, -y) = (x, (prime - y) % prime)
+ *
+ * @param [in] group EC group.
+ * @param [in, out] point EC point to invert.
+ * @param [in] ctx Context to use for BN operations. Unused.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int wolfSSL_EC_POINT_invert(const WOLFSSL_EC_GROUP *group,
+ WOLFSSL_EC_POINT *point, WOLFSSL_BN_CTX *ctx)
+{
+ int ret = 1;
+
+ /* No BN operations performed. */
+ (void)ctx;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_invert");
+
+ /* Validate parameters. */
+ if ((group == NULL) || (point == NULL) || (point->internal == NULL)) {
+ ret = 0;
+ }
+
+ /* Ensure internal representation of point is setup. */
+ if ((ret == 1) && (ec_point_setup(point) != 1)) {
+ ret = 0;
+ }
+
+#ifdef DEBUG_WOLFSSL
+ if (ret == 1) {
+ int nid = wolfSSL_EC_GROUP_get_curve_name(group);
+ const char* curve = wolfSSL_OBJ_nid2ln(nid);
+ const char* nistName = wolfSSL_EC_curve_nid2nist(nid);
+ wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_invert input", point);
+ if (curve != NULL)
+ WOLFSSL_MSG_EX("curve name: %s", curve);
+ if (nistName != NULL)
+ WOLFSSL_MSG_EX("nist curve name: %s", nistName);
+
+ }
+#endif
+
+ if (ret == 1 && !wolfSSL_BN_is_one(point->Z)) {
+#if !defined(WOLFSSL_SP_MATH) && !defined(WOLF_CRYPTO_CB_ONLY_ECC)
+ if (ec_point_convert_to_affine(group, point) != 0)
+ ret = 0;
+#else
+ WOLFSSL_MSG("wolfSSL_EC_POINT_invert called on non-affine point");
+ ret = 0;
+#endif
+ }
+
+ if (ret == 1) {
+ /* Perform inversion using wolfCrypt objects. */
+ ret = wolfssl_ec_point_invert(group->curve_idx,
+ (ecc_point*)point->internal);
+ }
+
+ /* Set the external EC point representation based on internal. */
+ if ((ret == 1) && (ec_point_external_set(point) != 1)) {
+ WOLFSSL_MSG("ec_point_external_set error");
+ ret = 0;
+ }
+
+#ifdef DEBUG_WOLFSSL
+ if (ret == 1) {
+ wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_invert result", point);
+ }
+#endif
+
+ return ret;
+}
+
+#ifdef WOLFSSL_EC_POINT_CMP_JACOBIAN
+/* Compare two points on a the same curve.
+ *
+ * (Ax, Ay, Az) => (Ax / (Az ^ 2), Ay / (Az ^ 3))
+ * (Bx, By, Bz) => (Bx / (Bz ^ 2), By / (Bz ^ 3))
+ * When equal:
+ * (Ax / (Az ^ 2), Ay / (Az ^ 3)) = (Bx / (Bz ^ 2), By / (Bz ^ 3))
+ * => (Ax * (Bz ^ 2), Ay * (Bz ^ 3)) = (Bx * (Az ^ 2), By * (Az ^ 3))
+ *
+ * @param [in] group EC group.
+ * @param [in] a EC point to compare.
+ * @param [in] b EC point to compare.
+ * @return 0 when equal.
+ * @return 1 when different.
+ * @return -1 on error.
+ */
+static int ec_point_cmp_jacobian(const WOLFSSL_EC_GROUP* group,
+ const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b, WOLFSSL_BN_CTX *ctx)
+{
+ int ret = 0;
+ BIGNUM* at = BN_new();
+ BIGNUM* bt = BN_new();
+ BIGNUM* az = BN_new();
+ BIGNUM* bz = BN_new();
+ BIGNUM* mod = BN_new();
+
+ /* Check that the big numbers were allocated. */
+ if ((at == NULL) || (bt == NULL) || (az == NULL) || (bz == NULL) ||
+ (mod == NULL)) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ /* Get the modulus for the curve. */
+ if ((ret == 0) &&
+ (BN_hex2bn(&mod, ecc_sets[group->curve_idx].prime) != 1)) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ if (ret == 0) {
+ /* bt = Bx * (Az ^ 2). When Az is one then just copy. */
+ if (BN_is_one(a->Z)) {
+ if (BN_copy(bt, b->X) == NULL) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+ /* az = Az ^ 2 */
+ else if ((BN_mod_mul(az, a->Z, a->Z, mod, ctx) != 1)) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ /* bt = Bx * az = Bx * (Az ^ 2) */
+ else if (BN_mod_mul(bt, b->X, az, mod, ctx) != 1) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+ if (ret == 0) {
+ /* at = Ax * (Bz ^ 2). When Bz is one then just copy. */
+ if (BN_is_one(b->Z)) {
+ if (BN_copy(at, a->X) == NULL) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+ /* bz = Bz ^ 2 */
+ else if (BN_mod_mul(bz, b->Z, b->Z, mod, ctx) != 1) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ /* at = Ax * bz = Ax * (Bz ^ 2) */
+ else if (BN_mod_mul(at, a->X, bz, mod, ctx) != 1) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+ /* Compare x-ordinates. */
+ if ((ret == 0) && (BN_cmp(at, bt) != 0)) {
+ ret = 1;
+ }
+ if (ret == 0) {
+ /* bt = By * (Az ^ 3). When Az is one then just copy. */
+ if (BN_is_one(a->Z)) {
+ if (BN_copy(bt, b->Y) == NULL) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+ /* az = az * Az = Az ^ 3 */
+ else if ((BN_mod_mul(az, az, a->Z, mod, ctx) != 1)) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ /* bt = By * az = By * (Az ^ 3) */
+ else if (BN_mod_mul(bt, b->Y, az, mod, ctx) != 1) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+ if (ret == 0) {
+ /* at = Ay * (Bz ^ 3). When Bz is one then just copy. */
+ if (BN_is_one(b->Z)) {
+ if (BN_copy(at, a->Y) == NULL) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+ /* bz = bz * Bz = Bz ^ 3 */
+ else if (BN_mod_mul(bz, bz, b->Z, mod, ctx) != 1) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ /* at = Ay * bz = Ay * (Bz ^ 3) */
+ else if (BN_mod_mul(at, a->Y, bz, mod, ctx) != 1) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+ /* Compare y-ordinates. */
+ if ((ret == 0) && (BN_cmp(at, bt) != 0)) {
+ ret = 1;
+ }
+
+ BN_free(mod);
+ BN_free(bz);
+ BN_free(az);
+ BN_free(bt);
+ BN_free(at);
+ return ret;
+}
+#endif
+
+/* Compare two points on a the same curve.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] group EC group.
+ * @param [in] a EC point to compare.
+ * @param [in] b EC point to compare.
+ * @param [in] ctx Context to use for BN operations. Unused.
+ * @return 0 when equal.
+ * @return 1 when different.
+ * @return -1 on error.
+ */
+int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group,
+ const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b, WOLFSSL_BN_CTX *ctx)
+{
+ int ret = 0;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp");
+
+ /* Validate parameters. */
+ if ((group == NULL) || (a == NULL) || (a->internal == NULL) ||
+ (b == NULL) || (b->internal == NULL)) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ if (ret != -1) {
+ #ifdef WOLFSSL_EC_POINT_CMP_JACOBIAN
+ /* If same Z ordinate then no need to convert to affine. */
+ if (BN_cmp(a->Z, b->Z) == 0) {
+ /* Compare */
+ ret = ((BN_cmp(a->X, b->X) != 0) || (BN_cmp(a->Y, b->Y) != 0));
+ }
+ else {
+ ret = ec_point_cmp_jacobian(group, a, b, ctx);
+ }
+ #else
+ /* No BN operations performed. */
+ (void)ctx;
+
+ ret = (wc_ecc_cmp_point((ecc_point*)a->internal,
+ (ecc_point*)b->internal) != MP_EQ);
+ #endif
+ }
+
+ return ret;
+}
+
+/* Copy EC point.
+ *
+ * @param [out] dest EC point to copy into.
+ * @param [in] src EC point to copy.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int wolfSSL_EC_POINT_copy(WOLFSSL_EC_POINT *dest, const WOLFSSL_EC_POINT *src)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_copy");
+
+ /* Validate parameters. */
+ if ((dest == NULL) || (src == NULL)) {
+ ret = 0;
+ }
+
+ /* Ensure internal EC point of src is setup. */
+ if ((ret == 1) && (ec_point_setup(src) != 1)) {
+ ret = 0;
+ }
+
+ /* Copy internal EC points. */
+ if ((ret == 1) && (wc_ecc_copy_point((ecc_point*)src->internal,
+ (ecc_point*)dest->internal) != MP_OKAY)) {
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ /* Destinatation internal point is set. */
+ dest->inSet = 1;
+
+ /* Set the external EC point of dest based on internal. */
+ if (ec_point_external_set(dest) != 1) {
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+/* Checks whether point is at infinity.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] group EC group.
+ * @param [in] point EC point to check.
+ * @return 1 when at infinity.
+ * @return 0 when not at infinity.
+ */
+int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group,
+ const WOLFSSL_EC_POINT *point)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity");
+
+ /* Validate parameters. */
+ if ((group == NULL) || (point == NULL) || (point->internal == NULL)) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error");
+ ret = 0;
+ }
+
+ /* Ensure internal EC point is setup. */
+ if ((ret == 1) && (ec_point_setup(point) != 1)) {
+ ret = 0;
+ }
+ if (ret == 1) {
+ #ifndef WOLF_CRYPTO_CB_ONLY_ECC
+ /* Check for infinity. */
+ ret = wc_ecc_point_is_at_infinity((ecc_point*)point->internal);
+ if (ret < 0) {
+ WOLFSSL_MSG("ecc_point_is_at_infinity failure");
+ /* Error return is 0 by OpenSSL. */
+ ret = 0;
+ }
+ #else
+ WOLFSSL_MSG("ecc_point_is_at_infinitiy compiled out");
+ ret = 0;
+ #endif
+ }
+
+ return ret;
+}
+
+#endif /* OPENSSL_EXTRA */
+
+/* End EC_POINT */
+
+/* Start EC_KEY */
+
+#ifdef OPENSSL_EXTRA
+
+/*
+ * EC key constructor/deconstructor APIs
+ */
+
+/* Allocate a new EC key.
+ *
+ * Not OpenSSL API.
+ *
+ * @param [in] heap Heap hint for dynamic memory allocation.
+ * @param [in] devId Device identifier value.
+ * @return New, allocated EC key on success.
+ * @return NULL on error.
+ */
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_ex(void* heap, int devId)
+{
+ WOLFSSL_EC_KEY *key = NULL;
+ int err = 0;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_new");
+
+ /* Allocate memory for EC key. */
+ key = (WOLFSSL_EC_KEY*)XMALLOC(sizeof(WOLFSSL_EC_KEY), heap,
+ DYNAMIC_TYPE_ECC);
+ if (key == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_KEY failure");
+ err = 1;
+ }
+ if (!err) {
+ /* Reset all fields to 0. */
+ XMEMSET(key, 0, sizeof(WOLFSSL_EC_KEY));
+ /* Cache heap hint. */
+ key->heap = heap;
+ /* Initialize fields to defaults. */
+ key->form = WC_POINT_CONVERSION_UNCOMPRESSED;
+
+ /* Initialize reference count. */
+ wolfSSL_RefInit(&key->ref, &err);
+#ifdef WOLFSSL_REFCNT_ERROR_RETURN
+ }
+ if (!err) {
+#endif
+ /* Allocate memory for internal EC key representation. */
+ key->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), heap,
+ DYNAMIC_TYPE_ECC);
+ if (key->internal == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc ecc key failure");
+ err = 1;
+ }
+ }
+ if (!err) {
+ /* Initialize wolfCrypt EC key. */
+ if (wc_ecc_init_ex((ecc_key*)key->internal, heap, devId) != 0) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_new init ecc key failure");
+ err = 1;
+ }
+ }
+
+ if (!err) {
+ /* Group unknown at creation */
+ key->group = wolfSSL_EC_GROUP_new_by_curve_name(WC_NID_undef);
+ if (key->group == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure");
+ err = 1;
+ }
+ }
+
+ if (!err) {
+ /* Allocate a point as public key. */
+ key->pub_key = wolfSSL_EC_POINT_new(key->group);
+ if (key->pub_key == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_new failure");
+ err = 1;
+ }
+ }
+
+ if (!err) {
+ /* Allocate a BN as private key. */
+ key->priv_key = wolfSSL_BN_new();
+ if (key->priv_key == NULL) {
+ WOLFSSL_MSG("wolfSSL_BN_new failure");
+ err = 1;
+ }
+ }
+
+ if (err) {
+ /* Dispose of EC key on error. */
+ wolfSSL_EC_KEY_free(key);
+ key = NULL;
+ }
+ /* Return new EC key object. */
+ return key;
+}
+
+/* Allocate a new EC key.
+ *
+ * @return New, allocated EC key on success.
+ * @return NULL on error.
+ */
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void)
+{
+ return wolfSSL_EC_KEY_new_ex(NULL, INVALID_DEVID);
+}
+
+/* Create new EC key with the group having the specified numeric ID.
+ *
+ * @param [in] nid Numeric ID.
+ * @return New, allocated EC key on success.
+ * @return NULL on error.
+ */
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid)
+{
+ WOLFSSL_EC_KEY *key;
+ int err = 0;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_new_by_curve_name");
+
+ /* Allocate empty, EC key. */
+ key = wolfSSL_EC_KEY_new();
+ if (key == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_new failure");
+ err = 1;
+ }
+
+ if (!err) {
+ /* Set group to be nid. */
+ ec_group_set_nid(key->group, nid);
+ if (key->group->curve_idx == -1) {
+ wolfSSL_EC_KEY_free(key);
+ key = NULL;
+ }
+ }
+
+ /* Return the new EC key object. */
+ return key;
+}
+
+/* Dispose of the EC key and allocated data.
+ *
+ * Cannot use key after this call.
+ *
+ * @param [in] key EC key to free.
+ */
+void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key)
+{
+ int doFree = 0;
+ int err;
+
+ (void)err;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_free");
+
+ if (key != NULL) {
+ void* heap = key->heap;
+
+ /* Decrement reference count. */
+ wolfSSL_RefDec(&key->ref, &doFree, &err);
+ if (doFree) {
+ /* Dispose of allocated reference counting data. */
+ wolfSSL_RefFree(&key->ref);
+
+ /* Dispose of private key. */
+ wolfSSL_BN_free(key->priv_key);
+ wolfSSL_EC_POINT_free(key->pub_key);
+ wolfSSL_EC_GROUP_free(key->group);
+ if (key->internal != NULL) {
+ /* Dispose of wolfCrypt representation of EC key. */
+ wc_ecc_free((ecc_key*)key->internal);
+ XFREE(key->internal, heap, DYNAMIC_TYPE_ECC);
+ }
+
+ /* Set back to NULLs for safety. */
+ ForceZero(key, sizeof(*key));
+
+ /* Dispose of the memory associated with the EC key. */
+ XFREE(key, heap, DYNAMIC_TYPE_ECC);
+ (void)heap;
+ }
+ }
+}
+
+/* Increments ref count of EC key.
+ *
+ * @param [in, out] key EC key.
+ * @return 1 on success
+ * @return 0 on error
+ */
+int wolfSSL_EC_KEY_up_ref(WOLFSSL_EC_KEY* key)
+{
+ int err = 1;
+
+ if (key != NULL) {
+ wolfSSL_RefInc(&key->ref, &err);
+ }
+
+ return !err;
+}
+
+#ifndef NO_CERTS
+
+#if defined(OPENSSL_ALL)
+/* Copy the internal, wolfCrypt EC key.
+ *
+ * @param [in, out] dst Destination wolfCrypt EC key.
+ * @param [in] src Source wolfCrypt EC key.
+ * @return 0 on success.
+ * @return Negative on error.
+ */
+static int wolfssl_ec_key_int_copy(ecc_key* dst, const ecc_key* src)
+{
+ int ret;
+
+ /* Copy public key. */
+#if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)
+ ret = wc_ecc_copy_point(&src->pubkey, &dst->pubkey);
+#else
+ ret = wc_ecc_copy_point((ecc_point*)&src->pubkey, &dst->pubkey);
+#endif
+ if (ret != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_copy_point error");
+ }
+
+ if (ret == 0) {
+ /* Copy private key. */
+ ret = mp_copy(wc_ecc_key_get_priv((ecc_key*)src),
+ wc_ecc_key_get_priv(dst));
+ if (ret != MP_OKAY) {
+ WOLFSSL_MSG("mp_copy error");
+ }
+ }
+
+ if (ret == 0) {
+ /* Copy domain parameters. */
+ if (src->dp) {
+ ret = wc_ecc_set_curve(dst, 0, src->dp->id);
+ if (ret != 0) {
+ WOLFSSL_MSG("wc_ecc_set_curve error");
+ }
+ }
+ }
+
+ if (ret == 0) {
+ /* Copy the other components. */
+ dst->type = src->type;
+ dst->idx = src->idx;
+ dst->state = src->state;
+ dst->flags = src->flags;
+ }
+
+ return ret;
+}
+
+/* Copies ecc_key into new WOLFSSL_EC_KEY object
+ *
+ * Copies the internal representation as well.
+ *
+ * @param [in] src EC key to duplicate.
+ *
+ * @return EC key on success.
+ * @return NULL on error.
+ */
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_dup(const WOLFSSL_EC_KEY *src)
+{
+ int err = 0;
+ WOLFSSL_EC_KEY* newKey = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_dup");
+
+ /* Validate EC key. */
+ if ((src == NULL) || (src->internal == NULL) || (src->group == NULL) ||
+ (src->pub_key == NULL) || (src->priv_key == NULL)) {
+ WOLFSSL_MSG("src NULL error");
+ err = 1;
+ }
+
+ if (!err) {
+ /* Create a new, empty key. */
+ newKey = wolfSSL_EC_KEY_new();
+ if (newKey == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_new error");
+ err = 1;
+ }
+ }
+
+ if (!err) {
+ /* Copy internal EC key. */
+ if (wolfssl_ec_key_int_copy((ecc_key*)newKey->internal,
+ (ecc_key*)src->internal) != 0) {
+ WOLFSSL_MSG("Copying internal EC key error");
+ err = 1;
+ }
+ }
+ if (!err) {
+ /* Internal key set. */
+ newKey->inSet = 1;
+
+ /* Copy group */
+ err = wolfssl_ec_group_copy(newKey->group, src->group);
+ }
+ /* Copy public key. */
+ if ((!err) && (wolfSSL_EC_POINT_copy(newKey->pub_key, src->pub_key) != 1)) {
+ WOLFSSL_MSG("Copying EC public key error");
+ err = 1;
+ }
+
+ if (!err) {
+ /* Set header size of private key in PKCS#8 format.*/
+ newKey->pkcs8HeaderSz = src->pkcs8HeaderSz;
+
+ /* Copy private key. */
+ if (wolfSSL_BN_copy(newKey->priv_key, src->priv_key) == NULL) {
+ WOLFSSL_MSG("Copying EC private key error");
+ err = 1;
+ }
+ }
+
+ if (err) {
+ /* Dispose of EC key on error. */
+ wolfSSL_EC_KEY_free(newKey);
+ newKey = NULL;
+ }
+ /* Return the new EC key. */
+ return newKey;
+}
+
+#endif /* OPENSSL_ALL */
+
+#endif /* !NO_CERTS */
+
+/*
+ * EC key to/from bin/octet APIs
+ */
+
+/* Create an EC key from the octet encoded public key.
+ *
+ * Behaviour checked against OpenSSL.
+ *
+ * @param [out] key Reference to EC key. Must pass in a valid object with
+ * group set.
+ * @param [in, out] in On in, reference to buffer that contains data.
+ * On out, reference to buffer after public key data.
+ * @param [in] len Length of data in the buffer. Must be length of the
+ * encoded public key.
+ * @return Allocated EC key on success.
+ * @return NULL on error.
+ */
+WOLFSSL_EC_KEY *wolfSSL_o2i_ECPublicKey(WOLFSSL_EC_KEY **key,
+ const unsigned char **in, long len)
+{
+ int err = 0;
+ WOLFSSL_EC_KEY* ret = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_o2i_ECPublicKey");
+
+ /* Validate parameters: EC group needed to perform import. */
+ if ((key == NULL) || (*key == NULL) || ((*key)->group == NULL) ||
+ (in == NULL) || (*in == NULL) || (len <= 0)) {
+ WOLFSSL_MSG("wolfSSL_o2i_ECPublicKey Bad arguments");
+ err = 1;
+ }
+
+ if (!err) {
+ /* Return the EC key object passed in. */
+ ret = *key;
+
+ /* Import point into public key field. */
+ if (wolfSSL_EC_POINT_oct2point(ret->group, ret->pub_key, *in,
+ (size_t)len, NULL) != 1) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_oct2point error");
+ ret = NULL;
+ err = 1;
+ }
+ }
+ if (!err) {
+ /* Assumed length passed in is all the data. */
+ *in += len;
+ }
+
+ return ret;
+}
+
+/* Puts the encoded public key into out.
+ *
+ * Passing in NULL for out returns length only.
+ * Passing in NULL for *out has buffer allocated, encoded into and passed back.
+ * Passing non-NULL for *out has it encoded into and pointer moved past.
+ *
+ * @param [in] key EC key to encode.
+ * @param [in, out] out Reference to buffer to encode into. May be NULL or
+ * point to NULL.
+ * @return Length of encoding in bytes on success.
+ * @return 0 on error.
+ */
+int wolfSSL_i2o_ECPublicKey(const WOLFSSL_EC_KEY *key, unsigned char **out)
+{
+ int ret = 1;
+ size_t len = 0;
+ int form = WC_POINT_CONVERSION_UNCOMPRESSED;
+
+ WOLFSSL_ENTER("wolfSSL_i2o_ECPublicKey");
+
+ /* Validate parameters. */
+ if (key == NULL) {
+ WOLFSSL_MSG("wolfSSL_i2o_ECPublicKey Bad arguments");
+ ret = 0;
+ }
+
+ /* Ensure the external key data is set from the internal EC key. */
+ if ((ret == 1) && (!key->exSet) && (SetECKeyExternal((WOLFSSL_EC_KEY*)
+ key) != 1)) {
+ WOLFSSL_MSG("SetECKeyExternal failure");
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ #ifdef HAVE_COMP_KEY
+ /* Default to compressed form if not set */
+ form = (key->form == WC_POINT_CONVERSION_UNCOMPRESSED) ?
+ WC_POINT_CONVERSION_UNCOMPRESSED :
+ WC_POINT_CONVERSION_COMPRESSED;
+ #endif
+
+ /* Calculate length of point encoding. */
+ len = wolfSSL_EC_POINT_point2oct(key->group, key->pub_key, form, NULL,
+ 0, NULL);
+ }
+ /* Encode if length calculated and pointer supplied to update. */
+ if ((ret == 1) && (len != 0) && (out != NULL)) {
+ unsigned char *tmp = NULL;
+
+ /* Allocate buffer for encoding if no buffer supplied. */
+ if (*out == NULL) {
+ tmp = (unsigned char*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (tmp == NULL) {
+ WOLFSSL_MSG("malloc failed");
+ ret = 0;
+ }
+ }
+ else {
+ /* Get buffer to encode into. */
+ tmp = *out;
+ }
+
+ /* Encode public key into buffer. */
+ if ((ret == 1) && (wolfSSL_EC_POINT_point2oct(key->group, key->pub_key,
+ form, tmp, len, NULL) == 0)) {
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ /* Return buffer if allocated. */
+ if (*out == NULL) {
+ *out = tmp;
+ }
+ else {
+ /* Step over encoded data if not allocated. */
+ *out += len;
+ }
+ }
+ else if (*out == NULL) {
+ /* Dispose of allocated buffer. */
+ XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+ }
+
+ if (ret == 1) {
+ /* Return length on success. */
+ ret = (int)len;
+ }
+ return ret;
+}
+
+#ifdef HAVE_ECC_KEY_IMPORT
+/* Create a EC key from the DER encoded private key.
+ *
+ * @param [out] key Reference to EC key.
+ * @param [in, out] in On in, reference to buffer that contains DER data.
+ * On out, reference to buffer after private key data.
+ * @param [in] long Length of data in the buffer. May be larger than the
+ * length of the encoded private key.
+ * @return Allocated EC key on success.
+ * @return NULL on error.
+ */
+WOLFSSL_EC_KEY* wolfSSL_d2i_ECPrivateKey(WOLFSSL_EC_KEY** key,
+ const unsigned char** in, long len)
+{
+ int err = 0;
+ word32 idx = 0;
+ WOLFSSL_EC_KEY* ret = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_ECPrivateKey");
+
+ /* Validate parameters. */
+ if ((in == NULL) || (*in == NULL) || (len <= 0)) {
+ WOLFSSL_MSG("wolfSSL_d2i_ECPrivateKey Bad arguments");
+ err = 1;
+ }
+
+ /* Create a new, empty EC key. */
+ if ((!err) && ((ret = wolfSSL_EC_KEY_new()) == NULL)) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_new error");
+ err = 1;
+ }
+
+ /* Decode the private key DER data into internal EC key. */
+ if ((!err) && (wc_EccPrivateKeyDecode(*in, &idx, (ecc_key*)ret->internal,
+ (word32)len) != 0)) {
+ WOLFSSL_MSG("wc_EccPrivateKeyDecode error");
+ err = 1;
+ }
+
+ if (!err) {
+ /* Internal EC key setup. */
+ ret->inSet = 1;
+
+ /* Set the EC key from the internal values. */
+ if (SetECKeyExternal(ret) != 1) {
+ WOLFSSL_MSG("SetECKeyExternal error");
+ err = 1;
+ }
+ }
+
+ if (!err) {
+ /* Move buffer on to next byte after data used. */
+ *in += idx;
+ if (key) {
+ /* Return new EC key through reference. */
+ *key = ret;
+ }
+ }
+
+ if (err && (ret != NULL)) {
+ /* Dispose of allocated EC key. */
+ wolfSSL_EC_KEY_free(ret);
+ ret = NULL;
+ }
+ return ret;
+}
+#endif /* HAVE_ECC_KEY_IMPORT */
+
+/* Enecode the private key of the EC key into the buffer as DER.
+ *
+ * @param [in] key EC key to encode.
+ * @param [in, out] out On in, reference to buffer to place DER encoding into.
+ * On out, reference to buffer after the encoding.
+ * May be NULL.
+ * @return Length of DER encoding on success.
+ * @return 0 on error.
+ */
+int wolfSSL_i2d_ECPrivateKey(const WOLFSSL_EC_KEY *key, unsigned char **out)
+{
+ int err = 0;
+ word32 len = 0;
+
+ WOLFSSL_ENTER("wolfSSL_i2d_ECPrivateKey");
+
+ /* Validate parameters. */
+ if (key == NULL) {
+ WOLFSSL_MSG("wolfSSL_i2d_ECPrivateKey Bad arguments");
+ err = 1;
+ }
+
+ /* Update the internal EC key if not set. */
+ if ((!err) && (!key->inSet) && (SetECKeyInternal((WOLFSSL_EC_KEY*)key) !=
+ 1)) {
+ WOLFSSL_MSG("SetECKeyInternal error");
+ err = 1;
+ }
+
+ /* Calculate the length of the private key DER encoding using internal EC
+ * key. */
+ if ((!err) && ((int)(len = (word32)wc_EccKeyDerSize((ecc_key*)key->internal,
+ 0)) <= 0)) {
+ WOLFSSL_MSG("wc_EccKeyDerSize error");
+ err = 1;
+ }
+
+ /* Only return length when out is NULL. */
+ if ((!err) && (out != NULL)) {
+ unsigned char* buf = NULL;
+
+ /* Must have a buffer to encode into. */
+ if (*out == NULL) {
+ /* Allocate a new buffer of appropriate length. */
+ buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (buf == NULL) {
+ /* Error and return 0. */
+ err = 1;
+ len = 0;
+ }
+ else {
+ /* Return the allocated buffer. */
+ *out = buf;
+ }
+ }
+ /* Encode the internal EC key as a private key in DER format. */
+ if ((!err) && wc_EccPrivateKeyToDer((ecc_key*)key->internal, *out,
+ len) < 0) {
+ WOLFSSL_MSG("wc_EccPrivateKeyToDer error");
+ err = 1;
+ }
+ else if (buf != *out) {
+ /* Move the reference to byte past encoded private key. */
+ *out += len;
+ }
+
+ /* Dispose of any allocated buffer on error. */
+ if (err && (*out == buf)) {
+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ *out = NULL;
+ }
+ }
+
+ return (int)len;
+}
+
+/* Load private key into EC key from DER encoding.
+ *
+ * Not an OpenSSL compatibility API.
+ *
+ * @param [in, out] key EC key to put private key values into.
+ * @param [in] derBuf Buffer holding DER encoding.
+ * @param [in] derSz Size of DER encoding in bytes.
+ * @return 1 on success.
+ * @return -1 on error.
+ */
+int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
+ int derSz)
+{
+ return wolfSSL_EC_KEY_LoadDer_ex(key, derBuf, derSz,
+ WOLFSSL_EC_KEY_LOAD_PRIVATE);
+}
+
+/* Load private/public key into EC key from DER encoding.
+ *
+ * Not an OpenSSL compatibility API.
+ *
+ * @param [in, out] key EC key to put private/public key values into.
+ * @param [in] derBuf Buffer holding DER encoding.
+ * @param [in] derSz Size of DER encoding in bytes.
+ * @param [in] opt Key type option. Valid values:
+ * WOLFSSL_EC_KEY_LOAD_PRIVATE,
+ * WOLFSSL_EC_KEY_LOAD_PUBLIC.
+ * @return 1 on success.
+ * @return -1 on error.
+ */
+int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
+ int derSz, int opt)
+{
+ int res = 1;
+ int ret;
+ word32 idx = 0;
+ word32 algId;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer");
+
+ /* Validate parameters. */
+ if ((key == NULL) || (key->internal == NULL) || (derBuf == NULL) ||
+ (derSz <= 0)) {
+ WOLFSSL_MSG("Bad function arguments");
+ res = WOLFSSL_FATAL_ERROR;
+ }
+ if ((res == 1) && (opt != WOLFSSL_EC_KEY_LOAD_PRIVATE) &&
+ (opt != WOLFSSL_EC_KEY_LOAD_PUBLIC)) {
+ res = WOLFSSL_FATAL_ERROR;
+ }
+
+ if (res == 1) {
+ /* Assume no PKCS#8 header. */
+ key->pkcs8HeaderSz = 0;
+
+ /* Check if input buffer has PKCS8 header. In the case that it does not
+ * have a PKCS8 header then do not error out.
+ */
+ if ((ret = ToTraditionalInline_ex((const byte*)derBuf, &idx,
+ (word32)derSz, &algId)) > 0) {
+ WOLFSSL_MSG("Found PKCS8 header");
+ key->pkcs8HeaderSz = (word16)idx;
+ res = 1;
+ }
+ /* Error out on parsing error. */
+ else if (ret != WC_NO_ERR_TRACE(ASN_PARSE_E)) {
+ WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header");
+ res = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ if (res == 1) {
+ /* Load into internal EC key based on key type option. */
+ if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) {
+ ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal,
+ (word32)derSz);
+ }
+ else {
+ ret = wc_EccPublicKeyDecode(derBuf, &idx, (ecc_key*)key->internal,
+ (word32)derSz);
+ if (ret < 0) {
+ ecc_key *tmp = (ecc_key*)XMALLOC(sizeof(ecc_key),
+ ((ecc_key*)key->internal)->heap, DYNAMIC_TYPE_ECC);
+ if (tmp == NULL) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ else {
+ /* We now try again as x.963 [point type][x][opt y]. */
+ ret = wc_ecc_init_ex(tmp, ((ecc_key*)key->internal)->heap,
+ INVALID_DEVID);
+ if (ret == 0) {
+ ret = wc_ecc_import_x963(derBuf, (word32)derSz, tmp);
+ if (ret == 0) {
+ /* Take ownership of new key - set tmp to the old
+ * key which will then be freed below. */
+ ecc_key *old = (ecc_key *)key->internal;
+ key->internal = tmp;
+ tmp = old;
+
+ idx = (word32)derSz;
+ }
+ wc_ecc_free(tmp);
+ }
+ XFREE(tmp, ((ecc_key*)key->internal)->heap,
+ DYNAMIC_TYPE_ECC);
+ }
+ }
+ }
+ if (ret < 0) {
+ /* Error returned from wolfSSL. */
+ if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) {
+ WOLFSSL_MSG("wc_EccPrivateKeyDecode failed");
+ }
+ else {
+ WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
+ }
+ res = WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Internal key updated - update whether it is a valid key. */
+ key->inSet = (res == 1);
+ }
+
+ /* Set the external EC key based on value in internal. */
+ if ((res == 1) && (SetECKeyExternal(key) != 1)) {
+ WOLFSSL_MSG("SetECKeyExternal failed");
+ res = WOLFSSL_FATAL_ERROR;
+ }
+
+ return res;
+}
+
+
+#ifndef NO_BIO
+
+WOLFSSL_EC_KEY *wolfSSL_d2i_EC_PUBKEY_bio(WOLFSSL_BIO *bio,
+ WOLFSSL_EC_KEY **out)
+{
+ char* data = NULL;
+ int dataSz = 0;
+ int memAlloced = 0;
+ WOLFSSL_EC_KEY* ec = NULL;
+ int err = 0;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_EC_PUBKEY_bio");
+
+ if (bio == NULL)
+ return NULL;
+
+ if (err == 0 && wolfssl_read_bio(bio, &data, &dataSz, &memAlloced) != 0) {
+ WOLFSSL_ERROR_MSG("wolfssl_read_bio failed");
+ err = 1;
+ }
+
+ if (err == 0 && (ec = wolfSSL_EC_KEY_new()) == NULL) {
+ WOLFSSL_ERROR_MSG("wolfSSL_EC_KEY_new failed");
+ err = 1;
+ }
+
+ /* Load the EC key with the public key from the DER encoding. */
+ if (err == 0 && wolfSSL_EC_KEY_LoadDer_ex(ec, (const unsigned char*)data,
+ dataSz, WOLFSSL_EC_KEY_LOAD_PUBLIC) != 1) {
+ WOLFSSL_ERROR_MSG("wolfSSL_EC_KEY_LoadDer_ex failed");
+ err = 1;
+ }
+
+ if (memAlloced)
+ XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (err) { /* on error */
+ wolfSSL_EC_KEY_free(ec);
+ ec = NULL;
+ }
+ else { /* on success */
+ if (out != NULL)
+ *out = ec;
+ }
+
+ return ec;
+}
+
+#endif /* !NO_BIO */
+
+/*
+ * EC key PEM APIs
+ */
+
+#ifdef HAVE_ECC_KEY_EXPORT
+#if defined(WOLFSSL_KEY_GEN) && (!defined(NO_FILESYSTEM) || !defined(NO_BIO))
+/* Encode the EC public key as DER.
+ *
+ * @param [in] key EC key to encode.
+ * @param [out] der Pointer through which buffer is returned.
+ * @param [in] heap Heap hint.
+ * @return Size of encoding on success.
+ * @return 0 on error.
+ */
+static int wolfssl_ec_key_to_pubkey_der(WOLFSSL_EC_KEY* key,
+ unsigned char** der, void* heap)
+{
+ int sz;
+ unsigned char* buf = NULL;
+
+ (void)heap;
+
+ /* Calculate encoded size to allocate. */
+ sz = wc_EccPublicKeyDerSize((ecc_key*)key->internal, 1);
+ if (sz <= 0) {
+ WOLFSSL_MSG("wc_EccPublicKeyDerSize failed");
+ sz = 0;
+ }
+ if (sz > 0) {
+ /* Allocate memory to hold encoding. */
+ buf = (byte*)XMALLOC((size_t)sz, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (buf == NULL) {
+ WOLFSSL_MSG("malloc failed");
+ sz = 0;
+ }
+ }
+ if (sz > 0) {
+ /* Encode public key to DER using wolfSSL. */
+ sz = wc_EccPublicKeyToDer((ecc_key*)key->internal, buf, (word32)sz, 1);
+ if (sz < 0) {
+ WOLFSSL_MSG("wc_EccPublicKeyToDer failed");
+ sz = 0;
+ }
+ }
+
+ /* Return buffer on success. */
+ if (sz > 0) {
+ *der = buf;
+ }
+ else {
+ /* Dispose of any dynamically allocated data not returned. */
+ XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+
+ return sz;
+}
+#endif
+
+#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_KEY_GEN)
+/*
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] fp File pointer to write PEM encoding to.
+ * @param [in] key EC key to encode and write.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY* key)
+{
+ int ret = 1;
+ unsigned char* derBuf = NULL;
+ int derSz = 0;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_EC_PUBKEY");
+
+ /* Validate parameters. */
+ if ((fp == XBADFILE) || (key == NULL)) {
+ WOLFSSL_MSG("Bad argument.");
+ return 0;
+ }
+
+ /* Encode public key in EC key as DER. */
+ derSz = wolfssl_ec_key_to_pubkey_der(key, &derBuf, key->heap);
+ if (derSz == 0) {
+ ret = 0;
+ }
+
+ /* Write out to file the PEM encoding of the DER. */
+ if ((ret == 1) && (der_write_to_file_as_pem(derBuf, derSz, fp,
+ ECC_PUBLICKEY_TYPE, key->heap) != 1)) {
+ ret = 0;
+ }
+
+ /* Dispose of any dynamically allocated data. */
+ XFREE(derBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ WOLFSSL_LEAVE("wolfSSL_PEM_write_EC_PUBKEY", ret);
+
+ return ret;
+}
+#endif
+#endif
+
+#ifndef NO_BIO
+/* Read a PEM encoded EC public key from a BIO.
+ *
+ * @param [in] bio BIO to read EC public key from.
+ * @param [out] out Pointer to return EC key object through. May be NULL.
+ * @param [in] cb Password callback when PEM encrypted.
+ * @param [in] pass NUL terminated string for passphrase when PEM
+ * encrypted.
+ * @return New EC key object on success.
+ * @return NULL on error.
+ */
+WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_EC_PUBKEY(WOLFSSL_BIO* bio,
+ WOLFSSL_EC_KEY** out, wc_pem_password_cb* cb, void *pass)
+{
+ int err = 0;
+ WOLFSSL_EC_KEY* ec = NULL;
+ DerBuffer* der = NULL;
+ int keyFormat = 0;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_EC_PUBKEY");
+
+ /* Validate parameters. */
+ if (bio == NULL) {
+ err = 1;
+ }
+
+ if (!err) {
+ /* Create an empty EC key. */
+ ec = wolfSSL_EC_KEY_new();
+ if (ec == NULL) {
+ err = 1;
+ }
+ }
+ /* Read a PEM key in to a new DER buffer. */
+ if ((!err) && (pem_read_bio_key(bio, cb, pass, ECC_PUBLICKEY_TYPE,
+ &keyFormat, &der) <= 0)) {
+ err = 1;
+ }
+ /* Load the EC key with the public key from the DER encoding. */
+ if ((!err) && (wolfSSL_EC_KEY_LoadDer_ex(ec, der->buffer, (int)der->length,
+ WOLFSSL_EC_KEY_LOAD_PUBLIC) != 1)) {
+ WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_EC_KEY");
+ err = 1;
+ }
+
+ /* Dispose of dynamically allocated data not needed anymore. */
+ FreeDer(&der);
+ if (err) {
+ wolfSSL_EC_KEY_free(ec);
+ ec = NULL;
+ }
+
+ /* Return EC key through out if required. */
+ if ((out != NULL) && (ec != NULL)) {
+ *out = ec;
+ }
+ return ec;
+}
+
+/* Read a PEM encoded EC private key from a BIO.
+ *
+ * @param [in] bio BIO to read EC private key from.
+ * @param [out] out Pointer to return EC key object through. May be NULL.
+ * @param [in] cb Password callback when PEM encrypted.
+ * @param [in] pass NUL terminated string for passphrase when PEM
+ * encrypted.
+ * @return New EC key object on success.
+ * @return NULL on error.
+ */
+WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_ECPrivateKey(WOLFSSL_BIO* bio,
+ WOLFSSL_EC_KEY** out, wc_pem_password_cb* cb, void *pass)
+{
+ int err = 0;
+ WOLFSSL_EC_KEY* ec = NULL;
+ DerBuffer* der = NULL;
+ int keyFormat = 0;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_ECPrivateKey");
+
+ /* Validate parameters. */
+ if (bio == NULL) {
+ err = 1;
+ }
+
+ if (!err) {
+ /* Create an empty EC key. */
+ ec = wolfSSL_EC_KEY_new();
+ if (ec == NULL) {
+ err = 1;
+ }
+ }
+ /* Read a PEM key in to a new DER buffer.
+ * To check ENC EC PRIVATE KEY, it uses PRIVATEKEY_TYPE to call
+ * pem_read_bio_key(), and then check key format if it is EC.
+ */
+ if ((!err) && (pem_read_bio_key(bio, cb, pass, PRIVATEKEY_TYPE,
+ &keyFormat, &der) <= 0)) {
+ err = 1;
+ }
+ if (keyFormat != ECDSAk) {
+ WOLFSSL_ERROR_MSG("Error not EC key format");
+ err = 1;
+ }
+ /* Load the EC key with the private key from the DER encoding. */
+ if ((!err) && (wolfSSL_EC_KEY_LoadDer_ex(ec, der->buffer, (int)der->length,
+ WOLFSSL_EC_KEY_LOAD_PRIVATE) != 1)) {
+ WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_EC_KEY");
+ err = 1;
+ }
+
+ /* Dispose of dynamically allocated data not needed anymore. */
+ FreeDer(&der);
+ if (err) {
+ wolfSSL_EC_KEY_free(ec);
+ ec = NULL;
+ }
+
+ /* Return EC key through out if required. */
+ if ((out != NULL) && (ec != NULL)) {
+ *out = ec;
+ }
+ return ec;
+}
+#endif /* !NO_BIO */
+
+#if defined(WOLFSSL_KEY_GEN) && defined(HAVE_ECC_KEY_EXPORT)
+#ifndef NO_BIO
+/* Write out the EC public key as PEM to the BIO.
+ *
+ * @param [in] bio BIO to write PEM encoding to.
+ * @param [in] ec EC public key to encode.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int wolfSSL_PEM_write_bio_EC_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec)
+{
+ int ret = 1;
+ unsigned char* derBuf = NULL;
+ int derSz = 0;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_bio_EC_PUBKEY");
+
+ /* Validate parameters. */
+ if ((bio == NULL) || (ec == NULL)) {
+ WOLFSSL_MSG("Bad Function Arguments");
+ return 0;
+ }
+
+ /* Encode public key in EC key as DER. */
+ derSz = wolfssl_ec_key_to_pubkey_der(ec, &derBuf, ec->heap);
+ if (derSz == 0) {
+ ret = 0;
+ }
+
+ /* Write out to BIO the PEM encoding of the EC public key. */
+ if ((ret == 1) && (der_write_to_bio_as_pem(derBuf, derSz, bio,
+ ECC_PUBLICKEY_TYPE) != 1)) {
+ ret = 0;
+ }
+
+ /* Dispose of any dynamically allocated data. */
+ XFREE(derBuf, ec->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return ret;
+}
+
+/* Write out the EC private key as PEM to the BIO.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] bio BIO to write PEM encoding to.
+ * @param [in] ec EC private key to encode.
+ * @param [in] cipher Cipher to use when PEM encrypted. May be NULL.
+ * @param [in] passwd Password string when PEM encrypted. May be NULL.
+ * @param [in] passwdSz Length of password string when PEM encrypted.
+ * @param [in] cb Password callback when PEM encrypted. Unused.
+ * @param [in] pass NUL terminated string for passphrase when PEM
+ * encrypted. Unused.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec,
+ const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz,
+ wc_pem_password_cb* cb, void* arg)
+{
+ int ret = 1;
+ unsigned char* pem = NULL;
+ int pLen = 0;
+
+ (void)cb;
+ (void)arg;
+
+ /* Validate parameters. */
+ if ((bio == NULL) || (ec == NULL)) {
+ ret = 0;
+ }
+
+ /* Write EC private key to PEM. */
+ if ((ret == 1) && (wolfSSL_PEM_write_mem_ECPrivateKey(ec, cipher, passwd,
+ passwdSz, &pem, &pLen) != 1)) {
+ ret = 0;
+ }
+ /* Write PEM to BIO. */
+ if ((ret == 1) && (wolfSSL_BIO_write(bio, pem, pLen) != pLen)) {
+ WOLFSSL_ERROR_MSG("EC private key BIO write failed");
+ ret = 0;
+ }
+
+ XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+
+ return ret;
+}
+
+#endif /* !NO_BIO */
+
+/* Encode the EC private key as PEM into buffer.
+ *
+ * Return code compliant with OpenSSL.
+ * Not an OpenSSL API.
+ *
+ * @param [in] ec EC private key to encode.
+ * @param [in] cipher Cipher to use when PEM encrypted. May be NULL.
+ * @param [in] passwd Password string when PEM encrypted. May be NULL.
+ * @param [in] passwdSz Length of password string when PEM encrypted.
+ * @param [out] pem Newly allocated buffer holding PEM encoding.
+ * @param [out] pLen Length of PEM encoding in bytes.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ec,
+ const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz,
+ unsigned char **pem, int *pLen)
+{
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+ int ret = 1;
+ byte* derBuf = NULL;
+ word32 der_max_len = 0;
+ int derSz = 0;
+
+ WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey");
+
+ /* Validate parameters. */
+ if ((pem == NULL) || (pLen == NULL) || (ec == NULL) ||
+ (ec->internal == NULL)) {
+ WOLFSSL_MSG("Bad function arguments");
+ ret = 0;
+ }
+
+ /* Ensure internal EC key is set from external. */
+ if ((ret == 1) && (ec->inSet == 0)) {
+ WOLFSSL_MSG("No ECC internal set, do it");
+
+ if (SetECKeyInternal(ec) != 1) {
+ WOLFSSL_MSG("SetECKeyInternal failed");
+ ret = 0;
+ }
+ }
+
+ if (ret == 1) {
+ /* Calculate maximum size of DER encoding.
+ * 4 > size of pub, priv + ASN.1 additional information */
+ der_max_len = 4 * (word32)wc_ecc_size((ecc_key*)ec->internal) +
+ WC_AES_BLOCK_SIZE;
+
+ /* Allocate buffer big enough to hold encoding. */
+ derBuf = (byte*)XMALLOC((size_t)der_max_len, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (derBuf == NULL) {
+ WOLFSSL_MSG("malloc failed");
+ ret = 0;
+ }
+ }
+
+ if (ret == 1) {
+ /* Encode EC private key as DER. */
+ derSz = wc_EccKeyToDer((ecc_key*)ec->internal, derBuf, der_max_len);
+ if (derSz < 0) {
+ WOLFSSL_MSG("wc_EccKeyToDer failed");
+ XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
+ ret = 0;
+ }
+ }
+
+ /* Convert DER to PEM - possibly encrypting. */
+ if ((ret == 1) && (der_to_enc_pem_alloc(derBuf, derSz, cipher, passwd,
+ passwdSz, ECC_PRIVATEKEY_TYPE, NULL, pem, pLen) != 1)) {
+ WOLFSSL_ERROR_MSG("der_to_enc_pem_alloc failed");
+ ret = 0;
+ }
+
+ return ret;
+#else
+ (void)ec;
+ (void)cipher;
+ (void)passwd;
+ (void)passwdSz;
+ (void)pem;
+ (void)pLen;
+ return 0;
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+}
+
+#ifndef NO_FILESYSTEM
+/* Write out the EC private key as PEM to file.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] fp File pointer to write PEM encoding to.
+ * @param [in] ec EC private key to encode.
+ * @param [in] cipher Cipher to use when PEM encrypted. May be NULL.
+ * @param [in] passwd Password string when PEM encrypted. May be NULL.
+ * @param [in] passwdSz Length of password string when PEM encrypted.
+ * @param [in] cb Password callback when PEM encrypted. Unused.
+ * @param [in] pass NUL terminated string for passphrase when PEM
+ * encrypted. Unused.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *ec,
+ const WOLFSSL_EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz,
+ wc_pem_password_cb *cb, void *pass)
+{
+ int ret = 1;
+ byte *pem = NULL;
+ int pLen = 0;
+
+ (void)cb;
+ (void)pass;
+
+ WOLFSSL_MSG("wolfSSL_PEM_write_ECPrivateKey");
+
+ /* Validate parameters. */
+ if ((fp == XBADFILE) || (ec == NULL) || (ec->internal == NULL)) {
+ WOLFSSL_MSG("Bad function arguments");
+ ret = 0;
+ }
+
+ /* Write EC private key to PEM. */
+ if ((ret == 1) && (wolfSSL_PEM_write_mem_ECPrivateKey(ec, cipher, passwd,
+ passwdSz, &pem, &pLen) != 1)) {
+ WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed");
+ ret = 0;
+ }
+
+ /* Write out to file the PEM encoding of the EC private key. */
+ if ((ret == 1) && ((int)XFWRITE(pem, 1, (size_t)pLen, fp) != pLen)) {
+ WOLFSSL_MSG("ECC private key file write failed");
+ ret = 0;
+ }
+
+ /* Dispose of any dynamically allocated data. */
+ XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+
+ return ret;
+}
+
+#endif /* NO_FILESYSTEM */
+#endif /* WOLFSSL_KEY_GEN && HAVE_ECC_KEY_EXPORT */
+
+/*
+ * EC key print APIs
+ */
+
+#ifndef NO_CERTS
+
+#if defined(XFPRINTF) && !defined(NO_FILESYSTEM) && \
+ !defined(NO_STDIO_FILESYSTEM)
+/* Print the EC key to a file pointer as text.
+ *
+ * @param [in] fp File pointer.
+ * @param [in] key EC key to print.
+ * @param [in] indent Number of spaces to place before each line printed.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_EC_KEY_print_fp(XFILE fp, WOLFSSL_EC_KEY* key, int indent)
+{
+ int ret = 1;
+ int bits = 0;
+ int priv = 0;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_print_fp");
+
+ /* Validate parameters. */
+ if ((fp == XBADFILE) || (key == NULL) || (key->group == NULL) ||
+ (indent < 0)) {
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ /* Get EC groups order size in bits. */
+ bits = wolfSSL_EC_GROUP_order_bits(key->group);
+ if (bits <= 0) {
+ WOLFSSL_MSG("Failed to get group order bits.");
+ ret = 0;
+ }
+ }
+ if (ret == 1) {
+ const char* keyType;
+
+ /* Determine whether this is a private or public key. */
+ if ((key->priv_key != NULL) && (!wolfSSL_BN_is_zero(key->priv_key))) {
+ keyType = "Private-Key";
+ priv = 1;
+ }
+ else {
+ keyType = "Public-Key";
+ }
+
+ /* Print key header. */
+ if (XFPRINTF(fp, "%*s%s: (%d bit)\n", indent, "", keyType, bits) < 0) {
+ ret = 0;
+ }
+ }
+ if ((ret == 1) && priv) {
+ /* Print the private key BN. */
+ ret = pk_bn_field_print_fp(fp, indent, "priv", key->priv_key);
+ }
+ /* Check for public key data in EC key. */
+ if ((ret == 1) && (key->pub_key != NULL) && (key->pub_key->exSet)) {
+ /* Get the public key point as one BN. */
+ WOLFSSL_BIGNUM* pubBn = wolfSSL_EC_POINT_point2bn(key->group,
+ key->pub_key, WC_POINT_CONVERSION_UNCOMPRESSED, NULL, NULL);
+ if (pubBn == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_point2bn failed.");
+ ret = 0;
+ }
+ else {
+ /* Print the public key in a BN. */
+ ret = pk_bn_field_print_fp(fp, indent, "pub", pubBn);
+ wolfSSL_BN_free(pubBn);
+ }
+ }
+ if (ret == 1) {
+ /* Get the NID of the group. */
+ int nid = wolfSSL_EC_GROUP_get_curve_name(key->group);
+ if (nid > 0) {
+ /* Convert the NID into a long name and NIST name. */
+ const char* curve = wolfSSL_OBJ_nid2ln(nid);
+ const char* nistName = wolfSSL_EC_curve_nid2nist(nid);
+
+ /* Print OID name if known. */
+ if ((curve != NULL) &&
+ (XFPRINTF(fp, "%*sASN1 OID: %s\n", indent, "", curve) < 0)) {
+ ret = 0;
+ }
+ /* Print NIST curve name if known. */
+ if ((nistName != NULL) &&
+ (XFPRINTF(fp, "%*sNIST CURVE: %s\n", indent, "",
+ nistName) < 0)) {
+ ret = 0;
+ }
+ }
+ }
+
+
+ WOLFSSL_LEAVE("wolfSSL_EC_KEY_print_fp", ret);
+
+ return ret;
+}
+#endif /* XFPRINTF && !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */
+
+#endif /* !NO_CERTS */
+
+/*
+ * EC_KEY get/set/test APIs
+ */
+
+/* Set data of internal, wolfCrypt EC key object into EC key.
+ *
+ * EC_KEY wolfSSL -> OpenSSL
+ *
+ * @param [in, out] p EC key to update.
+ * @return 1 on success.
+ * @return -1 on failure.
+ */
+int SetECKeyExternal(WOLFSSL_EC_KEY* eckey)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("SetECKeyExternal");
+
+ /* Validate parameter. */
+ if ((eckey == NULL) || (eckey->internal == NULL)) {
+ WOLFSSL_MSG("ec key NULL error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ else {
+ ecc_key* key = (ecc_key*)eckey->internal;
+
+ /* Set group (OID, nid and idx) from wolfCrypt EC key. */
+ eckey->group->curve_oid = (int)key->dp->oidSum;
+ eckey->group->curve_nid = EccEnumToNID(key->dp->id);
+ eckey->group->curve_idx = key->idx;
+
+ if (eckey->pub_key->internal != NULL) {
+ /* Copy internal public point from internal key's public point. */
+ if (wc_ecc_copy_point(&key->pubkey,
+ (ecc_point*)eckey->pub_key->internal) != MP_OKAY) {
+ WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Set external public key from internal wolfCrypt, public key. */
+ if ((ret == 1) && (ec_point_external_set(eckey->pub_key) != 1)) {
+ WOLFSSL_MSG("SetECKeyExternal ec_point_external_set failed");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ /* set the external privkey */
+ if ((ret == 1) && (key->type == ECC_PRIVATEKEY) &&
+ (wolfssl_bn_set_value(&eckey->priv_key,
+ wc_ecc_key_get_priv(key)) != 1)) {
+ WOLFSSL_MSG("ec priv key error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ /* External values set when operations succeeded. */
+ eckey->exSet = (ret == 1);
+ }
+
+ return ret;
+}
+
+/* Set data of EC key into internal, wolfCrypt EC key object.
+ *
+ * EC_KEY Openssl -> WolfSSL
+ *
+ * @param [in, out] p EC key to update.
+ * @return 1 on success.
+ * @return -1 on failure.
+ */
+int SetECKeyInternal(WOLFSSL_EC_KEY* eckey)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("SetECKeyInternal");
+
+ /* Validate parameter. */
+ if ((eckey == NULL) || (eckey->internal == NULL) ||
+ (eckey->group == NULL)) {
+ WOLFSSL_MSG("ec key NULL error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ else {
+ ecc_key* key = (ecc_key*)eckey->internal;
+ int pubSet = 0;
+
+ /* Validate group. */
+ if ((eckey->group->curve_idx < 0) ||
+ (wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) {
+ WOLFSSL_MSG("invalid curve idx");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ if (ret == 1) {
+ /* Set group (idx of curve and corresponding domain parameters). */
+ key->idx = eckey->group->curve_idx;
+ key->dp = &ecc_sets[key->idx];
+ pubSet = (eckey->pub_key != NULL);
+ }
+ /* Set public key (point). */
+ if ((ret == 1) && pubSet) {
+ if (ec_point_internal_set(eckey->pub_key) != 1) {
+ WOLFSSL_MSG("ec key pub error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ /* Copy public point to key. */
+ if ((ret == 1) && (wc_ecc_copy_point(
+ (ecc_point*)eckey->pub_key->internal, &key->pubkey) !=
+ MP_OKAY)) {
+ WOLFSSL_MSG("wc_ecc_copy_point error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ if (ret == 1) {
+ /* Set that the internal key is a public key */
+ key->type = ECC_PUBLICKEY;
+ }
+ }
+
+ /* set privkey */
+ if ((ret == 1) && (eckey->priv_key != NULL)) {
+ if (wolfssl_bn_get_value(eckey->priv_key,
+ wc_ecc_key_get_priv(key)) != 1) {
+ WOLFSSL_MSG("ec key priv error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ /* private key */
+ if ((ret == 1) && (!mp_iszero(wc_ecc_key_get_priv(key)))) {
+ if (pubSet) {
+ key->type = ECC_PRIVATEKEY;
+ }
+ else {
+ key->type = ECC_PRIVATEKEY_ONLY;
+ }
+ }
+ }
+
+ /* Internal values set when operations succeeded. */
+ eckey->inSet = (ret == 1);
+ }
+
+ return ret;
+}
+
+/* Get point conversion format of EC key.
+ *
+ * @param [in] key EC key.
+ * @return Point conversion format on success.
+ * @return -1 on error.
+ */
+wc_point_conversion_form_t wolfSSL_EC_KEY_get_conv_form(
+ const WOLFSSL_EC_KEY* key)
+{
+ if (key == NULL)
+ return WOLFSSL_FATAL_ERROR;
+ return key->form;
+}
+
+/* Set point conversion format into EC key.
+ *
+ * @param [in, out] key EC key to set format into.
+ * @param [in] form Point conversion format. Valid values:
+ * WC_POINT_CONVERSION_UNCOMPRESSED,
+ * WC_POINT_CONVERSION_COMPRESSED (when HAVE_COMP_KEY)
+ */
+void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *key, int form)
+{
+ if (key == NULL) {
+ WOLFSSL_MSG("Key passed in NULL");
+ }
+ else if (form == WC_POINT_CONVERSION_UNCOMPRESSED
+#ifdef HAVE_COMP_KEY
+ || form == WC_POINT_CONVERSION_COMPRESSED
+#endif
+ ) {
+ key->form = (unsigned char)form;
+ }
+ else {
+ WOLFSSL_MSG("Incorrect form or HAVE_COMP_KEY not compiled in");
+ }
+}
+
+/* Get the EC group object that is in EC key.
+ *
+ * @param [in] key EC key.
+ * @return EC group object on success.
+ * @return NULL when key is NULL.
+ */
+const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key)
+{
+ WOLFSSL_EC_GROUP* group = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_group");
+
+ if (key != NULL) {
+ group = key->group;
+ }
+
+ return group;
+}
+
+/* Set the group in WOLFSSL_EC_KEY
+ *
+ * @param [in, out] key EC key to update.
+ * @param [in] group EC group to copy.
+ * @return 1 on success
+ * @return 0 on failure.
+ */
+int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group");
+
+ /* Validate parameters. */
+ if ((key == NULL) || (group == NULL)) {
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ /* Dispose of the current group. */
+ if (key->group != NULL) {
+ wolfSSL_EC_GROUP_free(key->group);
+ }
+ /* Duplicate the passed in group into EC key. */
+ key->group = wolfSSL_EC_GROUP_dup(group);
+ if (key->group == NULL) {
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+/* Get the BN object that is the private key in the EC key.
+ *
+ * @param [in] key EC key.
+ * @return BN object on success.
+ * @return NULL when key is NULL or private key is not set.
+ */
+WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key)
+{
+ WOLFSSL_BIGNUM* priv_key = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key");
+
+ /* Validate parameter. */
+ if (key == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_get0_private_key Bad arguments");
+ }
+ /* Only return private key if it is not 0. */
+ else if (!wolfSSL_BN_is_zero(key->priv_key)) {
+ priv_key = key->priv_key;
+ }
+
+ return priv_key;
+}
+
+/* Sets the private key value into EC key.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in, out] key EC key to set.
+ * @param [in] priv_key Private key value in a BN.
+ * @return 1 on success
+ * @return 0 on failure.
+ */
+int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key,
+ const WOLFSSL_BIGNUM *priv_key)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key");
+
+ /* Validate parameters. */
+ if ((key == NULL) || (priv_key == NULL)) {
+ WOLFSSL_MSG("Bad arguments");
+ ret = 0;
+ }
+
+ /* Check for obvious invalid values. */
+ if (wolfSSL_BN_is_negative(priv_key) || wolfSSL_BN_is_zero(priv_key) ||
+ wolfSSL_BN_is_one(priv_key)) {
+ WOLFSSL_MSG("Invalid private key value");
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ /* Free key if previously set. */
+ if (key->priv_key != NULL) {
+ wolfSSL_BN_free(key->priv_key);
+ }
+
+ /* Duplicate the BN passed in. */
+ key->priv_key = wolfSSL_BN_dup(priv_key);
+ if (key->priv_key == NULL) {
+ WOLFSSL_MSG("key ecc priv key NULL");
+ ret = 0;
+ }
+ }
+ /* Set the external values into internal EC key. */
+ if ((ret == 1) && (SetECKeyInternal(key) != 1)) {
+ WOLFSSL_MSG("SetECKeyInternal failed");
+ /* Dispose of new private key on error. */
+ wolfSSL_BN_free(key->priv_key);
+ key->priv_key = NULL;
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/* Get the public key EC point object that is in EC key.
+ *
+ * @param [in] key EC key.
+ * @return EC point object that is the public key on success.
+ * @return NULL when key is NULL.
+ */
+WOLFSSL_EC_POINT* wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key)
+{
+ WOLFSSL_EC_POINT* pub_key = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_public_key");
+
+ if (key != NULL) {
+ pub_key = key->pub_key;
+ }
+
+ return pub_key;
+}
+
+/*
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in, out] key EC key.
+ * @param [in] pub Public key as an EC point.
+ * @return 1 on success
+ * @return 0 on failure.
+ */
+int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key,
+ const WOLFSSL_EC_POINT *pub)
+{
+ int ret = 1;
+ ecc_point *pub_p = NULL;
+ ecc_point *key_p = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key");
+
+ /* Validate parameters. */
+ if ((key == NULL) || (key->internal == NULL) || (pub == NULL) ||
+ (pub->internal == NULL)) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_set_public_key Bad arguments");
+ ret = 0;
+ }
+
+ /* Ensure the internal EC key is set. */
+ if ((ret == 1) && (key->inSet == 0) && (SetECKeyInternal(key) != 1)) {
+ WOLFSSL_MSG("SetECKeyInternal failed");
+ ret = 0;
+ }
+
+ /* Ensure the internal EC point of pub is setup. */
+ if ((ret == 1) && (ec_point_setup(pub) != 1)) {
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ /* Get the internal point of pub and the public key in key. */
+ pub_p = (ecc_point*)pub->internal;
+ key_p = (ecc_point*)key->pub_key->internal;
+
+ /* Create new point if required. */
+ if (key_p == NULL) {
+ key_p = wc_ecc_new_point();
+ key->pub_key->internal = (void*)key_p;
+ }
+ /* Check point available. */
+ if (key_p == NULL) {
+ WOLFSSL_MSG("key ecc point NULL");
+ ret = 0;
+ }
+ }
+
+ /* Copy the internal pub point into internal key point. */
+ if ((ret == 1) && (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY)) {
+ WOLFSSL_MSG("ecc_copy_point failure");
+ ret = 0;
+ }
+
+ /* Copy the internal point data into external. */
+ if ((ret == 1) && (ec_point_external_set(key->pub_key) != 1)) {
+ WOLFSSL_MSG("SetECKeyInternal failed");
+ ret = 0;
+ }
+
+ /* Copy the internal key into external. */
+ if ((ret == 1) && (SetECKeyInternal(key) != 1)) {
+ WOLFSSL_MSG("SetECKeyInternal failed");
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ /* Dump out the point and the key's public key for debug. */
+ wolfSSL_EC_POINT_dump("pub", pub);
+ wolfSSL_EC_POINT_dump("key->pub_key", key->pub_key);
+ }
+
+ return ret;
+}
+
+#ifndef NO_WOLFSSL_STUB
+/* Set the ASN.1 encoding flag against the EC key.
+ *
+ * No implementation as only named curves supported for encoding.
+ *
+ * @param [in, out] key EC key.
+ * @param [in] flag ASN.1 flag to set. Valid values:
+ * OPENSSL_EC_EXPLICIT_CURVE, OPENSSL_EC_NAMED_CURVE
+ */
+void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag)
+{
+ (void)key;
+ (void)asn1_flag;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_set_asn1_flag");
+ WOLFSSL_STUB("EC_KEY_set_asn1_flag");
+}
+#endif
+
+/*
+ * EC key generate key APIs
+ */
+
+/* Generate an EC key.
+ *
+ * Uses the internal curve index set in the EC key or the default.
+ *
+ * @param [in, out] key EC key.
+ * @return 1 on success
+ * @return 0 on failure.
+ */
+int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key)
+{
+ int res = 1;
+ int initTmpRng = 0;
+ WC_RNG* rng = NULL;
+ WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key");
+
+ /* Validate parameters. */
+ if ((key == NULL) || (key->internal == NULL) || (key->group == NULL)) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key Bad arguments");
+ res = 0;
+ }
+ if (res == 1) {
+ /* Check if we know which internal curve index to use. */
+ if (key->group->curve_idx < 0) {
+ /* Generate key using the default curve. */
+#if FIPS_VERSION3_GE(6,0,0)
+ key->group->curve_idx = ECC_SECP256R1; /* FIPS default to 256 */
+#else
+ key->group->curve_idx = ECC_CURVE_DEF;
+#endif
+ }
+
+ /* Create a random number generator. */
+ rng = wolfssl_make_rng(tmpRng, &initTmpRng);
+ if (rng == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to make RNG");
+ res = 0;
+ }
+ }
+ if (res == 1) {
+ /* NIDToEccEnum returns -1 for invalid NID so if key->group->curve_nid
+ * is 0 then pass ECC_CURVE_DEF as arg */
+ int eccEnum = key->group->curve_nid ?
+#if FIPS_VERSION3_GE(6,0,0)
+ NIDToEccEnum(key->group->curve_nid) : ECC_SECP256R1;
+#else
+ NIDToEccEnum(key->group->curve_nid) : ECC_CURVE_DEF;
+#endif
+ /* Get the internal EC key. */
+ ecc_key* ecKey = (ecc_key*)key->internal;
+ /* Make the key using internal API. */
+ int ret = 0;
+
+#if FIPS_VERSION3_GE(6,0,0)
+ /* In the case of FIPS only allow key generation with approved curves */
+ if (eccEnum != ECC_SECP256R1 && eccEnum != ECC_SECP224R1 &&
+ eccEnum != ECC_SECP384R1 && eccEnum != ECC_SECP521R1) {
+ WOLFSSL_MSG("Unsupported curve selected in FIPS mode");
+ res = 0;
+ }
+ if (res == 1) {
+#endif
+ ret = wc_ecc_make_key_ex(rng, 0, ecKey, eccEnum);
+#if FIPS_VERSION3_GE(6,0,0)
+ }
+#endif
+
+ #if defined(WOLFSSL_ASYNC_CRYPT)
+ /* Wait on asynchronouse operation. */
+ ret = wc_AsyncWait(ret, &ecKey->asyncDev, WC_ASYNC_FLAG_NONE);
+ #endif
+ if (ret != 0) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed");
+ res = 0;
+ }
+ }
+
+ /* Dispose of local random number generator if initialized. */
+ if (initTmpRng) {
+ wc_FreeRng(rng);
+ WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG);
+ }
+
+ /* Set the external key from new internal key values. */
+ if ((res == 1) && (SetECKeyExternal(key) != 1)) {
+ WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed");
+ res = 0;
+ }
+
+ return res;
+}
+
+/*
+ * EC key check key APIs
+ */
+
+/* Check that the EC key is valid.
+ *
+ * @param [in] key EC key.
+ * @return 1 on valid.
+ * @return 0 on invalid or error.
+ */
+int wolfSSL_EC_KEY_check_key(const WOLFSSL_EC_KEY *key)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_check_key");
+
+ /* Validate parameter. */
+ if ((key == NULL) || (key->internal == NULL)) {
+ WOLFSSL_MSG("Bad parameter");
+ ret = 0;
+ }
+
+ /* Set the external EC key values into internal if not already. */
+ if ((ret == 1) && (key->inSet == 0) && (SetECKeyInternal(
+ (WOLFSSL_EC_KEY*)key) != 1)) {
+ WOLFSSL_MSG("SetECKeyInternal failed");
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ /* Have internal EC implementation check key. */
+ ret = wc_ecc_check_key((ecc_key*)key->internal) == 0;
+ }
+
+ return ret;
+}
+
+/* End EC_KEY */
+
+#if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)
+/* Get the supported, built-in EC curves
+ *
+ * @param [in, out] curves Pre-allocated list to put supported curves into.
+ * @param [in] len Maximum number of items to place in list.
+ * @return Number of built-in EC curves when curves is NULL or len is 0.
+ * @return Number of items placed in list otherwise.
+ */
+size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *curves,
+ size_t len)
+{
+ size_t i;
+ size_t cnt;
+#ifdef HAVE_SELFTEST
+ /* Defined in ecc.h when available. */
+ size_t ecc_sets_count;
+
+ /* Count the pre-defined curves since global not available. */
+ for (i = 0; ecc_sets[i].size != 0 && ecc_sets[i].name != NULL; i++) {
+ /* Do nothing. */
+ }
+ ecc_sets_count = i;
+#endif
+
+ /* Assume we are going to return total count. */
+ cnt = ecc_sets_count;
+ /* Check we have a list that can hold data. */
+ if ((curves != NULL) && (len != 0)) {
+ /* Limit count to length of list. */
+ if (cnt > len) {
+ cnt = len;
+ }
+
+ /* Put in built-in EC curve nid and short name. */
+ for (i = 0; i < cnt; i++) {
+ curves[i].nid = EccEnumToNID(ecc_sets[i].id);
+ curves[i].comment = wolfSSL_OBJ_nid2sn(curves[i].nid);
+ }
+ }
+
+ return cnt;
+}
+#endif /* !HAVE_FIPS || FIPS_VERSION_GT(2,0) */
+
+/* Start ECDSA_SIG */
+
+/* Allocate a new ECDSA signature object.
+ *
+ * @return New, allocated ECDSA signature object on success.
+ * @return NULL on error.
+ */
+WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void)
+{
+ int err = 0;
+ WOLFSSL_ECDSA_SIG *sig;
+
+ WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_new");
+
+ /* Allocate memory for ECDSA signature object. */
+ sig = (WOLFSSL_ECDSA_SIG*)XMALLOC(sizeof(WOLFSSL_ECDSA_SIG), NULL,
+ DYNAMIC_TYPE_ECC);
+ if (sig == NULL) {
+ WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA signature failure");
+ err = 1;
+ }
+
+ if (!err) {
+ /* Set s to NULL in case of error. */
+ sig->s = NULL;
+ /* Allocate BN into r. */
+ sig->r = wolfSSL_BN_new();
+ if (sig->r == NULL) {
+ WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA r failure");
+ err = 1;
+ }
+ }
+ if (!err) {
+ /* Allocate BN into s. */
+ sig->s = wolfSSL_BN_new();
+ if (sig->s == NULL) {
+ WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA s failure");
+ err = 1;
+ }
+ }
+
+ if (err && (sig != NULL)) {
+ /* Dispose of allocated memory. */
+ wolfSSL_ECDSA_SIG_free(sig);
+ sig = NULL;
+ }
+ return sig;
+}
+
+/* Dispose of ECDSA signature object.
+ *
+ * Cannot use object after this call.
+ *
+ * @param [in] sig ECDSA signature object to free.
+ */
+void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig)
+{
+ WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free");
+
+ if (sig != NULL) {
+ /* Dispose of BNs allocated for r and s. */
+ wolfSSL_BN_free(sig->r);
+ wolfSSL_BN_free(sig->s);
+
+ /* Dispose of memory associated with ECDSA signature object. */
+ XFREE(sig, NULL, DYNAMIC_TYPE_ECC);
+ }
+}
+
+/* Create an ECDSA signature from the DER encoding.
+ *
+ * @param [in, out] sig Reference to ECDSA signature object. May be NULL.
+ * @param [in, out] pp On in, reference to buffer containing DER encoding.
+ * On out, reference to buffer after signature data.
+ * @param [in] len Length of the data in the buffer. May be more than
+ * the length of the signature.
+ * @return ECDSA signature object on success.
+ * @return NULL on error.
+ */
+WOLFSSL_ECDSA_SIG* wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG** sig,
+ const unsigned char** pp, long len)
+{
+ int err = 0;
+ /* ECDSA signature object to return. */
+ WOLFSSL_ECDSA_SIG *s = NULL;
+
+ /* Validate parameter. */
+ if (pp == NULL) {
+ err = 1;
+ }
+ if (!err) {
+ if (sig != NULL) {
+ /* Use the ECDSA signature object passed in. */
+ s = *sig;
+ }
+ if (s == NULL) {
+ /* No ECDSA signature object passed in - create a new one. */
+ s = wolfSSL_ECDSA_SIG_new();
+ if (s == NULL) {
+ err = 1;
+ }
+ }
+ }
+ if (!err) {
+ /* DecodeECC_DSA_Sig calls mp_init, so free these. */
+ mp_free((mp_int*)s->r->internal);
+ mp_free((mp_int*)s->s->internal);
+
+ /* Decode the signature into internal r and s fields. */
+ if (DecodeECC_DSA_Sig(*pp, (word32)len, (mp_int*)s->r->internal,
+ (mp_int*)s->s->internal) != MP_OKAY) {
+ err = 1;
+ }
+ }
+
+ if (!err) {
+ /* Move pointer passed signature data successfully decoded. */
+ *pp += wolfssl_der_length(*pp, (int)len);
+ if (sig != NULL) {
+ /* Update reference to ECDSA signature object. */
+ *sig = s;
+ }
+ }
+
+ /* Dispose of newly allocated object on error. */
+ if (err) {
+ if ((s != NULL) && ((sig == NULL) || (*sig != s))) {
+ wolfSSL_ECDSA_SIG_free(s);
+ }
+ /* Return NULL for object on error. */
+ s = NULL;
+ }
+ return s;
+}
+
+/* Encode the ECDSA signature as DER.
+ *
+ * @param [in] sig ECDSA signature object.
+ * @param [in, out] pp On in, reference to buffer in which to place encoding.
+ * On out, reference to buffer after encoding.
+ * May be NULL or point to NULL in which case no encoding
+ * is done.
+ * @return Length of encoding on success.
+ * @return 0 on error.
+ */
+int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp)
+{
+ word32 len = 0;
+ int update_p = 1;
+
+ /* Validate parameter. */
+ if (sig != NULL) {
+ /* ASN.1: SEQ + INT + INT
+ * ASN.1 Integer must be a positive value - prepend zero if number has
+ * top bit set.
+ */
+ /* Get total length of r including any prepended zero. */
+ word32 rLen = (word32)(mp_leading_bit((mp_int*)sig->r->internal) +
+ mp_unsigned_bin_size((mp_int*)sig->r->internal));
+ /* Get total length of s including any prepended zero. */
+ word32 sLen = (word32)(mp_leading_bit((mp_int*)sig->s->internal) +
+ mp_unsigned_bin_size((mp_int*)sig->s->internal));
+ /* Calculate length of data in sequence. */
+ len = (word32)1 + ASN_LEN_SIZE(rLen) + rLen +
+ (word32)1 + ASN_LEN_SIZE(sLen) + sLen;
+ /* Add in the length of the SEQUENCE. */
+ len += (word32)1 + ASN_LEN_SIZE(len);
+
+ #ifdef WOLFSSL_I2D_ECDSA_SIG_ALLOC
+ if ((pp != NULL) && (*pp == NULL)) {
+ *pp = (unsigned char *)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (*pp != NULL) {
+ WOLFSSL_MSG("malloc error");
+ return 0;
+ }
+ update_p = 0;
+ }
+ #endif
+
+ /* Encode only if there is a buffer to encode into. */
+ if ((pp != NULL) && (*pp != NULL)) {
+ /* Encode using the internal representations of r and s. */
+ if (StoreECC_DSA_Sig(*pp, &len, (mp_int*)sig->r->internal,
+ (mp_int*)sig->s->internal) != MP_OKAY) {
+ /* No bytes encoded. */
+ len = 0;
+ }
+ else if (update_p) {
+ /* Update pointer to after encoding. */
+ *pp += len;
+ }
+ }
+ }
+
+ return (int)len;
+}
+
+/* Get the pointer to the fields of the ECDSA signature.
+ *
+ * r and s untouched when sig is NULL.
+ *
+ * @param [in] sig ECDSA signature object.
+ * @param [out] r R field of ECDSA signature as a BN. May be NULL.
+ * @param [out] s S field of ECDSA signature as a BN. May be NULL.
+ */
+void wolfSSL_ECDSA_SIG_get0(const WOLFSSL_ECDSA_SIG* sig,
+ const WOLFSSL_BIGNUM** r, const WOLFSSL_BIGNUM** s)
+{
+ /* Validate parameter. */
+ if (sig != NULL) {
+ /* Return the r BN when pointer to return through. */
+ if (r != NULL) {
+ *r = sig->r;
+ }
+ /* Return the s BN when pointer to return through. */
+ if (s != NULL) {
+ *s = sig->s;
+ }
+ }
+}
+
+/* Set the pointers to the fields of the ECDSA signature.
+ *
+ * @param [in, out] sig ECDSA signature object to update.
+ * @param [in] r R field of ECDSA signature as a BN.
+ * @param [in] s S field of ECDSA signature as a BN.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int wolfSSL_ECDSA_SIG_set0(WOLFSSL_ECDSA_SIG* sig, WOLFSSL_BIGNUM* r,
+ WOLFSSL_BIGNUM* s)
+{
+ int ret = 1;
+
+ /* Validate parameters. */
+ if ((sig == NULL) || (r == NULL) || (s == NULL)) {
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ /* Dispose of old BN objects. */
+ wolfSSL_BN_free(sig->r);
+ wolfSSL_BN_free(sig->s);
+
+ /* Assign new BN objects. */
+ sig->r = r;
+ sig->s = s;
+ }
+
+ return ret;
+}
+
+/* End ECDSA_SIG */
+
+/* Start ECDSA */
+
+/* Calculate maximum size of the DER encoded ECDSA signature for the curve.
+ *
+ * @param [in] key EC key.
+ * @return Size of DER encoded signature on success.
+ * @return 0 on error.
+ */
+int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key)
+{
+ int err = 0;
+ int len = 0;
+ const WOLFSSL_EC_GROUP *group = NULL;
+ int bits = 0;
+
+ /* Validate parameter. */
+ if (key == NULL) {
+ err = 1;
+ }
+
+ /* Get group from key to get order bits. */
+ if ((!err) && ((group = wolfSSL_EC_KEY_get0_group(key)) == NULL)) {
+ err = 1;
+ }
+ /* Get order bits of group. */
+ if ((!err) && ((bits = wolfSSL_EC_GROUP_order_bits(group)) == 0)) {
+ /* Group is not set. */
+ err = 1;
+ }
+
+ if (!err) {
+ /* r and s are mod order. */
+ int bytes = (bits + 7) / 8; /* Bytes needed to hold bits. */
+ len = SIG_HEADER_SZ + /* 2*ASN_TAG + 2*LEN(ENUM) */
+ ECC_MAX_PAD_SZ + /* possible leading zeroes in r and s */
+ bytes + bytes; /* max r and s in bytes */
+ }
+
+ return len;
+}
+
+/* Create ECDSA signature by signing digest with key.
+ *
+ * @param [in] dgst Digest to sign.
+ * @param [in] dLen Length of digest in bytes.
+ * @param [in] key EC key to sign with.
+ * @return ECDSA signature object on success.
+ * @return NULL on error.
+ */
+WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *dgst, int dLen,
+ WOLFSSL_EC_KEY *key)
+{
+ int err = 0;
+ WOLFSSL_ECDSA_SIG *sig = NULL;
+ WC_DECLARE_VAR(out, byte, ECC_BUFSIZE, 0);
+ unsigned int outLen = ECC_BUFSIZE;
+
+ WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign");
+
+ /* Validate parameters. */
+ if ((dgst == NULL) || (key == NULL) || (key->internal == NULL)) {
+ WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad arguments");
+ err = 1;
+ }
+
+ /* Ensure internal EC key is set from external. */
+ if ((!err) && (key->inSet == 0)) {
+ WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it");
+
+ if (SetECKeyInternal(key) != 1) {
+ WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed");
+ err = 1;
+ }
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ if (!err) {
+ /* Allocate buffer to hold encoded signature. */
+ out = (byte*)XMALLOC(outLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (out == NULL) {
+ err = 1;
+ }
+ }
+#endif
+
+ /* Sign the digest with the key to create encoded ECDSA signature. */
+ if ((!err) && (wolfSSL_ECDSA_sign(0, dgst, dLen, out, &outLen, key) != 1)) {
+ err = 1;
+ }
+
+ if (!err) {
+ const byte* p = out;
+ /* Decode the ECDSA signature into a new object. */
+ sig = wolfSSL_d2i_ECDSA_SIG(NULL, &p, outLen);
+ }
+
+ WC_FREE_VAR_EX(out, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return sig;
+}
+
+/* Verify ECDSA signature in the object using digest and key.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [in] dgst Digest to verify.
+ * @param [in] dLen Length of the digest in bytes.
+ * @param [in] sig ECDSA signature object.
+ * @param [in] key EC key containing public key.
+ * @return 1 when signature is valid.
+ * @return 0 when signature is invalid.
+ * @return -1 on error.
+ */
+int wolfSSL_ECDSA_do_verify(const unsigned char *dgst, int dLen,
+ const WOLFSSL_ECDSA_SIG *sig, WOLFSSL_EC_KEY *key)
+{
+ int ret = 1;
+ int verified = 0;
+#ifdef WOLF_CRYPTO_CB_ONLY_ECC
+ byte signature[ECC_MAX_SIG_SIZE];
+ int signatureLen;
+ byte* p = signature;
+#endif
+
+ WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify");
+
+ /* Validate parameters. */
+ if ((dgst == NULL) || (sig == NULL) || (key == NULL) ||
+ (key->internal == NULL)) {
+ WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Ensure internal EC key is set from external. */
+ if ((ret == 1) && (key->inSet == 0)) {
+ WOLFSSL_MSG("No EC key internal set, do it");
+
+ if (SetECKeyInternal(key) != 1) {
+ WOLFSSL_MSG("SetECKeyInternal failed");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ if (ret == 1) {
+#ifndef WOLF_CRYPTO_CB_ONLY_ECC
+ /* Verify hash using digest, r and s as MP ints and internal EC key. */
+ if (wc_ecc_verify_hash_ex((mp_int*)sig->r->internal,
+ (mp_int*)sig->s->internal, dgst, (word32)dLen, &verified,
+ (ecc_key *)key->internal) != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_verify_hash failed");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ else if (verified == 0) {
+ WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected");
+ ret = 0;
+ }
+#else
+ signatureLen = i2d_ECDSA_SIG(sig, &p);
+ if (signatureLen > 0) {
+ /* verify hash. expects to call wc_CryptoCb_EccVerify internally */
+ ret = wc_ecc_verify_hash(signature, signatureLen, dgst,
+ (word32)dLen, &verified, (ecc_key*)key->internal);
+ if (ret != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_verify_hash failed");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ else if (verified == 0) {
+ WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected");
+ ret = 0;
+ }
+ }
+#endif /* WOLF_CRYPTO_CB_ONLY_ECC */
+ }
+
+ return ret;
+}
+
+/* Sign the digest with the key to produce a DER encode signature.
+ *
+ * @param [in] type Digest algorithm used to create digest. Unused.
+ * @param [in] digest Digest of the message to sign.
+ * @param [in] digestSz Size of the digest in bytes.
+ * @param [out] sig Buffer to hold signature.
+ * @param [in, out] sigSz On in, size of buffer in bytes.
+ * On out, size of signatre in bytes.
+ * @param [in] key EC key containing private key.
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int wolfSSL_ECDSA_sign(int type, const unsigned char *digest, int digestSz,
+ unsigned char *sig, unsigned int *sigSz, WOLFSSL_EC_KEY *key)
+{
+ int ret = 1;
+ WC_RNG* rng = NULL;
+ WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
+ int initTmpRng = 0;
+
+ WOLFSSL_ENTER("wolfSSL_ECDSA_sign");
+
+ /* Digest algorithm not used in DER encoding. */
+ (void)type;
+
+ /* Validate parameters. */
+ if (key == NULL) {
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ /* Make an RNG - create local or get global. */
+ rng = wolfssl_make_rng(tmpRng, &initTmpRng);
+ if (rng == NULL) {
+ ret = 0;
+ }
+ }
+ /* Sign the digest with the key using the RNG and put signature into buffer
+ * update sigSz to be actual length.
+ */
+ if ((ret == 1) && (wc_ecc_sign_hash(digest, (word32)digestSz, sig, sigSz,
+ rng, (ecc_key*)key->internal) != 0)) {
+ ret = 0;
+ }
+
+ if (initTmpRng) {
+ wc_FreeRng(rng);
+ WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG);
+ }
+
+ return ret;
+}
+
+/* Verify the signature with the digest and key.
+ *
+ * @param [in] type Digest algorithm used to create digest. Unused.
+ * @param [in] digest Digest of the message to verify.
+ * @param [in] digestSz Size of the digest in bytes.
+ * @param [in] sig Buffer holding signature.
+ * @param [in] sigSz Size of signature data in bytes.
+ * @param [in] key EC key containing public key.
+ * @return 1 when signature is valid.
+ * @return 0 when signature is invalid or error.
+ */
+int wolfSSL_ECDSA_verify(int type, const unsigned char *digest, int digestSz,
+ const unsigned char *sig, int sigSz, WOLFSSL_EC_KEY *key)
+{
+ int ret = 1;
+ int verify = 0;
+
+ WOLFSSL_ENTER("wolfSSL_ECDSA_verify");
+
+ /* Digest algorithm not used in DER encoding. */
+ (void)type;
+
+ /* Validate parameters. */
+ if (key == NULL) {
+ ret = 0;
+ }
+
+ /* Verify signature using digest and key. */
+ if ((ret == 1) && (wc_ecc_verify_hash(sig, (word32)sigSz, digest,
+ (word32)digestSz, &verify, (ecc_key*)key->internal) != 0)) {
+ ret = 0;
+ }
+ /* When no error, verification may still have failed - check now. */
+ if ((ret == 1) && (verify != 1)) {
+ WOLFSSL_MSG("wolfSSL_ECDSA_verify failed");
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/* End ECDSA */
+
+/* Start ECDH */
+
+#ifndef WOLF_CRYPTO_CB_ONLY_ECC
+/* Compute the shared secret (key) using ECDH.
+ *
+ * KDF not supported.
+ *
+ * Return code compliant with OpenSSL.
+ *
+ * @param [out] out Buffer to hold key.
+ * @param [in] outLen Length of buffer in bytes.
+ * @param [in] pubKey Public key as an EC point.
+ * @param [in] privKey EC key holding a private key.
+ * @param [in] kdf Key derivation function to apply to secret.
+ * @return Length of computed key on success
+ * @return 0 on error.
+ */
+int wolfSSL_ECDH_compute_key(void *out, size_t outLen,
+ const WOLFSSL_EC_POINT *pubKey, WOLFSSL_EC_KEY *privKey,
+ void *(*kdf) (const void *in, size_t inlen, void *out, size_t *outLen))
+{
+ int err = 0;
+ word32 len = 0;
+ ecc_key* key = NULL;
+#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \
+ (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0))
+ int setGlobalRNG = 0;
+#endif
+
+ /* TODO: support using the KDF. */
+ (void)kdf;
+
+ WOLFSSL_ENTER("wolfSSL_ECDH_compute_key");
+
+ /* Validate parameters. */
+ if ((out == NULL) || (pubKey == NULL) || (pubKey->internal == NULL) ||
+ (privKey == NULL) || (privKey->internal == NULL)) {
+ WOLFSSL_MSG("Bad function arguments");
+ err = 1;
+ }
+
+ /* Ensure internal EC key is set from external. */
+ if ((!err) && (privKey->inSet == 0)) {
+ WOLFSSL_MSG("No EC key internal set, do it");
+
+ if (SetECKeyInternal(privKey) != 1) {
+ WOLFSSL_MSG("SetECKeyInternal failed");
+ err = 1;
+ }
+ }
+
+ if (!err) {
+ int ret;
+
+ /* Get the internal key. */
+ key = (ecc_key*)privKey->internal;
+ /* Set length into variable of type suitable for wolfSSL API. */
+ len = (word32)outLen;
+
+ #if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \
+ (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0))
+ /* An RNG is needed. */
+ if (key->rng == NULL) {
+ key->rng = wolfssl_make_global_rng();
+ /* RNG set and needs to be unset. */
+ setGlobalRNG = 1;
+ }
+ #endif
+
+ PRIVATE_KEY_UNLOCK();
+ /* Create secret using wolfSSL. */
+ ret = wc_ecc_shared_secret_ex(key, (ecc_point*)pubKey->internal,
+ (byte *)out, &len);
+ PRIVATE_KEY_LOCK();
+ if (ret != MP_OKAY) {
+ WOLFSSL_MSG("wc_ecc_shared_secret failed");
+ err = 1;
+ }
+ }
+
+#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \
+ (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0))
+ /* Remove global from key. */
+ if (setGlobalRNG) {
+ key->rng = NULL;
+ }
+#endif
+
+ if (err) {
+ /* Make returned value zero. */
+ len = 0;
+ }
+ return (int)len;
+}
+#endif /* WOLF_CRYPTO_CB_ONLY_ECC */
+
+/* End ECDH */
+
+#ifndef NO_WOLFSSL_STUB
+const WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_OpenSSL(void)
+{
+ WOLFSSL_STUB("wolfSSL_EC_KEY_OpenSSL");
+
+ return NULL;
+}
+
+WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_METHOD_new(
+ const WOLFSSL_EC_KEY_METHOD *meth)
+{
+ WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_new");
+
+ (void)meth;
+
+ return NULL;
+}
+
+void wolfSSL_EC_KEY_METHOD_free(WOLFSSL_EC_KEY_METHOD *meth)
+{
+ WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_free");
+
+ (void)meth;
+}
+
+void wolfSSL_EC_KEY_METHOD_set_init(WOLFSSL_EC_KEY_METHOD *meth,
+ void* a1, void* a2, void* a3, void* a4, void* a5, void* a6)
+{
+ WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_set_init");
+
+ (void)meth;
+ (void)a1;
+ (void)a2;
+ (void)a3;
+ (void)a4;
+ (void)a5;
+ (void)a6;
+}
+
+void wolfSSL_EC_KEY_METHOD_set_sign(WOLFSSL_EC_KEY_METHOD *meth,
+ void* a1, void* a2, void* a3)
+{
+ WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_set_sign");
+
+ (void)meth;
+ (void)a1;
+ (void)a2;
+ (void)a3;
+}
+
+const WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_get_method(
+ const WOLFSSL_EC_KEY *key)
+{
+ WOLFSSL_STUB("wolfSSL_EC_KEY_get_method");
+
+ (void)key;
+
+ return NULL;
+}
+
+int wolfSSL_EC_KEY_set_method(WOLFSSL_EC_KEY *key,
+ const WOLFSSL_EC_KEY_METHOD *meth)
+{
+ WOLFSSL_STUB("wolfSSL_EC_KEY_set_method");
+
+ (void)key;
+ (void)meth;
+
+ return 0;
+}
+
+#endif /* !NO_WOLFSSL_STUB */
+
+#endif /* OPENSSL_EXTRA */
+
+#endif /* HAVE_ECC */
+
+/*******************************************************************************
+ * END OF EC API
+ ******************************************************************************/
+
+#endif /* !WOLFSSL_PK_EC_INCLUDED */
+
diff --git a/src/pk_rsa.c b/src/pk_rsa.c
new file mode 100644
index 0000000000..abef08bf8d
--- /dev/null
+++ b/src/pk_rsa.c
@@ -0,0 +1,3943 @@
+/* pk_rsa.c
+ *
+ * Copyright (C) 2006-2025 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#include
+
+#include
+#ifndef WC_NO_RNG
+ #include
+#endif
+
+#if !defined(WOLFSSL_PK_RSA_INCLUDED)
+ #ifndef WOLFSSL_IGNORE_FILE_WARN
+ #warning pk_rsa.c does not need to be compiled separately from ssl.c
+ #endif
+#else
+
+#ifndef NO_RSA
+ #include
+#endif
+
+/*******************************************************************************
+ * START OF RSA API
+ ******************************************************************************/
+
+#ifndef NO_RSA
+
+/*
+ * RSA METHOD
+ * Could be used to hold function pointers to implementations of RSA operations.
+ */
+
+#if defined(OPENSSL_EXTRA)
+/* Return a blank RSA method and set the name and flags.
+ *
+ * Only one implementation of RSA operations.
+ * name is duplicated.
+ *
+ * @param [in] name Name to use in method.
+ * @param [in] flags Flags to set into method.
+ * @return Newly allocated RSA method on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_RSA_METHOD *wolfSSL_RSA_meth_new(const char *name, int flags)
+{
+ WOLFSSL_RSA_METHOD* meth = NULL;
+ int name_len = 0;
+ int err;
+
+ /* Validate name is not NULL. */
+ if (name == NULL)
+ return NULL;
+ /* Allocate an RSA METHOD to return. */
+ meth = (WOLFSSL_RSA_METHOD*)XMALLOC(sizeof(WOLFSSL_RSA_METHOD), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (meth == NULL)
+ return NULL;
+
+ XMEMSET(meth, 0, sizeof(*meth));
+ meth->flags = flags;
+ meth->dynamic = 1;
+
+ name_len = (int)XSTRLEN(name);
+ meth->name = (char*)XMALLOC((size_t)(name_len + 1), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ err = (meth->name == NULL);
+
+ if (!err) {
+ XMEMCPY(meth->name, name, (size_t)(name_len + 1));
+ }
+
+ if (err) {
+ /* meth->name won't be allocated on error. */
+ XFREE(meth, NULL, DYNAMIC_TYPE_OPENSSL);
+ meth = NULL;
+ }
+ return meth;
+}
+
+/* Default RSA method is one with wolfSSL name and no flags.
+ *
+ * @return Newly allocated wolfSSL RSA method on success.
+ * @return NULL on failure.
+ */
+const WOLFSSL_RSA_METHOD* wolfSSL_RSA_get_default_method(void)
+{
+ static const WOLFSSL_RSA_METHOD wolfssl_rsa_meth = {
+ 0, /* No flags. */
+ (char*)"wolfSSL RSA",
+ 0 /* Static definition. */
+ };
+ return &wolfssl_rsa_meth;
+}
+
+/* Dispose of RSA method and allocated data.
+ *
+ * @param [in] meth RSA method to free.
+ */
+void wolfSSL_RSA_meth_free(WOLFSSL_RSA_METHOD *meth)
+{
+ /* Free method if available and dynamically allocated. */
+ if ((meth != NULL) && meth->dynamic) {
+ /* Name was duplicated and must be freed. */
+ XFREE(meth->name, NULL, DYNAMIC_TYPE_OPENSSL);
+ /* Dispose of RSA method. */
+ XFREE(meth, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+}
+
+#ifndef NO_WOLFSSL_STUB
+/* Stub function for any RSA method setting function.
+ *
+ * Nothing is stored - not even flags or name.
+ *
+ * @param [in] meth RSA method.
+ * @param [in] p A pointer.
+ * @return 1 to indicate success.
+ */
+int wolfSSL_RSA_meth_set(WOLFSSL_RSA_METHOD *meth, void* p)
+{
+ WOLFSSL_STUB("RSA_METHOD is not implemented.");
+
+ (void)meth;
+ (void)p;
+
+ return 1;
+}
+#endif /* !NO_WOLFSSL_STUB */
+#endif /* OPENSSL_EXTRA */
+
+/*
+ * RSA constructor/deconstructor APIs
+ */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* Dispose of RSA key and allocated data.
+ *
+ * Cannot use rsa after this call.
+ *
+ * @param [in] rsa RSA key to free.
+ */
+void wolfSSL_RSA_free(WOLFSSL_RSA* rsa)
+{
+ int doFree = 1;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_free");
+
+ /* Validate parameter. */
+ if (rsa == NULL) {
+ doFree = 0;
+ }
+ if (doFree) {
+ int err;
+
+ /* Decrement reference count. */
+ wolfSSL_RefDec(&rsa->ref, &doFree, &err);
+ #ifndef WOLFSSL_REFCNT_ERROR_RETURN
+ (void)err;
+ #endif
+ }
+ if (doFree) {
+ void* heap = rsa->heap;
+
+ /* Dispose of allocated reference counting data. */
+ wolfSSL_RefFree(&rsa->ref);
+
+ #ifdef HAVE_EX_DATA_CLEANUP_HOOKS
+ wolfSSL_CRYPTO_cleanup_ex_data(&rsa->ex_data);
+ #endif
+
+ if (rsa->internal != NULL) {
+ #if !defined(HAVE_FIPS) && defined(WC_RSA_BLINDING)
+ /* Check if RNG is owned before freeing it. */
+ if (rsa->ownRng) {
+ WC_RNG* rng = ((RsaKey*)(rsa->internal))->rng;
+ if ((rng != NULL) && (rng != wolfssl_get_global_rng())) {
+ wc_FreeRng(rng);
+ XFREE(rng, heap, DYNAMIC_TYPE_RNG);
+ }
+ /* RNG isn't freed by wolfCrypt RSA free. */
+ }
+ #endif
+ /* Dispose of allocated data in wolfCrypt RSA key. */
+ wc_FreeRsaKey((RsaKey*)rsa->internal);
+ /* Dispose of memory for wolfCrypt RSA key. */
+ XFREE(rsa->internal, heap, DYNAMIC_TYPE_RSA);
+ }
+
+ /* Dispose of external representation of RSA values. */
+ wolfSSL_BN_clear_free(rsa->iqmp);
+ wolfSSL_BN_clear_free(rsa->dmq1);
+ wolfSSL_BN_clear_free(rsa->dmp1);
+ wolfSSL_BN_clear_free(rsa->q);
+ wolfSSL_BN_clear_free(rsa->p);
+ wolfSSL_BN_clear_free(rsa->d);
+ wolfSSL_BN_free(rsa->e);
+ wolfSSL_BN_free(rsa->n);
+
+ #if defined(OPENSSL_EXTRA)
+ if (rsa->meth) {
+ wolfSSL_RSA_meth_free((WOLFSSL_RSA_METHOD*)rsa->meth);
+ }
+ #endif
+
+ /* Set back to NULLs for safety. */
+ ForceZero(rsa, sizeof(*rsa));
+
+ XFREE(rsa, heap, DYNAMIC_TYPE_RSA);
+ (void)heap;
+ }
+}
+
+/* Allocate and initialize a new RSA key.
+ *
+ * Not OpenSSL API.
+ *
+ * @param [in] heap Heap hint for dynamic memory allocation.
+ * @param [in] devId Device identifier value.
+ * @return RSA key on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_RSA* wolfSSL_RSA_new_ex(void* heap, int devId)
+{
+ WOLFSSL_RSA* rsa = NULL;
+ RsaKey* key = NULL;
+ int err = 0;
+ int rsaKeyInited = 0;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_new");
+
+ /* Allocate memory for new wolfCrypt RSA key. */
+ key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA);
+ if (key == NULL) {
+ WOLFSSL_ERROR_MSG("wolfSSL_RSA_new malloc RsaKey failure");
+ err = 1;
+ }
+ if (!err) {
+ /* Allocate memory for new RSA key. */
+ rsa = (WOLFSSL_RSA*)XMALLOC(sizeof(WOLFSSL_RSA), heap,
+ DYNAMIC_TYPE_RSA);
+ if (rsa == NULL) {
+ WOLFSSL_ERROR_MSG("wolfSSL_RSA_new malloc WOLFSSL_RSA failure");
+ err = 1;
+ }
+ }
+ if (!err) {
+ /* Clear all fields of RSA key. */
+ XMEMSET(rsa, 0, sizeof(WOLFSSL_RSA));
+ /* Cache heap to use for all allocations. */
+ rsa->heap = heap;
+ #ifdef OPENSSL_EXTRA
+ /* Always have a method set. */
+ rsa->meth = wolfSSL_RSA_get_default_method();
+ #endif
+
+ /* Initialize reference counting. */
+ wolfSSL_RefInit(&rsa->ref, &err);
+#ifdef WOLFSSL_REFCNT_ERROR_RETURN
+ }
+ if (!err) {
+#endif
+ /* Initialize wolfCrypt RSA key. */
+ if (wc_InitRsaKey_ex(key, heap, devId) != 0) {
+ WOLFSSL_ERROR_MSG("InitRsaKey WOLFSSL_RSA failure");
+ err = 1;
+ }
+ else {
+ rsaKeyInited = 1;
+ }
+ }
+ #if !defined(HAVE_FIPS) && defined(WC_RSA_BLINDING)
+ if (!err) {
+ WC_RNG* rng;
+
+ /* Create a local RNG. */
+ rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), heap, DYNAMIC_TYPE_RNG);
+ if ((rng != NULL) && (wc_InitRng_ex(rng, heap, devId) != 0)) {
+ WOLFSSL_MSG("InitRng failure, attempting to use global RNG");
+ XFREE(rng, heap, DYNAMIC_TYPE_RNG);
+ rng = NULL;
+ }
+
+ rsa->ownRng = 1;
+ if (rng == NULL) {
+ /* Get the wolfSSL global RNG - not thread safe. */
+ rng = wolfssl_get_global_rng();
+ rsa->ownRng = 0;
+ }
+ if (rng == NULL) {
+ /* Couldn't create global either. */
+ WOLFSSL_ERROR_MSG("wolfSSL_RSA_new no WC_RNG for blinding");
+ err = 1;
+ }
+ else {
+ /* Set the local or global RNG into the wolfCrypt RSA key. */
+ (void)wc_RsaSetRNG(key, rng);
+ /* Won't fail as key and rng are not NULL. */
+ }
+ }
+ #endif /* !HAVE_FIPS && WC_RSA_BLINDING */
+ if (!err) {
+ /* Set wolfCrypt RSA key into RSA key. */
+ rsa->internal = key;
+ /* Data from external RSA key has not been set into internal one. */
+ rsa->inSet = 0;
+ }
+
+ if (err) {
+ /* Dispose of any allocated data on error. */
+ /* No failure after RNG allocation - no need to free RNG. */
+ if (rsaKeyInited) {
+ wc_FreeRsaKey(key);
+ }
+ XFREE(key, heap, DYNAMIC_TYPE_RSA);
+ XFREE(rsa, heap, DYNAMIC_TYPE_RSA);
+ /* Return NULL. */
+ rsa = NULL;
+ }
+ return rsa;
+}
+
+/* Allocate and initialize a new RSA key.
+ *
+ * @return RSA key on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_RSA* wolfSSL_RSA_new(void)
+{
+ /* Call wolfSSL API to do work. */
+ return wolfSSL_RSA_new_ex(NULL, INVALID_DEVID);
+}
+
+/* Increments ref count of RSA key.
+ *
+ * @param [in, out] rsa RSA key.
+ * @return 1 on success
+ * @return 0 on error
+ */
+int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa)
+{
+ int err = 0;
+ if (rsa != NULL) {
+ wolfSSL_RefInc(&rsa->ref, &err);
+ }
+ return !err;
+}
+
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+#ifdef OPENSSL_EXTRA
+
+#if defined(WOLFSSL_KEY_GEN)
+
+/* Allocate a new RSA key and make it a copy.
+ *
+ * Encodes to and from DER to copy.
+ *
+ * @param [in] rsa RSA key to duplicate.
+ * @return RSA key on success.
+ * @return NULL on error.
+ */
+WOLFSSL_RSA* wolfSSL_RSAPublicKey_dup(WOLFSSL_RSA *rsa)
+{
+ WOLFSSL_RSA* ret = NULL;
+ int derSz = 0;
+ byte* derBuf = NULL;
+ int err;
+
+ WOLFSSL_ENTER("wolfSSL_RSAPublicKey_dup");
+
+ err = (rsa == NULL);
+ if (!err) {
+ /* Create a new RSA key to return. */
+ ret = wolfSSL_RSA_new();
+ if (ret == NULL) {
+ WOLFSSL_ERROR_MSG("Error creating a new WOLFSSL_RSA structure");
+ err = 1;
+ }
+ }
+ if (!err) {
+ /* Encode RSA public key to copy to DER - allocates DER buffer. */
+ if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 1, rsa->heap)) < 0) {
+ WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
+ err = 1;
+ }
+ }
+ if (!err) {
+ /* Decode DER of the RSA public key into new key. */
+ if (wolfSSL_RSA_LoadDer_ex(ret, derBuf, derSz,
+ WOLFSSL_RSA_LOAD_PUBLIC) != 1) {
+ WOLFSSL_ERROR_MSG("wolfSSL_RSA_LoadDer_ex failed");
+ err = 1;
+ }
+ }
+
+ /* Dispose of any allocated DER buffer. */
+ XFREE(derBuf, rsa ? rsa->heap : NULL, DYNAMIC_TYPE_ASN1);
+ if (err) {
+ /* Disposes of any created RSA key - on error. */
+ wolfSSL_RSA_free(ret);
+ ret = NULL;
+ }
+ return ret;
+}
+
+/* wolfSSL_RSAPrivateKey_dup not supported */
+
+#endif /* WOLFSSL_KEY_GEN */
+
+static int wolfSSL_RSA_To_Der_ex(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey,
+ void* heap);
+
+/*
+ * RSA to/from bin APIs
+ */
+
+/* Convert RSA public key data to internal.
+ *
+ * Creates new RSA key from the DER encoded RSA public key.
+ *
+ * @param [out] out Pointer to RSA key to return through. May be NULL.
+ * @param [in, out] derBuf Pointer to start of DER encoded data.
+ * @param [in] derSz Length of the data in the DER buffer.
+ * @return RSA key on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_RSA *wolfSSL_d2i_RSAPublicKey(WOLFSSL_RSA **out,
+ const unsigned char **derBuf, long derSz)
+{
+ WOLFSSL_RSA *rsa = NULL;
+ int err = 0;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_RSAPublicKey");
+
+ /* Validate parameters. */
+ if (derBuf == NULL) {
+ WOLFSSL_ERROR_MSG("Bad argument");
+ err = 1;
+ }
+ /* Create a new RSA key to return. */
+ if ((!err) && ((rsa = wolfSSL_RSA_new()) == NULL)) {
+ WOLFSSL_ERROR_MSG("RSA_new failed");
+ err = 1;
+ }
+ /* Decode RSA key from DER. */
+ if ((!err) && (wolfSSL_RSA_LoadDer_ex(rsa, *derBuf, (int)derSz,
+ WOLFSSL_RSA_LOAD_PUBLIC) != 1)) {
+ WOLFSSL_ERROR_MSG("RSA_LoadDer failed");
+ err = 1;
+ }
+ if ((!err) && (out != NULL)) {
+ /* Return through parameter too. */
+ *out = rsa;
+ /* Move buffer on by the used amount. */
+ *derBuf += wolfssl_der_length(*derBuf, (int)derSz);
+ }
+
+ if (err) {
+ /* Dispose of any created RSA key. */
+ wolfSSL_RSA_free(rsa);
+ rsa = NULL;
+ }
+ return rsa;
+}
+
+/* Convert RSA private key data to internal.
+ *
+ * Create a new RSA key from the DER encoded RSA private key.
+ *
+ * @param [out] out Pointer to RSA key to return through. May be NULL.
+ * @param [in, out] derBuf Pointer to start of DER encoded data.
+ * @param [in] derSz Length of the data in the DER buffer.
+ * @return RSA key on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_RSA *wolfSSL_d2i_RSAPrivateKey(WOLFSSL_RSA **out,
+ const unsigned char **derBuf, long derSz)
+{
+ WOLFSSL_RSA *rsa = NULL;
+ int err = 0;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_RSAPublicKey");
+
+ /* Validate parameters. */
+ if (derBuf == NULL) {
+ WOLFSSL_ERROR_MSG("Bad argument");
+ err = 1;
+ }
+ /* Create a new RSA key to return. */
+ if ((!err) && ((rsa = wolfSSL_RSA_new()) == NULL)) {
+ WOLFSSL_ERROR_MSG("RSA_new failed");
+ err = 1;
+ }
+ /* Decode RSA key from DER. */
+ if ((!err) && (wolfSSL_RSA_LoadDer_ex(rsa, *derBuf, (int)derSz,
+ WOLFSSL_RSA_LOAD_PRIVATE) != 1)) {
+ WOLFSSL_ERROR_MSG("RSA_LoadDer failed");
+ err = 1;
+ }
+ if ((!err) && (out != NULL)) {
+ /* Return through parameter too. */
+ *out = rsa;
+ /* Move buffer on by the used amount. */
+ *derBuf += wolfssl_der_length(*derBuf, (int)derSz);
+ }
+
+ if (err) {
+ /* Dispose of any created RSA key. */
+ wolfSSL_RSA_free(rsa);
+ rsa = NULL;
+ }
+ return rsa;
+}
+
+/* Converts an internal RSA structure to DER format for the private key.
+ *
+ * If "pp" is null then buffer size only is returned.
+ * If "*pp" is null then a created buffer is set in *pp and the caller is
+ * responsible for free'ing it.
+ *
+ * @param [in] rsa RSA key.
+ * @param [in, out] pp On in, pointer to allocated buffer or NULL.
+ * May be NULL.
+ * On out, newly allocated buffer or pointer to byte after
+ * encoding in passed in buffer.
+ *
+ * @return Size of DER encoding on success
+ * @return BAD_FUNC_ARG when rsa is NULL.
+ * @return 0 on failure.
+ */
+int wolfSSL_i2d_RSAPrivateKey(WOLFSSL_RSA *rsa, unsigned char **pp)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_i2d_RSAPrivateKey");
+
+ /* Validate parameters. */
+ if (rsa == NULL) {
+ WOLFSSL_ERROR_MSG("Bad Function Arguments");
+ ret = BAD_FUNC_ARG;
+ }
+ /* Encode the RSA key as a DER. Call allocates buffer into pp.
+ * No heap hint as this gets returned to the user */
+ else if ((ret = wolfSSL_RSA_To_Der_ex(rsa, pp, 0, NULL)) < 0) {
+ WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
+ ret = 0;
+ }
+
+ /* Size of DER encoding. */
+ return ret;
+}
+
+/* Converts an internal RSA structure to DER format for the public key.
+ *
+ * If "pp" is null then buffer size only is returned.
+ * If "*pp" is null then a created buffer is set in *pp and the caller is
+ * responsible for free'ing it.
+ *
+ * @param [in] rsa RSA key.
+ * @param [in, out] pp On in, pointer to allocated buffer or NULL.
+ * May be NULL.
+ * On out, newly allocated buffer or pointer to byte after
+ * encoding in passed in buffer.
+ * @return Size of DER encoding on success
+ * @return BAD_FUNC_ARG when rsa is NULL.
+ * @return 0 on failure.
+ */
+int wolfSSL_i2d_RSAPublicKey(WOLFSSL_RSA *rsa, unsigned char **pp)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_i2d_RSAPublicKey");
+
+ /* check for bad functions arguments */
+ if (rsa == NULL) {
+ WOLFSSL_ERROR_MSG("Bad Function Arguments");
+ ret = BAD_FUNC_ARG;
+ }
+ /* Encode the RSA key as a DER. Call allocates buffer into pp.
+ * No heap hint as this gets returned to the user */
+ else if ((ret = wolfSSL_RSA_To_Der_ex(rsa, pp, 1, NULL)) < 0) {
+ WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
+ ret = 0;
+ }
+
+ return ret;
+}
+
+#endif /* OPENSSL_EXTRA */
+
+/*
+ * RSA to/from BIO APIs
+ */
+
+/* wolfSSL_d2i_RSAPublicKey_bio not supported */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \
+ || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT)
+
+#if defined(WOLFSSL_KEY_GEN) && !defined(NO_BIO)
+
+/* Read DER data from a BIO.
+ *
+ * DER structures start with a constructed sequence. Use this to calculate the
+ * total length of the DER data.
+ *
+ * @param [in] bio BIO object to read from.
+ * @param [out] out Buffer holding DER encoding.
+ * @return Number of bytes to DER encoding on success.
+ * @return 0 on failure.
+ */
+static int wolfssl_read_der_bio(WOLFSSL_BIO* bio, unsigned char** out)
+{
+ int err = 0;
+ unsigned char seq[MAX_SEQ_SZ];
+ unsigned char* der = NULL;
+ int derLen = 0;
+
+ /* Read in a minimal amount to get a SEQUENCE header of any size. */
+ if (wolfSSL_BIO_read(bio, seq, sizeof(seq)) != sizeof(seq)) {
+ WOLFSSL_ERROR_MSG("wolfSSL_BIO_read() of sequence failure");
+ err = 1;
+ }
+ /* Calculate complete DER encoding length. */
+ if ((!err) && ((derLen = wolfssl_der_length(seq, sizeof(seq))) <= 0)) {
+ WOLFSSL_ERROR_MSG("DER SEQUENCE decode failed");
+ err = 1;
+ }
+ /* Allocate a buffer to read DER data into. */
+ if ((!err) && ((der = (unsigned char*)XMALLOC((size_t)derLen, bio->heap,
+ DYNAMIC_TYPE_TMP_BUFFER)) == NULL)) {
+ WOLFSSL_ERROR_MSG("Malloc failure");
+ err = 1;
+ }
+ if ((!err) && (derLen <= (int)sizeof(seq))) {
+ /* Copy the previously read data into the buffer. */
+ XMEMCPY(der, seq, derLen);
+ }
+ else if (!err) {
+ /* Calculate the unread amount. */
+ int len = derLen - (int)sizeof(seq);
+ /* Copy the previously read data into the buffer. */
+ XMEMCPY(der, seq, sizeof(seq));
+ /* Read rest of DER data from BIO. */
+ if (wolfSSL_BIO_read(bio, der + sizeof(seq), len) != len) {
+ WOLFSSL_ERROR_MSG("wolfSSL_BIO_read() failure");
+ err = 1;
+ }
+ }
+ if (!err) {
+ /* Return buffer through parameter. */
+ *out = der;
+ }
+
+ if (err) {
+ /* Dispose of any allocated buffer on error. */
+ XFREE(der, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ derLen = 0;
+ }
+ return derLen;
+}
+
+/* Reads the RSA private key data from a BIO to the internal form.
+ *
+ * Creates new RSA key from the DER encoded RSA private key read from the BIO.
+ *
+ * @param [in] bio BIO object to read from.
+ * @param [out] out Pointer to RSA key to return through. May be NULL.
+ * @return RSA key on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out)
+{
+ WOLFSSL_RSA* key = NULL;
+ unsigned char* der = NULL;
+ int derLen = 0;
+ int err;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_RSAPrivateKey_bio");
+
+ /* Validate parameters. */
+ err = (bio == NULL);
+ /* Read just DER encoding from BIO - buffer allocated in call. */
+ if ((!err) && ((derLen = wolfssl_read_der_bio(bio, &der)) == 0)) {
+ err = 1;
+ }
+ if (!err) {
+ /* Keep der for call to deallocate. */
+ const unsigned char* cder = der;
+ /* Create an RSA key from the data from the BIO. */
+ key = wolfSSL_d2i_RSAPrivateKey(NULL, &cder, derLen);
+ err = (key == NULL);
+ }
+ if ((!err) && (out != NULL)) {
+ /* Return the created RSA key through the parameter. */
+ *out = key;
+ }
+
+ if (err) {
+ /* Dispose of created key on error. */
+ wolfSSL_RSA_free(key);
+ key = NULL;
+ }
+ /* Dispose of allocated data. */
+ XFREE(der, bio ? bio->heap : NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return key;
+}
+#endif /* defined(WOLFSSL_KEY_GEN) && !NO_BIO */
+
+#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT */
+
+/*
+ * RSA DER APIs
+ */
+
+#ifdef OPENSSL_EXTRA
+
+/* Create a DER encoding of key.
+ *
+ * Not OpenSSL API.
+ *
+ * @param [in] rsa RSA key.
+ * @param [out] outBuf Allocated buffer containing DER encoding.
+ * May be NULL.
+ * @param [in] publicKey Whether to encode as public key.
+ * @param [in] heap Heap hint.
+ * @return Encoding size on success.
+ * @return Negative on failure.
+ */
+int wolfSSL_RSA_To_Der(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey,
+ void* heap)
+{
+ byte* p = NULL;
+ int ret;
+
+ if (outBuf != NULL) {
+ p = *outBuf;
+ }
+ ret = wolfSSL_RSA_To_Der_ex(rsa, outBuf, publicKey, heap);
+ if ((ret > 0) && (p != NULL)) {
+ *outBuf = p;
+ }
+ return ret;
+}
+
+/* Create a DER encoding of key.
+ *
+ * Buffer allocated with heap and DYNAMIC_TYPE_TMP_BUFFER.
+ *
+ * @param [in] rsa RSA key.
+ * @param [in, out] outBuf On in, pointer to allocated buffer or NULL.
+ * May be NULL.
+ * On out, newly allocated buffer or pointer to byte
+ * after encoding in passed in buffer.
+ * @param [in] publicKey Whether to encode as public key.
+ * @param [in] heap Heap hint.
+ * @return Encoding size on success.
+ * @return Negative on failure.
+ */
+static int wolfSSL_RSA_To_Der_ex(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey,
+ void* heap)
+{
+ int ret = 1;
+ int derSz = 0;
+ byte* derBuf = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_To_Der");
+
+ /* Unused if memory is disabled. */
+ (void)heap;
+
+ /* Validate parameters. */
+ if ((rsa == NULL) || ((publicKey != 0) && (publicKey != 1))) {
+ WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", BAD_FUNC_ARG);
+ ret = BAD_FUNC_ARG;
+ }
+ /* Push external RSA data into internal RSA key if not set. */
+ if ((ret == 1) && (!rsa->inSet)) {
+ ret = SetRsaInternal(rsa);
+ }
+ /* wc_RsaKeyToPublicDer encode regardless of values. */
+ if ((ret == 1) && publicKey && (mp_iszero(&((RsaKey*)rsa->internal)->n) ||
+ mp_iszero(&((RsaKey*)rsa->internal)->e))) {
+ ret = BAD_FUNC_ARG;
+ }
+
+ if (ret == 1) {
+ if (publicKey) {
+ /* Calculate length of DER encoded RSA public key. */
+ derSz = wc_RsaPublicKeyDerSize((RsaKey*)rsa->internal, 1);
+ if (derSz < 0) {
+ WOLFSSL_ERROR_MSG("wc_RsaPublicKeyDerSize failed");
+ ret = derSz;
+ }
+ }
+ else {
+ /* Calculate length of DER encoded RSA private key. */
+ derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, NULL, 0);
+ if (derSz < 0) {
+ WOLFSSL_ERROR_MSG("wc_RsaKeyToDer failed");
+ ret = derSz;
+ }
+ }
+ }
+
+ if ((ret == 1) && (outBuf != NULL)) {
+ derBuf = *outBuf;
+ if (derBuf == NULL) {
+ /* Allocate buffer to hold DER encoded RSA key. */
+ derBuf = (byte*)XMALLOC((size_t)derSz, heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (derBuf == NULL) {
+ WOLFSSL_ERROR_MSG("Memory allocation failed");
+ ret = MEMORY_ERROR;
+ }
+ }
+ }
+ if ((ret == 1) && (outBuf != NULL)) {
+ if (publicKey > 0) {
+ /* RSA public key to DER. */
+ derSz = wc_RsaKeyToPublicDer((RsaKey*)rsa->internal, derBuf,
+ (word32)derSz);
+ }
+ else {
+ /* RSA private key to DER. */
+ derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, derBuf,
+ (word32)derSz);
+ }
+ if (derSz < 0) {
+ WOLFSSL_ERROR_MSG("RSA key encoding failed");
+ ret = derSz;
+ }
+ else if ((*outBuf) != NULL) {
+ derBuf = NULL;
+ *outBuf += derSz;
+ }
+ else {
+ /* Return allocated buffer. */
+ *outBuf = derBuf;
+ }
+ }
+ if (ret == 1) {
+ /* Success - return DER encoding size. */
+ ret = derSz;
+ }
+
+ if ((outBuf != NULL) && (*outBuf != derBuf)) {
+ /* Not returning buffer, needs to be disposed of. */
+ XFREE(derBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", ret);
+ return ret;
+}
+
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* Load the DER encoded private RSA key.
+ *
+ * Not OpenSSL API.
+ *
+ * @param [in] rsa RSA key.
+ * @param [in] derBuf Buffer holding DER encoding.
+ * @param [in] derSz Length of DER encoding.
+ * @return 1 on success.
+ * @return -1 on failure.
+ */
+int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf,
+ int derSz)
+{
+ /* Call implementation that handles both private and public keys. */
+ return wolfSSL_RSA_LoadDer_ex(rsa, derBuf, derSz, WOLFSSL_RSA_LOAD_PRIVATE);
+}
+
+/* Load the DER encoded public or private RSA key.
+ *
+ * Not OpenSSL API.
+ *
+ * @param [in] rsa RSA key.
+ * @param [in] derBuf Buffer holding DER encoding.
+ * @param [in] derSz Length of DER encoding.
+ * @param [in] opt Indicates public or private key.
+ * (WOLFSSL_RSA_LOAD_PUBLIC or WOLFSSL_RSA_LOAD_PRIVATE)
+ * @return 1 on success.
+ * @return -1 on failure.
+ */
+int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf,
+ int derSz, int opt)
+{
+ int ret = 1;
+ int res;
+ word32 idx = 0;
+ word32 algId;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_LoadDer");
+
+ /* Validate parameters. */
+ if ((rsa == NULL) || (rsa->internal == NULL) || (derBuf == NULL) ||
+ (derSz <= 0)) {
+ WOLFSSL_ERROR_MSG("Bad function arguments");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ if (ret == 1) {
+ rsa->pkcs8HeaderSz = 0;
+ /* Check if input buffer has PKCS8 header. In the case that it does not
+ * have a PKCS8 header then do not error out. */
+ res = ToTraditionalInline_ex((const byte*)derBuf, &idx, (word32)derSz,
+ &algId);
+ if (res > 0) {
+ /* Store size of PKCS#8 header for encoding. */
+ WOLFSSL_MSG("Found PKCS8 header");
+ rsa->pkcs8HeaderSz = (word16)idx;
+ }
+ /* When decoding and not PKCS#8, return will be ASN_PARSE_E. */
+ else if (res != WC_NO_ERR_TRACE(ASN_PARSE_E)) {
+ /* Something went wrong while decoding. */
+ WOLFSSL_ERROR_MSG("Unexpected error with trying to remove PKCS#8 "
+ "header");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+ if (ret == 1) {
+ /* Decode private or public key data. */
+ if (opt == WOLFSSL_RSA_LOAD_PRIVATE) {
+ res = wc_RsaPrivateKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal,
+ (word32)derSz);
+ }
+ else {
+ res = wc_RsaPublicKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal,
+ (word32)derSz);
+ }
+ /* Check for error. */
+ if (res < 0) {
+ if (opt == WOLFSSL_RSA_LOAD_PRIVATE) {
+ WOLFSSL_ERROR_MSG("RsaPrivateKeyDecode failed");
+ }
+ else {
+ WOLFSSL_ERROR_MSG("RsaPublicKeyDecode failed");
+ }
+ WOLFSSL_ERROR_VERBOSE(res);
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+ if (ret == 1) {
+ /* Set external RSA key data from wolfCrypt key. */
+ if (SetRsaExternal(rsa) != 1) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ else {
+ rsa->inSet = 1;
+ }
+ }
+
+ return ret;
+}
+
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+
+#if !defined(NO_BIO) || !defined(NO_FILESYSTEM)
+/* Load DER encoded data into WOLFSSL_RSA object.
+ *
+ * Creates a new WOLFSSL_RSA object if one is not passed in.
+ *
+ * @param [in, out] rsa WOLFSSL_RSA object to load into.
+ * When rsa or *rsa is NULL a new object is created.
+ * When not NULL and *rsa is NULL then new object
+ * returned through pointer.
+ * @param [in] in DER encoded RSA key data.
+ * @param [in] inSz Size of DER encoded data in bytes.
+ * @param [in] opt Public or private key encoded in data. Valid values:
+ * WOLFSSL_RSA_LOAD_PRIVATE, WOLFSSL_RSA_LOAD_PUBLIC.
+ * @return NULL on failure.
+ * @return WOLFSSL_RSA object on success.
+ */
+static WOLFSSL_RSA* wolfssl_rsa_d2i(WOLFSSL_RSA** rsa, const unsigned char* in,
+ long inSz, int opt)
+{
+ WOLFSSL_RSA* ret = NULL;
+
+ if ((rsa != NULL) && (*rsa != NULL)) {
+ ret = *rsa;
+ }
+ else {
+ ret = wolfSSL_RSA_new();
+ }
+ if ((ret != NULL) && (wolfSSL_RSA_LoadDer_ex(ret, in, (int)inSz, opt)
+ != 1)) {
+ if ((rsa == NULL) || (ret != *rsa)) {
+ wolfSSL_RSA_free(ret);
+ }
+ ret = NULL;
+ }
+
+ if ((rsa != NULL) && (*rsa == NULL)) {
+ *rsa = ret;
+ }
+ return ret;
+}
+#endif
+
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+
+/*
+ * RSA PEM APIs
+ */
+
+#ifdef OPENSSL_EXTRA
+
+#ifndef NO_BIO
+#if defined(WOLFSSL_KEY_GEN)
+/* Writes PEM encoding of an RSA public key to a BIO.
+ *
+ * @param [in] bio BIO object to write to.
+ * @param [in] rsa RSA key to write.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_PEM_write_bio_RSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa)
+{
+ int ret = 1;
+ int derSz = 0;
+ byte* derBuf = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_bio_RSA_PUBKEY");
+
+ /* Validate parameters. */
+ if ((bio == NULL) || (rsa == NULL)) {
+ WOLFSSL_ERROR_MSG("Bad Function Arguments");
+ return 0;
+ }
+
+ if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 1, bio->heap)) < 0) {
+ WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
+ ret = 0;
+ }
+ if (derBuf == NULL) {
+ WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed to get buffer");
+ ret = 0;
+ }
+ if ((ret == 1) && (der_write_to_bio_as_pem(derBuf, derSz, bio,
+ PUBLICKEY_TYPE) != 1)) {
+ ret = 0;
+ }
+
+ /* Dispose of DER buffer. */
+ XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+}
+
+#endif /* WOLFSSL_KEY_GEN */
+#endif /* !NO_BIO */
+
+#if defined(WOLFSSL_KEY_GEN)
+#ifndef NO_FILESYSTEM
+
+/* Writes PEM encoding of an RSA public key to a file pointer.
+ *
+ * @param [in] fp File pointer to write to.
+ * @param [in] rsa RSA key to write.
+ * @param [in] type PEM type to write out.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+static int wolfssl_pem_write_rsa_public_key(XFILE fp, WOLFSSL_RSA* rsa,
+ int type)
+{
+ int ret = 1;
+ int derSz;
+ byte* derBuf = NULL;
+
+ /* Validate parameters. */
+ if ((fp == XBADFILE) || (rsa == NULL)) {
+ WOLFSSL_ERROR_MSG("Bad Function Arguments");
+ return 0;
+ }
+
+ if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 1, rsa->heap)) < 0) {
+ WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
+ ret = 0;
+ }
+ if (derBuf == NULL) {
+ WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed to get buffer");
+ ret = 0;
+ }
+ if ((ret == 1) && (der_write_to_file_as_pem(derBuf, derSz, fp, type,
+ rsa->heap) != 1)) {
+ ret = 0;
+ }
+
+ /* Dispose of DER buffer. */
+ XFREE(derBuf, rsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return ret;
+}
+
+/* Writes PEM encoding of an RSA public key to a file pointer.
+ *
+ * Header/footer will contain: PUBLIC KEY
+ *
+ * @param [in] fp File pointer to write to.
+ * @param [in] rsa RSA key to write.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_PEM_write_RSA_PUBKEY(XFILE fp, WOLFSSL_RSA* rsa)
+{
+ return wolfssl_pem_write_rsa_public_key(fp, rsa, PUBLICKEY_TYPE);
+}
+
+/* Writes PEM encoding of an RSA public key to a file pointer.
+ *
+ * Header/footer will contain: RSA PUBLIC KEY
+ *
+ * @param [in] fp File pointer to write to.
+ * @param [in] rsa RSA key to write.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_PEM_write_RSAPublicKey(XFILE fp, WOLFSSL_RSA* rsa)
+{
+ return wolfssl_pem_write_rsa_public_key(fp, rsa, RSA_PUBLICKEY_TYPE);
+}
+#endif /* !NO_FILESYSTEM */
+#endif /* WOLFSSL_KEY_GEN */
+
+#ifndef NO_BIO
+/* Create an RSA public key by reading the PEM encoded data from the BIO.
+ *
+ * @param [in] bio BIO object to read from.
+ * @param [out] out RSA key created.
+ * @param [in] cb Password callback when PEM encrypted.
+ * @param [in] pass NUL terminated string for passphrase when PEM encrypted.
+ * @return RSA key on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_RSA *wolfSSL_PEM_read_bio_RSA_PUBKEY(WOLFSSL_BIO* bio,
+ WOLFSSL_RSA** out, wc_pem_password_cb* cb, void *pass)
+{
+ WOLFSSL_RSA* rsa = NULL;
+ DerBuffer* der = NULL;
+ int keyFormat = 0;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_RSA_PUBKEY");
+
+ if ((bio != NULL) && (pem_read_bio_key(bio, cb, pass, PUBLICKEY_TYPE,
+ &keyFormat, &der) >= 0)) {
+ rsa = wolfssl_rsa_d2i(out, der->buffer, der->length,
+ WOLFSSL_RSA_LOAD_PUBLIC);
+ if (rsa == NULL) {
+ WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_RSA");
+ }
+ }
+
+ FreeDer(&der);
+ if ((out != NULL) && (rsa != NULL)) {
+ *out = rsa;
+ }
+ return rsa;
+}
+
+WOLFSSL_RSA *wolfSSL_d2i_RSA_PUBKEY_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out)
+{
+ char* data = NULL;
+ int dataSz = 0;
+ int memAlloced = 0;
+ WOLFSSL_RSA* rsa = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_RSA_PUBKEY_bio");
+
+ if (bio == NULL)
+ return NULL;
+
+ if (wolfssl_read_bio(bio, &data, &dataSz, &memAlloced) != 0) {
+ if (memAlloced)
+ XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return NULL;
+ }
+
+ rsa = wolfssl_rsa_d2i(out, (const unsigned char*)data, dataSz,
+ WOLFSSL_RSA_LOAD_PUBLIC);
+ if (memAlloced)
+ XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return rsa;
+}
+#endif /* !NO_BIO */
+
+#ifndef NO_FILESYSTEM
+/* Create an RSA public key by reading the PEM encoded data from the BIO.
+ *
+ * Header/footer should contain: PUBLIC KEY
+ * PEM decoder supports either 'RSA PUBLIC KEY' or 'PUBLIC KEY'.
+ *
+ * @param [in] fp File pointer to read from.
+ * @param [out] out RSA key created.
+ * @param [in] cb Password callback when PEM encrypted.
+ * @param [in] pass NUL terminated string for passphrase when PEM encrypted.
+ * @return RSA key on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_RSA *wolfSSL_PEM_read_RSA_PUBKEY(XFILE fp,
+ WOLFSSL_RSA** out, wc_pem_password_cb* cb, void *pass)
+{
+ WOLFSSL_RSA* rsa = NULL;
+ DerBuffer* der = NULL;
+ int keyFormat = 0;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_RSA_PUBKEY");
+
+ if ((fp != XBADFILE) && (pem_read_file_key(fp, cb, pass, PUBLICKEY_TYPE,
+ &keyFormat, &der) >= 0)) {
+ rsa = wolfssl_rsa_d2i(out, der->buffer, der->length,
+ WOLFSSL_RSA_LOAD_PUBLIC);
+ if (rsa == NULL) {
+ WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_RSA");
+ }
+ }
+
+ FreeDer(&der);
+ if ((out != NULL) && (rsa != NULL)) {
+ *out = rsa;
+ }
+ return rsa;
+}
+
+/* Create an RSA public key by reading the PEM encoded data from the BIO.
+ *
+ * Header/footer should contain: RSA PUBLIC KEY
+ * PEM decoder supports either 'RSA PUBLIC KEY' or 'PUBLIC KEY'.
+ *
+ * @param [in] fp File pointer to read from.
+ * @param [out] rsa RSA key created.
+ * @param [in] cb Password callback when PEM encrypted. May be NULL.
+ * @param [in] pass NUL terminated string for passphrase when PEM encrypted.
+ * May be NULL.
+ * @return RSA key on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_RSA* wolfSSL_PEM_read_RSAPublicKey(XFILE fp, WOLFSSL_RSA** rsa,
+ wc_pem_password_cb* cb, void* pass)
+{
+ return wolfSSL_PEM_read_RSA_PUBKEY(fp, rsa, cb, pass);
+}
+
+#endif /* NO_FILESYSTEM */
+
+#if defined(WOLFSSL_KEY_GEN) && \
+ (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM))
+
+/* Writes PEM encoding of an RSA private key to newly allocated buffer.
+ *
+ * Buffer returned was allocated with: DYNAMIC_TYPE_KEY.
+ *
+ * @param [in] rsa RSA key to write.
+ * @param [in] cipher Cipher to use when PEM encrypted. May be NULL.
+ * @param [in] passwd Password string when PEM encrypted. May be NULL.
+ * @param [in] passwdSz Length of password string when PEM encrypted.
+ * @param [out] pem Allocated buffer with PEM encoding.
+ * @param [out] pLen Length of PEM encoding.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_PEM_write_mem_RSAPrivateKey(WOLFSSL_RSA* rsa,
+ const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz,
+ unsigned char **pem, int *pLen)
+{
+ int ret = 1;
+ byte* derBuf = NULL;
+ int derSz = 0;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_mem_RSAPrivateKey");
+
+ /* Validate parameters. */
+ if ((pem == NULL) || (pLen == NULL) || (rsa == NULL) ||
+ (rsa->internal == NULL)) {
+ WOLFSSL_ERROR_MSG("Bad function arguments");
+ ret = 0;
+ }
+
+ /* Set the RSA key data into the wolfCrypt RSA key if not done so. */
+ if ((ret == 1) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
+ ret = 0;
+ }
+
+ /* Encode wolfCrypt RSA key to DER - derBuf allocated in call. */
+ if ((ret == 1) && ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 0,
+ rsa->heap)) < 0)) {
+ WOLFSSL_ERROR_MSG("wolfSSL_RSA_To_Der failed");
+ ret = 0;
+ }
+
+ if ((ret == 1) && (der_to_enc_pem_alloc(derBuf, derSz, cipher, passwd,
+ passwdSz, PRIVATEKEY_TYPE, NULL, pem, pLen) != 1)) {
+ WOLFSSL_ERROR_MSG("der_to_enc_pem_alloc failed");
+ ret = 0;
+ }
+
+ return ret;
+}
+
+#ifndef NO_BIO
+/* Writes PEM encoding of an RSA private key to a BIO.
+ *
+ * @param [in] bio BIO object to write to.
+ * @param [in] rsa RSA key to write.
+ * @param [in] cipher Cipher to use when PEM encrypted.
+ * @param [in] passwd Password string when PEM encrypted.
+ * @param [in] len Length of password string when PEM encrypted.
+ * @param [in] cb Password callback to use when PEM encrypted.
+ * @param [in] arg NUL terminated string for passphrase when PEM encrypted.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa,
+ const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int len,
+ wc_pem_password_cb* cb, void* arg)
+{
+ int ret = 1;
+ byte* pem = NULL;
+ int pLen = 0;
+
+ (void)cb;
+ (void)arg;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_bio_RSAPrivateKey");
+
+ /* Validate parameters. */
+ if ((bio == NULL) || (rsa == NULL) || (rsa->internal == NULL)) {
+ WOLFSSL_ERROR_MSG("Bad function arguments");
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ /* Write PEM to buffer that is allocated in the call. */
+ ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, cipher, passwd, len,
+ &pem, &pLen);
+ if (ret != 1) {
+ WOLFSSL_ERROR_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed");
+ }
+ }
+ /* Write PEM to BIO. */
+ if ((ret == 1) && (wolfSSL_BIO_write(bio, pem, pLen) <= 0)) {
+ WOLFSSL_ERROR_MSG("RSA private key BIO write failed");
+ ret = 0;
+ }
+
+ /* Dispose of any allocated PEM buffer. */
+ XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+ return ret;
+}
+#endif /* !NO_BIO */
+
+#ifndef NO_FILESYSTEM
+/* Writes PEM encoding of an RSA private key to a file pointer.
+ *
+ * TODO: Support use of the password callback and callback context.
+ *
+ * @param [in] fp File pointer to write to.
+ * @param [in] rsa RSA key to write.
+ * @param [in] cipher Cipher to use when PEM encrypted. May be NULL.
+ * @param [in] passwd Password string when PEM encrypted. May be NULL.
+ * @param [in] passwdSz Length of password string when PEM encrypted.
+ * @param [in] cb Password callback to use when PEM encrypted. Unused.
+ * @param [in] arg NUL terminated string for passphrase when PEM
+ * encrypted. Unused.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_PEM_write_RSAPrivateKey(XFILE fp, WOLFSSL_RSA *rsa,
+ const WOLFSSL_EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz,
+ wc_pem_password_cb *cb, void *arg)
+{
+ int ret = 1;
+ byte* pem = NULL;
+ int pLen = 0;
+
+ (void)cb;
+ (void)arg;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_RSAPrivateKey");
+
+ /* Validate parameters. */
+ if ((fp == XBADFILE) || (rsa == NULL) || (rsa->internal == NULL)) {
+ WOLFSSL_ERROR_MSG("Bad function arguments");
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ /* Write PEM to buffer that is allocated in the call. */
+ ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, cipher, passwd, passwdSz,
+ &pem, &pLen);
+ if (ret != 1) {
+ WOLFSSL_ERROR_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed");
+ }
+ }
+ /* Write PEM to file pointer. */
+ if ((ret == 1) && ((int)XFWRITE(pem, 1, (size_t)pLen, fp) != pLen)) {
+ WOLFSSL_ERROR_MSG("RSA private key file write failed");
+ ret = 0;
+ }
+
+ /* Dispose of any allocated PEM buffer. */
+ XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+ return ret;
+}
+#endif /* NO_FILESYSTEM */
+#endif /* WOLFSSL_KEY_GEN && WOLFSSL_PEM_TO_DER */
+
+#ifndef NO_BIO
+/* Create an RSA private key by reading the PEM encoded data from the BIO.
+ *
+ * @param [in] bio BIO object to read from.
+ * @param [out] out RSA key created.
+ * @param [in] cb Password callback when PEM encrypted.
+ * @param [in] pass NUL terminated string for passphrase when PEM encrypted.
+ * @return RSA key on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_RSA* wolfSSL_PEM_read_bio_RSAPrivateKey(WOLFSSL_BIO* bio,
+ WOLFSSL_RSA** out, wc_pem_password_cb* cb, void* pass)
+{
+ WOLFSSL_RSA* rsa = NULL;
+ DerBuffer* der = NULL;
+ int keyFormat = 0;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_RSAPrivateKey");
+
+ if ((bio != NULL) && (pem_read_bio_key(bio, cb, pass, PRIVATEKEY_TYPE,
+ &keyFormat, &der) >= 0)) {
+ rsa = wolfssl_rsa_d2i(out, der->buffer, der->length,
+ WOLFSSL_RSA_LOAD_PRIVATE);
+ if (rsa == NULL) {
+ WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_RSA");
+ }
+ }
+
+ FreeDer(&der);
+ if ((out != NULL) && (rsa != NULL)) {
+ *out = rsa;
+ }
+ return rsa;
+}
+#endif /* !NO_BIO */
+
+/* Create an RSA private key by reading the PEM encoded data from the file
+ * pointer.
+ *
+ * @param [in] fp File pointer to read from.
+ * @param [out] out RSA key created.
+ * @param [in] cb Password callback when PEM encrypted.
+ * @param [in] pass NUL terminated string for passphrase when PEM encrypted.
+ * @return RSA key on success.
+ * @return NULL on failure.
+ */
+#ifndef NO_FILESYSTEM
+WOLFSSL_RSA* wolfSSL_PEM_read_RSAPrivateKey(XFILE fp, WOLFSSL_RSA** out,
+ wc_pem_password_cb* cb, void* pass)
+{
+ WOLFSSL_RSA* rsa = NULL;
+ DerBuffer* der = NULL;
+ int keyFormat = 0;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_RSAPrivateKey");
+
+ if ((fp != XBADFILE) && (pem_read_file_key(fp, cb, pass, PRIVATEKEY_TYPE,
+ &keyFormat, &der) >= 0)) {
+ rsa = wolfssl_rsa_d2i(out, der->buffer, der->length,
+ WOLFSSL_RSA_LOAD_PRIVATE);
+ if (rsa == NULL) {
+ WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_RSA");
+ }
+ }
+
+ FreeDer(&der);
+ if ((out != NULL) && (rsa != NULL)) {
+ *out = rsa;
+ }
+ return rsa;
+}
+#endif /* !NO_FILESYSTEM */
+
+/*
+ * RSA print APIs
+ */
+
+#if defined(XFPRINTF) && !defined(NO_FILESYSTEM) && \
+ !defined(NO_STDIO_FILESYSTEM)
+/* Print an RSA key to a file pointer.
+ *
+ * @param [in] fp File pointer to write to.
+ * @param [in] rsa RSA key to write.
+ * @param [in] indent Number of spaces to prepend to each line.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_RSA_print_fp(XFILE fp, WOLFSSL_RSA* rsa, int indent)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_print_fp");
+
+ /* Validate parameters. */
+ if ((fp == XBADFILE) || (rsa == NULL)) {
+ ret = 0;
+ }
+
+ /* Set the external data from the wolfCrypt RSA key if not done. */
+ if ((ret == 1) && (!rsa->exSet)) {
+ ret = SetRsaExternal(rsa);
+ }
+
+ /* Get the key size from modulus if available. */
+ if ((ret == 1) && (rsa->n != NULL)) {
+ int keySize = wolfSSL_BN_num_bits(rsa->n);
+ if (keySize == 0) {
+ ret = 0;
+ }
+ else {
+ if (XFPRINTF(fp, "%*s", indent, "") < 0)
+ ret = 0;
+ else if (XFPRINTF(fp, "RSA Private-Key: (%d bit, 2 primes)\n",
+ keySize) < 0)
+ ret = 0;
+ }
+ }
+ /* Print out any components available. */
+ if ((ret == 1) && (rsa->n != NULL)) {
+ ret = pk_bn_field_print_fp(fp, indent, "modulus", rsa->n);
+ }
+ if ((ret == 1) && (rsa->d != NULL)) {
+ ret = pk_bn_field_print_fp(fp, indent, "privateExponent", rsa->d);
+ }
+ if ((ret == 1) && (rsa->p != NULL)) {
+ ret = pk_bn_field_print_fp(fp, indent, "prime1", rsa->p);
+ }
+ if ((ret == 1) && (rsa->q != NULL)) {
+ ret = pk_bn_field_print_fp(fp, indent, "prime2", rsa->q);
+ }
+ if ((ret == 1) && (rsa->dmp1 != NULL)) {
+ ret = pk_bn_field_print_fp(fp, indent, "exponent1", rsa->dmp1);
+ }
+ if ((ret == 1) && (rsa->dmq1 != NULL)) {
+ ret = pk_bn_field_print_fp(fp, indent, "exponent2", rsa->dmq1);
+ }
+ if ((ret == 1) && (rsa->iqmp != NULL)) {
+ ret = pk_bn_field_print_fp(fp, indent, "coefficient", rsa->iqmp);
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_RSA_print_fp", ret);
+
+ return ret;
+}
+#endif /* XFPRINTF && !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */
+
+#if defined(XSNPRINTF) && !defined(NO_BIO)
+/* snprintf() must be available */
+
+/* Maximum size of a header line. */
+#define RSA_PRINT_MAX_HEADER_LINE PRINT_NUM_MAX_INDENT
+
+/* Writes the human readable form of RSA to a BIO.
+ *
+ * @param [in] bio BIO object to write to.
+ * @param [in] rsa RSA key to write.
+ * @param [in] indent Number of spaces before each line.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_RSA_print(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, int indent)
+{
+ int ret = 1;
+ int sz = 0;
+ RsaKey* key = NULL;
+ char line[RSA_PRINT_MAX_HEADER_LINE];
+ int i = 0;
+ mp_int *num = NULL;
+ /* Header strings. */
+ const char *name[] = {
+ "Modulus:", "Exponent:", "PrivateExponent:", "Prime1:", "Prime2:",
+ "Exponent1:", "Exponent2:", "Coefficient:"
+ };
+
+ WOLFSSL_ENTER("wolfSSL_RSA_print");
+
+ /* Validate parameters. */
+ if ((bio == NULL) || (rsa == NULL) || (indent > PRINT_NUM_MAX_INDENT)) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ if (ret == 1) {
+ key = (RsaKey*)rsa->internal;
+
+ /* Get size in bits of key for printing out. */
+ sz = wolfSSL_RSA_bits(rsa);
+ if (sz <= 0) {
+ WOLFSSL_ERROR_MSG("Error getting RSA key size");
+ ret = 0;
+ }
+ }
+ if (ret == 1) {
+ /* Print any indent spaces. */
+ ret = wolfssl_print_indent(bio, line, sizeof(line), indent);
+ }
+ if (ret == 1) {
+ /* Print header line. */
+ int len = XSNPRINTF(line, sizeof(line), "\nRSA %s: (%d bit)\n",
+ (!mp_iszero(&key->d)) ? "Private-Key" : "Public-Key", sz);
+ if (len >= (int)sizeof(line)) {
+ WOLFSSL_ERROR_MSG("Buffer overflow while formatting key preamble");
+ ret = 0;
+ }
+ else {
+ if (wolfSSL_BIO_write(bio, line, len) <= 0) {
+ ret = 0;
+ }
+ }
+ }
+
+ for (i = 0; (ret == 1) && (i < RSA_INTS); i++) {
+ /* Get mp_int for index. */
+ switch (i) {
+ case 0:
+ /* Print out modulus */
+ num = &key->n;
+ break;
+ case 1:
+ num = &key->e;
+ break;
+ case 2:
+ num = &key->d;
+ break;
+ case 3:
+ num = &key->p;
+ break;
+ case 4:
+ num = &key->q;
+ break;
+ case 5:
+ num = &key->dP;
+ break;
+ case 6:
+ num = &key->dQ;
+ break;
+ case 7:
+ num = &key->u;
+ break;
+ default:
+ WOLFSSL_ERROR_MSG("Bad index value");
+ }
+
+ if (i == 1) {
+ /* Print exponent as a 32-bit value. */
+ ret = wolfssl_print_value(bio, num, name[i], indent);
+ }
+ else if (!mp_iszero(num)) {
+ /* Print name and MP integer. */
+ ret = wolfssl_print_number(bio, num, name[i], indent);
+ }
+ }
+
+ return ret;
+}
+#endif /* XSNPRINTF && !NO_BIO */
+
+#endif /* OPENSSL_EXTRA */
+
+/*
+ * RSA get/set/test APIs
+ */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+/* Set RSA key data (external) from wolfCrypt RSA key (internal).
+ *
+ * @param [in, out] rsa RSA key.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int SetRsaExternal(WOLFSSL_RSA* rsa)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("SetRsaExternal");
+
+ /* Validate parameters. */
+ if ((rsa == NULL) || (rsa->internal == NULL)) {
+ WOLFSSL_ERROR_MSG("rsa key NULL error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ if (ret == 1) {
+ RsaKey* key = (RsaKey*)rsa->internal;
+
+ /* Copy modulus. */
+ ret = wolfssl_bn_set_value(&rsa->n, &key->n);
+ if (ret != 1) {
+ WOLFSSL_ERROR_MSG("rsa n error");
+ }
+ if (ret == 1) {
+ /* Copy public exponent. */
+ ret = wolfssl_bn_set_value(&rsa->e, &key->e);
+ if (ret != 1) {
+ WOLFSSL_ERROR_MSG("rsa e error");
+ }
+ }
+
+ if (key->type == RSA_PRIVATE) {
+ #ifndef WOLFSSL_RSA_PUBLIC_ONLY
+ if (ret == 1) {
+ /* Copy private exponent. */
+ ret = wolfssl_bn_set_value(&rsa->d, &key->d);
+ if (ret != 1) {
+ WOLFSSL_ERROR_MSG("rsa d error");
+ }
+ }
+ if (ret == 1) {
+ /* Copy first prime. */
+ ret = wolfssl_bn_set_value(&rsa->p, &key->p);
+ if (ret != 1) {
+ WOLFSSL_ERROR_MSG("rsa p error");
+ }
+ }
+ if (ret == 1) {
+ /* Copy second prime. */
+ ret = wolfssl_bn_set_value(&rsa->q, &key->q);
+ if (ret != 1) {
+ WOLFSSL_ERROR_MSG("rsa q error");
+ }
+ }
+ #if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || \
+ !defined(RSA_LOW_MEM)
+ if (ret == 1) {
+ /* Copy d mod p-1. */
+ ret = wolfssl_bn_set_value(&rsa->dmp1, &key->dP);
+ if (ret != 1) {
+ WOLFSSL_ERROR_MSG("rsa dP error");
+ }
+ }
+ if (ret == 1) {
+ /* Copy d mod q-1. */
+ ret = wolfssl_bn_set_value(&rsa->dmq1, &key->dQ);
+ if (ret != 1) {
+ WOLFSSL_ERROR_MSG("rsa dq error");
+ }
+ }
+ if (ret == 1) {
+ /* Copy 1/q mod p. */
+ ret = wolfssl_bn_set_value(&rsa->iqmp, &key->u);
+ if (ret != 1) {
+ WOLFSSL_ERROR_MSG("rsa u error");
+ }
+ }
+ #endif
+ #else
+ WOLFSSL_ERROR_MSG("rsa private key not compiled in ");
+ ret = 0;
+ #endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
+ }
+ }
+ if (ret == 1) {
+ /* External values set. */
+ rsa->exSet = 1;
+ }
+ else {
+ /* Return 0 on failure. */
+ ret = 0;
+ }
+
+ return ret;
+}
+#endif /* (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */
+
+#ifdef OPENSSL_EXTRA
+
+/* Set wolfCrypt RSA key data (internal) from RSA key (external).
+ *
+ * @param [in, out] rsa RSA key.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int SetRsaInternal(WOLFSSL_RSA* rsa)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("SetRsaInternal");
+
+ /* Validate parameters. */
+ if ((rsa == NULL) || (rsa->internal == NULL)) {
+ WOLFSSL_ERROR_MSG("rsa key NULL error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ if (ret == 1) {
+ RsaKey* key = (RsaKey*)rsa->internal;
+
+ /* Copy down modulus if available. */
+ if ((rsa->n != NULL) && (wolfssl_bn_get_value(rsa->n, &key->n) != 1)) {
+ WOLFSSL_ERROR_MSG("rsa n key error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Copy down public exponent if available. */
+ if ((ret == 1) && (rsa->e != NULL) &&
+ (wolfssl_bn_get_value(rsa->e, &key->e) != 1)) {
+ WOLFSSL_ERROR_MSG("rsa e key error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Enough numbers for public key */
+ key->type = RSA_PUBLIC;
+
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
+ /* Copy down private exponent if available. */
+ if ((ret == 1) && (rsa->d != NULL)) {
+ if (wolfssl_bn_get_value(rsa->d, &key->d) != 1) {
+ WOLFSSL_ERROR_MSG("rsa d key error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ else {
+ /* Enough numbers for private key */
+ key->type = RSA_PRIVATE;
+ }
+ }
+
+ /* Copy down first prime if available. */
+ if ((ret == 1) && (rsa->p != NULL) &&
+ (wolfssl_bn_get_value(rsa->p, &key->p) != 1)) {
+ WOLFSSL_ERROR_MSG("rsa p key error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Copy down second prime if available. */
+ if ((ret == 1) && (rsa->q != NULL) &&
+ (wolfssl_bn_get_value(rsa->q, &key->q) != 1)) {
+ WOLFSSL_ERROR_MSG("rsa q key error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)
+ /* Copy down d mod p-1 if available. */
+ if ((ret == 1) && (rsa->dmp1 != NULL) &&
+ (wolfssl_bn_get_value(rsa->dmp1, &key->dP) != 1)) {
+ WOLFSSL_ERROR_MSG("rsa dP key error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Copy down d mod q-1 if available. */
+ if ((ret == 1) && (rsa->dmq1 != NULL) &&
+ (wolfssl_bn_get_value(rsa->dmq1, &key->dQ) != 1)) {
+ WOLFSSL_ERROR_MSG("rsa dQ key error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Copy down 1/q mod p if available. */
+ if ((ret == 1) && (rsa->iqmp != NULL) &&
+ (wolfssl_bn_get_value(rsa->iqmp, &key->u) != 1)) {
+ WOLFSSL_ERROR_MSG("rsa u key error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+#endif
+#endif
+
+ if (ret == 1) {
+ /* All available numbers have been set down. */
+ rsa->inSet = 1;
+ }
+ }
+
+ return ret;
+}
+
+/* Set the RSA method into object.
+ *
+ * @param [in, out] rsa RSA key.
+ * @param [in] meth RSA method.
+ * @return 1 always.
+ */
+int wolfSSL_RSA_set_method(WOLFSSL_RSA *rsa, WOLFSSL_RSA_METHOD *meth)
+{
+ if (rsa != NULL) {
+ /* Store the method into object. */
+ rsa->meth = meth;
+ /* Copy over flags. */
+ rsa->flags = meth->flags;
+ }
+ /* OpenSSL always assumes it will work. */
+ return 1;
+}
+
+/* Get the RSA method from the RSA object.
+ *
+ * @param [in] rsa RSA key.
+ * @return RSA method on success.
+ * @return NULL when RSA is NULL or no method set.
+ */
+const WOLFSSL_RSA_METHOD* wolfSSL_RSA_get_method(const WOLFSSL_RSA *rsa)
+{
+ return (rsa != NULL) ? rsa->meth : NULL;
+}
+
+/* Get the size in bytes of the RSA key.
+ *
+ * Return compliant with OpenSSL
+ *
+ * @param [in] rsa RSA key.
+ * @return RSA modulus size in bytes.
+ * @return 0 on error.
+ */
+int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa)
+{
+ int ret = 0;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_size");
+
+ if (rsa != NULL) {
+ /* Make sure we have set the RSA values into wolfCrypt RSA key. */
+ if (rsa->inSet || (SetRsaInternal((WOLFSSL_RSA*)rsa) == 1)) {
+ /* Get key size in bytes using wolfCrypt RSA key. */
+ ret = wc_RsaEncryptSize((RsaKey*)rsa->internal);
+ }
+ }
+
+ return ret;
+}
+
+/* Get the size in bits of the RSA key.
+ *
+ * Uses external modulus field.
+ *
+ * @param [in] rsa RSA key.
+ * @return RSA modulus size in bits.
+ * @return 0 on error.
+ */
+int wolfSSL_RSA_bits(const WOLFSSL_RSA* rsa)
+{
+ int ret = 0;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_bits");
+
+ if (rsa != NULL) {
+ /* Get number of bits in external modulus. */
+ ret = wolfSSL_BN_num_bits(rsa->n);
+ }
+
+ return ret;
+}
+
+/* Get the BN objects that are the Chinese-Remainder Theorem (CRT) parameters.
+ *
+ * Only for those that are not NULL parameters.
+ *
+ * @param [in] rsa RSA key.
+ * @param [out] dmp1 BN that is d mod (p - 1). May be NULL.
+ * @param [out] dmq1 BN that is d mod (q - 1). May be NULL.
+ * @param [out] iqmp BN that is 1/q mod p. May be NULL.
+ */
+void wolfSSL_RSA_get0_crt_params(const WOLFSSL_RSA *rsa,
+ const WOLFSSL_BIGNUM **dmp1, const WOLFSSL_BIGNUM **dmq1,
+ const WOLFSSL_BIGNUM **iqmp)
+{
+ WOLFSSL_ENTER("wolfSSL_RSA_get0_crt_params");
+
+ /* For any parameters not NULL, return the BN from the key or NULL. */
+ if (dmp1 != NULL) {
+ *dmp1 = (rsa != NULL) ? rsa->dmp1 : NULL;
+ }
+ if (dmq1 != NULL) {
+ *dmq1 = (rsa != NULL) ? rsa->dmq1 : NULL;
+ }
+ if (iqmp != NULL) {
+ *iqmp = (rsa != NULL) ? rsa->iqmp : NULL;
+ }
+}
+
+/* Set the BN objects that are the Chinese-Remainder Theorem (CRT) parameters
+ * into RSA key.
+ *
+ * If CRT parameter is NULL then there must be one in the RSA key already.
+ *
+ * @param [in, out] rsa RSA key.
+ * @param [in] dmp1 BN that is d mod (p - 1). May be NULL.
+ * @param [in] dmq1 BN that is d mod (q - 1). May be NULL.
+ * @param [in] iqmp BN that is 1/q mod p. May be NULL.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_RSA_set0_crt_params(WOLFSSL_RSA *rsa, WOLFSSL_BIGNUM *dmp1,
+ WOLFSSL_BIGNUM *dmq1, WOLFSSL_BIGNUM *iqmp)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_set0_crt_params");
+
+ /* If a param is NULL in rsa then it must be non-NULL in the
+ * corresponding user input. */
+ if ((rsa == NULL) || ((rsa->dmp1 == NULL) && (dmp1 == NULL)) ||
+ ((rsa->dmq1 == NULL) && (dmq1 == NULL)) ||
+ ((rsa->iqmp == NULL) && (iqmp == NULL))) {
+ WOLFSSL_ERROR_MSG("Bad parameters");
+ ret = 0;
+ }
+ if (ret == 1) {
+ /* Replace the BNs. */
+ if (dmp1 != NULL) {
+ wolfSSL_BN_clear_free(rsa->dmp1);
+ rsa->dmp1 = dmp1;
+ }
+ if (dmq1 != NULL) {
+ wolfSSL_BN_clear_free(rsa->dmq1);
+ rsa->dmq1 = dmq1;
+ }
+ if (iqmp != NULL) {
+ wolfSSL_BN_clear_free(rsa->iqmp);
+ rsa->iqmp = iqmp;
+ }
+
+ /* Set the values into the wolfCrypt RSA key. */
+ if (SetRsaInternal(rsa) != 1) {
+ if (dmp1 != NULL) {
+ rsa->dmp1 = NULL;
+ }
+ if (dmq1 != NULL) {
+ rsa->dmq1 = NULL;
+ }
+ if (iqmp != NULL) {
+ rsa->iqmp = NULL;
+ }
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+/* Get the BN objects that are the factors of the RSA key (two primes p and q).
+ *
+ * @param [in] rsa RSA key.
+ * @param [out] p BN that is first prime. May be NULL.
+ * @param [out] q BN that is second prime. May be NULL.
+ */
+void wolfSSL_RSA_get0_factors(const WOLFSSL_RSA *rsa, const WOLFSSL_BIGNUM **p,
+ const WOLFSSL_BIGNUM **q)
+{
+ WOLFSSL_ENTER("wolfSSL_RSA_get0_factors");
+
+ /* For any primes not NULL, return the BN from the key or NULL. */
+ if (p != NULL) {
+ *p = (rsa != NULL) ? rsa->p : NULL;
+ }
+ if (q != NULL) {
+ *q = (rsa != NULL) ? rsa->q : NULL;
+ }
+}
+
+/* Set the BN objects that are the factors of the RSA key (two primes p and q).
+ *
+ * If factor parameter is NULL then there must be one in the RSA key already.
+ *
+ * @param [in, out] rsa RSA key.
+ * @param [in] p BN that is first prime. May be NULL.
+ * @param [in] q BN that is second prime. May be NULL.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_RSA_set0_factors(WOLFSSL_RSA *rsa, WOLFSSL_BIGNUM *p,
+ WOLFSSL_BIGNUM *q)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_set0_factors");
+
+ /* If a param is null in r then it must be non-null in the
+ * corresponding user input. */
+ if (rsa == NULL || ((rsa->p == NULL) && (p == NULL)) ||
+ ((rsa->q == NULL) && (q == NULL))) {
+ WOLFSSL_ERROR_MSG("Bad parameters");
+ ret = 0;
+ }
+ if (ret == 1) {
+ /* Replace the BNs. */
+ if (p != NULL) {
+ wolfSSL_BN_clear_free(rsa->p);
+ rsa->p = p;
+ }
+ if (q != NULL) {
+ wolfSSL_BN_clear_free(rsa->q);
+ rsa->q = q;
+ }
+
+ /* Set the values into the wolfCrypt RSA key. */
+ if (SetRsaInternal(rsa) != 1) {
+ if (p != NULL) {
+ rsa->p = NULL;
+ }
+ if (q != NULL) {
+ rsa->q = NULL;
+ }
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+/* Get the BN objects for the basic key numbers of the RSA key (modulus, public
+ * exponent, private exponent).
+ *
+ * @param [in] rsa RSA key.
+ * @param [out] n BN that is the modulus. May be NULL.
+ * @param [out] e BN that is the public exponent. May be NULL.
+ * @param [out] d BN that is the private exponent. May be NULL.
+ */
+void wolfSSL_RSA_get0_key(const WOLFSSL_RSA *rsa, const WOLFSSL_BIGNUM **n,
+ const WOLFSSL_BIGNUM **e, const WOLFSSL_BIGNUM **d)
+{
+ WOLFSSL_ENTER("wolfSSL_RSA_get0_key");
+
+ /* For any parameters not NULL, return the BN from the key or NULL. */
+ if (n != NULL) {
+ *n = (rsa != NULL) ? rsa->n : NULL;
+ }
+ if (e != NULL) {
+ *e = (rsa != NULL) ? rsa->e : NULL;
+ }
+ if (d != NULL) {
+ *d = (rsa != NULL) ? rsa->d : NULL;
+ }
+}
+
+/* Set the BN objects for the basic key numbers into the RSA key (modulus,
+ * public exponent, private exponent).
+ *
+ * If BN parameter is NULL then there must be one in the RSA key already.
+ *
+ * @param [in,out] rsa RSA key.
+ * @param [in] n BN that is the modulus. May be NULL.
+ * @param [in] e BN that is the public exponent. May be NULL.
+ * @param [in] d BN that is the private exponent. May be NULL.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_RSA_set0_key(WOLFSSL_RSA *rsa, WOLFSSL_BIGNUM *n, WOLFSSL_BIGNUM *e,
+ WOLFSSL_BIGNUM *d)
+{
+ int ret = 1;
+
+ /* If the fields n and e in r are NULL, the corresponding input
+ * parameters MUST be non-NULL for n and e. d may be
+ * left NULL (in case only the public key is used).
+ */
+ if ((rsa == NULL) || ((rsa->n == NULL) && (n == NULL)) ||
+ ((rsa->e == NULL) && (e == NULL))) {
+ ret = 0;
+ }
+ if (ret == 1) {
+ /* Replace the BNs. */
+ if (n != NULL) {
+ wolfSSL_BN_free(rsa->n);
+ rsa->n = n;
+ }
+ if (e != NULL) {
+ wolfSSL_BN_free(rsa->e);
+ rsa->e = e;
+ }
+ if (d != NULL) {
+ /* Private key is sensitive data. */
+ wolfSSL_BN_clear_free(rsa->d);
+ rsa->d = d;
+ }
+
+ /* Set the values into the wolfCrypt RSA key. */
+ if (SetRsaInternal(rsa) != 1) {
+ if (n != NULL) {
+ rsa->n = NULL;
+ }
+ if (e != NULL) {
+ rsa->e = NULL;
+ }
+ if (d != NULL) {
+ rsa->d = NULL;
+ }
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+/* Get the flags of the RSA key.
+ *
+ * @param [in] rsa RSA key.
+ * @return Flags set in RSA key on success.
+ * @return 0 when RSA key is NULL.
+ */
+int wolfSSL_RSA_flags(const WOLFSSL_RSA *rsa)
+{
+ int ret = 0;
+
+ /* Get flags from the RSA key if available. */
+ if (rsa != NULL) {
+ ret = rsa->flags;
+ }
+
+ return ret;
+}
+
+/* Set the flags into the RSA key.
+ *
+ * @param [in, out] rsa RSA key.
+ * @param [in] flags Flags to set.
+ */
+void wolfSSL_RSA_set_flags(WOLFSSL_RSA *rsa, int flags)
+{
+ /* Add the flags into RSA key if available. */
+ if (rsa != NULL) {
+ rsa->flags |= flags;
+ }
+}
+
+/* Clear the flags in the RSA key.
+ *
+ * @param [in, out] rsa RSA key.
+ * @param [in] flags Flags to clear.
+ */
+void wolfSSL_RSA_clear_flags(WOLFSSL_RSA *rsa, int flags)
+{
+ /* Clear the flags passed in that are on the RSA key if available. */
+ if (rsa != NULL) {
+ rsa->flags &= ~flags;
+ }
+}
+
+/* Test the flags in the RSA key.
+ *
+ * @param [in] rsa RSA key.
+ * @return Matching flags of RSA key on success.
+ * @return 0 when RSA key is NULL.
+ */
+int wolfSSL_RSA_test_flags(const WOLFSSL_RSA *rsa, int flags)
+{
+ /* Return the flags passed in that are set on the RSA key if available. */
+ return (rsa != NULL) ? (rsa->flags & flags) : 0;
+}
+
+/* Get the extra data, by index, associated with the RSA key.
+ *
+ * @param [in] rsa RSA key.
+ * @param [in] idx Index of extra data.
+ * @return Extra data (anonymous type) on success.
+ * @return NULL on failure.
+ */
+void* wolfSSL_RSA_get_ex_data(const WOLFSSL_RSA *rsa, int idx)
+{
+ WOLFSSL_ENTER("wolfSSL_RSA_get_ex_data");
+
+#ifdef HAVE_EX_DATA
+ return (rsa == NULL) ? NULL :
+ wolfSSL_CRYPTO_get_ex_data(&rsa->ex_data, idx);
+#else
+ (void)rsa;
+ (void)idx;
+
+ return NULL;
+#endif
+}
+
+/* Set extra data against the RSA key at an index.
+ *
+ * @param [in, out] rsa RSA key.
+ * @param [in] idx Index set set extra data at.
+ * @param [in] data Extra data of anonymous type.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_RSA_set_ex_data(WOLFSSL_RSA *rsa, int idx, void *data)
+{
+ WOLFSSL_ENTER("wolfSSL_RSA_set_ex_data");
+
+#ifdef HAVE_EX_DATA
+ return (rsa == NULL) ? 0 :
+ wolfSSL_CRYPTO_set_ex_data(&rsa->ex_data, idx, data);
+#else
+ (void)rsa;
+ (void)idx;
+ (void)data;
+
+ return 0;
+#endif
+}
+
+#ifdef HAVE_EX_DATA_CLEANUP_HOOKS
+/* Set the extra data and cleanup callback against the RSA key at an index.
+ *
+ * Not OpenSSL API.
+ *
+ * @param [in, out] rsa RSA key.
+ * @param [in] idx Index set set extra data at.
+ * @param [in] data Extra data of anonymous type.
+ * @param [in] freeCb Callback function to free extra data.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_RSA_set_ex_data_with_cleanup(WOLFSSL_RSA *rsa, int idx, void *data,
+ wolfSSL_ex_data_cleanup_routine_t freeCb)
+{
+ WOLFSSL_ENTER("wolfSSL_RSA_set_ex_data_with_cleanup");
+
+ return (rsa == NULL) ? 0 :
+ wolfSSL_CRYPTO_set_ex_data_with_cleanup(&rsa->ex_data, idx, data,
+ freeCb);
+}
+#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */
+
+/*
+ * RSA check key APIs
+ */
+
+#ifdef WOLFSSL_RSA_KEY_CHECK
+/* Check that the RSA key is valid using wolfCrypt.
+ *
+ * @param [in] rsa RSA key.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_RSA_check_key(const WOLFSSL_RSA* rsa)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_check_key");
+
+ /* Validate parameters. */
+ if ((rsa == NULL) || (rsa->internal == NULL)) {
+ ret = 0;
+ }
+
+ /* Constant RSA - assume internal data has been set. */
+
+ /* Check wolfCrypt RSA key. */
+ if ((ret == 1) && (wc_CheckRsaKey((RsaKey*)rsa->internal) != 0)) {
+ ret = 0;
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_RSA_check_key", ret);
+
+ return ret;
+}
+#endif /* WOLFSSL_RSA_KEY_CHECK */
+
+/*
+ * RSA generate APIs
+ */
+
+/* Get a random number generator associated with the RSA key.
+ *
+ * If not able, then get the global if possible.
+ * *tmpRng must not be an initialized RNG.
+ * *tmpRng is allocated when WOLFSSL_SMALL_STACK is defined and an RNG isn't
+ * associated with the wolfCrypt RSA key.
+ *
+ * @param [in] rsa RSA key.
+ * @param [out] tmpRng Temporary random number generator.
+ * @param [out] initTmpRng Temporary random number generator was initialized.
+ *
+ * @return A wolfCrypt RNG to use on success.
+ * @return NULL on error.
+ */
+WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA* rsa, WC_RNG** tmpRng, int* initTmpRng)
+{
+ WC_RNG* rng = NULL;
+ int err = 0;
+
+ /* Check validity of parameters. */
+ if ((rsa == NULL) || (initTmpRng == NULL)) {
+ err = 1;
+ }
+ if (!err) {
+ /* Haven't initialized any RNG passed through tmpRng. */
+ *initTmpRng = 0;
+
+ #if !defined(HAVE_FIPS) && defined(WC_RSA_BLINDING)
+ /* Use wolfCrypt RSA key's RNG if available/set. */
+ rng = ((RsaKey*)rsa->internal)->rng;
+ #endif
+ }
+ if ((!err) && (rng == NULL) && (tmpRng != NULL)) {
+ /* Make an RNG with tmpRng or get global. */
+ rng = wolfssl_make_rng(*tmpRng, initTmpRng);
+ if ((rng != NULL) && *initTmpRng) {
+ *tmpRng = rng;
+ }
+ }
+
+ return rng;
+}
+
+/* Use the wolfCrypt RSA APIs to generate a new RSA key.
+ *
+ * @param [in, out] rsa RSA key.
+ * @param [in] bits Number of bits that the modulus must have.
+ * @param [in] e A BN object holding the public exponent to use.
+ * @param [in] cb Status callback. Unused.
+ * @return 0 on success.
+ * @return wolfSSL native error code on error.
+ */
+static int wolfssl_rsa_generate_key_native(WOLFSSL_RSA* rsa, int bits,
+ WOLFSSL_BIGNUM* e, void* cb)
+{
+#ifdef WOLFSSL_KEY_GEN
+ int ret = 0;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG* tmpRng = NULL;
+#else
+ WC_RNG _tmpRng[1];
+ WC_RNG* tmpRng = _tmpRng;
+#endif
+ int initTmpRng = 0;
+ WC_RNG* rng = NULL;
+ long en = 0;
+#endif
+
+ (void)cb;
+
+ WOLFSSL_ENTER("wolfssl_rsa_generate_key_native");
+
+#ifdef WOLFSSL_KEY_GEN
+ /* Get RNG in wolfCrypt RSA key or initialize a new one (or global). */
+ rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
+ if (rng == NULL) {
+ /* Something went wrong so return memory error. */
+ ret = MEMORY_E;
+ }
+ if ((ret == 0) && ((en = (long)wolfSSL_BN_get_word(e)) <= 0)) {
+ ret = BAD_FUNC_ARG;
+ }
+ if (ret == 0) {
+ /* Generate an RSA key. */
+ ret = wc_MakeRsaKey((RsaKey*)rsa->internal, bits, en, rng);
+ if (ret != MP_OKAY) {
+ WOLFSSL_ERROR_MSG("wc_MakeRsaKey failed");
+ }
+ }
+ if (ret == 0) {
+ /* Get the values from wolfCrypt RSA key into external RSA key. */
+ ret = SetRsaExternal(rsa);
+ if (ret == 1) {
+ /* Internal matches external. */
+ rsa->inSet = 1;
+ /* Return success. */
+ ret = 0;
+ }
+ else {
+ /* Something went wrong so return memory error. */
+ ret = MEMORY_E;
+ }
+ }
+
+ /* Finalize RNG if initialized in WOLFSSL_RSA_GetRNG(). */
+ if (initTmpRng) {
+ wc_FreeRng(tmpRng);
+ }
+ WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
+
+ return ret;
+#else
+ WOLFSSL_ERROR_MSG("No Key Gen built in");
+
+ (void)rsa;
+ (void)e;
+ (void)bits;
+
+ return NOT_COMPILED_IN;
+#endif
+}
+
+/* Generate an RSA key that has the specified modulus size and public exponent.
+ *
+ * Note: Because of wc_MakeRsaKey an RSA key size generated can be rounded
+ * down to nearest multiple of 8. For example generating a key of size
+ * 2999 bits will make a key of size 374 bytes instead of 375 bytes.
+ *
+ * @param [in] bits Number of bits that the modulus must have i.e. 2048.
+ * @param [in] e Public exponent to use i.e. 65537.
+ * @param [in] cb Status callback. Unused.
+ * @param [in] data Data to pass to status callback. Unused.
+ * @return A new RSA key on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_RSA* wolfSSL_RSA_generate_key(int bits, unsigned long e,
+ void(*cb)(int, int, void*), void* data)
+{
+ WOLFSSL_RSA* rsa = NULL;
+ WOLFSSL_BIGNUM* bn = NULL;
+ int err = 0;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_generate_key");
+
+ (void)cb;
+ (void)data;
+
+ /* Validate bits. */
+ if (bits < 0) {
+ WOLFSSL_ERROR_MSG("Bad argument: bits was less than 0");
+ err = 1;
+ }
+ /* Create a new BN to hold public exponent - for when wolfCrypt supports
+ * longer values. */
+ if ((!err) && ((bn = wolfSSL_BN_new()) == NULL)) {
+ WOLFSSL_ERROR_MSG("Error creating big number");
+ err = 1;
+ }
+ /* Set public exponent. */
+ if ((!err) && (wolfSSL_BN_set_word(bn, e) != 1)) {
+ WOLFSSL_ERROR_MSG("Error using e value");
+ err = 1;
+ }
+
+ /* Create an RSA key object to hold generated key. */
+ if ((!err) && ((rsa = wolfSSL_RSA_new()) == NULL)) {
+ WOLFSSL_ERROR_MSG("memory error");
+ err = 1;
+ }
+ while (!err) {
+ int ret;
+
+ /* Use wolfCrypt to generate RSA key. */
+ ret = wolfssl_rsa_generate_key_native(rsa, bits, bn, NULL);
+ #ifdef HAVE_FIPS
+ /* Keep trying if failed to find a prime. */
+ if (ret == WC_NO_ERR_TRACE(PRIME_GEN_E)) {
+ continue;
+ }
+ #endif
+ if (ret != WOLFSSL_ERROR_NONE) {
+ /* Unrecoverable error in generation. */
+ err = 1;
+ }
+ /* Done generating - unrecoverable error or success. */
+ break;
+ }
+ if (err) {
+ /* Dispose of RSA key object if generation didn't work. */
+ wolfSSL_RSA_free(rsa);
+ /* Returning NULL on error. */
+ rsa = NULL;
+ }
+ /* Dispose of the temporary BN used for the public exponent. */
+ wolfSSL_BN_free(bn);
+
+ return rsa;
+}
+
+/* Generate an RSA key that has the specified modulus size and public exponent.
+ *
+ * Note: Because of wc_MakeRsaKey an RSA key size generated can be rounded
+ * down to nearest multiple of 8. For example generating a key of size
+ * 2999 bits will make a key of size 374 bytes instead of 375 bytes.
+ *
+ * @param [in] bits Number of bits that the modulus must have i.e. 2048.
+ * @param [in] e Public exponent to use, i.e. 65537, as a BN.
+ * @param [in] cb Status callback. Unused.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* e,
+ void* cb)
+{
+ int ret = 1;
+
+ /* Validate parameters. */
+ if ((rsa == NULL) || (rsa->internal == NULL)) {
+ WOLFSSL_ERROR_MSG("bad arguments");
+ ret = 0;
+ }
+ else {
+ for (;;) {
+ /* Use wolfCrypt to generate RSA key. */
+ int gen_ret = wolfssl_rsa_generate_key_native(rsa, bits, e, cb);
+ #ifdef HAVE_FIPS
+ /* Keep trying again if public key value didn't work. */
+ if (gen_ret == WC_NO_ERR_TRACE(PRIME_GEN_E)) {
+ continue;
+ }
+ #endif
+ if (gen_ret != WOLFSSL_ERROR_NONE) {
+ /* Unrecoverable error in generation. */
+ ret = 0;
+ }
+ /* Done generating - unrecoverable error or success. */
+ break;
+ }
+ }
+
+ return ret;
+}
+
+#endif /* OPENSSL_EXTRA */
+
+/*
+ * RSA padding APIs
+ */
+
+#ifdef WC_RSA_PSS
+
+#if defined(OPENSSL_EXTRA) && !defined(HAVE_SELFTEST) && \
+ (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+static int rsa_pss_calc_salt(int saltLen, int hashLen, int emLen)
+{
+ /* Calculate the salt length to use for special cases. */
+ switch (saltLen) {
+ /* Negative saltLen values are treated differently. */
+ case WC_RSA_PSS_SALTLEN_DIGEST:
+ saltLen = hashLen;
+ break;
+ case WC_RSA_PSS_SALTLEN_MAX_SIGN:
+ case WC_RSA_PSS_SALTLEN_MAX:
+ #ifdef WOLFSSL_PSS_LONG_SALT
+ saltLen = emLen - hashLen - 2;
+ #else
+ saltLen = hashLen;
+ (void)emLen;
+ #endif
+ break;
+ default:
+ break;
+ }
+ if (saltLen < 0) {
+ /* log invalid salt, let wolfCrypt handle error */
+ WOLFSSL_ERROR_MSG("invalid saltLen");
+ saltLen = -3; /* for wolfCrypt to produce error must be < -2 */
+ }
+ return saltLen;
+}
+#endif /* OPENSSL_EXTRA && !HAVE_SELFTEST */
+
+#if (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \
+ defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX)) && \
+ (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+
+/* Add PKCS#1 PSS padding to hash.
+ *
+ *
+ * +-----------+
+ * | M |
+ * +-----------+
+ * |
+ * V
+ * Hash
+ * |
+ * V
+ * +--------+----------+----------+
+ * M' = |Padding1| mHash | salt |
+ * +--------+----------+----------+
+ * |
+ * +--------+----------+ V
+ * DB = |Padding2|maskedseed| Hash
+ * +--------+----------+ |
+ * | |
+ * V | +--+
+ * xor <--- MGF <---| |bc|
+ * | | +--+
+ * | | |
+ * V V V
+ * +-------------------+----------+--+
+ * EM = | maskedDB |maskedseed|bc|
+ * +-------------------+----------+--+
+ * Diagram taken from https://tools.ietf.org/html/rfc3447#section-9.1
+ *
+ * @param [in] rsa RSA key.
+ * @param [out] em Encoded message.
+ * @param [in[ mHash Message hash.
+ * @param [in] hashAlg Hash algorithm.
+ * @param [in] mgf1Hash MGF algorithm.
+ * @param [in] saltLen Length of salt to generate.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+
+int wolfSSL_RSA_padding_add_PKCS1_PSS_mgf1(WOLFSSL_RSA *rsa, unsigned char *em,
+ const unsigned char *mHash, const WOLFSSL_EVP_MD *hashAlg,
+ const WOLFSSL_EVP_MD *mgf1Hash, int saltLen)
+{
+ int ret = 1;
+ enum wc_HashType hashType = WC_HASH_TYPE_NONE;
+ int hashLen = 0;
+ int emLen = 0;
+ int mgf = 0;
+ int initTmpRng = 0;
+ WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG* tmpRng = NULL;
+#else
+ WC_RNG _tmpRng[1];
+ WC_RNG* tmpRng = _tmpRng;
+#endif
+
+ WOLFSSL_ENTER("wolfSSL_RSA_padding_add_PKCS1_PSS");
+
+ /* Validate parameters. */
+ if ((rsa == NULL) || (em == NULL) || (mHash == NULL) || (hashAlg == NULL)) {
+ ret = 0;
+ }
+
+ if (mgf1Hash == NULL)
+ mgf1Hash = hashAlg;
+
+ if (ret == 1) {
+ /* Get/create an RNG. */
+ rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
+ if (rng == NULL) {
+ WOLFSSL_ERROR_MSG("WOLFSSL_RSA_GetRNG error");
+ ret = 0;
+ }
+ }
+
+ /* TODO: use wolfCrypt RSA key to get emLen and bits? */
+ /* Set the external data from the wolfCrypt RSA key if not done. */
+ if ((ret == 1) && (!rsa->exSet)) {
+ ret = SetRsaExternal(rsa);
+ }
+
+ if (ret == 1) {
+ /* Get the wolfCrypt hash algorithm type. */
+ hashType = EvpMd2MacType(hashAlg);
+ if (hashType > WC_HASH_TYPE_MAX) {
+ WOLFSSL_ERROR_MSG("EvpMd2MacType error");
+ ret = 0;
+ }
+ }
+ if (ret == 1) {
+ /* Get the wolfCrypt MGF algorithm from hash algorithm. */
+ mgf = wc_hash2mgf(EvpMd2MacType(mgf1Hash));
+ if (mgf == WC_MGF1NONE) {
+ WOLFSSL_ERROR_MSG("wc_hash2mgf error");
+ ret = 0;
+ }
+ }
+ if (ret == 1) {
+ /* Get the length of the hash output. */
+ hashLen = wolfSSL_EVP_MD_size(hashAlg);
+ if (hashLen < 0) {
+ WOLFSSL_ERROR_MSG("wolfSSL_EVP_MD_size error");
+ ret = 0;
+ }
+ }
+
+ if (ret == 1) {
+ /* Get length of RSA key - encrypted message length. */
+ emLen = wolfSSL_RSA_size(rsa);
+ if (emLen <= 0) {
+ WOLFSSL_ERROR_MSG("wolfSSL_RSA_size error");
+ ret = 0;
+ }
+ }
+
+ if (ret == 1) {
+ saltLen = rsa_pss_calc_salt(saltLen, hashLen, emLen);
+ }
+
+ if (ret == 1) {
+ /* Generate RSA PKCS#1 PSS padding for hash using wolfCrypt. */
+ if (wc_RsaPad_ex(mHash, (word32)hashLen, em, (word32)emLen,
+ RSA_BLOCK_TYPE_1, rng, WC_RSA_PSS_PAD, hashType, mgf, NULL, 0,
+ saltLen, wolfSSL_BN_num_bits(rsa->n), NULL) != MP_OKAY) {
+ WOLFSSL_ERROR_MSG("wc_RsaPad_ex error");
+ ret = 0;
+ }
+ }
+
+ /* Finalize RNG if initialized in WOLFSSL_RSA_GetRNG(). */
+ if (initTmpRng) {
+ wc_FreeRng(tmpRng);
+ }
+ WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
+
+ return ret;
+}
+
+int wolfSSL_RSA_padding_add_PKCS1_PSS(WOLFSSL_RSA *rsa, unsigned char *em,
+ const unsigned char *mHash, const WOLFSSL_EVP_MD *hashAlg, int saltLen)
+{
+ return wolfSSL_RSA_padding_add_PKCS1_PSS_mgf1(rsa, em, mHash, hashAlg, NULL,
+ saltLen);
+}
+
+/* Checks that the hash is valid for the RSA PKCS#1 PSS encoded message.
+ *
+ * Refer to wolfSSL_RSA_padding_add_PKCS1_PSS for a diagram.
+ *
+ * @param [in] rsa RSA key.
+ * @param [in[ mHash Message hash.
+ * @param [in] hashAlg Hash algorithm.
+ * @param [in] mgf1Hash MGF algorithm.
+ * @param [in] em Encoded message.
+ * @param [in] saltLen Length of salt to generate.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_RSA_verify_PKCS1_PSS_mgf1(WOLFSSL_RSA *rsa,
+ const unsigned char *mHash, const WOLFSSL_EVP_MD *hashAlg,
+ const WOLFSSL_EVP_MD *mgf1Hash, const unsigned char *em, int saltLen)
+{
+ int ret = 1;
+ int hashLen = 0;
+ int mgf = 0;
+ int emLen = 0;
+ int mPrimeLen = 0;
+ enum wc_HashType hashType = WC_HASH_TYPE_NONE;
+ byte *mPrime = NULL;
+ byte *buf = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_verify_PKCS1_PSS");
+
+ /* Validate parameters. */
+ if ((rsa == NULL) || (mHash == NULL) || (hashAlg == NULL) || (em == NULL)) {
+ ret = 0;
+ }
+
+ if (mgf1Hash == NULL)
+ mgf1Hash = hashAlg;
+
+ /* TODO: use wolfCrypt RSA key to get emLen and bits? */
+ /* Set the external data from the wolfCrypt RSA key if not done. */
+ if ((ret == 1) && (!rsa->exSet)) {
+ ret = SetRsaExternal(rsa);
+ }
+
+ if (ret == 1) {
+ /* Get hash length for hash algorithm. */
+ hashLen = wolfSSL_EVP_MD_size(hashAlg);
+ if (hashLen < 0) {
+ ret = 0;
+ }
+ }
+
+ if (ret == 1) {
+ /* Get length of RSA key - encrypted message length. */
+ emLen = wolfSSL_RSA_size(rsa);
+ if (emLen <= 0) {
+ WOLFSSL_ERROR_MSG("wolfSSL_RSA_size error");
+ ret = 0;
+ }
+ }
+
+ if (ret == 1) {
+ saltLen = rsa_pss_calc_salt(saltLen, hashLen, emLen);
+ }
+
+ if (ret == 1) {
+ /* Get the wolfCrypt hash algorithm type. */
+ hashType = EvpMd2MacType(hashAlg);
+ if (hashType > WC_HASH_TYPE_MAX) {
+ WOLFSSL_ERROR_MSG("EvpMd2MacType error");
+ ret = 0;
+ }
+ }
+
+ if (ret == 1) {
+ /* Get the wolfCrypt MGF algorithm from hash algorithm. */
+ if ((mgf = wc_hash2mgf(EvpMd2MacType(mgf1Hash))) == WC_MGF1NONE) {
+ WOLFSSL_ERROR_MSG("wc_hash2mgf error");
+ ret = 0;
+ }
+ }
+
+ if (ret == 1) {
+ /* Allocate buffer to unpad inline with. */
+ buf = (byte*)XMALLOC((size_t)emLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (buf == NULL) {
+ WOLFSSL_ERROR_MSG("malloc error");
+ ret = 0;
+ }
+ }
+
+ if (ret == 1) {
+ /* Copy encrypted message to temp for inline unpadding. */
+ XMEMCPY(buf, em, (size_t)emLen);
+
+ /* Remove and verify the PSS padding. */
+ mPrimeLen = wc_RsaUnPad_ex(buf, (word32)emLen, &mPrime,
+ RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD, hashType, mgf, NULL, 0, saltLen,
+ wolfSSL_BN_num_bits(rsa->n), NULL);
+ if (mPrimeLen < 0) {
+ WOLFSSL_ERROR_MSG("wc_RsaPad_ex error");
+ ret = 0;
+ }
+ }
+
+ if (ret == 1) {
+ /* Verify the hash is correct. */
+ if (wc_RsaPSS_CheckPadding_ex(mHash, (word32)hashLen, mPrime,
+ (word32)mPrimeLen, hashType, saltLen,
+ wolfSSL_BN_num_bits(rsa->n)) != MP_OKAY) {
+ WOLFSSL_ERROR_MSG("wc_RsaPSS_CheckPadding_ex error");
+ ret = 0;
+ }
+ }
+
+ /* Dispose of any allocated buffer. */
+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+}
+
+int wolfSSL_RSA_verify_PKCS1_PSS(WOLFSSL_RSA *rsa, const unsigned char *mHash,
+ const WOLFSSL_EVP_MD *hashAlg,
+ const unsigned char *em, int saltLen)
+{
+ return wolfSSL_RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, hashAlg, NULL, em,
+ saltLen);
+}
+#endif /* (!HAVE_FIPS || FIPS_VERSION_GT(2,0)) && \
+ (OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_NGINX) */
+#endif /* WC_RSA_PSS */
+
+/*
+ * RSA sign/verify APIs
+ */
+
+#if defined(WC_RSA_PSS) && !defined(HAVE_SELFTEST) && \
+ (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,1))
+ #ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER
+ #define DEF_PSS_SALT_LEN RSA_PSS_SALT_LEN_DEFAULT
+ #else
+ #define DEF_PSS_SALT_LEN RSA_PSS_SALT_LEN_DISCOVER
+ #endif
+#else
+ #define DEF_PSS_SALT_LEN 0 /* not used */
+#endif
+
+#if defined(OPENSSL_EXTRA)
+
+/* Encode the message hash.
+ *
+ * Used by signing and verification.
+ *
+ * @param [in] hashAlg Hash algorithm OID.
+ * @param [in] hash Hash of message to encode for signing.
+ * @param [in] hLen Length of hash of message.
+ * @param [out] enc Encoded message hash.
+ * @param [out] encLen Length of encoded message hash.
+ * @param [in] padding Which padding scheme is being used.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+static int wolfssl_rsa_sig_encode(int hashAlg, const unsigned char* hash,
+ unsigned int hLen, unsigned char* enc, unsigned int* encLen, int padding)
+{
+ int ret = 1;
+ int hType = WC_HASH_TYPE_NONE;
+
+ /* Validate parameters. */
+ if ((hash == NULL) || (enc == NULL) || (encLen == NULL)) {
+ ret = 0;
+ }
+
+ if ((ret == 1) && (hashAlg != WC_NID_undef) &&
+ (padding == WC_RSA_PKCS1_PADDING)) {
+ /* Convert hash algorithm to hash type for PKCS#1.5 padding. */
+ hType = (int)nid2oid(hashAlg, oidHashType);
+ if (hType == -1) {
+ ret = 0;
+ }
+ }
+ if ((ret == 1) && (padding == WC_RSA_PKCS1_PADDING)) {
+ /* PKCS#1.5 encoding. */
+ word32 encSz = wc_EncodeSignature(enc, hash, hLen, hType);
+ if (encSz == 0) {
+ WOLFSSL_ERROR_MSG("Bad Encode Signature");
+ ret = 0;
+ }
+ else {
+ *encLen = (unsigned int)encSz;
+ }
+ }
+ /* Other padding schemes require the hash as is. */
+ if ((ret == 1) && (padding != WC_RSA_PKCS1_PADDING)) {
+ XMEMCPY(enc, hash, hLen);
+ *encLen = hLen;
+ }
+
+ return ret;
+}
+
+/* Sign the message hash using hash algorithm and RSA key.
+ *
+ * @param [in] hashAlg Hash algorithm OID.
+ * @param [in] hash Hash of message to encode for signing.
+ * @param [in] hLen Length of hash of message.
+ * @param [out] enc Encoded message hash.
+ * @param [out] encLen Length of encoded message hash.
+ * @param [in] rsa RSA key.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_RSA_sign(int hashAlg, const unsigned char* hash, unsigned int hLen,
+ unsigned char* sigRet, unsigned int* sigLen, WOLFSSL_RSA* rsa)
+{
+ if (sigLen != NULL) {
+ /* No size checking in this API */
+ *sigLen = RSA_MAX_SIZE / CHAR_BIT;
+ }
+ /* flag is 1: output complete signature. */
+ return wolfSSL_RSA_sign_generic_padding(hashAlg, hash, hLen, sigRet,
+ sigLen, rsa, 1, WC_RSA_PKCS1_PADDING);
+}
+
+/* Sign the message hash using hash algorithm and RSA key.
+ *
+ * Not OpenSSL API.
+ *
+ * @param [in] hashAlg Hash algorithm NID.
+ * @param [in] hash Hash of message to encode for signing.
+ * @param [in] hLen Length of hash of message.
+ * @param [out] enc Encoded message hash.
+ * @param [out] encLen Length of encoded message hash.
+ * @param [in] rsa RSA key.
+ * @param [in] flag When 1: Output encrypted signature.
+ * When 0: Output encoded hash.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_RSA_sign_ex(int hashAlg, const unsigned char* hash,
+ unsigned int hLen, unsigned char* sigRet, unsigned int* sigLen,
+ WOLFSSL_RSA* rsa, int flag)
+{
+ int ret = 0;
+
+ if ((flag == 0) || (flag == 1)) {
+ if (sigLen != NULL) {
+ /* No size checking in this API */
+ *sigLen = RSA_MAX_SIZE / CHAR_BIT;
+ }
+ ret = wolfSSL_RSA_sign_generic_padding(hashAlg, hash, hLen, sigRet,
+ sigLen, rsa, flag, WC_RSA_PKCS1_PADDING);
+ }
+
+ return ret;
+}
+
+int wolfSSL_RSA_sign_generic_padding(int hashAlg, const unsigned char* hash,
+ unsigned int hLen, unsigned char* sigRet, unsigned int* sigLen,
+ WOLFSSL_RSA* rsa, int flag, int padding)
+{
+ return wolfSSL_RSA_sign_mgf(hashAlg, hash, hLen, sigRet, sigLen, rsa, flag,
+ padding, hashAlg, DEF_PSS_SALT_LEN);
+}
+
+/**
+ * Sign a message hash with the chosen message digest, padding, and RSA key.
+ *
+ * Not OpenSSL API.
+ *
+ * @param [in] hashAlg Hash NID
+ * @param [in] hash Message hash to sign.
+ * @param [in] mLen Length of message hash to sign.
+ * @param [out] sigRet Output buffer.
+ * @param [in, out] sigLen On Input: length of sigRet buffer.
+ * On Output: length of data written to sigRet.
+ * @param [in] rsa RSA key used to sign the input.
+ * @param [in] flag 1: Output the signature.
+ * 0: Output the value that the unpadded signature
+ * should be compared to.
+ * @param [in] padding Padding to use. Only RSA_PKCS1_PSS_PADDING and
+ * WC_RSA_PKCS1_PADDING are currently supported for
+ * signing.
+ * @param [in] mgf1Hash MGF1 Hash NID
+ * @param [in] saltLen Length of RSA PSS salt
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_RSA_sign_mgf(int hashAlg, const unsigned char* hash,
+ unsigned int hLen, unsigned char* sigRet, unsigned int* sigLen,
+ WOLFSSL_RSA* rsa, int flag, int padding, int mgf1Hash, int saltLen)
+{
+ int ret = 1;
+ word32 outLen = 0;
+ int signSz = 0;
+ WC_RNG* rng = NULL;
+ int initTmpRng = 0;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG* tmpRng = NULL;
+ byte* encodedSig = NULL;
+#else
+ WC_RNG _tmpRng[1];
+ WC_RNG* tmpRng = _tmpRng;
+ byte encodedSig[MAX_ENCODED_SIG_SZ];
+#endif
+ unsigned int encSz = 0;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_sign_mgf");
+
+ if (flag == 0) {
+ /* Only encode message. */
+ return wolfssl_rsa_sig_encode(hashAlg, hash, hLen, sigRet, sigLen,
+ padding);
+ }
+
+ /* Validate parameters. */
+ if ((hash == NULL) || (sigRet == NULL) || sigLen == NULL || rsa == NULL) {
+ WOLFSSL_ERROR_MSG("Bad function arguments");
+ ret = 0;
+ }
+
+ /* Set wolfCrypt RSA key data from external if not already done. */
+ if ((ret == 1) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ /* Get the maximum signature length. */
+ outLen = (word32)wolfSSL_BN_num_bytes(rsa->n);
+ /* Check not an error return. */
+ if (outLen == 0) {
+ WOLFSSL_ERROR_MSG("Bad RSA size");
+ ret = 0;
+ }
+ /* Check signature buffer is big enough. */
+ else if (outLen > *sigLen) {
+ WOLFSSL_ERROR_MSG("Output buffer too small");
+ ret = 0;
+ }
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ if (ret == 1) {
+ /* Allocate encoded signature buffer if doing PKCS#1 padding. */
+ encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
+ DYNAMIC_TYPE_SIGNATURE);
+ if (encodedSig == NULL) {
+ ret = 0;
+ }
+ }
+#endif
+
+ if (ret == 1) {
+ /* Get/create an RNG. */
+ rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
+ if (rng == NULL) {
+ WOLFSSL_ERROR_MSG("WOLFSSL_RSA_GetRNG error");
+ ret = 0;
+ }
+ }
+
+ /* Either encodes with PKCS#1.5 or copies hash into encodedSig. */
+ if ((ret == 1) && (wolfssl_rsa_sig_encode(hashAlg, hash, hLen, encodedSig,
+ &encSz, padding) == 0)) {
+ WOLFSSL_ERROR_MSG("Bad Encode Signature");
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ switch (padding) {
+ #if defined(WC_RSA_NO_PADDING) || defined(WC_RSA_DIRECT)
+ case WC_RSA_NO_PAD:
+ if ((signSz = wc_RsaDirect(encodedSig, encSz, sigRet, &outLen,
+ (RsaKey*)rsa->internal, RSA_PRIVATE_ENCRYPT, rng)) <= 0) {
+ WOLFSSL_ERROR_MSG("Bad RSA Sign no pad");
+ ret = 0;
+ }
+ break;
+ #endif
+ #if defined(WC_RSA_PSS) && !defined(HAVE_SELFTEST) && \
+ (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,1))
+ case WC_RSA_PKCS1_PSS_PADDING:
+ {
+ RsaKey* key = (RsaKey*)rsa->internal;
+ enum wc_HashType mgf1, hType;
+ hType = wc_OidGetHash((int)nid2oid(hashAlg, oidHashType));
+ if (mgf1Hash == WC_NID_undef)
+ mgf1Hash = hashAlg;
+ mgf1 = wc_OidGetHash((int)nid2oid(mgf1Hash, oidHashType));
+ /* handle compat layer salt special cases */
+ saltLen = rsa_pss_calc_salt(saltLen, wc_HashGetDigestSize(hType),
+ wolfSSL_RSA_size(rsa));
+
+ /* Create RSA PSS signature. */
+ if ((signSz = wc_RsaPSS_Sign_ex(encodedSig, encSz, sigRet, outLen,
+ hType, wc_hash2mgf(mgf1), saltLen, key, rng)) <= 0) {
+ WOLFSSL_ERROR_MSG("Bad RSA PSS Sign");
+ ret = 0;
+ }
+ break;
+ }
+ #endif
+ #ifndef WC_NO_RSA_OAEP
+ case WC_RSA_PKCS1_OAEP_PADDING:
+ /* Not a signature padding scheme. */
+ WOLFSSL_ERROR_MSG("RSA_PKCS1_OAEP_PADDING not supported for "
+ "signing");
+ ret = 0;
+ break;
+ #endif
+ case WC_RSA_PKCS1_PADDING:
+ {
+ /* Sign (private encrypt) PKCS#1 encoded signature. */
+ if ((signSz = wc_RsaSSL_Sign(encodedSig, encSz, sigRet, outLen,
+ (RsaKey*)rsa->internal, rng)) <= 0) {
+ WOLFSSL_ERROR_MSG("Bad PKCS1 RSA Sign");
+ ret = 0;
+ }
+ break;
+ }
+ default:
+ WOLFSSL_ERROR_MSG("Unsupported padding");
+ (void)mgf1Hash;
+ (void)saltLen;
+ ret = 0;
+ break;
+ }
+ }
+
+ if (ret == 1) {
+ /* Return the size of signature generated. */
+ *sigLen = (unsigned int)signSz;
+ }
+
+ /* Finalize RNG if initialized in WOLFSSL_RSA_GetRNG(). */
+ if (initTmpRng) {
+ wc_FreeRng(tmpRng);
+ }
+ WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
+ WC_FREE_VAR_EX(encodedSig, NULL, DYNAMIC_TYPE_SIGNATURE);
+
+ WOLFSSL_LEAVE("wolfSSL_RSA_sign_mgf", ret);
+ return ret;
+}
+
+/**
+ * Verify a message hash with the chosen message digest, padding, and RSA key.
+ *
+ * @param [in] hashAlg Hash NID
+ * @param [in] hash Message hash.
+ * @param [in] mLen Length of message hash.
+ * @param [in] sigRet Signature data.
+ * @param [in] sigLen Length of signature data.
+ * @param [in] rsa RSA key used to sign the input
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_RSA_verify(int hashAlg, const unsigned char* hash,
+ unsigned int hLen, const unsigned char* sig, unsigned int sigLen,
+ WOLFSSL_RSA* rsa)
+{
+ return wolfSSL_RSA_verify_ex(hashAlg, hash, hLen, sig, sigLen, rsa,
+ WC_RSA_PKCS1_PADDING);
+}
+
+int wolfSSL_RSA_verify_ex(int hashAlg, const unsigned char* hash,
+ unsigned int hLen, const unsigned char* sig, unsigned int sigLen,
+ WOLFSSL_RSA* rsa, int padding)
+{
+ return wolfSSL_RSA_verify_mgf(hashAlg, hash, hLen, sig, sigLen, rsa,
+ padding, hashAlg, DEF_PSS_SALT_LEN);
+}
+
+/**
+ * Verify a message hash with the chosen message digest, padding, and RSA key.
+ *
+ * Not OpenSSL API.
+ *
+ * @param [in] hashAlg Hash NID
+ * @param [in] hash Message hash.
+ * @param [in] mLen Length of message hash.
+ * @param [in] sigRet Signature data.
+ * @param [in] sigLen Length of signature data.
+ * @param [in] rsa RSA key used to sign the input
+ * @param [in] padding Padding to use. Only RSA_PKCS1_PSS_PADDING and
+ * WC_RSA_PKCS1_PADDING are currently supported for
+ * signing.
+ * @param [in] mgf1Hash MGF1 Hash NID
+ * @param [in] saltLen Length of RSA PSS salt
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_RSA_verify_mgf(int hashAlg, const unsigned char* hash,
+ unsigned int hLen, const unsigned char* sig, unsigned int sigLen,
+ WOLFSSL_RSA* rsa, int padding, int mgf1Hash, int saltLen)
+{
+ int ret = 1;
+#ifdef WOLFSSL_SMALL_STACK
+ unsigned char* encodedSig = NULL;
+#else
+ unsigned char encodedSig[MAX_ENCODED_SIG_SZ];
+#endif
+ unsigned char* sigDec = NULL;
+ unsigned int len = MAX_ENCODED_SIG_SZ;
+ int verLen = 0;
+#if (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 1)) && !defined(HAVE_SELFTEST)
+ enum wc_HashType hType = WC_HASH_TYPE_NONE;
+#endif
+
+ WOLFSSL_ENTER("wolfSSL_RSA_verify_mgf");
+
+ /* Validate parameters. */
+ if ((hash == NULL) || (sig == NULL) || (rsa == NULL)) {
+ WOLFSSL_ERROR_MSG("Bad function arguments");
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ /* Allocate memory for decrypted signature. */
+ sigDec = (unsigned char *)XMALLOC(sigLen, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (sigDec == NULL) {
+ WOLFSSL_ERROR_MSG("Memory allocation failure");
+ ret = 0;
+ }
+ }
+ if (ret == 1 && padding == WC_RSA_PKCS1_PSS_PADDING) {
+ #if defined(WC_RSA_PSS) && !defined(HAVE_SELFTEST) && \
+ (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,1))
+ RsaKey* key = (RsaKey*)rsa->internal;
+ enum wc_HashType mgf1;
+ hType = wc_OidGetHash((int)nid2oid(hashAlg, oidHashType));
+ if (mgf1Hash == WC_NID_undef)
+ mgf1Hash = hashAlg;
+ mgf1 = wc_OidGetHash((int)nid2oid(mgf1Hash, oidHashType));
+
+ /* handle compat layer salt special cases */
+ saltLen = rsa_pss_calc_salt(saltLen, wc_HashGetDigestSize(hType),
+ wolfSSL_RSA_size(rsa));
+
+ verLen = wc_RsaPSS_Verify_ex((byte*)sig, sigLen, sigDec, sigLen,
+ hType, wc_hash2mgf(mgf1), saltLen, key);
+ if (verLen > 0) {
+ /* Check PSS padding is valid. */
+ if (wc_RsaPSS_CheckPadding_ex(hash, hLen, sigDec, (word32)verLen,
+ hType, saltLen, mp_count_bits(&key->n)) != 0) {
+ WOLFSSL_ERROR_MSG("wc_RsaPSS_CheckPadding_ex error");
+ ret = WOLFSSL_FAILURE;
+ }
+ else {
+ /* Success! Free resources and return early */
+ XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_SUCCESS;
+ }
+ }
+ else {
+ WOLFSSL_ERROR_MSG("wc_RsaPSS_Verify_ex failed!");
+ ret = WOLFSSL_FAILURE;
+ }
+ #else
+ (void)mgf1Hash;
+ (void)saltLen;
+ WOLFSSL_ERROR_MSG("RSA PSS not compiled in!");
+ ret = WOLFSSL_FAILURE;
+ #endif
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ if (ret == 1) {
+ /* Allocate memory for encoded signature. */
+ encodedSig = (unsigned char *)XMALLOC(len, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (encodedSig == NULL) {
+ WOLFSSL_ERROR_MSG("Memory allocation failure");
+ ret = 0;
+ }
+ }
+#endif
+ if (ret == 1) {
+ /* Make encoded signature to compare with decrypted signature. */
+ if (wolfssl_rsa_sig_encode(hashAlg, hash, hLen, encodedSig, &len,
+ padding) <= 0) {
+ WOLFSSL_ERROR_MSG("Message Digest Error");
+ ret = 0;
+ }
+ }
+ if (ret == 1) {
+ /* Decrypt signature */
+ #if (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 1)) && \
+ !defined(HAVE_SELFTEST)
+ hType = wc_OidGetHash((int)nid2oid(hashAlg, oidHashType));
+ if ((verLen = wc_RsaSSL_Verify_ex2(sig, sigLen, (unsigned char *)sigDec,
+ sigLen, (RsaKey*)rsa->internal, padding, hType)) <= 0) {
+ WOLFSSL_ERROR_MSG("RSA Decrypt error");
+ ret = 0;
+ }
+ #else
+ verLen = wc_RsaSSL_Verify(sig, sigLen, (unsigned char *)sigDec, sigLen,
+ (RsaKey*)rsa->internal);
+ if (verLen < 0) {
+ ret = 0;
+ }
+ #endif
+ }
+ if (ret == 1) {
+ /* Compare decrypted signature to encoded signature. */
+ if (((int)len != verLen) ||
+ (XMEMCMP(encodedSig, sigDec, (size_t)verLen) != 0)) {
+ WOLFSSL_ERROR_MSG("wolfSSL_RSA_verify_ex failed");
+ ret = 0;
+ }
+ }
+
+ /* Dispose of any allocated data. */
+ WC_FREE_VAR_EX(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ WOLFSSL_LEAVE("wolfSSL_RSA_verify_mgf", ret);
+ return ret;
+}
+
+/*
+ * RSA public/private encrypt/decrypt APIs
+ */
+
+/* Encrypt with the RSA public key.
+ *
+ * Return compliant with OpenSSL.
+ *
+ * @param [in] len Length of data to encrypt.
+ * @param [in] from Data to encrypt.
+ * @param [out] to Encrypted data.
+ * @param [in] rsa RSA key.
+ * @param [in] padding Type of padding to place around plaintext.
+ * @return Size of encrypted data on success.
+ * @return -1 on failure.
+ */
+int wolfSSL_RSA_public_encrypt(int len, const unsigned char* from,
+ unsigned char* to, WOLFSSL_RSA* rsa, int padding)
+{
+ int ret = 0;
+ int initTmpRng = 0;
+ WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG* tmpRng = NULL;
+#else
+ WC_RNG _tmpRng[1];
+ WC_RNG* tmpRng = _tmpRng;
+#endif
+#if !defined(HAVE_FIPS)
+ int mgf = WC_MGF1NONE;
+ enum wc_HashType hash = WC_HASH_TYPE_NONE;
+ int pad_type = WC_RSA_NO_PAD;
+#endif
+ int outLen = 0;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_public_encrypt");
+
+ /* Validate parameters. */
+ if ((len < 0) || (rsa == NULL) || (rsa->internal == NULL) ||
+ (from == NULL)) {
+ WOLFSSL_ERROR_MSG("Bad function arguments");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ if (ret == 0) {
+ #if !defined(HAVE_FIPS)
+ /* Convert to wolfCrypt padding, hash and MGF. */
+ switch (padding) {
+ case WC_RSA_PKCS1_PADDING:
+ pad_type = WC_RSA_PKCSV15_PAD;
+ break;
+ case WC_RSA_PKCS1_OAEP_PADDING:
+ pad_type = WC_RSA_OAEP_PAD;
+ hash = WC_HASH_TYPE_SHA;
+ mgf = WC_MGF1SHA1;
+ break;
+ case WC_RSA_NO_PAD:
+ pad_type = WC_RSA_NO_PAD;
+ break;
+ default:
+ WOLFSSL_ERROR_MSG("RSA_public_encrypt doesn't support padding "
+ "scheme");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ #else
+ /* Check for supported padding schemes in FIPS. */
+ /* TODO: Do we support more schemes in later versions of FIPS? */
+ if (padding != WC_RSA_PKCS1_PADDING) {
+ WOLFSSL_ERROR_MSG("RSA_public_encrypt pad type not supported in "
+ "FIPS");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ #endif
+ }
+
+ /* Set wolfCrypt RSA key data from external if not already done. */
+ if ((ret == 0) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ if (ret == 0) {
+ /* Calculate maximum length of encrypted data. */
+ outLen = wolfSSL_RSA_size(rsa);
+ if (outLen == 0) {
+ WOLFSSL_ERROR_MSG("Bad RSA size");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ if (ret == 0) {
+ /* Get an RNG. */
+ rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
+ if (rng == NULL) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ if (ret == 0) {
+ /* Use wolfCrypt to public-encrypt with RSA key. */
+ #if !defined(HAVE_FIPS)
+ ret = wc_RsaPublicEncrypt_ex(from, (word32)len, to, (word32)outLen,
+ (RsaKey*)rsa->internal, rng, pad_type, hash, mgf, NULL, 0);
+ #else
+ ret = wc_RsaPublicEncrypt(from, (word32)len, to, (word32)outLen,
+ (RsaKey*)rsa->internal, rng);
+ #endif
+ }
+
+ /* Finalize RNG if initialized in WOLFSSL_RSA_GetRNG(). */
+ if (initTmpRng) {
+ wc_FreeRng(tmpRng);
+ }
+ WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
+
+ /* wolfCrypt error means return -1. */
+ if (ret <= 0) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ WOLFSSL_LEAVE("wolfSSL_RSA_public_encrypt", ret);
+ return ret;
+}
+
+/* Decrypt with the RSA public key.
+ *
+ * Return compliant with OpenSSL.
+ *
+ * @param [in] len Length of encrypted data.
+ * @param [in] from Encrypted data.
+ * @param [out] to Decrypted data.
+ * @param [in] rsa RSA key.
+ * @param [in] padding Type of padding to around plaintext to remove.
+ * @return Size of decrypted data on success.
+ * @return -1 on failure.
+ */
+int wolfSSL_RSA_private_decrypt(int len, const unsigned char* from,
+ unsigned char* to, WOLFSSL_RSA* rsa, int padding)
+{
+ int ret = 0;
+#if !defined(HAVE_FIPS)
+ int mgf = WC_MGF1NONE;
+ enum wc_HashType hash = WC_HASH_TYPE_NONE;
+ int pad_type = WC_RSA_NO_PAD;
+#endif
+ int outLen = 0;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_private_decrypt");
+
+ /* Validate parameters. */
+ if ((len < 0) || (rsa == NULL) || (rsa->internal == NULL) ||
+ (from == NULL)) {
+ WOLFSSL_ERROR_MSG("Bad function arguments");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ if (ret == 0) {
+ #if !defined(HAVE_FIPS)
+ switch (padding) {
+ case WC_RSA_PKCS1_PADDING:
+ pad_type = WC_RSA_PKCSV15_PAD;
+ break;
+ case WC_RSA_PKCS1_OAEP_PADDING:
+ pad_type = WC_RSA_OAEP_PAD;
+ hash = WC_HASH_TYPE_SHA;
+ mgf = WC_MGF1SHA1;
+ break;
+ case WC_RSA_NO_PAD:
+ pad_type = WC_RSA_NO_PAD;
+ break;
+ default:
+ WOLFSSL_ERROR_MSG("RSA_private_decrypt unsupported padding");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ #else
+ /* Check for supported padding schemes in FIPS. */
+ /* TODO: Do we support more schemes in later versions of FIPS? */
+ if (padding != WC_RSA_PKCS1_PADDING) {
+ WOLFSSL_ERROR_MSG("RSA_public_encrypt pad type not supported in "
+ "FIPS");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ #endif
+ }
+
+ /* Set wolfCrypt RSA key data from external if not already done. */
+ if ((ret == 0) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ if (ret == 0) {
+ /* Calculate maximum length of decrypted data. */
+ outLen = wolfSSL_RSA_size(rsa);
+ if (outLen == 0) {
+ WOLFSSL_ERROR_MSG("Bad RSA size");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ if (ret == 0) {
+ /* Use wolfCrypt to private-decrypt with RSA key.
+ * Size of 'to' buffer must be size of RSA key */
+ #if !defined(HAVE_FIPS)
+ ret = wc_RsaPrivateDecrypt_ex(from, (word32)len, to, (word32)outLen,
+ (RsaKey*)rsa->internal, pad_type, hash, mgf, NULL, 0);
+ #else
+ ret = wc_RsaPrivateDecrypt(from, (word32)len, to, (word32)outLen,
+ (RsaKey*)rsa->internal);
+ #endif
+ }
+
+ /* wolfCrypt error means return -1. */
+ if (ret <= 0) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ WOLFSSL_LEAVE("wolfSSL_RSA_private_decrypt", ret);
+ return ret;
+}
+
+/* Decrypt with the RSA public key.
+ *
+ * @param [in] len Length of encrypted data.
+ * @param [in] from Encrypted data.
+ * @param [out] to Decrypted data.
+ * @param [in] rsa RSA key.
+ * @param [in] padding Type of padding to around plaintext to remove.
+ * @return Size of decrypted data on success.
+ * @return -1 on failure.
+ */
+int wolfSSL_RSA_public_decrypt(int len, const unsigned char* from,
+ unsigned char* to, WOLFSSL_RSA* rsa, int padding)
+{
+ int ret = 0;
+#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+ int pad_type = WC_RSA_NO_PAD;
+#endif
+ int outLen = 0;
+
+ WOLFSSL_ENTER("wolfSSL_RSA_public_decrypt");
+
+ /* Validate parameters. */
+ if ((len < 0) || (rsa == NULL) || (rsa->internal == NULL) ||
+ (from == NULL)) {
+ WOLFSSL_ERROR_MSG("Bad function arguments");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ if (ret == 0) {
+ #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+ switch (padding) {
+ case WC_RSA_PKCS1_PADDING:
+ pad_type = WC_RSA_PKCSV15_PAD;
+ break;
+ case WC_RSA_NO_PAD:
+ pad_type = WC_RSA_NO_PAD;
+ break;
+ /* TODO: RSA_X931_PADDING not supported */
+ default:
+ WOLFSSL_ERROR_MSG("RSA_public_decrypt unsupported padding");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ #else
+ if (padding != WC_RSA_PKCS1_PADDING) {
+ WOLFSSL_ERROR_MSG("RSA_public_decrypt pad type not supported in "
+ "FIPS");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ #endif
+ }
+
+ /* Set wolfCrypt RSA key data from external if not already done. */
+ if ((ret == 0) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ if (ret == 0) {
+ /* Calculate maximum length of encrypted data. */
+ outLen = wolfSSL_RSA_size(rsa);
+ if (outLen == 0) {
+ WOLFSSL_ERROR_MSG("Bad RSA size");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ if (ret == 0) {
+ /* Use wolfCrypt to public-decrypt with RSA key. */
+ #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+ /* Size of 'to' buffer must be size of RSA key. */
+ ret = wc_RsaSSL_Verify_ex(from, (word32)len, to, (word32)outLen,
+ (RsaKey*)rsa->internal, pad_type);
+ #else
+ /* For FIPS v1/v2 only PKCSV15 padding is supported */
+ ret = wc_RsaSSL_Verify(from, (word32)len, to, (word32)outLen,
+ (RsaKey*)rsa->internal);
+ #endif
+ }
+
+ /* wolfCrypt error means return -1. */
+ if (ret <= 0) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ WOLFSSL_LEAVE("wolfSSL_RSA_public_decrypt", ret);
+ return ret;
+}
+
+/* Encrypt with the RSA private key.
+ *
+ * Calls wc_RsaSSL_Sign.
+ *
+ * @param [in] len Length of data to encrypt.
+ * @param [in] from Data to encrypt.
+ * @param [out] to Encrypted data.
+ * @param [in] rsa RSA key.
+ * @param [in] padding Type of padding to place around plaintext.
+ * @return Size of encrypted data on success.
+ * @return -1 on failure.
+ */
+int wolfSSL_RSA_private_encrypt(int len, const unsigned char* from,
+ unsigned char* to, WOLFSSL_RSA* rsa, int padding)
+{
+ int ret = 0;
+ int initTmpRng = 0;
+ WC_RNG *rng = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ WC_RNG* tmpRng = NULL;
+#else
+ WC_RNG _tmpRng[1];
+ WC_RNG* tmpRng = _tmpRng;
+#endif
+
+ WOLFSSL_ENTER("wolfSSL_RSA_private_encrypt");
+
+ /* Validate parameters. */
+ if ((len < 0) || (rsa == NULL) || (rsa->internal == NULL) ||
+ (from == NULL)) {
+ WOLFSSL_ERROR_MSG("Bad function arguments");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ if (ret == 0) {
+ switch (padding) {
+ case WC_RSA_PKCS1_PADDING:
+ #ifdef WC_RSA_NO_PADDING
+ case WC_RSA_NO_PAD:
+ #endif
+ break;
+ /* TODO: RSA_X931_PADDING not supported */
+ default:
+ WOLFSSL_ERROR_MSG("RSA_private_encrypt unsupported padding");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ /* Set wolfCrypt RSA key data from external if not already done. */
+ if ((ret == 0) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+ if (ret == 0) {
+ /* Get an RNG. */
+ rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
+ if (rng == NULL) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ if (ret == 0) {
+ /* Use wolfCrypt to private-encrypt with RSA key.
+ * Size of output buffer must be size of RSA key. */
+ if (padding == WC_RSA_PKCS1_PADDING) {
+ ret = wc_RsaSSL_Sign(from, (word32)len, to,
+ (word32)wolfSSL_RSA_size(rsa), (RsaKey*)rsa->internal, rng);
+ }
+ #ifdef WC_RSA_NO_PADDING
+ else if (padding == WC_RSA_NO_PAD) {
+ word32 outLen = (word32)wolfSSL_RSA_size(rsa);
+ ret = wc_RsaFunction(from, (word32)len, to, &outLen,
+ RSA_PRIVATE_ENCRYPT, (RsaKey*)rsa->internal, rng);
+ if (ret == 0)
+ ret = (int)outLen;
+ }
+ #endif
+ }
+
+ /* Finalize RNG if initialized in WOLFSSL_RSA_GetRNG(). */
+ if (initTmpRng) {
+ wc_FreeRng(tmpRng);
+ }
+ WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
+
+ /* wolfCrypt error means return -1. */
+ if (ret <= 0) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ WOLFSSL_LEAVE("wolfSSL_RSA_private_encrypt", ret);
+ return ret;
+}
+
+/*
+ * RSA misc operation APIs
+ */
+
+/* Calculate d mod p-1 and q-1 into BNs.
+ *
+ * Not OpenSSL API.
+ *
+ * @param [in, out] rsa RSA key.
+ * @return 1 on success.
+ * @return -1 on failure.
+ */
+int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
+{
+ int ret = 1;
+ int err;
+ mp_int* t = NULL;
+ WC_DECLARE_VAR(tmp, mp_int, 1, 0);
+
+ WOLFSSL_ENTER("wolfSSL_RsaGenAdd");
+
+ /* Validate parameters. */
+ if ((rsa == NULL) || (rsa->p == NULL) || (rsa->q == NULL) ||
+ (rsa->d == NULL) || (rsa->dmp1 == NULL) || (rsa->dmq1 == NULL)) {
+ WOLFSSL_ERROR_MSG("rsa no init error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ if (ret == 1) {
+ tmp = (mp_int *)XMALLOC(sizeof(*tmp), rsa->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (tmp == NULL) {
+ WOLFSSL_ERROR_MSG("Memory allocation failure");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+#endif
+
+ if (ret == 1) {
+ /* Initialize temp MP integer. */
+ if (mp_init(tmp) != MP_OKAY) {
+ WOLFSSL_ERROR_MSG("mp_init error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ if (ret == 1) {
+ t = tmp;
+
+ /* Sub 1 from p into temp. */
+ err = mp_sub_d((mp_int*)rsa->p->internal, 1, tmp);
+ if (err != MP_OKAY) {
+ WOLFSSL_ERROR_MSG("mp_sub_d error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+ if (ret == 1) {
+ /* Calculate d mod (p - 1) into dmp1 MP integer of BN. */
+ err = mp_mod((mp_int*)rsa->d->internal, tmp,
+ (mp_int*)rsa->dmp1->internal);
+ if (err != MP_OKAY) {
+ WOLFSSL_ERROR_MSG("mp_mod error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+ if (ret == 1) {
+ /* Sub 1 from q into temp. */
+ err = mp_sub_d((mp_int*)rsa->q->internal, 1, tmp);
+ if (err != MP_OKAY) {
+ WOLFSSL_ERROR_MSG("mp_sub_d error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+ if (ret == 1) {
+ /* Calculate d mod (q - 1) into dmq1 MP integer of BN. */
+ err = mp_mod((mp_int*)rsa->d->internal, tmp,
+ (mp_int*)rsa->dmq1->internal);
+ if (err != MP_OKAY) {
+ WOLFSSL_ERROR_MSG("mp_mod error");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ mp_clear(t);
+
+#ifdef WOLFSSL_SMALL_STACK
+ if (rsa != NULL) {
+ XFREE(tmp, rsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+
+ return ret;
+}
+
+
+#ifndef NO_WOLFSSL_STUB
+/* Enable blinding for RSA key operations.
+ *
+ * Blinding is a compile time option in wolfCrypt.
+ *
+ * @param [in] rsa RSA key. Unused.
+ * @param [in] bnCtx BN context to use for blinding. Unused.
+ * @return 1 always.
+ */
+int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bnCtx)
+{
+ WOLFSSL_STUB("RSA_blinding_on");
+ WOLFSSL_ENTER("wolfSSL_RSA_blinding_on");
+
+ (void)rsa;
+ (void)bnCtx;
+
+ return 1; /* on by default */
+}
+#endif
+
+#endif /* OPENSSL_EXTRA */
+
+#endif /* !NO_RSA */
+
+/*******************************************************************************
+ * END OF RSA API
+ ******************************************************************************/
+
+#endif /* !WOLFSSL_PK_RSA_INCLUDED */
diff --git a/src/ssl.c b/src/ssl.c
index ff0a4eb0e5..bff77b2ec1 100644
--- a/src/ssl.c
+++ b/src/ssl.c
@@ -190,6 +190,12 @@
#define WOLFSSL_SSL_SESS_INCLUDED
#include "src/ssl_sess.c"
+
+#define WOLFSSL_SSL_API_CERT_INCLUDED
+#include "src/ssl_api_cert.c"
+
+#define WOLFSSL_SSL_API_PK_INCLUDED
+#include "src/ssl_api_pk.c"
#endif
#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
@@ -359,6 +365,9 @@ WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local)
#define WOLFSSL_PK_INCLUDED
#include "src/pk.c"
+#define WOLFSSL_EVP_PK_INCLUDED
+#include "wolfcrypt/src/evp_pk.c"
+
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
/* copies over data of "in" to "out" */
static void wolfSSL_CIPHER_copy(WOLFSSL_CIPHER* in, WOLFSSL_CIPHER* out)
@@ -404,710 +413,8 @@ static WOLFSSL_X509_OBJECT* wolfSSL_X509_OBJECT_dup(WOLFSSL_X509_OBJECT* obj)
#include
-#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
-/* create the hpke key and ech config to send to clients */
-int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx, const char* publicName,
- word16 kemId, word16 kdfId, word16 aeadId)
-{
- int ret = 0;
- word16 encLen = DHKEM_X25519_ENC_LEN;
- WOLFSSL_EchConfig* newConfig;
- WOLFSSL_EchConfig* parentConfig;
-#ifdef WOLFSSL_SMALL_STACK
- Hpke* hpke = NULL;
- WC_RNG* rng;
-#else
- Hpke hpke[1];
- WC_RNG rng[1];
-#endif
-
- if (ctx == NULL || publicName == NULL)
- return BAD_FUNC_ARG;
-
- WC_ALLOC_VAR_EX(rng, WC_RNG, 1, ctx->heap, DYNAMIC_TYPE_RNG,
- return MEMORY_E);
- ret = wc_InitRng(rng);
- if (ret != 0) {
- WC_FREE_VAR_EX(rng, ctx->heap, DYNAMIC_TYPE_RNG);
- return ret;
- }
-
- newConfig = (WOLFSSL_EchConfig*)XMALLOC(sizeof(WOLFSSL_EchConfig),
- ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (newConfig == NULL)
- ret = MEMORY_E;
- else
- XMEMSET(newConfig, 0, sizeof(WOLFSSL_EchConfig));
-
- /* set random config id */
- if (ret == 0)
- ret = wc_RNG_GenerateByte(rng, &newConfig->configId);
-
- /* if 0 is selected for algorithms use default, may change with draft */
- if (kemId == 0)
- kemId = DHKEM_X25519_HKDF_SHA256;
-
- if (kdfId == 0)
- kdfId = HKDF_SHA256;
-
- if (aeadId == 0)
- aeadId = HPKE_AES_128_GCM;
-
- if (ret == 0) {
- /* set the kem id */
- newConfig->kemId = kemId;
-
- /* set the cipher suite, only 1 for now */
- newConfig->numCipherSuites = 1;
- newConfig->cipherSuites =
- (EchCipherSuite*)XMALLOC(sizeof(EchCipherSuite), ctx->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
-
- if (newConfig->cipherSuites == NULL) {
- ret = MEMORY_E;
- }
- else {
- newConfig->cipherSuites[0].kdfId = kdfId;
- newConfig->cipherSuites[0].aeadId = aeadId;
- }
- }
-
-#ifdef WOLFSSL_SMALL_STACK
- if (ret == 0) {
- hpke = (Hpke*)XMALLOC(sizeof(Hpke), ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (hpke == NULL)
- ret = MEMORY_E;
- }
-#endif
-
- if (ret == 0)
- ret = wc_HpkeInit(hpke, kemId, kdfId, aeadId, ctx->heap);
-
- /* generate the receiver private key */
- if (ret == 0)
- ret = wc_HpkeGenerateKeyPair(hpke, &newConfig->receiverPrivkey, rng);
-
- /* done with RNG */
- wc_FreeRng(rng);
-
- /* serialize the receiver key */
- if (ret == 0)
- ret = wc_HpkeSerializePublicKey(hpke, newConfig->receiverPrivkey,
- newConfig->receiverPubkey, &encLen);
-
- if (ret == 0) {
- newConfig->publicName = (char*)XMALLOC(XSTRLEN(publicName) + 1,
- ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (newConfig->publicName == NULL) {
- ret = MEMORY_E;
- }
- else {
- XMEMCPY(newConfig->publicName, publicName,
- XSTRLEN(publicName) + 1);
- }
- }
-
- if (ret != 0) {
- if (newConfig) {
- XFREE(newConfig->cipherSuites, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(newConfig->publicName, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(newConfig, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
- }
- else {
- parentConfig = ctx->echConfigs;
-
- if (parentConfig == NULL) {
- ctx->echConfigs = newConfig;
- }
- else {
- while (parentConfig->next != NULL) {
- parentConfig = parentConfig->next;
- }
-
- parentConfig->next = newConfig;
- }
- }
-
- if (ret == 0)
- ret = WOLFSSL_SUCCESS;
-
- WC_FREE_VAR_EX(hpke, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
- WC_FREE_VAR_EX(rng, ctx->heap, DYNAMIC_TYPE_RNG);
-
- return ret;
-}
-
-int wolfSSL_CTX_SetEchConfigsBase64(WOLFSSL_CTX* ctx, const char* echConfigs64,
- word32 echConfigs64Len)
-{
- int ret = 0;
- word32 decodedLen = echConfigs64Len * 3 / 4 + 1;
- byte* decodedConfigs;
-
- if (ctx == NULL || echConfigs64 == NULL || echConfigs64Len == 0)
- return BAD_FUNC_ARG;
-
- decodedConfigs = (byte*)XMALLOC(decodedLen, ctx->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
-
- if (decodedConfigs == NULL)
- return MEMORY_E;
-
- decodedConfigs[decodedLen - 1] = 0;
-
- /* decode the echConfigs */
- ret = Base64_Decode((const byte*)echConfigs64, echConfigs64Len,
- decodedConfigs, &decodedLen);
-
- if (ret != 0) {
- XFREE(decodedConfigs, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
- }
-
- ret = wolfSSL_CTX_SetEchConfigs(ctx, decodedConfigs, decodedLen);
-
- XFREE(decodedConfigs, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
-
- return ret;
-}
-
-int wolfSSL_CTX_SetEchConfigs(WOLFSSL_CTX* ctx, const byte* echConfigs,
- word32 echConfigsLen)
-{
- int ret;
-
- if (ctx == NULL || echConfigs == NULL || echConfigsLen == 0)
- return BAD_FUNC_ARG;
-
- FreeEchConfigs(ctx->echConfigs, ctx->heap);
- ctx->echConfigs = NULL;
- ret = SetEchConfigsEx(&ctx->echConfigs, ctx->heap, echConfigs,
- echConfigsLen);
-
- if (ret == 0)
- return WOLFSSL_SUCCESS;
-
- return ret;
-}
-
-/* get the ech configs that the server context is using */
-int wolfSSL_CTX_GetEchConfigs(WOLFSSL_CTX* ctx, byte* output,
- word32* outputLen) {
- if (ctx == NULL || outputLen == NULL)
- return BAD_FUNC_ARG;
-
- /* if we don't have ech configs */
- if (ctx->echConfigs == NULL)
- return WOLFSSL_FATAL_ERROR;
-
- return GetEchConfigsEx(ctx->echConfigs, output, outputLen);
-}
-
-void wolfSSL_CTX_SetEchEnable(WOLFSSL_CTX* ctx, byte enable)
-{
- if (ctx != NULL) {
- ctx->disableECH = !enable;
- if (ctx->disableECH) {
- TLSX_Remove(&ctx->extensions, TLSX_ECH, ctx->heap);
- FreeEchConfigs(ctx->echConfigs, ctx->heap);
- ctx->echConfigs = NULL;
- }
- }
-}
-
-/* set the ech config from base64 for our client ssl object, base64 is the
- * format ech configs are sent using dns records */
-int wolfSSL_SetEchConfigsBase64(WOLFSSL* ssl, char* echConfigs64,
- word32 echConfigs64Len)
-{
- int ret = 0;
- word32 decodedLen = echConfigs64Len * 3 / 4 + 1;
- byte* decodedConfigs;
-
- if (ssl == NULL || echConfigs64 == NULL || echConfigs64Len == 0)
- return BAD_FUNC_ARG;
-
- /* already have ech configs */
- if (ssl->options.useEch == 1) {
- return WOLFSSL_FATAL_ERROR;
- }
-
- decodedConfigs = (byte*)XMALLOC(decodedLen, ssl->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
-
- if (decodedConfigs == NULL)
- return MEMORY_E;
-
- decodedConfigs[decodedLen - 1] = 0;
-
- /* decode the echConfigs */
- ret = Base64_Decode((byte*)echConfigs64, echConfigs64Len,
- decodedConfigs, &decodedLen);
-
- if (ret != 0) {
- XFREE(decodedConfigs, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
- }
-
- ret = wolfSSL_SetEchConfigs(ssl, decodedConfigs, decodedLen);
-
- XFREE(decodedConfigs, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
-
- return ret;
-}
-
-/* set the ech config from a raw buffer, this is the format ech configs are
- * sent using retry_configs from the ech server */
-int wolfSSL_SetEchConfigs(WOLFSSL* ssl, const byte* echConfigs,
- word32 echConfigsLen)
-{
- int ret;
-
- if (ssl == NULL || echConfigs == NULL || echConfigsLen == 0)
- return BAD_FUNC_ARG;
-
- /* already have ech configs */
- if (ssl->options.useEch == 1) {
- return WOLFSSL_FATAL_ERROR;
- }
-
- ret = SetEchConfigsEx(&ssl->echConfigs, ssl->heap, echConfigs,
- echConfigsLen);
-
- /* if we found valid configs */
- if (ret == 0) {
- ssl->options.useEch = 1;
- return WOLFSSL_SUCCESS;
- }
-
- return ret;
-}
-
-/* get the raw ech config from our struct */
-int GetEchConfig(WOLFSSL_EchConfig* config, byte* output, word32* outputLen)
-{
- int i;
- word16 totalLen = 0;
-
- if (config == NULL || (output == NULL && outputLen == NULL))
- return BAD_FUNC_ARG;
-
- /* 2 for version */
- totalLen += 2;
- /* 2 for length */
- totalLen += 2;
- /* 1 for configId */
- totalLen += 1;
- /* 2 for kemId */
- totalLen += 2;
- /* 2 for hpke_len */
- totalLen += 2;
-
- /* hpke_pub_key */
- switch (config->kemId) {
- case DHKEM_P256_HKDF_SHA256:
- totalLen += DHKEM_P256_ENC_LEN;
- break;
- case DHKEM_P384_HKDF_SHA384:
- totalLen += DHKEM_P384_ENC_LEN;
- break;
- case DHKEM_P521_HKDF_SHA512:
- totalLen += DHKEM_P521_ENC_LEN;
- break;
- case DHKEM_X25519_HKDF_SHA256:
- totalLen += DHKEM_X25519_ENC_LEN;
- break;
- case DHKEM_X448_HKDF_SHA512:
- totalLen += DHKEM_X448_ENC_LEN;
- break;
- }
-
- /* cipherSuitesLen */
- totalLen += 2;
- /* cipherSuites */
- totalLen += config->numCipherSuites * 4;
- /* public name len */
- totalLen += 2;
-
- /* public name */
- totalLen += XSTRLEN(config->publicName);
- /* trailing zeros */
- totalLen += 2;
-
- if (output == NULL) {
- *outputLen = totalLen;
- return WC_NO_ERR_TRACE(LENGTH_ONLY_E);
- }
-
- if (totalLen > *outputLen) {
- *outputLen = totalLen;
- return INPUT_SIZE_E;
- }
-
- /* version */
- c16toa(TLSX_ECH, output);
- output += 2;
-
- /* length - 4 for version and length itself */
- c16toa(totalLen - 4, output);
- output += 2;
-
- /* configId */
- *output = config->configId;
- output++;
- /* kemId */
- c16toa(config->kemId, output);
- output += 2;
-
- /* length and key itself */
- switch (config->kemId) {
- case DHKEM_P256_HKDF_SHA256:
- c16toa(DHKEM_P256_ENC_LEN, output);
- output += 2;
- XMEMCPY(output, config->receiverPubkey, DHKEM_P256_ENC_LEN);
- output += DHKEM_P256_ENC_LEN;
- break;
- case DHKEM_P384_HKDF_SHA384:
- c16toa(DHKEM_P384_ENC_LEN, output);
- output += 2;
- XMEMCPY(output, config->receiverPubkey, DHKEM_P384_ENC_LEN);
- output += DHKEM_P384_ENC_LEN;
- break;
- case DHKEM_P521_HKDF_SHA512:
- c16toa(DHKEM_P521_ENC_LEN, output);
- output += 2;
- XMEMCPY(output, config->receiverPubkey, DHKEM_P521_ENC_LEN);
- output += DHKEM_P521_ENC_LEN;
- break;
- case DHKEM_X25519_HKDF_SHA256:
- c16toa(DHKEM_X25519_ENC_LEN, output);
- output += 2;
- XMEMCPY(output, config->receiverPubkey, DHKEM_X25519_ENC_LEN);
- output += DHKEM_X25519_ENC_LEN;
- break;
- case DHKEM_X448_HKDF_SHA512:
- c16toa(DHKEM_X448_ENC_LEN, output);
- output += 2;
- XMEMCPY(output, config->receiverPubkey, DHKEM_X448_ENC_LEN);
- output += DHKEM_X448_ENC_LEN;
- break;
- }
-
- /* cipherSuites len */
- c16toa(config->numCipherSuites * 4, output);
- output += 2;
-
- /* cipherSuites */
- for (i = 0; i < config->numCipherSuites; i++) {
- c16toa(config->cipherSuites[i].kdfId, output);
- output += 2;
- c16toa(config->cipherSuites[i].aeadId, output);
- output += 2;
- }
-
- /* set maximum name length to 0 */
- *output = 0;
- output++;
-
- /* publicName len */
- *output = XSTRLEN(config->publicName);
- output++;
-
- /* publicName */
- XMEMCPY(output, config->publicName,
- XSTRLEN(config->publicName));
- output += XSTRLEN(config->publicName);
-
- /* terminating zeros */
- c16toa(0, output);
- /* output += 2; */
-
- *outputLen = totalLen;
-
- return 0;
-}
-
-/* wrapper function to get ech configs from application code */
-int wolfSSL_GetEchConfigs(WOLFSSL* ssl, byte* output, word32* outputLen)
-{
- if (ssl == NULL || outputLen == NULL)
- return BAD_FUNC_ARG;
-
- /* if we don't have ech configs */
- if (ssl->options.useEch != 1) {
- return WOLFSSL_FATAL_ERROR;
- }
-
- return GetEchConfigsEx(ssl->echConfigs, output, outputLen);
-}
-
-void wolfSSL_SetEchEnable(WOLFSSL* ssl, byte enable)
-{
- if (ssl != NULL) {
- ssl->options.disableECH = !enable;
- if (ssl->options.disableECH) {
- TLSX_Remove(&ssl->extensions, TLSX_ECH, ssl->heap);
- FreeEchConfigs(ssl->echConfigs, ssl->heap);
- ssl->echConfigs = NULL;
- }
- }
-}
-
-int SetEchConfigsEx(WOLFSSL_EchConfig** outputConfigs, void* heap,
- const byte* echConfigs, word32 echConfigsLen)
-{
- int ret = 0;
- int i;
- int j;
- word16 totalLength;
- word16 version;
- word16 length;
- word16 hpkePubkeyLen;
- word16 cipherSuitesLen;
- word16 publicNameLen;
- WOLFSSL_EchConfig* configList = NULL;
- WOLFSSL_EchConfig* workingConfig = NULL;
- WOLFSSL_EchConfig* lastConfig = NULL;
- byte* echConfig = NULL;
-
- if (outputConfigs == NULL || echConfigs == NULL || echConfigsLen == 0)
- return BAD_FUNC_ARG;
-
- /* check that the total length is well formed */
- ato16(echConfigs, &totalLength);
-
- if (totalLength != echConfigsLen - 2) {
- return WOLFSSL_FATAL_ERROR;
- }
-
- /* skip the total length uint16_t */
- i = 2;
-
- do {
- echConfig = (byte*)echConfigs + i;
- ato16(echConfig, &version);
- ato16(echConfig + 2, &length);
-
- /* if the version does not match */
- if (version != TLSX_ECH) {
- /* we hit the end of the configs */
- if ( (word32)i + 2 >= echConfigsLen ) {
- break;
- }
-
- /* skip this config, +4 for version and length */
- i += length + 4;
- continue;
- }
-
- /* check if the length will overrun the buffer */
- if ((word32)i + length + 4 > echConfigsLen) {
- break;
- }
-
- if (workingConfig == NULL) {
- workingConfig =
- (WOLFSSL_EchConfig*)XMALLOC(sizeof(WOLFSSL_EchConfig), heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- configList = workingConfig;
- if (workingConfig != NULL) {
- workingConfig->next = NULL;
- }
- }
- else {
- lastConfig = workingConfig;
- workingConfig->next =
- (WOLFSSL_EchConfig*)XMALLOC(sizeof(WOLFSSL_EchConfig),
- heap, DYNAMIC_TYPE_TMP_BUFFER);
- workingConfig = workingConfig->next;
- }
-
- if (workingConfig == NULL) {
- ret = MEMORY_E;
- break;
- }
-
- XMEMSET(workingConfig, 0, sizeof(WOLFSSL_EchConfig));
-
- /* rawLen */
- workingConfig->rawLen = length + 4;
-
- /* raw body */
- workingConfig->raw = (byte*)XMALLOC(workingConfig->rawLen,
- heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (workingConfig->raw == NULL) {
- ret = MEMORY_E;
- break;
- }
-
- XMEMCPY(workingConfig->raw, echConfig, workingConfig->rawLen);
-
- /* skip over version and length */
- echConfig += 4;
-
- /* configId, 1 byte */
- workingConfig->configId = *(echConfig);
- echConfig++;
- /* kemId, 2 bytes */
- ato16(echConfig, &workingConfig->kemId);
- echConfig += 2;
- /* hpke public_key length, 2 bytes */
- ato16(echConfig, &hpkePubkeyLen);
- echConfig += 2;
- /* hpke public_key */
- XMEMCPY(workingConfig->receiverPubkey, echConfig, hpkePubkeyLen);
- echConfig += hpkePubkeyLen;
- /* cipherSuitesLen */
- ato16(echConfig, &cipherSuitesLen);
-
- workingConfig->cipherSuites = (EchCipherSuite*)XMALLOC(cipherSuitesLen,
- heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (workingConfig->cipherSuites == NULL) {
- ret = MEMORY_E;
- break;
- }
-
- echConfig += 2;
- workingConfig->numCipherSuites = cipherSuitesLen / 4;
- /* cipherSuites */
- for (j = 0; j < workingConfig->numCipherSuites; j++) {
- ato16(echConfig + j * 4, &workingConfig->cipherSuites[j].kdfId);
- ato16(echConfig + j * 4 + 2,
- &workingConfig->cipherSuites[j].aeadId);
- }
- echConfig += cipherSuitesLen;
- /* ignore the maximum name length */
- echConfig++;
- /* publicNameLen */
- publicNameLen = *(echConfig);
- workingConfig->publicName = (char*)XMALLOC(publicNameLen + 1,
- heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (workingConfig->publicName == NULL) {
- ret = MEMORY_E;
- break;
- }
- echConfig++;
- /* publicName */
- XMEMCPY(workingConfig->publicName, echConfig, publicNameLen);
- /* null terminated */
- workingConfig->publicName[publicNameLen] = 0;
-
- /* add length to go to next config, +4 for version and length */
- i += length + 4;
-
- /* check that we support this config */
- for (j = 0; j < HPKE_SUPPORTED_KEM_LEN; j++) {
- if (hpkeSupportedKem[j] == workingConfig->kemId)
- break;
- }
-
- /* if we don't support the kem or at least one cipher suite */
- if (j >= HPKE_SUPPORTED_KEM_LEN ||
- EchConfigGetSupportedCipherSuite(workingConfig) < 0)
- {
- XFREE(workingConfig->cipherSuites, heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(workingConfig->publicName, heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(workingConfig->raw, heap, DYNAMIC_TYPE_TMP_BUFFER);
- workingConfig = lastConfig;
- }
- } while ((word32)i < echConfigsLen);
-
- /* if we found valid configs */
- if (ret == 0 && configList != NULL) {
- *outputConfigs = configList;
-
- return ret;
- }
-
- workingConfig = configList;
-
- while (workingConfig != NULL) {
- lastConfig = workingConfig;
- workingConfig = workingConfig->next;
-
- XFREE(lastConfig->cipherSuites, heap, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(lastConfig->publicName, heap, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(lastConfig->raw, heap, DYNAMIC_TYPE_TMP_BUFFER);
-
- XFREE(lastConfig, heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
-
- if (ret == 0)
- return WOLFSSL_FATAL_ERROR;
-
- return ret;
-}
-
-/* get the raw ech configs from our linked list of ech config structs */
-int GetEchConfigsEx(WOLFSSL_EchConfig* configs, byte* output, word32* outputLen)
-{
- int ret = 0;
- WOLFSSL_EchConfig* workingConfig = NULL;
- byte* outputStart = output;
- word32 totalLen = 2;
- word32 workingOutputLen = 0;
-
- if (configs == NULL || outputLen == NULL ||
- (output != NULL && *outputLen < totalLen)) {
- return BAD_FUNC_ARG;
- }
-
-
- /* skip over total length which we fill in later */
- if (output != NULL) {
- workingOutputLen = *outputLen - totalLen;
- output += 2;
- }
- else {
- /* caller getting the size only, set current 2 byte length size */
- *outputLen = totalLen;
- }
-
- workingConfig = configs;
-
- while (workingConfig != NULL) {
- /* get this config */
- ret = GetEchConfig(workingConfig, output, &workingOutputLen);
-
- if (output != NULL)
- output += workingOutputLen;
-
- /* add this config's length to the total length */
- totalLen += workingOutputLen;
-
- if (totalLen > *outputLen)
- workingOutputLen = 0;
- else
- workingOutputLen = *outputLen - totalLen;
-
- /* only error we break on, other 2 we need to keep finding length */
- if (ret == WC_NO_ERR_TRACE(BAD_FUNC_ARG))
- return BAD_FUNC_ARG;
-
- workingConfig = workingConfig->next;
- }
-
- if (output == NULL) {
- *outputLen = totalLen;
- return WC_NO_ERR_TRACE(LENGTH_ONLY_E);
- }
-
- if (totalLen > *outputLen) {
- *outputLen = totalLen;
- return INPUT_SIZE_E;
- }
-
- /* total size -2 for size itself */
- c16toa(totalLen - 2, outputStart);
-
- *outputLen = totalLen;
-
- return WOLFSSL_SUCCESS;
-}
-#endif /* WOLFSSL_TLS13 && HAVE_ECH */
+#define WOLFSSL_SSL_ECH_INCLUDED
+#include "src/ssl_ech.c"
#ifdef OPENSSL_EXTRA
static int wolfSSL_parse_cipher_list(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
@@ -1858,48 +1165,6 @@ int wolfSSL_dtls(WOLFSSL* ssl)
return dtlsOpt;
}
-#if !defined(NO_CERTS)
-/* Set whether mutual authentication is required for connections.
- * Server side only.
- *
- * ctx The SSL/TLS CTX object.
- * req 1 to indicate required and 0 when not.
- * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a server and
- * 0 on success.
- */
-int wolfSSL_CTX_mutual_auth(WOLFSSL_CTX* ctx, int req)
-{
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- if (ctx->method->side != WOLFSSL_SERVER_END)
- return SIDE_ERROR;
-
- ctx->mutualAuth = (byte)req;
-
- return 0;
-}
-
-/* Set whether mutual authentication is required for the connection.
- * Server side only.
- *
- * ssl The SSL/TLS object.
- * req 1 to indicate required and 0 when not.
- * returns BAD_FUNC_ARG when ssl is NULL and
- * SIDE_ERROR when not a server and 0 on success.
- */
-int wolfSSL_mutual_auth(WOLFSSL* ssl, int req)
-{
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- if (ssl->options.side != WOLFSSL_SERVER_END)
- return SIDE_ERROR;
-
- ssl->options.mutualAuth = (word16)req;
-
- return 0;
-}
-#endif /* NO_CERTS */
-
#ifdef WOLFSSL_WOLFSENTRY_HOOKS
int wolfSSL_CTX_set_AcceptFilter(
@@ -3666,60 +2931,6 @@ int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx)
#endif /* NO_WOLFSSL_CLIENT */
#endif /* HAVE_TRUNCATED_HMAC */
-#ifndef NO_WOLFSSL_CLIENT
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
-
-int wolfSSL_UseOCSPStapling(WOLFSSL* ssl, byte status_type, byte options)
-{
- WOLFSSL_ENTER("wolfSSL_UseOCSPStapling");
-
- if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END)
- return BAD_FUNC_ARG;
-
- return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type,
- options, NULL, ssl->heap, ssl->devId);
-}
-
-
-int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx, byte status_type,
- byte options)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_UseOCSPStapling");
-
- if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
- return BAD_FUNC_ARG;
-
- return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type,
- options, NULL, ctx->heap, ctx->devId);
-}
-
-#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
-
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
-
-int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl, byte status_type, byte options)
-{
- if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END)
- return BAD_FUNC_ARG;
-
- return TLSX_UseCertificateStatusRequestV2(&ssl->extensions, status_type,
- options, ssl->heap, ssl->devId);
-}
-
-
-int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, byte status_type,
- byte options)
-{
- if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
- return BAD_FUNC_ARG;
-
- return TLSX_UseCertificateStatusRequestV2(&ctx->extensions, status_type,
- options, ctx->heap, ctx->devId);
-}
-
-#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
-#endif /* !NO_WOLFSSL_CLIENT */
-
/* Elliptic Curves */
#if defined(HAVE_SUPPORTED_CURVES)
@@ -5202,16 +4413,6 @@ int wolfSSL_GetSequenceNumber(WOLFSSL* ssl, word64 *seq)
#endif /* ATOMIC_USER */
-#ifndef NO_CERTS
-WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX* ctx)
-{
- WOLFSSL_CERT_MANAGER* cm = NULL;
- if (ctx)
- cm = ctx->cm;
- return cm;
-}
-#endif /* NO_CERTS */
-
#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) \
&& defined(XFPRINTF)
@@ -5538,826 +4739,6 @@ int wolfSSL_SetVersion(WOLFSSL* ssl, int version)
}
#endif /* !leanpsk */
-#ifndef NO_CERTS
-
-/* hash is the SHA digest of name, just use first 32 bits as hash */
-static WC_INLINE word32 HashSigner(const byte* hash)
-{
- return MakeWordFromHash(hash) % CA_TABLE_SIZE;
-}
-
-
-/* does CA already exist on signer list */
-int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash)
-{
- Signer* signers;
- int ret = 0;
- word32 row;
-
- if (cm == NULL || hash == NULL) {
- return ret;
- }
-
- row = HashSigner(hash);
-
- if (wc_LockMutex(&cm->caLock) != 0) {
- return ret;
- }
- signers = cm->caTable[row];
- while (signers) {
- byte* subjectHash;
-
- #ifndef NO_SKID
- subjectHash = signers->subjectKeyIdHash;
- #else
- subjectHash = signers->subjectNameHash;
- #endif
-
- if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
- ret = 1; /* success */
- break;
- }
- signers = signers->next;
- }
- wc_UnLockMutex(&cm->caLock);
-
- return ret;
-}
-
-
-#ifdef WOLFSSL_TRUST_PEER_CERT
-/* hash is the SHA digest of name, just use first 32 bits as hash */
-static WC_INLINE word32 TrustedPeerHashSigner(const byte* hash)
-{
- return MakeWordFromHash(hash) % TP_TABLE_SIZE;
-}
-
-/* does trusted peer already exist on signer list */
-int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DecodedCert* cert)
-{
- TrustedPeerCert* tp;
- int ret = 0;
- word32 row = TrustedPeerHashSigner(cert->subjectHash);
-
- if (wc_LockMutex(&cm->tpLock) != 0)
- return ret;
- tp = cm->tpTable[row];
- while (tp) {
- if ((XMEMCMP(cert->subjectHash, tp->subjectNameHash,
- SIGNER_DIGEST_SIZE) == 0)
- #ifndef WOLFSSL_NO_ISSUERHASH_TDPEER
- && (XMEMCMP(cert->issuerHash, tp->issuerHash,
- SIGNER_DIGEST_SIZE) == 0)
- #endif
- )
- ret = 1;
- #ifndef NO_SKID
- if (cert->extSubjKeyIdSet) {
- /* Compare SKID as well if available */
- if (ret == 1 && XMEMCMP(cert->extSubjKeyId, tp->subjectKeyIdHash,
- SIGNER_DIGEST_SIZE) != 0)
- ret = 0;
- }
- #endif
- if (ret == 1)
- break;
- tp = tp->next;
- }
- wc_UnLockMutex(&cm->tpLock);
-
- return ret;
-}
-
-
-/* return Trusted Peer if found, otherwise NULL
- type is what to match on
- */
-TrustedPeerCert* GetTrustedPeer(void* vp, DecodedCert* cert)
-{
- WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
- TrustedPeerCert* ret = NULL;
- TrustedPeerCert* tp = NULL;
- word32 row;
-
- if (cm == NULL || cert == NULL)
- return NULL;
-
- row = TrustedPeerHashSigner(cert->subjectHash);
-
- if (wc_LockMutex(&cm->tpLock) != 0)
- return ret;
-
- tp = cm->tpTable[row];
- while (tp) {
- if ((XMEMCMP(cert->subjectHash, tp->subjectNameHash,
- SIGNER_DIGEST_SIZE) == 0)
- #ifndef WOLFSSL_NO_ISSUERHASH_TDPEER
- && (XMEMCMP(cert->issuerHash, tp->issuerHash,
- SIGNER_DIGEST_SIZE) == 0)
- #endif
- )
- ret = tp;
- #ifndef NO_SKID
- if (cert->extSubjKeyIdSet) {
- /* Compare SKID as well if available */
- if (ret != NULL && XMEMCMP(cert->extSubjKeyId, tp->subjectKeyIdHash,
- SIGNER_DIGEST_SIZE) != 0)
- ret = NULL;
- }
- #endif
- if (ret != NULL)
- break;
- tp = tp->next;
- }
- wc_UnLockMutex(&cm->tpLock);
-
- return ret;
-}
-
-
-int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert)
-{
- if (tp == NULL || cert == NULL)
- return BAD_FUNC_ARG;
-
- /* subject key id or subject hash has been compared when searching
- tpTable for the cert from function GetTrustedPeer */
-
- /* compare signatures */
- if (tp->sigLen == cert->sigLength) {
- if (XMEMCMP(tp->sig, cert->signature, cert->sigLength)) {
- return WOLFSSL_FAILURE;
- }
- }
- else {
- return WOLFSSL_FAILURE;
- }
-
- return WOLFSSL_SUCCESS;
-}
-#endif /* WOLFSSL_TRUST_PEER_CERT */
-
-
-/* return CA if found, otherwise NULL */
-Signer* GetCA(void* vp, byte* hash)
-{
- WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
- Signer* ret = NULL;
- Signer* signers;
- word32 row = 0;
-
- if (cm == NULL || hash == NULL)
- return NULL;
-
- row = HashSigner(hash);
-
- if (wc_LockMutex(&cm->caLock) != 0)
- return ret;
-
- signers = cm->caTable[row];
- while (signers) {
- byte* subjectHash;
- #ifndef NO_SKID
- subjectHash = signers->subjectKeyIdHash;
- #else
- subjectHash = signers->subjectNameHash;
- #endif
- if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
- ret = signers;
- break;
- }
- signers = signers->next;
- }
- wc_UnLockMutex(&cm->caLock);
-
- return ret;
-}
-
-#if defined(HAVE_OCSP)
-Signer* GetCAByKeyHash(void* vp, const byte* keyHash)
-{
- WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
- Signer* ret = NULL;
- Signer* signers;
- int row;
-
- if (cm == NULL || keyHash == NULL)
- return NULL;
-
- /* try lookup using keyHash as subjKeyID first */
- ret = GetCA(vp, (byte*)keyHash);
- if (ret != NULL && XMEMCMP(ret->subjectKeyHash, keyHash, KEYID_SIZE) == 0) {
- return ret;
- }
-
- /* if we can't find the cert, we have to scan the full table */
- if (wc_LockMutex(&cm->caLock) != 0)
- return NULL;
-
- /* Unfortunately we need to look through the entire table */
- for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
- for (signers = cm->caTable[row]; signers != NULL;
- signers = signers->next) {
- if (XMEMCMP(signers->subjectKeyHash, keyHash, KEYID_SIZE) == 0) {
- ret = signers;
- break;
- }
- }
- }
-
- wc_UnLockMutex(&cm->caLock);
- return ret;
-}
-#endif
-#ifdef WOLFSSL_AKID_NAME
-Signer* GetCAByAKID(void* vp, const byte* issuer, word32 issuerSz,
- const byte* serial, word32 serialSz)
-{
- WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
- Signer* ret = NULL;
- Signer* signers;
- byte nameHash[SIGNER_DIGEST_SIZE];
- byte serialHash[SIGNER_DIGEST_SIZE];
- word32 row;
-
- if (cm == NULL || issuer == NULL || issuerSz == 0 ||
- serial == NULL || serialSz == 0)
- return NULL;
-
- if (CalcHashId(issuer, issuerSz, nameHash) != 0 ||
- CalcHashId(serial, serialSz, serialHash) != 0)
- return NULL;
-
- if (wc_LockMutex(&cm->caLock) != 0)
- return ret;
-
- /* Unfortunately we need to look through the entire table */
- for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
- for (signers = cm->caTable[row]; signers != NULL;
- signers = signers->next) {
- if (XMEMCMP(signers->issuerNameHash, nameHash, SIGNER_DIGEST_SIZE)
- == 0 && XMEMCMP(signers->serialHash, serialHash,
- SIGNER_DIGEST_SIZE) == 0) {
- ret = signers;
- break;
- }
- }
- }
-
- wc_UnLockMutex(&cm->caLock);
-
- return ret;
-}
-#endif
-
-#ifndef NO_SKID
-/* return CA if found, otherwise NULL. Walk through hash table. */
-Signer* GetCAByName(void* vp, byte* hash)
-{
- WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
- Signer* ret = NULL;
- Signer* signers;
- word32 row;
-
- if (cm == NULL)
- return NULL;
-
- if (wc_LockMutex(&cm->caLock) != 0)
- return ret;
-
- for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
- signers = cm->caTable[row];
- while (signers && ret == NULL) {
- if (XMEMCMP(hash, signers->subjectNameHash,
- SIGNER_DIGEST_SIZE) == 0) {
- ret = signers;
- }
- signers = signers->next;
- }
- }
- wc_UnLockMutex(&cm->caLock);
-
- return ret;
-}
-#endif
-
-
-#ifdef WOLFSSL_TRUST_PEER_CERT
-/* add a trusted peer cert to linked list */
-int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify)
-{
- int ret = 0;
- int row = 0;
- TrustedPeerCert* peerCert;
- DecodedCert* cert;
- DerBuffer* der = *pDer;
-
- WOLFSSL_MSG("Adding a Trusted Peer Cert");
-
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
- DYNAMIC_TYPE_DCERT);
- if (cert == NULL) {
- FreeDer(&der);
- return MEMORY_E;
- }
-
- InitDecodedCert(cert, der->buffer, der->length, cm->heap);
- if ((ret = ParseCert(cert, TRUSTED_PEER_TYPE, verify, cm)) != 0) {
- FreeDecodedCert(cert);
- XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
- FreeDer(&der);
- return ret;
- }
- WOLFSSL_MSG("\tParsed new trusted peer cert");
-
- peerCert = (TrustedPeerCert*)XMALLOC(sizeof(TrustedPeerCert), cm->heap,
- DYNAMIC_TYPE_CERT);
- if (peerCert == NULL) {
- FreeDecodedCert(cert);
- XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
- FreeDer(&der);
- return MEMORY_E;
- }
- XMEMSET(peerCert, 0, sizeof(TrustedPeerCert));
-
- #ifndef IGNORE_NAME_CONSTRAINTS
- if (peerCert->permittedNames)
- FreeNameSubtrees(peerCert->permittedNames, cm->heap);
- if (peerCert->excludedNames)
- FreeNameSubtrees(peerCert->excludedNames, cm->heap);
- #endif
-
- if (AlreadyTrustedPeer(cm, cert)) {
- WOLFSSL_MSG("\tAlready have this CA, not adding again");
- FreeTrustedPeer(peerCert, cm->heap);
- (void)ret;
- }
- else {
- /* add trusted peer signature */
- peerCert->sigLen = cert->sigLength;
- peerCert->sig = (byte *)XMALLOC(cert->sigLength, cm->heap,
- DYNAMIC_TYPE_SIGNATURE);
- if (peerCert->sig == NULL) {
- FreeDecodedCert(cert);
- XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
- FreeTrustedPeer(peerCert, cm->heap);
- FreeDer(&der);
- return MEMORY_E;
- }
- XMEMCPY(peerCert->sig, cert->signature, cert->sigLength);
-
- /* add trusted peer name */
- peerCert->nameLen = cert->subjectCNLen;
- peerCert->name = cert->subjectCN;
- #ifndef IGNORE_NAME_CONSTRAINTS
- peerCert->permittedNames = cert->permittedNames;
- peerCert->excludedNames = cert->excludedNames;
- #endif
-
- /* add SKID when available and hash of name */
- #ifndef NO_SKID
- XMEMCPY(peerCert->subjectKeyIdHash, cert->extSubjKeyId,
- SIGNER_DIGEST_SIZE);
- #endif
- XMEMCPY(peerCert->subjectNameHash, cert->subjectHash,
- SIGNER_DIGEST_SIZE);
- #ifndef WOLFSSL_NO_ISSUERHASH_TDPEER
- XMEMCPY(peerCert->issuerHash, cert->issuerHash,
- SIGNER_DIGEST_SIZE);
- #endif
- /* If Key Usage not set, all uses valid. */
- peerCert->next = NULL;
- cert->subjectCN = 0;
- #ifndef IGNORE_NAME_CONSTRAINTS
- cert->permittedNames = NULL;
- cert->excludedNames = NULL;
- #endif
-
- row = (int)TrustedPeerHashSigner(peerCert->subjectNameHash);
-
- if (wc_LockMutex(&cm->tpLock) == 0) {
- peerCert->next = cm->tpTable[row];
- cm->tpTable[row] = peerCert; /* takes ownership */
- wc_UnLockMutex(&cm->tpLock);
- }
- else {
- WOLFSSL_MSG("\tTrusted Peer Cert Mutex Lock failed");
- FreeDecodedCert(cert);
- XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
- FreeTrustedPeer(peerCert, cm->heap);
- FreeDer(&der);
- return BAD_MUTEX_E;
- }
- }
-
- WOLFSSL_MSG("\tFreeing parsed trusted peer cert");
- FreeDecodedCert(cert);
- XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
- WOLFSSL_MSG("\tFreeing der trusted peer cert");
- FreeDer(&der);
- WOLFSSL_MSG("\t\tOK Freeing der trusted peer cert");
- WOLFSSL_LEAVE("AddTrustedPeer", ret);
-
- return WOLFSSL_SUCCESS;
-}
-#endif /* WOLFSSL_TRUST_PEER_CERT */
-
-int AddSigner(WOLFSSL_CERT_MANAGER* cm, Signer *s)
-{
- byte* subjectHash;
- Signer* signers;
- word32 row;
-
- if (cm == NULL || s == NULL)
- return BAD_FUNC_ARG;
-
-#ifndef NO_SKID
- subjectHash = s->subjectKeyIdHash;
-#else
- subjectHash = s->subjectNameHash;
-#endif
-
- if (AlreadySigner(cm, subjectHash)) {
- FreeSigner(s, cm->heap);
- return 0;
- }
-
- row = HashSigner(subjectHash);
-
- if (wc_LockMutex(&cm->caLock) != 0)
- return BAD_MUTEX_E;
-
- signers = cm->caTable[row];
- s->next = signers;
- cm->caTable[row] = s;
-
- wc_UnLockMutex(&cm->caLock);
- return 0;
-}
-
-/* owns der, internal now uses too */
-/* type flag ids from user or from chain received during verify
- don't allow chain ones to be added w/o isCA extension */
-int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
-{
- int ret;
- Signer* signer = NULL;
- word32 row;
- byte* subjectHash;
- WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
- DerBuffer* der = *pDer;
-
- WOLFSSL_MSG_CERT_LOG("Adding a CA");
-
- if (cm == NULL) {
- FreeDer(pDer);
- return BAD_FUNC_ARG;
- }
-
- #ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
- if (cert == NULL) {
- FreeDer(pDer);
- return MEMORY_E;
- }
- #endif
-
- InitDecodedCert(cert, der->buffer, der->length, cm->heap);
-
-#ifdef WC_ASN_UNKNOWN_EXT_CB
- if (cm->unknownExtCallback != NULL) {
- wc_SetUnknownExtCallback(cert, cm->unknownExtCallback);
- }
-#endif
-
- WOLFSSL_MSG_CERT("\tParsing new CA");
- ret = ParseCert(cert, CA_TYPE, verify, cm);
-
- WOLFSSL_MSG("\tParsed new CA");
-#ifdef WOLFSSL_DEBUG_CERTS
- {
- const char* err_msg;
- if (ret == 0) {
- WOLFSSL_MSG_CERT_EX(WOLFSSL_MSG_CERT_INDENT "issuer: '%s'",
- cert->issuer);
- WOLFSSL_MSG_CERT_EX(WOLFSSL_MSG_CERT_INDENT "subject: '%s'",
- cert->subject);
- }
- else {
- WOLFSSL_MSG_CERT(
- WOLFSSL_MSG_CERT_INDENT "Failed during parse of new CA");
- err_msg = wc_GetErrorString(ret);
- WOLFSSL_MSG_CERT_EX(WOLFSSL_MSG_CERT_INDENT "error ret: %d; %s",
- ret, err_msg);
- }
- }
-#endif /* WOLFSSL_DEBUG_CERTS */
-
-#ifndef NO_SKID
- subjectHash = cert->extSubjKeyId;
-#else
- subjectHash = cert->subjectHash;
-#endif
-
- /* check CA key size */
- if (verify && (ret == 0 )) {
- switch (cert->keyOID) {
- #ifndef NO_RSA
- #ifdef WC_RSA_PSS
- case RSAPSSk:
- #endif
- case RSAk:
- if (cm->minRsaKeySz < 0 ||
- cert->pubKeySize < (word16)cm->minRsaKeySz) {
- ret = RSA_KEY_SIZE_E;
- WOLFSSL_MSG_CERT_LOG("\tCA RSA key size error");
- WOLFSSL_MSG_CERT_EX("\tCA RSA pubKeySize = %d; "
- "minRsaKeySz = %d",
- cert->pubKeySize, cm->minRsaKeySz);
- }
- break;
- #endif /* !NO_RSA */
- #ifdef HAVE_ECC
- case ECDSAk:
- if (cm->minEccKeySz < 0 ||
- cert->pubKeySize < (word16)cm->minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG_CERT_LOG("\tCA ECC key size error");
- WOLFSSL_MSG_CERT_EX("\tCA ECC pubKeySize = %d; "
- "minEccKeySz = %d",
- cert->pubKeySize, cm->minEccKeySz);
- }
- break;
- #endif /* HAVE_ECC */
- #ifdef HAVE_ED25519
- case ED25519k:
- if (cm->minEccKeySz < 0 ||
- ED25519_KEY_SIZE < (word16)cm->minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA ECC key size error");
- }
- break;
- #endif /* HAVE_ED25519 */
- #ifdef HAVE_ED448
- case ED448k:
- if (cm->minEccKeySz < 0 ||
- ED448_KEY_SIZE < (word16)cm->minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA ECC key size error");
- }
- break;
- #endif /* HAVE_ED448 */
- #if defined(HAVE_FALCON)
- case FALCON_LEVEL1k:
- if (cm->minFalconKeySz < 0 ||
- FALCON_LEVEL1_KEY_SIZE < (word16)cm->minFalconKeySz) {
- ret = FALCON_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA Falcon level 1 key size error");
- }
- break;
- case FALCON_LEVEL5k:
- if (cm->minFalconKeySz < 0 ||
- FALCON_LEVEL5_KEY_SIZE < (word16)cm->minFalconKeySz) {
- ret = FALCON_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA Falcon level 5 key size error");
- }
- break;
- #endif /* HAVE_FALCON */
- #if defined(HAVE_DILITHIUM)
- #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
- case DILITHIUM_LEVEL2k:
- if (cm->minDilithiumKeySz < 0 ||
- DILITHIUM_LEVEL2_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
- ret = DILITHIUM_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA Dilithium level 2 key size error");
- }
- break;
- case DILITHIUM_LEVEL3k:
- if (cm->minDilithiumKeySz < 0 ||
- DILITHIUM_LEVEL3_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
- ret = DILITHIUM_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA Dilithium level 3 key size error");
- }
- break;
- case DILITHIUM_LEVEL5k:
- if (cm->minDilithiumKeySz < 0 ||
- DILITHIUM_LEVEL5_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
- ret = DILITHIUM_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA Dilithium level 5 key size error");
- }
- break;
- #endif /* WOLFSSL_DILITHIUM_FIPS204_DRAFT */
- case ML_DSA_LEVEL2k:
- if (cm->minDilithiumKeySz < 0 ||
- ML_DSA_LEVEL2_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
- ret = DILITHIUM_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA Dilithium level 2 key size error");
- }
- break;
- case ML_DSA_LEVEL3k:
- if (cm->minDilithiumKeySz < 0 ||
- ML_DSA_LEVEL3_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
- ret = DILITHIUM_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA Dilithium level 3 key size error");
- }
- break;
- case ML_DSA_LEVEL5k:
- if (cm->minDilithiumKeySz < 0 ||
- ML_DSA_LEVEL5_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
- ret = DILITHIUM_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA Dilithium level 5 key size error");
- }
- break;
- #endif /* HAVE_DILITHIUM */
-
- default:
- WOLFSSL_MSG("\tNo key size check done on CA");
- break; /* no size check if key type is not in switch */
- }
- }
-
- if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA &&
- type != WOLFSSL_TEMP_CA) {
- WOLFSSL_MSG("\tCan't add as CA if not actually one");
- ret = NOT_CA_ERROR;
- }
-#ifndef ALLOW_INVALID_CERTSIGN
- else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA &&
- type != WOLFSSL_TEMP_CA && !cert->selfSigned &&
- (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) {
- /* Intermediate CA certs are required to have the keyCertSign
- * extension set. User loaded root certs are not. */
- WOLFSSL_MSG("\tDoesn't have key usage certificate signing");
- ret = NOT_CA_ERROR;
- }
-#endif
- else if (ret == 0 && AlreadySigner(cm, subjectHash)) {
- WOLFSSL_MSG("\tAlready have this CA, not adding again");
- (void)ret;
- }
- else if (ret == 0) {
- /* take over signer parts */
- signer = MakeSigner(cm->heap);
- if (!signer)
- ret = MEMORY_ERROR;
- }
- if (ret == 0 && signer != NULL) {
- ret = FillSigner(signer, cert, type, der);
-
- if (ret == 0){
- #ifndef NO_SKID
- row = HashSigner(signer->subjectKeyIdHash);
- #else
- row = HashSigner(signer->subjectNameHash);
- #endif
- }
-
- #if defined(WOLFSSL_RENESAS_TSIP_TLS) || defined(WOLFSSL_RENESAS_FSPSM_TLS)
- /* Verify CA by TSIP so that generated tsip key is going to */
- /* be able to be used for peer's cert verification */
- /* TSIP is only able to handle USER CA, and only one CA. */
- /* Therefore, it doesn't need to call TSIP again if there is already */
- /* verified CA. */
- if ( ret == 0 && signer != NULL ) {
- signer->cm_idx = row;
- if (type == WOLFSSL_USER_CA) {
- if ((ret = wc_Renesas_cmn_RootCertVerify(cert->source,
- cert->maxIdx,
- cert->sigCtx.CertAtt.pubkey_n_start,
- cert->sigCtx.CertAtt.pubkey_n_len - 1,
- cert->sigCtx.CertAtt.pubkey_e_start,
- cert->sigCtx.CertAtt.pubkey_e_len - 1,
- row/* cm index */))
- < 0)
- WOLFSSL_MSG("Renesas_RootCertVerify() failed");
- else
- WOLFSSL_MSG("Renesas_RootCertVerify() succeed or skipped");
- }
- }
- #endif /* TSIP or SCE */
-
- if (ret == 0 && wc_LockMutex(&cm->caLock) == 0) {
- signer->next = cm->caTable[row];
- cm->caTable[row] = signer; /* takes ownership */
- wc_UnLockMutex(&cm->caLock);
- if (cm->caCacheCallback)
- cm->caCacheCallback(der->buffer, (int)der->length, type);
- }
- else {
- WOLFSSL_MSG("\tCA Mutex Lock failed");
- ret = BAD_MUTEX_E;
- }
- }
-
- WOLFSSL_MSG("\tFreeing Parsed CA");
- FreeDecodedCert(cert);
- if (ret != 0 && signer != NULL)
- FreeSigner(signer, cm->heap);
- WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
- WOLFSSL_MSG("\tFreeing der CA");
- FreeDer(pDer);
- WOLFSSL_MSG("\t\tOK Freeing der CA");
-
- WOLFSSL_LEAVE("AddCA", ret);
-
- return ret == 0 ? WOLFSSL_SUCCESS : ret;
-}
-
-/* Removes the CA with the passed in subject hash from the
- cert manager's CA cert store. */
-int RemoveCA(WOLFSSL_CERT_MANAGER* cm, byte* hash, int type)
-{
- Signer* current;
- Signer** prev;
- int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
- word32 row;
-
- WOLFSSL_MSG("Removing a CA");
-
- if (cm == NULL || hash == NULL) {
- return BAD_FUNC_ARG;
- }
-
- row = HashSigner(hash);
-
- if (wc_LockMutex(&cm->caLock) != 0) {
- return BAD_MUTEX_E;
- }
- current = cm->caTable[row];
- prev = &cm->caTable[row];
- while (current) {
- byte* subjectHash;
-
- #ifndef NO_SKID
- subjectHash = current->subjectKeyIdHash;
- #else
- subjectHash = current->subjectNameHash;
- #endif
-
- if ((current->type == type) &&
- (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0)) {
- *prev = current->next;
- FreeSigner(current, cm->heap);
- ret = WOLFSSL_SUCCESS;
- break;
- }
- prev = ¤t->next;
- current = current->next;
- }
- wc_UnLockMutex(&cm->caLock);
-
- WOLFSSL_LEAVE("RemoveCA", ret);
-
- return ret;
-}
-
-
-/* Sets the CA with the passed in subject hash
- to the provided type. */
-int SetCAType(WOLFSSL_CERT_MANAGER* cm, byte* hash, int type)
-{
- Signer* current;
- int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
- word32 row;
-
- WOLFSSL_MSG_EX("Setting CA to type %d", type);
-
- if (cm == NULL || hash == NULL ||
- type < WOLFSSL_USER_CA || type > WOLFSSL_USER_INTER) {
- return ret;
- }
-
- row = HashSigner(hash);
-
- if (wc_LockMutex(&cm->caLock) != 0) {
- return ret;
- }
- current = cm->caTable[row];
- while (current) {
- byte* subjectHash;
-
- #ifndef NO_SKID
- subjectHash = current->subjectKeyIdHash;
- #else
- subjectHash = current->subjectNameHash;
- #endif
-
- if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
- current->type = (byte)type;
- ret = WOLFSSL_SUCCESS;
- break;
- }
- current = current->next;
- }
- wc_UnLockMutex(&cm->caLock);
-
- WOLFSSL_LEAVE("SetCAType", ret);
-
- return ret;
-}
-#endif /* !NO_CERTS */
-
-
#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_OPENSSL_RAND_CB)
static int wolfSSL_RAND_InitMutex(void);
#endif
@@ -6862,2580 +5243,8 @@ void wolfSSL_set_security_level(WOLFSSL * ssl, int level)
#define WOLFSSL_SSL_LOAD_INCLUDED
#include
-#ifndef NO_CERTS
-
-#ifdef HAVE_CRL
-
-int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
- long sz, int type)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_LoadCRLBuffer");
-
- if (ctx == NULL)
- return BAD_FUNC_ARG;
-
- return wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, buff, sz, type);
-}
-
-
-int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff,
- long sz, int type)
-{
- WOLFSSL_ENTER("wolfSSL_LoadCRLBuffer");
-
- if (ssl == NULL || ssl->ctx == NULL)
- return BAD_FUNC_ARG;
-
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerLoadCRLBuffer(SSL_CM(ssl), buff, sz, type);
-}
-
-#endif /* HAVE_CRL */
-
-#ifdef HAVE_OCSP
-int wolfSSL_EnableOCSP(WOLFSSL* ssl, int options)
-{
- WOLFSSL_ENTER("wolfSSL_EnableOCSP");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerEnableOCSP(SSL_CM(ssl), options);
- }
- else
- return BAD_FUNC_ARG;
-}
-
-int wolfSSL_DisableOCSP(WOLFSSL* ssl)
-{
- WOLFSSL_ENTER("wolfSSL_DisableOCSP");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerDisableOCSP(SSL_CM(ssl));
- }
- else
- return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_EnableOCSPStapling(WOLFSSL* ssl)
-{
- WOLFSSL_ENTER("wolfSSL_EnableOCSPStapling");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerEnableOCSPStapling(SSL_CM(ssl));
- }
- else
- return BAD_FUNC_ARG;
-}
-
-int wolfSSL_DisableOCSPStapling(WOLFSSL* ssl)
-{
- WOLFSSL_ENTER("wolfSSL_DisableOCSPStapling");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerDisableOCSPStapling(SSL_CM(ssl));
- }
- else
- return BAD_FUNC_ARG;
-}
-
-int wolfSSL_SetOCSP_OverrideURL(WOLFSSL* ssl, const char* url)
-{
- WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerSetOCSPOverrideURL(SSL_CM(ssl), url);
- }
- else
- return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_SetOCSP_Cb(WOLFSSL* ssl,
- CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx)
-{
- WOLFSSL_ENTER("wolfSSL_SetOCSP_Cb");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- ssl->ocspIOCtx = ioCbCtx; /* use SSL specific ioCbCtx */
- return wolfSSL_CertManagerSetOCSP_Cb(SSL_CM(ssl),
- ioCb, respFreeCb, NULL);
- }
- else
- return BAD_FUNC_ARG;
-}
-
-int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX* ctx, int options)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSP");
- if (ctx)
- return wolfSSL_CertManagerEnableOCSP(ctx->cm, options);
- else
- return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX* ctx)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSP");
- if (ctx)
- return wolfSSL_CertManagerDisableOCSP(ctx->cm);
- else
- return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX* ctx, const char* url)
-{
- WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL");
- if (ctx)
- return wolfSSL_CertManagerSetOCSPOverrideURL(ctx->cm, url);
- else
- return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX* ctx, CbOCSPIO ioCb,
- CbOCSPRespFree respFreeCb, void* ioCbCtx)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_SetOCSP_Cb");
- if (ctx)
- return wolfSSL_CertManagerSetOCSP_Cb(ctx->cm, ioCb,
- respFreeCb, ioCbCtx);
- else
- return BAD_FUNC_ARG;
-}
-
-#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
-int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX* ctx)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPStapling");
- if (ctx)
- return wolfSSL_CertManagerEnableOCSPStapling(ctx->cm);
- else
- return BAD_FUNC_ARG;
-}
-
-int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX* ctx)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPStapling");
- if (ctx)
- return wolfSSL_CertManagerDisableOCSPStapling(ctx->cm);
- else
- return BAD_FUNC_ARG;
-}
-
-int wolfSSL_CTX_EnableOCSPMustStaple(WOLFSSL_CTX* ctx)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPMustStaple");
- if (ctx)
- return wolfSSL_CertManagerEnableOCSPMustStaple(ctx->cm);
- else
- return BAD_FUNC_ARG;
-}
-
-int wolfSSL_CTX_DisableOCSPMustStaple(WOLFSSL_CTX* ctx)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPMustStaple");
- if (ctx)
- return wolfSSL_CertManagerDisableOCSPMustStaple(ctx->cm);
- else
- return BAD_FUNC_ARG;
-}
-#endif /* HAVE_CERTIFICATE_STATUS_REQUEST || \
- * HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
-
-#endif /* HAVE_OCSP */
-
-#ifdef HAVE_CRL
-
-int wolfSSL_EnableCRL(WOLFSSL* ssl, int options)
-{
- WOLFSSL_ENTER("wolfSSL_EnableCRL");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerEnableCRL(SSL_CM(ssl), options);
- }
- else
- return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_DisableCRL(WOLFSSL* ssl)
-{
- WOLFSSL_ENTER("wolfSSL_DisableCRL");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerDisableCRL(SSL_CM(ssl));
- }
- else
- return BAD_FUNC_ARG;
-}
-
-#ifndef NO_FILESYSTEM
-int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor)
-{
- WOLFSSL_ENTER("wolfSSL_LoadCRL");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerLoadCRL(SSL_CM(ssl), path, type, monitor);
- }
- else
- return BAD_FUNC_ARG;
-}
-
-int wolfSSL_LoadCRLFile(WOLFSSL* ssl, const char* file, int type)
-{
- WOLFSSL_ENTER("wolfSSL_LoadCRLFile");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerLoadCRLFile(SSL_CM(ssl), file, type);
- }
- else
- return BAD_FUNC_ARG;
-}
-#endif
-
-int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb)
-{
- WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerSetCRL_Cb(SSL_CM(ssl), cb);
- }
- else
- return BAD_FUNC_ARG;
-}
-
-int wolfSSL_SetCRL_ErrorCb(WOLFSSL* ssl, crlErrorCb cb, void* ctx)
-{
- WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerSetCRL_ErrorCb(SSL_CM(ssl), cb, ctx);
- }
- else
- return BAD_FUNC_ARG;
-}
-
-#ifdef HAVE_CRL_IO
-int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb)
-{
- WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerSetCRL_IOCb(SSL_CM(ssl), cb);
- }
- else
- return BAD_FUNC_ARG;
-}
-#endif
-
-int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_EnableCRL");
- if (ctx)
- return wolfSSL_CertManagerEnableCRL(ctx->cm, options);
- else
- return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_DisableCRL");
- if (ctx)
- return wolfSSL_CertManagerDisableCRL(ctx->cm);
- else
- return BAD_FUNC_ARG;
-}
-
-
-#ifndef NO_FILESYSTEM
-int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path,
- int type, int monitor)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL");
- if (ctx)
- return wolfSSL_CertManagerLoadCRL(ctx->cm, path, type, monitor);
- else
- return BAD_FUNC_ARG;
-}
-
-int wolfSSL_CTX_LoadCRLFile(WOLFSSL_CTX* ctx, const char* file,
- int type)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL");
- if (ctx)
- return wolfSSL_CertManagerLoadCRLFile(ctx->cm, file, type);
- else
- return BAD_FUNC_ARG;
-}
-#endif
-
-
-int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_Cb");
- if (ctx)
- return wolfSSL_CertManagerSetCRL_Cb(ctx->cm, cb);
- else
- return BAD_FUNC_ARG;
-}
-
-int wolfSSL_CTX_SetCRL_ErrorCb(WOLFSSL_CTX* ctx, crlErrorCb cb, void* cbCtx)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_ErrorCb");
- if (ctx)
- return wolfSSL_CertManagerSetCRL_ErrorCb(ctx->cm, cb, cbCtx);
- else
- return BAD_FUNC_ARG;
-}
-
-#ifdef HAVE_CRL_IO
-int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX* ctx, CbCrlIO cb)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_IOCb");
- if (ctx)
- return wolfSSL_CertManagerSetCRL_IOCb(ctx->cm, cb);
- else
- return BAD_FUNC_ARG;
-}
-#endif
-
-
-#endif /* HAVE_CRL */
-
-
-/* Sets the max chain depth when verifying a certificate chain. Default depth
- * is set to MAX_CHAIN_DEPTH.
- *
- * ctx WOLFSSL_CTX structure to set depth in
- * depth max depth
- */
-void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) {
- WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth");
-
- if (ctx == NULL || depth < 0 || depth > MAX_CHAIN_DEPTH) {
- WOLFSSL_MSG("Bad depth argument, too large or less than 0");
- return;
- }
-
- ctx->verifyDepth = (byte)depth;
-}
-
-
-/* get cert chaining depth using ssl struct */
-long wolfSSL_get_verify_depth(WOLFSSL* ssl)
-{
- if(ssl == NULL) {
- return BAD_FUNC_ARG;
- }
-#ifndef OPENSSL_EXTRA
- return MAX_CHAIN_DEPTH;
-#else
- return ssl->options.verifyDepth;
-#endif
-}
-
-
-/* get cert chaining depth using ctx struct */
-long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx)
-{
- if (ctx == NULL) {
- return BAD_FUNC_ARG;
- }
-#ifndef OPENSSL_EXTRA
- return MAX_CHAIN_DEPTH;
-#else
- return ctx->verifyDepth;
-#endif
-}
-
-#ifndef NO_CHECK_PRIVATE_KEY
-
-#ifdef WOLF_PRIVATE_KEY_ID
-/* Check private against public in certificate for match using external
- * device with given devId */
-static int check_cert_key_dev(word32 keyOID, byte* privKey, word32 privSz,
- const byte* pubKey, word32 pubSz, int label, int id, void* heap, int devId)
-{
- int ret = 0;
- int type = 0;
- void *pkey = NULL;
-
- if (privKey == NULL) {
- return MISSING_KEY;
- }
-
-#ifndef NO_RSA
- if (keyOID == RSAk) {
- type = DYNAMIC_TYPE_RSA;
- }
-#ifdef WC_RSA_PSS
- if (keyOID == RSAPSSk) {
- type = DYNAMIC_TYPE_RSA;
- }
-#endif
-#endif
-#ifdef HAVE_ECC
- if (keyOID == ECDSAk) {
- type = DYNAMIC_TYPE_ECC;
- }
-#endif
-#if defined(HAVE_DILITHIUM)
- if ((keyOID == ML_DSA_LEVEL2k) ||
- (keyOID == ML_DSA_LEVEL3k) ||
- (keyOID == ML_DSA_LEVEL5k)
- #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
- || (keyOID == DILITHIUM_LEVEL2k)
- || (keyOID == DILITHIUM_LEVEL3k)
- || (keyOID == DILITHIUM_LEVEL5k)
- #endif /* WOLFSSL_DILITHIUM_FIPS204_DRAFT */
- ) {
- type = DYNAMIC_TYPE_DILITHIUM;
- }
-#endif
-#if defined(HAVE_FALCON)
- if ((keyOID == FALCON_LEVEL1k) ||
- (keyOID == FALCON_LEVEL5k)) {
- type = DYNAMIC_TYPE_FALCON;
- }
-#endif
-
- ret = CreateDevPrivateKey(&pkey, privKey, privSz, type, label, id,
- heap, devId);
- #ifdef WOLF_CRYPTO_CB
- if (ret == 0) {
- #ifndef NO_RSA
- if (keyOID == RSAk
- #ifdef WC_RSA_PSS
- || keyOID == RSAPSSk
- #endif
- ) {
- ret = wc_CryptoCb_RsaCheckPrivKey((RsaKey*)pkey, pubKey, pubSz);
- }
- #endif
- #ifdef HAVE_ECC
- if (keyOID == ECDSAk) {
- ret = wc_CryptoCb_EccCheckPrivKey((ecc_key*)pkey, pubKey, pubSz);
- }
- #endif
- #if defined(HAVE_DILITHIUM)
- if ((keyOID == ML_DSA_LEVEL2k) ||
- (keyOID == ML_DSA_LEVEL3k) ||
- (keyOID == ML_DSA_LEVEL5k)
- #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
- || (keyOID == DILITHIUM_LEVEL2k)
- || (keyOID == DILITHIUM_LEVEL3k)
- || (keyOID == DILITHIUM_LEVEL5k)
- #endif /* WOLFSSL_DILITHIUM_FIPS204_DRAFT */
- ) {
- ret = wc_CryptoCb_PqcSignatureCheckPrivKey(pkey,
- WC_PQC_SIG_TYPE_DILITHIUM,
- pubKey, pubSz);
- }
- #endif
- #if defined(HAVE_FALCON)
- if ((keyOID == FALCON_LEVEL1k) ||
- (keyOID == FALCON_LEVEL5k)) {
- ret = wc_CryptoCb_PqcSignatureCheckPrivKey(pkey,
- WC_PQC_SIG_TYPE_FALCON,
- pubKey, pubSz);
- }
- #endif
- }
- #else
- /* devId was set, don't check, for now */
- /* TODO: Add callback for private key check? */
- (void) pubKey;
- (void) pubSz;
- #endif
- if (pkey != NULL) {
- #ifndef NO_RSA
- if (keyOID == RSAk
- #ifdef WC_RSA_PSS
- || keyOID == RSAPSSk
- #endif
- ) {
- wc_FreeRsaKey((RsaKey*)pkey);
- }
- #endif
- #ifdef HAVE_ECC
- if (keyOID == ECDSAk) {
- wc_ecc_free((ecc_key*)pkey);
- }
- #endif
- #if defined(HAVE_DILITHIUM)
- if ((keyOID == ML_DSA_LEVEL2k) ||
- (keyOID == ML_DSA_LEVEL3k) ||
- (keyOID == ML_DSA_LEVEL5k)
- #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
- || (keyOID == DILITHIUM_LEVEL2k)
- || (keyOID == DILITHIUM_LEVEL3k)
- || (keyOID == DILITHIUM_LEVEL5k)
- #endif /* WOLFSSL_DILITHIUM_FIPS204_DRAFT */
- ) {
- wc_dilithium_free((dilithium_key*)pkey);
- }
- #endif
- #if defined(HAVE_FALCON)
- if ((keyOID == FALCON_LEVEL1k) ||
- (keyOID == FALCON_LEVEL5k)) {
- wc_falcon_free((falcon_key*)pkey);
- }
- #endif
- XFREE(pkey, heap, type);
- }
-
- return ret;
-}
-#endif /* WOLF_PRIVATE_KEY_ID */
-
-/* Check private against public in certificate for match
- *
- * Returns WOLFSSL_SUCCESS on good private key
- * WOLFSSL_FAILURE if mismatched */
-static int check_cert_key(const DerBuffer* cert, const DerBuffer* key,
- const DerBuffer* altKey, void* heap, int devId, int isKeyLabel, int isKeyId,
- int altDevId, int isAltKeyLabel, int isAltKeyId)
-{
- WC_DECLARE_VAR(der, DecodedCert, 1, 0);
- word32 size;
- byte* buff;
- int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
-
- WOLFSSL_ENTER("check_cert_key");
-
- if (cert == NULL || key == NULL) {
- return WOLFSSL_FAILURE;
- }
-
- WC_ALLOC_VAR_EX(der, DecodedCert, 1, heap, DYNAMIC_TYPE_DCERT,
- return MEMORY_E);
-
- size = cert->length;
- buff = cert->buffer;
- InitDecodedCert_ex(der, buff, size, heap, devId);
- if (ParseCertRelative(der, CERT_TYPE, NO_VERIFY, NULL, NULL) != 0) {
- FreeDecodedCert(der);
- WC_FREE_VAR_EX(der, heap, DYNAMIC_TYPE_DCERT);
- return WOLFSSL_FAILURE;
- }
-
- size = key->length;
- buff = key->buffer;
-#ifdef WOLF_PRIVATE_KEY_ID
- if (devId != INVALID_DEVID) {
- ret = check_cert_key_dev(der->keyOID, buff, size, der->publicKey,
- der->pubKeySize, isKeyLabel, isKeyId, heap,
- devId);
- if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
- ret = (ret == 0) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE;
- }
- }
- else {
- /* fall through if unavailable */
- ret = CRYPTOCB_UNAVAILABLE;
- }
-
- if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
-#endif /* WOLF_PRIVATE_KEY_ID */
- {
- ret = wc_CheckPrivateKeyCert(buff, size, der, 0, heap);
- ret = (ret == 1) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE;
- }
-
-#ifdef WOLFSSL_DUAL_ALG_CERTS
- if (ret == WOLFSSL_SUCCESS && der->extSapkiSet && der->sapkiDer != NULL) {
- /* Certificate contains an alternative public key. Hence, we also
- * need an alternative private key. */
- if (altKey == NULL) {
- ret = MISSING_KEY;
- buff = NULL;
- size = 0;
- }
- else {
- size = altKey->length;
- buff = altKey->buffer;
- }
-#ifdef WOLF_PRIVATE_KEY_ID
- if (ret == WOLFSSL_SUCCESS && altDevId != INVALID_DEVID) {
- /* We have to decode the public key first */
- /* Default to max pub key size. */
- word32 pubKeyLen = MAX_PUBLIC_KEY_SZ;
- byte* decodedPubKey = (byte*)XMALLOC(pubKeyLen, heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (decodedPubKey == NULL) {
- ret = MEMORY_E;
- }
- if (ret == WOLFSSL_SUCCESS) {
- if (der->sapkiOID == RSAk || der->sapkiOID == ECDSAk) {
- /* Simply copy the data */
- XMEMCPY(decodedPubKey, der->sapkiDer, der->sapkiLen);
- pubKeyLen = der->sapkiLen;
- ret = 0;
- }
- else {
- #if defined(WC_ENABLE_ASYM_KEY_IMPORT)
- word32 idx = 0;
- ret = DecodeAsymKeyPublic(der->sapkiDer, &idx,
- der->sapkiLen, decodedPubKey,
- &pubKeyLen, der->sapkiOID);
- #else
- ret = NOT_COMPILED_IN;
- #endif /* WC_ENABLE_ASYM_KEY_IMPORT */
- }
- }
- if (ret == 0) {
- ret = check_cert_key_dev(der->sapkiOID, buff, size,
- decodedPubKey, pubKeyLen,
- isAltKeyLabel, isAltKeyId,
- heap, altDevId);
- }
- XFREE(decodedPubKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
- ret = (ret == 0) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE;
- }
- }
- else {
- /* fall through if unavailable */
- ret = CRYPTOCB_UNAVAILABLE;
- }
-
- if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
-#else
- if (ret == WOLFSSL_SUCCESS)
-#endif /* WOLF_PRIVATE_KEY_ID */
- {
- ret = wc_CheckPrivateKeyCert(buff, size, der, 1, heap);
- ret = (ret == 1) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE;
- }
- }
-#endif /* WOLFSSL_DUAL_ALG_CERTS */
- FreeDecodedCert(der);
- WC_FREE_VAR_EX(der, heap, DYNAMIC_TYPE_DCERT);
-
- (void)devId;
- (void)isKeyLabel;
- (void)isKeyId;
- (void)altKey;
- (void)altDevId;
- (void)isAltKeyLabel;
- (void)isAltKeyId;
-
- return ret;
-}
-
-/* Check private against public in certificate for match
- *
- * ctx WOLFSSL_CTX structure to check private key in
- *
- * Returns WOLFSSL_SUCCESS on good private key
- * WOLFSSL_FAILURE if mismatched. */
-int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx)
-{
- int res = WOLFSSL_SUCCESS;
-#ifdef WOLFSSL_BLIND_PRIVATE_KEY
- DerBuffer *privateKey;
-#ifdef WOLFSSL_DUAL_ALG_CERTS
- DerBuffer *altPrivateKey;
-#endif
-#else
- const DerBuffer *privateKey;
-#ifdef WOLFSSL_DUAL_ALG_CERTS
- const DerBuffer *altPrivateKey;
-#endif
-#endif
-
- if (ctx == NULL) {
- return WOLFSSL_FAILURE;
- }
-
-#ifdef WOLFSSL_DUAL_ALG_CERTS
-#ifdef WOLFSSL_BLIND_PRIVATE_KEY
- privateKey = wolfssl_priv_der_unblind(ctx->privateKey, ctx->privateKeyMask);
- if (privateKey == NULL) {
- res = WOLFSSL_FAILURE;
- }
- if (ctx->altPrivateKey != NULL) {
- altPrivateKey = wolfssl_priv_der_unblind(ctx->altPrivateKey,
- ctx->altPrivateKeyMask);
- if (altPrivateKey == NULL) {
- res = WOLFSSL_FAILURE;
- }
- }
- else {
- altPrivateKey = NULL;
- }
-#else
- privateKey = ctx->privateKey;
- altPrivateKey = ctx->altPrivateKey;
-#endif
- if (res == WOLFSSL_SUCCESS) {
- res = check_cert_key(ctx->certificate, privateKey, altPrivateKey,
- ctx->heap, ctx->privateKeyDevId, ctx->privateKeyLabel,
- ctx->privateKeyId, ctx->altPrivateKeyDevId,
- ctx->altPrivateKeyLabel, ctx->altPrivateKeyId) != 0;
- }
-#ifdef WOLFSSL_BLIND_PRIVATE_KEY
- wolfssl_priv_der_unblind_free(privateKey);
- wolfssl_priv_der_unblind_free(altPrivateKey);
-#endif
-#else
-#ifdef WOLFSSL_BLIND_PRIVATE_KEY
- privateKey = wolfssl_priv_der_unblind(ctx->privateKey, ctx->privateKeyMask);
- if (privateKey == NULL) {
- res = WOLFSSL_FAILURE;
- }
-#else
- privateKey = ctx->privateKey;
-#endif
- if (res == WOLFSSL_SUCCESS) {
- res = check_cert_key(ctx->certificate, privateKey, NULL, ctx->heap,
- ctx->privateKeyDevId, ctx->privateKeyLabel,
- ctx->privateKeyId, INVALID_DEVID, 0, 0);
- }
-#ifdef WOLFSSL_BLIND_PRIVATE_KEY
- wolfssl_priv_der_unblind_free(privateKey);
-#endif
-#endif
-
- /* placing error into error queue for Python port */
- if (res != WOLFSSL_SUCCESS) {
- WOLFSSL_ERROR(WC_KEY_MISMATCH_E);
- }
-
- return res;
-}
-#endif /* !NO_CHECK_PRIVATE_KEY */
-
-#ifdef OPENSSL_ALL
-/**
- * Return the private key of the WOLFSSL_CTX struct
- * @return WOLFSSL_EVP_PKEY* The caller doesn *NOT*` free the returned object.
- *
- * Note, even though the supplied ctx pointer is designated const, on success
- * ctx->privateKeyPKey is changed by this call. The change is done safely using
- * a hardware-synchronized store.
- */
-WOLFSSL_EVP_PKEY* wolfSSL_CTX_get0_privatekey(const WOLFSSL_CTX* ctx)
-{
- WOLFSSL_EVP_PKEY* res;
- const unsigned char *key;
- int type;
-
- WOLFSSL_ENTER("wolfSSL_CTX_get0_privatekey");
-
- if (ctx == NULL || ctx->privateKey == NULL ||
- ctx->privateKey->buffer == NULL) {
- WOLFSSL_MSG("Bad parameter or key not set");
- return NULL;
- }
-
- switch (ctx->privateKeyType) {
-#ifndef NO_RSA
- case rsa_sa_algo:
- type = WC_EVP_PKEY_RSA;
- break;
-#endif
-#ifdef HAVE_ECC
- case ecc_dsa_sa_algo:
- type = WC_EVP_PKEY_EC;
- break;
-#endif
-#ifdef WOLFSSL_SM2
- case sm2_sa_algo:
- type = WC_EVP_PKEY_EC;
- break;
-#endif
- default:
- /* Other key types not supported either as ssl private keys
- * or in the EVP layer */
- WOLFSSL_MSG("Unsupported key type");
- return NULL;
- }
-
- if (ctx->privateKeyPKey != NULL) {
- res = ctx->privateKeyPKey;
- }
- else {
- #ifdef WOLFSSL_BLIND_PRIVATE_KEY
- DerBuffer *unblinded_privateKey =
- wolfssl_priv_der_unblind(ctx->privateKey, ctx->privateKeyMask);
- if (unblinded_privateKey == NULL)
- return NULL;
- key = unblinded_privateKey->buffer;
- #else
- key = ctx->privateKey->buffer;
- #endif
- res = wolfSSL_d2i_PrivateKey(type, NULL, &key,
- (long)ctx->privateKey->length);
- #ifdef WOLFSSL_BLIND_PRIVATE_KEY
- wolfssl_priv_der_unblind_free(unblinded_privateKey);
- #endif
- if (res) {
-#ifdef WOLFSSL_ATOMIC_OPS
- WOLFSSL_EVP_PKEY *current_pkey = NULL;
- if (! wolfSSL_Atomic_Ptr_CompareExchange(
- (void * volatile *)&ctx->privateKeyPKey,
- (void **)¤t_pkey, res))
- {
- wolfSSL_EVP_PKEY_free(res);
- res = current_pkey;
- }
-#else
- ((WOLFSSL_CTX *)ctx)->privateKeyPKey = res;
-#endif
- }
- }
-
- return res;
-}
-#endif
-
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
-
-#if !defined(NO_RSA)
-static int d2iTryRsaKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
- long memSz, int priv)
-{
- WOLFSSL_EVP_PKEY* pkey;
- word32 keyIdx = 0;
- int isRsaKey;
- int ret = 1;
-#ifndef WOLFSSL_SMALL_STACK
- RsaKey rsa[1];
-#else
- RsaKey *rsa = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
- if (rsa == NULL)
- return 0;
-#endif
-
- XMEMSET(rsa, 0, sizeof(RsaKey));
-
- if (wc_InitRsaKey(rsa, NULL) != 0) {
- WC_FREE_VAR_EX(rsa, NULL, DYNAMIC_TYPE_RSA);
- return 0;
- }
- /* test if RSA key */
- if (priv) {
- isRsaKey =
- (wc_RsaPrivateKeyDecode(mem, &keyIdx, rsa, (word32)memSz) == 0);
- }
- else {
- isRsaKey =
- (wc_RsaPublicKeyDecode(mem, &keyIdx, rsa, (word32)memSz) == 0);
- }
- wc_FreeRsaKey(rsa);
- WC_FREE_VAR_EX(rsa, NULL, DYNAMIC_TYPE_RSA);
-
- if (!isRsaKey) {
- return WOLFSSL_FATAL_ERROR;
- }
-
- if (*out != NULL) {
- pkey = *out;
- }
- else {
- pkey = wolfSSL_EVP_PKEY_new();
- if (pkey == NULL) {
- WOLFSSL_MSG("RSA wolfSSL_EVP_PKEY_new error");
- return 0;
- }
- }
-
- pkey->pkey_sz = (int)keyIdx;
- pkey->pkey.ptr = (char*)XMALLOC((size_t)memSz, NULL,
- priv ? DYNAMIC_TYPE_PRIVATE_KEY :
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (pkey->pkey.ptr == NULL) {
- ret = 0;
- }
- if (ret == 1) {
- XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
- pkey->type = WC_EVP_PKEY_RSA;
-
- pkey->ownRsa = 1;
- pkey->rsa = wolfssl_rsa_d2i(NULL, mem, memSz,
- priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC);
- if (pkey->rsa == NULL) {
- ret = 0;
- }
- }
-
- if (ret == 1) {
- *out = pkey;
- }
-
- if ((ret == 0) && (*out == NULL)) {
- wolfSSL_EVP_PKEY_free(pkey);
- }
- return ret;
-}
-#endif /* !NO_RSA */
-
-#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA)
-static int d2iTryEccKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
- long memSz, int priv)
-{
- WOLFSSL_EVP_PKEY* pkey;
- word32 keyIdx = 0;
- int isEccKey;
- int ret = 1;
-#ifndef WOLFSSL_SMALL_STACK
- ecc_key ecc[1];
-#else
- ecc_key *ecc = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL,
- DYNAMIC_TYPE_ECC);
- if (ecc == NULL)
- return 0;
-#endif
-
- XMEMSET(ecc, 0, sizeof(ecc_key));
-
- if (wc_ecc_init(ecc) != 0) {
- WC_FREE_VAR_EX(ecc, NULL, DYNAMIC_TYPE_ECC);
- return 0;
- }
-
- if (priv) {
- isEccKey =
- (wc_EccPrivateKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0);
- }
- else {
- isEccKey =
- (wc_EccPublicKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0);
- }
- wc_ecc_free(ecc);
- WC_FREE_VAR_EX(ecc, NULL, DYNAMIC_TYPE_ECC);
-
- if (!isEccKey) {
- return WOLFSSL_FATAL_ERROR;
- }
-
- if (*out != NULL) {
- pkey = *out;
- }
- else {
- pkey = wolfSSL_EVP_PKEY_new();
- if (pkey == NULL) {
- WOLFSSL_MSG("ECC wolfSSL_EVP_PKEY_new error");
- return 0;
- }
- }
-
- pkey->pkey_sz = (int)keyIdx;
- pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL,
- priv ? DYNAMIC_TYPE_PRIVATE_KEY :
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (pkey->pkey.ptr == NULL) {
- ret = 0;
- }
- if (ret == 1) {
- XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
- pkey->type = WC_EVP_PKEY_EC;
-
- pkey->ownEcc = 1;
- pkey->ecc = wolfSSL_EC_KEY_new();
- if (pkey->ecc == NULL) {
- ret = 0;
- }
- }
- if ((ret == 1) && (wolfSSL_EC_KEY_LoadDer_ex(pkey->ecc,
- (const unsigned char*)pkey->pkey.ptr,
- pkey->pkey_sz, priv ? WOLFSSL_RSA_LOAD_PRIVATE
- : WOLFSSL_RSA_LOAD_PUBLIC) != 1)) {
- ret = 0;
- }
- if (ret == 1) {
- *out = pkey;
- }
-
- if ((ret == 0) && (*out == NULL)) {
- wolfSSL_EVP_PKEY_free(pkey);
- }
- return ret;
-}
-#endif /* HAVE_ECC && OPENSSL_EXTRA */
-
-#if !defined(NO_DSA)
-static int d2iTryDsaKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
- long memSz, int priv)
-{
- WOLFSSL_EVP_PKEY* pkey;
- word32 keyIdx = 0;
- int isDsaKey;
- int ret = 1;
-#ifndef WOLFSSL_SMALL_STACK
- DsaKey dsa[1];
-#else
- DsaKey *dsa = (DsaKey*)XMALLOC(sizeof(DsaKey), NULL, DYNAMIC_TYPE_DSA);
- if (dsa == NULL)
- return 0;
-#endif
-
- XMEMSET(dsa, 0, sizeof(DsaKey));
-
- if (wc_InitDsaKey(dsa) != 0) {
- WC_FREE_VAR_EX(dsa, NULL, DYNAMIC_TYPE_DSA);
- return 0;
- }
-
- if (priv) {
- isDsaKey =
- (wc_DsaPrivateKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0);
- }
- else {
- isDsaKey =
- (wc_DsaPublicKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0);
- }
- wc_FreeDsaKey(dsa);
- WC_FREE_VAR_EX(dsa, NULL, DYNAMIC_TYPE_DSA);
-
- /* test if DSA key */
- if (!isDsaKey) {
- return WOLFSSL_FATAL_ERROR;
- }
-
- if (*out != NULL) {
- pkey = *out;
- }
- else {
- pkey = wolfSSL_EVP_PKEY_new();
- if (pkey == NULL) {
- WOLFSSL_MSG("DSA wolfSSL_EVP_PKEY_new error");
- return 0;
- }
- }
-
- pkey->pkey_sz = (int)keyIdx;
- pkey->pkey.ptr = (char*)XMALLOC((size_t)memSz, NULL,
- priv ? DYNAMIC_TYPE_PRIVATE_KEY :
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (pkey->pkey.ptr == NULL) {
- ret = 0;
- }
- if (ret == 1) {
- XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
- pkey->type = WC_EVP_PKEY_DSA;
-
- pkey->ownDsa = 1;
- pkey->dsa = wolfSSL_DSA_new();
- if (pkey->dsa == NULL) {
- ret = 0;
- }
- }
-
- if ((ret == 1) && (wolfSSL_DSA_LoadDer_ex(pkey->dsa,
- (const unsigned char*)pkey->pkey.ptr,
- pkey->pkey_sz, priv ? WOLFSSL_RSA_LOAD_PRIVATE
- : WOLFSSL_RSA_LOAD_PUBLIC) != 1)) {
- ret = 0;
- }
- if (ret == 1) {
- *out = pkey;
- }
-
- if ((ret == 0) && (*out == NULL)) {
- wolfSSL_EVP_PKEY_free(pkey);
- }
- return ret;
-}
-#endif /* NO_DSA */
-
-#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
-#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
- (HAVE_FIPS_VERSION > 2))
-static int d2iTryDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
- long memSz, int priv)
-{
- WOLFSSL_EVP_PKEY* pkey;
- int isDhKey;
- word32 keyIdx = 0;
- int ret = 1;
-#ifndef WOLFSSL_SMALL_STACK
- DhKey dh[1];
-#else
- DhKey *dh = (DhKey*)XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH);
- if (dh == NULL)
- return 0;
-#endif
-
- XMEMSET(dh, 0, sizeof(DhKey));
-
- if (wc_InitDhKey(dh) != 0) {
- WC_FREE_VAR_EX(dh, NULL, DYNAMIC_TYPE_DH);
- return 0;
- }
-
- isDhKey = (wc_DhKeyDecode(mem, &keyIdx, dh, (word32)memSz) == 0);
- wc_FreeDhKey(dh);
- WC_FREE_VAR_EX(dh, NULL, DYNAMIC_TYPE_DH);
-
- /* test if DH key */
- if (!isDhKey) {
- return WOLFSSL_FATAL_ERROR;
- }
-
- if (*out != NULL) {
- pkey = *out;
- }
- else {
- pkey = wolfSSL_EVP_PKEY_new();
- if (pkey == NULL) {
- WOLFSSL_MSG("DH wolfSSL_EVP_PKEY_new error");
- return 0;
- }
- }
-
- pkey->pkey_sz = (int)memSz;
- pkey->pkey.ptr = (char*)XMALLOC((size_t)memSz, NULL,
- priv ? DYNAMIC_TYPE_PRIVATE_KEY :
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (pkey->pkey.ptr == NULL) {
- ret = 0;
- }
- if (ret == 1) {
- XMEMCPY(pkey->pkey.ptr, mem, (size_t)memSz);
- pkey->type = WC_EVP_PKEY_DH;
-
- pkey->ownDh = 1;
- pkey->dh = wolfSSL_DH_new();
- if (pkey->dh == NULL) {
- ret = 0;
- }
- }
-
- if ((ret == 1) && (wolfSSL_DH_LoadDer(pkey->dh,
- (const unsigned char*)pkey->pkey.ptr,
- pkey->pkey_sz) != WOLFSSL_SUCCESS)) {
- ret = 0;
- }
- if (ret == 1) {
- *out = pkey;
- }
-
- if ((ret == 0) && (*out == NULL)) {
- wolfSSL_EVP_PKEY_free(pkey);
- }
- return ret;
-}
-#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
-#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */
-
-#if !defined(NO_DH) && defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA)
-#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
- (HAVE_FIPS_VERSION > 2))
-static int d2iTryAltDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
- long memSz, int priv)
-{
- WOLFSSL_EVP_PKEY* pkey;
- word32 keyIdx = 0;
- DhKey* key = NULL;
- int elements;
- int ret;
-#ifndef WOLFSSL_SMALL_STACK
- DhKey dh[1];
-#else
- DhKey* dh = (DhKey*)XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH);
- if (dh == NULL)
- return 0;
-#endif
- XMEMSET(dh, 0, sizeof(DhKey));
-
- /* test if DH-public key */
- if (wc_InitDhKey(dh) != 0) {
- WC_FREE_VAR_EX(dh, NULL, DYNAMIC_TYPE_DH);
- return 0;
- }
-
- ret = wc_DhKeyDecode(mem, &keyIdx, dh, (word32)memSz);
- wc_FreeDhKey(dh);
- WC_FREE_VAR_EX(dh, NULL, DYNAMIC_TYPE_DH);
-
- if (ret != 0) {
- return WOLFSSL_FATAL_ERROR;
- }
-
- if (*out != NULL) {
- pkey = *out;
- }
- else {
- pkey = wolfSSL_EVP_PKEY_new();
- if (pkey == NULL) {
- return 0;
- }
- }
-
- ret = 1;
- pkey->type = WC_EVP_PKEY_DH;
- pkey->pkey_sz = (int)memSz;
- pkey->pkey.ptr = (char*)XMALLOC((size_t)memSz, NULL,
- priv ? DYNAMIC_TYPE_PRIVATE_KEY :
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (pkey->pkey.ptr == NULL) {
- ret = 0;
- }
- if (ret == 1) {
- XMEMCPY(pkey->pkey.ptr, mem, (size_t)memSz);
- pkey->ownDh = 1;
- pkey->dh = wolfSSL_DH_new();
- if (pkey->dh == NULL) {
- ret = 0;
- }
- }
-
- if (ret == 1) {
- key = (DhKey*)pkey->dh->internal;
-
- keyIdx = 0;
- if (wc_DhKeyDecode(mem, &keyIdx, key, (word32)memSz) != 0) {
- ret = 0;
- }
- }
-
- if (ret == 1) {
- elements = ELEMENT_P | ELEMENT_G | ELEMENT_Q | ELEMENT_PUB;
- if (priv) {
- elements |= ELEMENT_PRV;
- }
- if (SetDhExternal_ex(pkey->dh, elements) != WOLFSSL_SUCCESS ) {
- ret = 0;
- }
- }
- if (ret == 1) {
- *out = pkey;
- }
-
- if ((ret == 0) && (*out == NULL)) {
- wolfSSL_EVP_PKEY_free(pkey);
- }
- return ret;
-}
-#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
-#endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */
-
-#ifdef HAVE_FALCON
-static int d2iTryFalconKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
- long memSz, int priv)
-{
- WOLFSSL_EVP_PKEY* pkey;
- int isFalcon = 0;
-#ifndef WOLFSSL_SMALL_STACK
- falcon_key falcon[1];
-#else
- falcon_key *falcon = (falcon_key *)XMALLOC(sizeof(falcon_key), NULL,
- DYNAMIC_TYPE_FALCON);
- if (falcon == NULL) {
- return 0;
- }
-#endif
-
- if (wc_falcon_init(falcon) != 0) {
- WC_FREE_VAR_EX(falcon, NULL, DYNAMIC_TYPE_FALCON);
- return 0;
- }
-
- /* test if Falcon key */
- if (priv) {
- /* Try level 1 */
- isFalcon = ((wc_falcon_set_level(falcon, 1) == 0) &&
- (wc_falcon_import_private_only(mem, (word32)memSz,
- falcon) == 0));
- if (!isFalcon) {
- /* Try level 5 */
- isFalcon = ((wc_falcon_set_level(falcon, 5) == 0) &&
- (wc_falcon_import_private_only(mem, (word32)memSz,
- falcon) == 0));
- }
- }
- else {
- /* Try level 1 */
- isFalcon = ((wc_falcon_set_level(falcon, 1) == 0) &&
- (wc_falcon_import_public(mem, (word32)memSz, falcon) == 0));
-
- if (!isFalcon) {
- /* Try level 5 */
- isFalcon = ((wc_falcon_set_level(falcon, 5) == 0) &&
- (wc_falcon_import_public(mem, (word32)memSz,
- falcon) == 0));
- }
- }
- wc_falcon_free(falcon);
- WC_FREE_VAR_EX(falcon, NULL, DYNAMIC_TYPE_FALCON);
-
- if (!isFalcon) {
- return WOLFSSL_FATAL_ERROR;
- }
-
- if (*out != NULL) {
- pkey = *out;
- }
- else {
- /* Create a fake Falcon EVP_PKEY. In the future, we might integrate
- * Falcon into the compatibility layer. */
- pkey = wolfSSL_EVP_PKEY_new();
- if (pkey == NULL) {
- WOLFSSL_MSG("Falcon wolfSSL_EVP_PKEY_new error");
- return 0;
- }
- }
- pkey->type = WC_EVP_PKEY_FALCON;
- pkey->pkey.ptr = NULL;
- pkey->pkey_sz = 0;
-
- *out = pkey;
- return 1;
-
-}
-#endif /* HAVE_FALCON */
-
-#ifdef HAVE_DILITHIUM
-static int d2iTryDilithiumKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
- long memSz, int priv)
-{
- WOLFSSL_EVP_PKEY* pkey;
- int isDilithium = 0;
-#ifndef WOLFSSL_SMALL_STACK
- dilithium_key dilithium[1];
-#else
- dilithium_key *dilithium = (dilithium_key *)
- XMALLOC(sizeof(dilithium_key), NULL, DYNAMIC_TYPE_DILITHIUM);
- if (dilithium == NULL) {
- return 0;
- }
-#endif
-
- if (wc_dilithium_init(dilithium) != 0) {
- WC_FREE_VAR_EX(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM);
- return 0;
- }
-
- /* Test if Dilithium key. Try all levels. */
- if (priv) {
- isDilithium = ((wc_dilithium_set_level(dilithium, WC_ML_DSA_44) == 0) &&
- (wc_dilithium_import_private(mem,
- (word32)memSz, dilithium) == 0));
- if (!isDilithium) {
- isDilithium = ((wc_dilithium_set_level(dilithium, WC_ML_DSA_65) == 0) &&
- (wc_dilithium_import_private(mem,
- (word32)memSz, dilithium) == 0));
- }
- if (!isDilithium) {
- isDilithium = ((wc_dilithium_set_level(dilithium, WC_ML_DSA_87) == 0) &&
- (wc_dilithium_import_private(mem,
- (word32)memSz, dilithium) == 0));
- }
- }
- else {
- isDilithium = ((wc_dilithium_set_level(dilithium, WC_ML_DSA_44) == 0) &&
- (wc_dilithium_import_public(mem, (word32)memSz,
- dilithium) == 0));
- if (!isDilithium) {
- isDilithium = ((wc_dilithium_set_level(dilithium, WC_ML_DSA_65) == 0) &&
- (wc_dilithium_import_public(mem, (word32)memSz,
- dilithium) == 0));
- }
- if (!isDilithium) {
- isDilithium = ((wc_dilithium_set_level(dilithium, WC_ML_DSA_87) == 0) &&
- (wc_dilithium_import_public(mem, (word32)memSz,
- dilithium) == 0));
- }
- }
- wc_dilithium_free(dilithium);
- WC_FREE_VAR_EX(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM);
-
- if (!isDilithium) {
- return WOLFSSL_FATAL_ERROR;
- }
-
- if (*out != NULL) {
- pkey = *out;
- }
- else {
- /* Create a fake Dilithium EVP_PKEY. In the future, we might
- * integrate Dilithium into the compatibility layer. */
- pkey = wolfSSL_EVP_PKEY_new();
- if (pkey == NULL) {
- WOLFSSL_MSG("Dilithium wolfSSL_EVP_PKEY_new error");
- return 0;
- }
- }
- pkey->type = WC_EVP_PKEY_DILITHIUM;
- pkey->pkey.ptr = NULL;
- pkey->pkey_sz = 0;
-
- *out = pkey;
- return 1;
-}
-#endif /* HAVE_DILITHIUM */
-
-static WOLFSSL_EVP_PKEY* d2iGenericKey(WOLFSSL_EVP_PKEY** out,
- const unsigned char** in, long inSz, int priv)
-{
- WOLFSSL_EVP_PKEY* pkey = NULL;
-
- WOLFSSL_ENTER("d2iGenericKey");
-
- if (in == NULL || *in == NULL || inSz < 0) {
- WOLFSSL_MSG("Bad argument");
- return NULL;
- }
-
- if ((out != NULL) && (*out != NULL)) {
- pkey = *out;
- }
-
-#if !defined(NO_RSA)
- if (d2iTryRsaKey(&pkey, *in, inSz, priv) >= 0) {
- ;
- }
- else
-#endif /* NO_RSA */
-#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA)
- if (d2iTryEccKey(&pkey, *in, inSz, priv) >= 0) {
- ;
- }
- else
-#endif /* HAVE_ECC && OPENSSL_EXTRA */
-#if !defined(NO_DSA)
- if (d2iTryDsaKey(&pkey, *in, inSz, priv) >= 0) {
- ;
- }
- else
-#endif /* NO_DSA */
-#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
-#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
- (HAVE_FIPS_VERSION > 2))
- if (d2iTryDhKey(&pkey, *in, inSz, priv) >= 0) {
- ;
- }
- else
-#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
-#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */
-
-#if !defined(NO_DH) && defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA)
-#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
- (HAVE_FIPS_VERSION > 2))
- if (d2iTryAltDhKey(&pkey, *in, inSz, priv) >= 0) {
- ;
- }
- else
-#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
-#endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */
-
-#ifdef HAVE_FALCON
- if (d2iTryFalconKey(&pkey, *in, inSz, priv) >= 0) {
- ;
- }
- else
-#endif /* HAVE_FALCON */
-#ifdef HAVE_DILITHIUM
- if (d2iTryDilithiumKey(&pkey, *in, inSz, priv) >= 0) {
- ;
- }
- else
-#endif /* HAVE_DILITHIUM */
- {
- WOLFSSL_MSG("wolfSSL_d2i_PUBKEY couldn't determine key type");
- }
-
- if ((pkey != NULL) && (out != NULL)) {
- *out = pkey;
- }
- return pkey;
-}
-#endif /* OPENSSL_EXTRA || WPA_SMALL */
-
-#ifdef OPENSSL_EXTRA
-
-WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY(
- WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey, const unsigned char** keyBuf,
- long keyLen)
-{
- WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL;
-#ifdef WOLFSSL_PEM_TO_DER
- int ret;
- DerBuffer* pkcs8Der = NULL;
- DerBuffer rawDer;
- EncryptedInfo info;
- int advanceLen = 0;
-
- XMEMSET(&info, 0, sizeof(info));
- XMEMSET(&rawDer, 0, sizeof(rawDer));
-
- if (keyBuf == NULL || *keyBuf == NULL || keyLen <= 0) {
- WOLFSSL_MSG("Bad key PEM/DER args");
- return NULL;
- }
-
- ret = PemToDer(*keyBuf, keyLen, PRIVATEKEY_TYPE, &pkcs8Der, NULL, &info,
- NULL);
- if (ret < 0) {
- WOLFSSL_MSG("Not PEM format");
- ret = AllocDer(&pkcs8Der, (word32)keyLen, PRIVATEKEY_TYPE, NULL);
- if (ret == 0) {
- XMEMCPY(pkcs8Der->buffer, *keyBuf, keyLen);
- }
- }
- else {
- advanceLen = (int)info.consumed;
- }
-
- if (ret == 0) {
- /* Verify this is PKCS8 Key */
- word32 inOutIdx = 0;
- word32 algId;
- ret = ToTraditionalInline_ex(pkcs8Der->buffer, &inOutIdx,
- pkcs8Der->length, &algId);
- if (ret >= 0) {
- if (advanceLen == 0) /* Set only if not PEM */
- advanceLen = (int)inOutIdx + ret;
- if (algId == DHk) {
- /* Special case for DH as we expect the DER buffer to be always
- * be in PKCS8 format */
- rawDer.buffer = pkcs8Der->buffer;
- rawDer.length = inOutIdx + (word32)ret;
- }
- else {
- rawDer.buffer = pkcs8Der->buffer + inOutIdx;
- rawDer.length = (word32)ret;
- }
- ret = 0; /* good DER */
- }
- }
-
- if (ret == 0) {
- pkcs8 = wolfSSL_EVP_PKEY_new();
- if (pkcs8 == NULL)
- ret = MEMORY_E;
- }
- if (ret == 0) {
- pkcs8->pkey.ptr = (char*)XMALLOC(rawDer.length, NULL,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (pkcs8->pkey.ptr == NULL)
- ret = MEMORY_E;
- }
- if (ret == 0) {
- XMEMCPY(pkcs8->pkey.ptr, rawDer.buffer, rawDer.length);
- pkcs8->pkey_sz = (int)rawDer.length;
- }
-
- FreeDer(&pkcs8Der);
- if (ret != 0) {
- wolfSSL_EVP_PKEY_free(pkcs8);
- pkcs8 = NULL;
- }
- else {
- *keyBuf += advanceLen;
- }
- if (pkey != NULL) {
- *pkey = pkcs8;
- }
-
-#else
- (void)bio;
- (void)pkey;
-#endif /* WOLFSSL_PEM_TO_DER */
-
- return pkcs8;
-}
-
-#ifdef OPENSSL_ALL
-int wolfSSL_i2d_PKCS8_PKEY(WOLFSSL_PKCS8_PRIV_KEY_INFO* key, unsigned char** pp)
-{
- word32 keySz = 0;
- unsigned char* out;
- int len;
-
- WOLFSSL_ENTER("wolfSSL_i2d_PKCS8_PKEY");
-
- if (key == NULL)
- return WOLFSSL_FATAL_ERROR;
-
- if (pkcs8_encode(key, NULL, &keySz) != WC_NO_ERR_TRACE(LENGTH_ONLY_E))
- return WOLFSSL_FATAL_ERROR;
- len = (int)keySz;
-
- if ((pp == NULL) || (len == 0))
- return len;
-
- if (*pp == NULL) {
- out = (unsigned char*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_ASN1);
- if (out == NULL)
- return WOLFSSL_FATAL_ERROR;
- }
- else {
- out = *pp;
- }
-
- if (pkcs8_encode(key, out, &keySz) != len) {
- if (*pp == NULL)
- XFREE(out, NULL, DYNAMIC_TYPE_ASN1);
- return WOLFSSL_FATAL_ERROR;
- }
-
- if (*pp == NULL)
- *pp = out;
- else
- *pp += len;
-
- return len;
-}
-#endif
-
-#ifndef NO_BIO
-/* put SSL type in extra for now, not very common */
-
-/* Converts a DER format key read from "bio" to a PKCS8 structure.
- *
- * bio input bio to read DER from
- * pkey If not NULL then this pointer will be overwritten with a new PKCS8
- * structure.
- *
- * returns a WOLFSSL_PKCS8_PRIV_KEY_INFO pointer on success and NULL in fail
- * case.
- */
-WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(WOLFSSL_BIO* bio,
- WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey)
-{
- WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL;
-#ifdef WOLFSSL_PEM_TO_DER
- unsigned char* mem = NULL;
- int memSz;
-
- WOLFSSL_ENTER("wolfSSL_d2i_PKCS8_PKEY_bio");
-
- if (bio == NULL) {
- return NULL;
- }
-
- if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) {
- return NULL;
- }
-
- pkcs8 = wolfSSL_d2i_PKCS8_PKEY(pkey, (const unsigned char**)&mem, memSz);
-#else
- (void)bio;
- (void)pkey;
-#endif /* WOLFSSL_PEM_TO_DER */
-
- return pkcs8;
-}
-
-
-/* expecting DER format public key
- *
- * bio input bio to read DER from
- * out If not NULL then this pointer will be overwritten with a new
- * WOLFSSL_EVP_PKEY pointer
- *
- * returns a WOLFSSL_EVP_PKEY pointer on success and NULL in fail case.
- */
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio,
- WOLFSSL_EVP_PKEY** out)
-{
- unsigned char* mem;
- long memSz;
- WOLFSSL_EVP_PKEY* pkey = NULL;
-
- WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio");
-
- if (bio == NULL) {
- return NULL;
- }
- (void)out;
-
- memSz = wolfSSL_BIO_get_len(bio);
- if (memSz <= 0) {
- return NULL;
- }
-
- mem = (unsigned char*)XMALLOC((size_t)memSz, bio->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (mem == NULL) {
- return NULL;
- }
-
- if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) {
- pkey = wolfSSL_d2i_PUBKEY(NULL, (const unsigned char**)&mem, memSz);
- if (out != NULL && pkey != NULL) {
- *out = pkey;
- }
- }
-
- XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return pkey;
-}
-
-#endif /* !NO_BIO */
-
-
-/* Converts a DER encoded public key to a WOLFSSL_EVP_PKEY structure.
- *
- * out pointer to new WOLFSSL_EVP_PKEY structure. Can be NULL
- * in DER buffer to convert
- * inSz size of in buffer
- *
- * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL
- * on fail
- */
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out,
- const unsigned char** in, long inSz)
-{
- WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY");
- return d2iGenericKey(out, in, inSz, 0);
-}
-
-#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_ASN) && \
- !defined(NO_PWDBASED)
-
-/* helper function to get raw pointer to DER buffer from WOLFSSL_EVP_PKEY */
-static int wolfSSL_EVP_PKEY_get_der(const WOLFSSL_EVP_PKEY* key,
- unsigned char** der)
-{
- int sz;
- word16 pkcs8HeaderSz;
-
- if (!key || !key->pkey_sz)
- return WOLFSSL_FATAL_ERROR;
-
- /* return the key without PKCS8 for compatibility */
- /* if pkcs8HeaderSz is invalid, use 0 and return all of pkey */
- pkcs8HeaderSz = 0;
- if (key->pkey_sz > key->pkcs8HeaderSz)
- pkcs8HeaderSz = key->pkcs8HeaderSz;
- sz = key->pkey_sz - pkcs8HeaderSz;
- if (der) {
- unsigned char* pt = (unsigned char*)key->pkey.ptr;
- if (*der) {
- /* since this function signature has no size value passed in it is
- * assumed that the user has allocated a large enough buffer */
- XMEMCPY(*der, pt + pkcs8HeaderSz, (size_t)sz);
- *der += sz;
- }
- else {
- *der = (unsigned char*)XMALLOC((size_t)sz, NULL,
- DYNAMIC_TYPE_OPENSSL);
- if (*der == NULL) {
- return WOLFSSL_FATAL_ERROR;
- }
- XMEMCPY(*der, pt + pkcs8HeaderSz, (size_t)sz);
- }
- }
- return sz;
-}
-
-int wolfSSL_i2d_PUBKEY(const WOLFSSL_EVP_PKEY *key, unsigned char **der)
-{
- return wolfSSL_i2d_PublicKey(key, der);
-}
-
-#endif /* OPENSSL_EXTRA && !NO_CERTS && !NO_ASN && !NO_PWDBASED */
-
-static WOLFSSL_EVP_PKEY* _d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out,
- const unsigned char **in, long inSz, int priv)
-{
- int ret = 0;
- word32 idx = 0, algId;
- word16 pkcs8HeaderSz = 0;
- WOLFSSL_EVP_PKEY* local;
- int opt = 0;
-
- (void)opt;
-
- if (in == NULL || inSz < 0) {
- WOLFSSL_MSG("Bad argument");
- return NULL;
- }
-
- if (priv == 1) {
- /* Check if input buffer has PKCS8 header. In the case that it does not
- * have a PKCS8 header then do not error out. */
- if ((ret = ToTraditionalInline_ex((const byte*)(*in), &idx,
- (word32)inSz, &algId)) > 0) {
- WOLFSSL_MSG("Found PKCS8 header");
- pkcs8HeaderSz = (word16)idx;
-
- if ((type == WC_EVP_PKEY_RSA && algId != RSAk
- #ifdef WC_RSA_PSS
- && algId != RSAPSSk
- #endif
- ) ||
- (type == WC_EVP_PKEY_EC && algId != ECDSAk) ||
- (type == WC_EVP_PKEY_DSA && algId != DSAk) ||
- (type == WC_EVP_PKEY_DH && algId != DHk)) {
- WOLFSSL_MSG("PKCS8 does not match EVP key type");
- return NULL;
- }
-
- (void)idx; /* not used */
- }
- else {
- if (ret != WC_NO_ERR_TRACE(ASN_PARSE_E)) {
- WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 "
- "header");
- return NULL;
- }
- }
- }
-
- if (out != NULL && *out != NULL) {
- wolfSSL_EVP_PKEY_free(*out);
- *out = NULL;
- }
- local = wolfSSL_EVP_PKEY_new();
- if (local == NULL) {
- return NULL;
- }
-
- local->type = type;
- local->pkey_sz = (int)inSz;
- local->pkcs8HeaderSz = pkcs8HeaderSz;
- local->pkey.ptr = (char*)XMALLOC((size_t)inSz, NULL,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (local->pkey.ptr == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- local = NULL;
- return NULL;
- }
- else {
- XMEMCPY(local->pkey.ptr, *in, (size_t)inSz);
- }
-
- switch (type) {
-#ifndef NO_RSA
- case WC_EVP_PKEY_RSA:
- opt = priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC;
- local->ownRsa = 1;
- local->rsa = wolfssl_rsa_d2i(NULL,
- (const unsigned char*)local->pkey.ptr, local->pkey_sz, opt);
- if (local->rsa == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- break;
-#endif /* NO_RSA */
-#ifdef HAVE_ECC
- case WC_EVP_PKEY_EC:
- local->ownEcc = 1;
- local->ecc = wolfSSL_EC_KEY_new();
- if (local->ecc == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- opt = priv ? WOLFSSL_EC_KEY_LOAD_PRIVATE :
- WOLFSSL_EC_KEY_LOAD_PUBLIC;
- if (wolfSSL_EC_KEY_LoadDer_ex(local->ecc,
- (const unsigned char*)local->pkey.ptr, local->pkey_sz,
- opt)
- != WOLFSSL_SUCCESS) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- break;
-#endif /* HAVE_ECC */
-#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)
-#ifndef NO_DSA
- case WC_EVP_PKEY_DSA:
- local->ownDsa = 1;
- local->dsa = wolfSSL_DSA_new();
- if (local->dsa == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- opt = priv ? WOLFSSL_DSA_LOAD_PRIVATE : WOLFSSL_DSA_LOAD_PUBLIC;
- if (wolfSSL_DSA_LoadDer_ex(local->dsa,
- (const unsigned char*)local->pkey.ptr, local->pkey_sz,
- opt)
- != WOLFSSL_SUCCESS) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- break;
-#endif /* NO_DSA */
-#ifndef NO_DH
-#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2))
- case WC_EVP_PKEY_DH:
- local->ownDh = 1;
- local->dh = wolfSSL_DH_new();
- if (local->dh == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- if (wolfSSL_DH_LoadDer(local->dh,
- (const unsigned char*)local->pkey.ptr, local->pkey_sz)
- != WOLFSSL_SUCCESS) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- break;
-#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
-#endif /* HAVE_DH */
-#endif /* WOLFSSL_QT || OPENSSL_ALL || WOLFSSL_OPENSSH */
- default:
- WOLFSSL_MSG("Unsupported key type");
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
-
- /* advance pointer with success */
- if (local != NULL) {
- if (local->pkey_sz <= (int)inSz) {
- *in += local->pkey_sz;
- }
-
- if (out != NULL) {
- *out = local;
- }
- }
-
- return local;
-}
-
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out,
- const unsigned char **in, long inSz)
-{
- WOLFSSL_ENTER("wolfSSL_d2i_PublicKey");
-
- return _d2i_PublicKey(type, out, in, inSz, 0);
-}
-/* Reads in a DER format key. If PKCS8 headers are found they are stripped off.
- *
- * type type of key
- * out newly created WOLFSSL_EVP_PKEY structure
- * in pointer to input key DER
- * inSz size of in buffer
- *
- * On success a non null pointer is returned and the pointer in is advanced the
- * same number of bytes read.
- */
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out,
- const unsigned char **in, long inSz)
-{
- WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey");
-
- return _d2i_PublicKey(type, out, in, inSz, 1);
-}
-
-#ifdef WOLF_PRIVATE_KEY_ID
-/* Create an EVP structure for use with crypto callbacks */
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_id(int type, WOLFSSL_EVP_PKEY** out,
- void* heap, int devId)
-{
- WOLFSSL_EVP_PKEY* local;
-
- if (out != NULL && *out != NULL) {
- wolfSSL_EVP_PKEY_free(*out);
- *out = NULL;
- }
-
- local = wolfSSL_EVP_PKEY_new_ex(heap);
- if (local == NULL) {
- return NULL;
- }
-
- local->type = type;
- local->pkey_sz = 0;
- local->pkcs8HeaderSz = 0;
-
- switch (type) {
-#ifndef NO_RSA
- case WC_EVP_PKEY_RSA:
- {
- RsaKey* key;
- local->ownRsa = 1;
- local->rsa = wolfSSL_RSA_new_ex(heap, devId);
- if (local->rsa == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- key = (RsaKey*)local->rsa->internal;
- #ifdef WOLF_CRYPTO_CB
- key->devId = devId;
- #endif
- (void)key;
- local->rsa->inSet = 1;
- break;
- }
-#endif /* !NO_RSA */
-#ifdef HAVE_ECC
- case WC_EVP_PKEY_EC:
- {
- ecc_key* key;
- local->ownEcc = 1;
- local->ecc = wolfSSL_EC_KEY_new_ex(heap, devId);
- if (local->ecc == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- key = (ecc_key*)local->ecc->internal;
- #ifdef WOLF_CRYPTO_CB
- key->devId = devId;
- #endif
- key->type = ECC_PRIVATEKEY;
- /* key is required to have a key size / curve set, although
- * actual one used is determined by devId callback function */
- wc_ecc_set_curve(key, ECDHE_SIZE, ECC_CURVE_DEF);
-
- local->ecc->inSet = 1;
- break;
- }
-#endif /* HAVE_ECC */
- default:
- WOLFSSL_MSG("Unsupported private key id type");
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
-
- if (local != NULL && out != NULL) {
- *out = local;
- }
-
- return local;
-}
-#endif /* WOLF_PRIVATE_KEY_ID */
-
-#ifndef NO_CERTS /* // NOLINT(readability-redundant-preprocessor) */
-
-#ifndef NO_CHECK_PRIVATE_KEY
-/* Check private against public in certificate for match
- *
- * ssl WOLFSSL structure to check private key in
- *
- * Returns WOLFSSL_SUCCESS on good private key
- * WOLFSSL_FAILURE if mismatched. */
-int wolfSSL_check_private_key(const WOLFSSL* ssl)
-{
- int res = WOLFSSL_SUCCESS;
-
-#ifdef WOLFSSL_BLIND_PRIVATE_KEY
- DerBuffer *privateKey;
-#ifdef WOLFSSL_DUAL_ALG_CERTS
- DerBuffer *altPrivateKey;
-#endif
-#else
- const DerBuffer *privateKey;
-#ifdef WOLFSSL_DUAL_ALG_CERTS
- const DerBuffer *altPrivateKey;
-#endif
-#endif
-
- if (ssl == NULL) {
- return WOLFSSL_FAILURE;
- }
-#ifdef WOLFSSL_DUAL_ALG_CERTS
-#ifdef WOLFSSL_BLIND_PRIVATE_KEY
- privateKey = wolfssl_priv_der_unblind(ssl->buffers.key,
- ssl->buffers.keyMask);
- if (privateKey == NULL) {
- res = WOLFSSL_FAILURE;
- }
- if (ssl->buffers.altKey != NULL) {
- altPrivateKey = wolfssl_priv_der_unblind(ssl->buffers.altKey,
- ssl->buffers.altKeyMask);
- if (altPrivateKey == NULL) {
- res = WOLFSSL_FAILURE;
- }
- }
- else {
- altPrivateKey = NULL;
- }
-#else
- privateKey = ssl->buffers.key;
- altPrivateKey = ssl->buffers.altKey;
-#endif
- if (res == WOLFSSL_SUCCESS) {
- res = check_cert_key(ssl->buffers.certificate, privateKey,
- altPrivateKey, ssl->heap, ssl->buffers.keyDevId,
- ssl->buffers.keyLabel, ssl->buffers.keyId, ssl->buffers.altKeyDevId,
- ssl->buffers.altKeyLabel, ssl->buffers.altKeyId);
- }
-#ifdef WOLFSSL_BLIND_PRIVATE_KEY
- wolfssl_priv_der_unblind_free(privateKey);
- wolfssl_priv_der_unblind_free(altPrivateKey);
-#endif
-#else
-#ifdef WOLFSSL_BLIND_PRIVATE_KEY
- privateKey = wolfssl_priv_der_unblind(ssl->buffers.key,
- ssl->buffers.keyMask);
- if (privateKey == NULL) {
- res = WOLFSSL_FAILURE;
- }
-#else
- privateKey = ssl->buffers.key;
-#endif
- if (res == WOLFSSL_SUCCESS) {
- res = check_cert_key(ssl->buffers.certificate, privateKey, NULL,
- ssl->heap, ssl->buffers.keyDevId, ssl->buffers.keyLabel,
- ssl->buffers.keyId, INVALID_DEVID, 0, 0);
- }
-#ifdef WOLFSSL_BLIND_PRIVATE_KEY
- wolfssl_priv_der_unblind_free(privateKey);
-#endif
-#endif
-
- return res;
-}
-#endif /* !NO_CHECK_PRIVATE_KEY */
-
-#endif /* !NO_CERTS */
-
-#endif /* OPENSSL_EXTRA */
-
-#if defined(HAVE_RPK)
-/* Confirm that all the byte data in the buffer is unique.
- * return 1 if all the byte data in the buffer is unique, otherwise 0.
- */
-static int isArrayUnique(const char* buf, size_t len)
-{
- size_t i, j;
- /* check the array is unique */
- for (i = 0; i < len -1; ++i) {
- for (j = i+ 1; j < len; ++j) {
- if (buf[i] == buf[j]) {
- return 0;
- }
- }
- }
- return 1;
-}
-
-/* Set user preference for the {client,server}_cert_type extension.
- * Takes byte array containing cert types the caller can provide to its peer.
- * Cert types are in preferred order in the array.
- */
-static int set_cert_type(RpkConfig* cfg,
- int client, const char* buf, int bufLen)
-{
- int i;
- byte* certTypeCnt;
- byte* certTypes;
-
- if (cfg == NULL || bufLen > (client ? MAX_CLIENT_CERT_TYPE_CNT :
- MAX_SERVER_CERT_TYPE_CNT)) {
- return BAD_FUNC_ARG;
- }
-
- if (client) {
- certTypeCnt = &cfg->preferred_ClientCertTypeCnt;
- certTypes = cfg->preferred_ClientCertTypes;
- }
- else {
- certTypeCnt = &cfg->preferred_ServerCertTypeCnt;
- certTypes = cfg->preferred_ServerCertTypes;
- }
- /* if buf is set to NULL or bufLen is zero, it defaults the setting*/
- if (buf == NULL || bufLen == 0) {
- *certTypeCnt = 1;
- for (i = 0; i < 2; i++)
- certTypes[i] = WOLFSSL_CERT_TYPE_X509;
- return WOLFSSL_SUCCESS;
- }
-
- if (!isArrayUnique(buf, (size_t)bufLen))
- return BAD_FUNC_ARG;
-
- for (i = 0; i < bufLen; i++) {
- if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509)
- return BAD_FUNC_ARG;
- certTypes[i] = (byte)buf[i];
- }
- *certTypeCnt = bufLen;
-
- return WOLFSSL_SUCCESS;
-}
-int wolfSSL_set_client_cert_type(WOLFSSL* ssl, const char* buf, int buflen)
-{
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return set_cert_type(&ssl->options.rpkConfig, 1, buf, buflen);
-}
-int wolfSSL_set_server_cert_type(WOLFSSL* ssl, const char* buf, int buflen)
-{
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return set_cert_type(&ssl->options.rpkConfig, 0, buf, buflen);
-}
-int wolfSSL_CTX_set_client_cert_type(WOLFSSL_CTX* ctx,
- const char* buf, int buflen)
-{
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- return set_cert_type(&ctx->rpkConfig, 1, buf, buflen);
-}
-int wolfSSL_CTX_set_server_cert_type(WOLFSSL_CTX* ctx,
- const char* buf, int buflen)
-{
- if (ctx == NULL)
- return BAD_FUNC_ARG;
- return set_cert_type(&ctx->rpkConfig, 0, buf, buflen);
-}
-
-/* get negotiated certificate type value and return it to the second parameter.
- * cert type value:
- * -1: WOLFSSL_CERT_TYPE_UNKNOWN
- * 0: WOLFSSL_CERT_TYPE_X509
- * 2: WOLFSSL_CERT_TYPE_RPK
- * return WOLFSSL_SUCCESS on success, otherwise negative value.
- * in case no negotiation performed, it returns WOLFSSL_SUCCESS and -1 is for
- * cert type.
- */
-int wolfSSL_get_negotiated_client_cert_type(WOLFSSL* ssl, int* tp)
-{
- int ret = WOLFSSL_SUCCESS;
-
- if (ssl == NULL || tp == NULL)
- return BAD_FUNC_ARG;
-
- if (ssl->options.side == WOLFSSL_CLIENT_END) {
- if (ssl->options.rpkState.received_ClientCertTypeCnt == 1)
- *tp = ssl->options.rpkState.received_ClientCertTypes[0];
- else
- *tp = WOLFSSL_CERT_TYPE_UNKNOWN;
- }
- else {
- if (ssl->options.rpkState.sending_ClientCertTypeCnt == 1)
- *tp = ssl->options.rpkState.sending_ClientCertTypes[0];
- else
- *tp = WOLFSSL_CERT_TYPE_UNKNOWN;
- }
- return ret;
-}
-
-/* get negotiated certificate type value and return it to the second parameter.
- * cert type value:
- * -1: WOLFSSL_CERT_TYPE_UNKNOWN
- * 0: WOLFSSL_CERT_TYPE_X509
- * 2: WOLFSSL_CERT_TYPE_RPK
- * return WOLFSSL_SUCCESS on success, otherwise negative value.
- * in case no negotiation performed, it returns WOLFSSL_SUCCESS and -1 is for
- * cert type.
- */
-int wolfSSL_get_negotiated_server_cert_type(WOLFSSL* ssl, int* tp)
-{
- int ret = WOLFSSL_SUCCESS;
-
- if (ssl == NULL || tp == NULL)
- return BAD_FUNC_ARG;
-
- if (ssl->options.side == WOLFSSL_CLIENT_END) {
- if (ssl->options.rpkState.received_ServerCertTypeCnt == 1)
- *tp = ssl->options.rpkState.received_ServerCertTypes[0];
- else
- *tp = WOLFSSL_CERT_TYPE_UNKNOWN;
- }
- else {
- if (ssl->options.rpkState.sending_ServerCertTypeCnt == 1)
- *tp = ssl->options.rpkState.sending_ServerCertTypes[0];
- else
- *tp = WOLFSSL_CERT_TYPE_UNKNOWN;
- }
- return ret;
-}
-
-#endif /* HAVE_RPK */
-
-#ifdef HAVE_ECC
-
-/* Set Temp CTX EC-DHE size in octets, can be 14 - 66 (112 - 521 bit) */
-int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX* ctx, word16 sz)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_SetTmpEC_DHE_Sz");
-
- if (ctx == NULL)
- return BAD_FUNC_ARG;
-
- /* if 0 then get from loaded private key */
- if (sz == 0) {
- /* applies only to ECDSA */
- if (ctx->privateKeyType != ecc_dsa_sa_algo)
- return WOLFSSL_SUCCESS;
-
- if (ctx->privateKeySz == 0) {
- WOLFSSL_MSG("Must set private key/cert first");
- return BAD_FUNC_ARG;
- }
-
- sz = (word16)ctx->privateKeySz;
- }
-
- /* check size */
-#if ECC_MIN_KEY_SZ > 0
- if (sz < ECC_MINSIZE)
- return BAD_FUNC_ARG;
-#endif
- if (sz > ECC_MAXSIZE)
- return BAD_FUNC_ARG;
-
- ctx->eccTempKeySz = sz;
-
- return WOLFSSL_SUCCESS;
-}
-
-
-/* Set Temp SSL EC-DHE size in octets, can be 14 - 66 (112 - 521 bit) */
-int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL* ssl, word16 sz)
-{
- WOLFSSL_ENTER("wolfSSL_SetTmpEC_DHE_Sz");
-
- if (ssl == NULL)
- return BAD_FUNC_ARG;
-
- /* check size */
-#if ECC_MIN_KEY_SZ > 0
- if (sz < ECC_MINSIZE)
- return BAD_FUNC_ARG;
-#endif
- if (sz > ECC_MAXSIZE)
- return BAD_FUNC_ARG;
-
- ssl->eccTempKeySz = sz;
-
- return WOLFSSL_SUCCESS;
-}
-
-#endif /* HAVE_ECC */
-
-
-typedef struct {
- byte verifyPeer:1;
- byte verifyNone:1;
- byte failNoCert:1;
- byte failNoCertxPSK:1;
- byte verifyPostHandshake:1;
-} SetVerifyOptions;
-
-static SetVerifyOptions ModeToVerifyOptions(int mode)
-{
- SetVerifyOptions opts;
- XMEMSET(&opts, 0, sizeof(SetVerifyOptions));
-
- if (mode != WOLFSSL_VERIFY_DEFAULT) {
- opts.verifyNone = (mode == WOLFSSL_VERIFY_NONE);
- if (!opts.verifyNone) {
- opts.verifyPeer =
- (mode & WOLFSSL_VERIFY_PEER) != 0;
- opts.failNoCertxPSK =
- (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) != 0;
- opts.failNoCert =
- (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT) != 0;
-#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
- opts.verifyPostHandshake =
- (mode & WOLFSSL_VERIFY_POST_HANDSHAKE) != 0;
-#endif
- }
- }
-
- return opts;
-}
-
-WOLFSSL_ABI
-void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback verify_callback)
-{
- SetVerifyOptions opts;
-
- WOLFSSL_ENTER("wolfSSL_CTX_set_verify");
- if (ctx == NULL)
- return;
-
- opts = ModeToVerifyOptions(mode);
-
- ctx->verifyNone = opts.verifyNone;
- ctx->verifyPeer = opts.verifyPeer;
- ctx->failNoCert = opts.failNoCert;
- ctx->failNoCertxPSK = opts.failNoCertxPSK;
-#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
- ctx->verifyPostHandshake = opts.verifyPostHandshake;
-#endif
-
- ctx->verifyCallback = verify_callback;
-}
-
-#ifdef OPENSSL_ALL
-void wolfSSL_CTX_set_cert_verify_callback(WOLFSSL_CTX* ctx,
- CertVerifyCallback cb, void* arg)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_set_cert_verify_callback");
- if (ctx == NULL)
- return;
-
- ctx->verifyCertCb = cb;
- ctx->verifyCertCbArg = arg;
-}
-#endif
-
-
-void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback verify_callback)
-{
- SetVerifyOptions opts;
-
- WOLFSSL_ENTER("wolfSSL_set_verify");
- if (ssl == NULL)
- return;
-
- opts = ModeToVerifyOptions(mode);
-
- ssl->options.verifyNone = opts.verifyNone;
- ssl->options.verifyPeer = opts.verifyPeer;
- ssl->options.failNoCert = opts.failNoCert;
- ssl->options.failNoCertxPSK = opts.failNoCertxPSK;
-#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
- ssl->options.verifyPostHandshake = opts.verifyPostHandshake;
-#endif
-
- ssl->verifyCallback = verify_callback;
-}
-
-void wolfSSL_set_verify_result(WOLFSSL *ssl, long v)
-{
- WOLFSSL_ENTER("wolfSSL_set_verify_result");
-
- if (ssl == NULL)
- return;
-
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
- defined(OPENSSL_ALL)
- ssl->peerVerifyRet = (unsigned long)v;
-#else
- (void)v;
- WOLFSSL_STUB("wolfSSL_set_verify_result");
-#endif
-}
-
-#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \
- defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
-/* For TLS v1.3 send handshake messages after handshake completes. */
-/* Returns 1=WOLFSSL_SUCCESS or 0=WOLFSSL_FAILURE */
-int wolfSSL_verify_client_post_handshake(WOLFSSL* ssl)
-{
- int ret = wolfSSL_request_certificate(ssl);
- if (ret != WOLFSSL_SUCCESS) {
- if (!IsAtLeastTLSv1_3(ssl->version)) {
- /* specific error of wrong version expected */
- WOLFSSL_ERROR(UNSUPPORTED_PROTO_VERSION);
-
- }
- else {
- WOLFSSL_ERROR(ret); /* log the error in the error queue */
- }
- }
- return (ret == WOLFSSL_SUCCESS) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
-}
-
-int wolfSSL_CTX_set_post_handshake_auth(WOLFSSL_CTX* ctx, int val)
-{
- int ret = wolfSSL_CTX_allow_post_handshake_auth(ctx);
- if (ret == 0) {
- ctx->postHandshakeAuth = (val != 0);
- }
- return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
-}
-int wolfSSL_set_post_handshake_auth(WOLFSSL* ssl, int val)
-{
- int ret = wolfSSL_allow_post_handshake_auth(ssl);
- if (ret == 0) {
- ssl->options.postHandshakeAuth = (val != 0);
- }
- return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
-}
-#endif /* OPENSSL_EXTRA && !NO_CERTS && WOLFSSL_TLS13 &&
- * WOLFSSL_POST_HANDSHAKE_AUTH */
-
-/* store user ctx for verify callback */
-void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx)
-{
- WOLFSSL_ENTER("wolfSSL_SetCertCbCtx");
- if (ssl)
- ssl->verifyCbCtx = ctx;
-}
-
-
-/* store user ctx for verify callback */
-void wolfSSL_CTX_SetCertCbCtx(WOLFSSL_CTX* ctx, void* userCtx)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_SetCertCbCtx");
- if (ctx)
- ctx->verifyCbCtx = userCtx;
-}
-
-
-/* store context CA Cache addition callback */
-void wolfSSL_CTX_SetCACb(WOLFSSL_CTX* ctx, CallbackCACache cb)
-{
- if (ctx && ctx->cm)
- ctx->cm->caCacheCallback = cb;
-}
-
-
-#if defined(PERSIST_CERT_CACHE)
-
-#if !defined(NO_FILESYSTEM)
-
-/* Persist cert cache to file */
-int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_save_cert_cache");
-
- if (ctx == NULL || fname == NULL)
- return BAD_FUNC_ARG;
-
- return CM_SaveCertCache(ctx->cm, fname);
-}
-
-
-/* Persist cert cache from file */
-int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_restore_cert_cache");
-
- if (ctx == NULL || fname == NULL)
- return BAD_FUNC_ARG;
-
- return CM_RestoreCertCache(ctx->cm, fname);
-}
-
-#endif /* NO_FILESYSTEM */
-
-/* Persist cert cache to memory */
-int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX* ctx, void* mem,
- int sz, int* used)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_memsave_cert_cache");
-
- if (ctx == NULL || mem == NULL || used == NULL || sz <= 0)
- return BAD_FUNC_ARG;
-
- return CM_MemSaveCertCache(ctx->cm, mem, sz, used);
-}
-
-
-/* Restore cert cache from memory */
-int wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX* ctx, const void* mem, int sz)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_memrestore_cert_cache");
-
- if (ctx == NULL || mem == NULL || sz <= 0)
- return BAD_FUNC_ARG;
-
- return CM_MemRestoreCertCache(ctx->cm, mem, sz);
-}
-
-
-/* get how big the the cert cache save buffer needs to be */
-int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX* ctx)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_get_cert_cache_memsize");
-
- if (ctx == NULL)
- return BAD_FUNC_ARG;
-
- return CM_GetCertCacheMemSize(ctx->cm);
-}
-
-#endif /* PERSIST_CERT_CACHE */
-#endif /* !NO_CERTS */
+#define WOLFSSL_SSL_API_CRL_OCSP_INCLUDED
+#include "src/ssl_api_crl_ocsp.c"
void wolfSSL_load_error_strings(void)
@@ -12098,126 +7907,6 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
#endif /* HAVE_ANON */
-#ifndef NO_CERTS
-
- /* unload any certs or keys that SSL owns, leave CTX as is
- WOLFSSL_SUCCESS on ok */
- int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl)
- {
- if (ssl == NULL) {
- WOLFSSL_MSG("Null function arg");
- return BAD_FUNC_ARG;
- }
-
- if (ssl->buffers.weOwnCert && !ssl->keepCert) {
- WOLFSSL_MSG("Unloading cert");
- FreeDer(&ssl->buffers.certificate);
- #ifdef KEEP_OUR_CERT
- wolfSSL_X509_free(ssl->ourCert);
- ssl->ourCert = NULL;
- #endif
- ssl->buffers.weOwnCert = 0;
- }
-
- if (ssl->buffers.weOwnCertChain) {
- WOLFSSL_MSG("Unloading cert chain");
- FreeDer(&ssl->buffers.certChain);
- ssl->buffers.weOwnCertChain = 0;
- }
-
- if (ssl->buffers.weOwnKey) {
- WOLFSSL_MSG("Unloading key");
- ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length);
- FreeDer(&ssl->buffers.key);
- #ifdef WOLFSSL_BLIND_PRIVATE_KEY
- FreeDer(&ssl->buffers.keyMask);
- #endif
- ssl->buffers.weOwnKey = 0;
- }
-
-#ifdef WOLFSSL_DUAL_ALG_CERTS
- if (ssl->buffers.weOwnAltKey) {
- WOLFSSL_MSG("Unloading alt key");
- ForceZero(ssl->buffers.altKey->buffer, ssl->buffers.altKey->length);
- FreeDer(&ssl->buffers.altKey);
- #ifdef WOLFSSL_BLIND_PRIVATE_KEY
- FreeDer(&ssl->buffers.altKeyMask);
- #endif
- ssl->buffers.weOwnAltKey = 0;
- }
-#endif /* WOLFSSL_DUAL_ALG_CERTS */
-
- return WOLFSSL_SUCCESS;
- }
-
-
- int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_UnloadCAs");
-
- if (ctx == NULL)
- return BAD_FUNC_ARG;
-
- return wolfSSL_CertManagerUnloadCAs(ctx->cm);
- }
-
- int wolfSSL_CTX_UnloadIntermediateCerts(WOLFSSL_CTX* ctx)
- {
- int ret;
-
- WOLFSSL_ENTER("wolfSSL_CTX_UnloadIntermediateCerts");
-
- if (ctx == NULL)
- return BAD_FUNC_ARG;
-
- ret = wolfSSL_RefWithMutexLock(&ctx->ref);
- if (ret < 0)
- return ret;
-
- if (ctx->ref.count > 1) {
- WOLFSSL_MSG("ctx object must have a ref count of 1 before "
- "unloading intermediate certs");
- ret = BAD_STATE_E;
- }
- else {
- ret = wolfSSL_CertManagerUnloadIntermediateCerts(ctx->cm);
- }
-
- if (wolfSSL_RefWithMutexUnlock(&ctx->ref) != 0)
- WOLFSSL_MSG("Failed to unlock mutex!");
-
- return ret;
- }
-
-
-#ifdef WOLFSSL_TRUST_PEER_CERT
- int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers");
-
- if (ctx == NULL)
- return BAD_FUNC_ARG;
-
- return wolfSSL_CertManagerUnload_trust_peers(ctx->cm);
- }
-
-#ifdef WOLFSSL_LOCAL_X509_STORE
- int wolfSSL_Unload_trust_peers(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers");
-
- if (ssl == NULL)
- return BAD_FUNC_ARG;
-
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerUnload_trust_peers(SSL_CM(ssl));
- }
-#endif /* WOLFSSL_LOCAL_X509_STORE */
-#endif /* WOLFSSL_TRUST_PEER_CERT */
-/* old NO_FILESYSTEM end */
-#endif /* !NO_CERTS */
-
-
#ifdef OPENSSL_EXTRA
int wolfSSL_add_all_algorithms(void)
@@ -12360,50 +8049,6 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
#endif /* !NO_BIO */
#endif /* OPENSSL_EXTRA */
-#ifndef WOLFSSL_NO_CA_NAMES
- void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx,
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_client_CA_list");
- if (ctx != NULL) {
- wolfSSL_sk_X509_NAME_pop_free(ctx->client_ca_names, NULL);
- ctx->client_ca_names = names;
- }
- }
-
- void wolfSSL_set_client_CA_list(WOLFSSL* ssl,
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
- {
- WOLFSSL_ENTER("wolfSSL_set_client_CA_list");
- if (ssl != NULL) {
- if (ssl->client_ca_names != ssl->ctx->client_ca_names)
- wolfSSL_sk_X509_NAME_pop_free(ssl->client_ca_names, NULL);
- ssl->client_ca_names = names;
- }
- }
-
- void wolfSSL_CTX_set0_CA_list(WOLFSSL_CTX* ctx,
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set0_CA_list");
- if (ctx != NULL) {
- wolfSSL_sk_X509_NAME_pop_free(ctx->ca_names, NULL);
- ctx->ca_names = names;
- }
- }
-
- void wolfSSL_set0_CA_list(WOLFSSL* ssl,
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
- {
- WOLFSSL_ENTER("wolfSSL_set0_CA_list");
- if (ssl != NULL) {
- if (ssl->ca_names != ssl->ctx->ca_names)
- wolfSSL_sk_X509_NAME_pop_free(ssl->ca_names, NULL);
- ssl->ca_names = names;
- }
- }
-#endif /* WOLFSSL_NO_CA_NAMES */
-
#ifdef WOLFSSL_CERT_SETUP_CB
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
/* registers client cert callback, called during handshake if server
@@ -12622,249 +8267,6 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
}
#endif /* WOLFSSL_CERT_SETUP_CB */
-#ifndef WOLFSSL_NO_CA_NAMES
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get_client_CA_list(
- const WOLFSSL_CTX *ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_get_client_CA_list");
-
- if (ctx == NULL) {
- WOLFSSL_MSG("Bad argument passed to "
- "wolfSSL_CTX_get_client_CA_list");
- return NULL;
- }
-
- return ctx->client_ca_names;
- }
-
- /* On server side: returns the CAs set via *_set_client_CA_list();
- * On client side: returns the CAs received from server -- same as
- * wolfSSL_get0_peer_CA_list() */
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list(
- const WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_get_client_CA_list");
-
- if (ssl == NULL) {
- WOLFSSL_MSG("Bad argument passed to wolfSSL_get_client_CA_list");
- return NULL;
- }
-
- if (ssl->options.side == WOLFSSL_CLIENT_END)
- return ssl->peer_ca_names;
- else
- return SSL_CLIENT_CA_NAMES(ssl);
- }
-
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get0_CA_list(
- const WOLFSSL_CTX *ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_get0_CA_list");
-
- if (ctx == NULL) {
- WOLFSSL_MSG("Bad argument passed to wolfSSL_CTX_get0_CA_list");
- return NULL;
- }
-
- return ctx->ca_names;
- }
-
- /* Always returns the CA's set via *_set0_CA_list */
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get0_CA_list(const WOLFSSL *ssl)
- {
- WOLFSSL_ENTER("wolfSSL_get0_CA_list");
-
- if (ssl == NULL) {
- WOLFSSL_MSG("Bad argument passed to wolfSSL_get0_CA_list");
- return NULL;
- }
-
- return SSL_CA_NAMES(ssl);
- }
-
- /* Always returns the CA's received from the peer */
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get0_peer_CA_list(
- const WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_get0_peer_CA_list");
-
- if (ssl == NULL) {
- WOLFSSL_MSG("Bad argument passed to wolfSSL_get0_peer_CA_list");
- return NULL;
- }
-
- return ssl->peer_ca_names;
- }
-
- #if !defined(NO_CERTS)
- static int add_to_CA_list(WOLFSSL_STACK* ca_names, WOLFSSL_X509* x509)
- {
- WOLFSSL_X509_NAME *nameCopy = NULL;
-
- nameCopy = wolfSSL_X509_NAME_dup(wolfSSL_X509_get_subject_name(x509));
- if (nameCopy == NULL) {
- WOLFSSL_MSG("wolfSSL_X509_NAME_dup error");
- return WOLFSSL_FAILURE;
- }
-
- if (wolfSSL_sk_X509_NAME_push(ca_names, nameCopy) <= 0) {
- WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error");
- wolfSSL_X509_NAME_free(nameCopy);
- return WOLFSSL_FAILURE;
- }
-
- return WOLFSSL_SUCCESS;
- }
-
- int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA");
- if (ctx == NULL || x509 == NULL) {
- WOLFSSL_MSG("Bad argument");
- return WOLFSSL_FAILURE;
- }
- if (ctx->client_ca_names == NULL) {
- ctx->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL);
- if (ctx->client_ca_names == NULL) {
- WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
- return WOLFSSL_FAILURE;
- }
- }
- return add_to_CA_list(ctx->client_ca_names, x509);
- }
-
- int wolfSSL_add_client_CA(WOLFSSL* ssl, WOLFSSL_X509* x509)
- {
- WOLFSSL_ENTER("wolfSSL_add_client_CA");
- if (ssl == NULL || x509 == NULL) {
- WOLFSSL_MSG("Bad argument");
- return WOLFSSL_FAILURE;
- }
- if (ssl->client_ca_names == NULL) {
- ssl->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL);
- if (ssl->client_ca_names == NULL) {
- WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
- return WOLFSSL_FAILURE;
- }
- }
- return add_to_CA_list(ssl->client_ca_names, x509);
- }
-
- int wolfSSL_CTX_add1_to_CA_list(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_add1_to_CA_list");
- if (ctx == NULL || x509 == NULL) {
- WOLFSSL_MSG("Bad argument");
- return WOLFSSL_FAILURE;
- }
- if (ctx->ca_names == NULL) {
- ctx->ca_names = wolfSSL_sk_X509_NAME_new(NULL);
- if (ctx->ca_names == NULL) {
- WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
- return WOLFSSL_FAILURE;
- }
- }
- return add_to_CA_list(ctx->ca_names, x509);
- }
-
- int wolfSSL_add1_to_CA_list(WOLFSSL* ssl, WOLFSSL_X509* x509)
- {
- WOLFSSL_ENTER("wolfSSL_add1_to_CA_list");
- if (ssl == NULL || x509 == NULL) {
- WOLFSSL_MSG("Bad argument");
- return WOLFSSL_FAILURE;
- }
- if (ssl->ca_names == NULL) {
- ssl->ca_names = wolfSSL_sk_X509_NAME_new(NULL);
- if (ssl->ca_names == NULL) {
- WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
- return WOLFSSL_FAILURE;
- }
- }
- return add_to_CA_list(ssl->ca_names, x509);
- }
- #endif /* !NO_CERTS */
-
- #ifndef NO_BIO
- #if !defined(NO_RSA) && !defined(NO_CERTS)
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(
- const char* fname)
- {
- /* The webserver build is using this to load a CA into the server
- * for client authentication as an option. Have this return NULL in
- * that case. If OPENSSL_EXTRA is enabled, go ahead and include
- * the function. */
- #ifdef OPENSSL_EXTRA
- WOLFSSL_STACK *list = NULL;
- WOLFSSL_BIO* bio = NULL;
- WOLFSSL_X509 *cert = NULL;
- WOLFSSL_X509_NAME *nameCopy = NULL;
- unsigned long err = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
-
- WOLFSSL_ENTER("wolfSSL_load_client_CA_file");
-
- bio = wolfSSL_BIO_new_file(fname, "rb");
- if (bio == NULL) {
- WOLFSSL_MSG("wolfSSL_BIO_new_file error");
- goto cleanup;
- }
-
- list = wolfSSL_sk_X509_NAME_new(NULL);
- if (list == NULL) {
- WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
- goto cleanup;
- }
-
- /* Read each certificate in the chain out of the file. */
- while (wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) {
- /* Need a persistent copy of the subject name. */
- nameCopy = wolfSSL_X509_NAME_dup(
- wolfSSL_X509_get_subject_name(cert));
- if (nameCopy == NULL) {
- WOLFSSL_MSG("wolfSSL_X509_NAME_dup error");
- goto cleanup;
- }
- /*
- * Original cert will be freed so make sure not to try to access
- * it in the future.
- */
- nameCopy->x509 = NULL;
-
- if (wolfSSL_sk_X509_NAME_push(list, nameCopy) <= 0) {
- WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error");
- /* Do free in loop because nameCopy is now responsibility
- * of list to free and adding jumps to cleanup after this
- * might result in a double free. */
- wolfSSL_X509_NAME_free(nameCopy);
- goto cleanup;
- }
-
- wolfSSL_X509_free(cert);
- cert = NULL;
- }
-
- CLEAR_ASN_NO_PEM_HEADER_ERROR(err);
-
- err = WOLFSSL_SUCCESS;
-cleanup:
- wolfSSL_X509_free(cert);
- cert = NULL;
- wolfSSL_BIO_free(bio);
- if (err != WOLFSSL_SUCCESS) {
- /* We failed so return NULL */
- wolfSSL_sk_X509_NAME_pop_free(list, NULL);
- list = NULL;
- }
- return list;
- #else
- (void)fname;
- return NULL;
- #endif
- }
- #endif
- #endif /* !NO_BIO */
-#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA */
-
#ifdef OPENSSL_EXTRA
#if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \
@@ -13215,130 +8617,6 @@ cleanup:
}
#endif /* OPENSSL_EXTRA */
-#if !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || \
- defined(WOLFSSL_WPAS_SMALL))
-
- WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(const WOLFSSL_CTX* ctx)
- {
- if (ctx == NULL) {
- return NULL;
- }
-
- if (ctx->x509_store_pt != NULL)
- return ctx->x509_store_pt;
- return &((WOLFSSL_CTX*)ctx)->x509_store;
- }
-
- void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_cert_store");
- if (ctx == NULL || str == NULL || ctx->cm == str->cm) {
- return;
- }
-
- if (wolfSSL_CertManager_up_ref(str->cm) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_CertManager_up_ref error");
- return;
- }
- /* free cert manager if have one */
- if (ctx->cm != NULL) {
- wolfSSL_CertManagerFree(ctx->cm);
- }
- ctx->cm = str->cm;
- ctx->x509_store.cm = str->cm;
-
- /* free existing store if it exists */
- wolfSSL_X509_STORE_free(ctx->x509_store_pt);
- ctx->x509_store.cache = str->cache;
- ctx->x509_store_pt = str; /* take ownership of store and free it
- with CTX free */
- ctx->cm->x509_store_p = ctx->x509_store_pt;/* CTX has ownership
- and free it with CTX free*/
- }
-
-#ifdef OPENSSL_ALL
- int wolfSSL_CTX_set1_verify_cert_store(WOLFSSL_CTX* ctx,
- WOLFSSL_X509_STORE* str)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set1_verify_cert_store");
-
- if (ctx == NULL || str == NULL) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
-
- /* NO-OP when setting existing store */
- if (str == CTX_STORE(ctx))
- return WOLFSSL_SUCCESS;
-
- if (wolfSSL_X509_STORE_up_ref(str) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error");
- return WOLFSSL_FAILURE;
- }
-
- /* free existing store if it exists */
- wolfSSL_X509_STORE_free(ctx->x509_store_pt);
- ctx->x509_store_pt = str; /* take ownership of store and free it
- with CTX free */
- return WOLFSSL_SUCCESS;
- }
-#endif
-
- int wolfSSL_set0_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str)
- {
- WOLFSSL_ENTER("wolfSSL_set0_verify_cert_store");
-
- if (ssl == NULL || str == NULL) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
-
- /* NO-OP when setting existing store */
- if (str == SSL_STORE(ssl))
- return WOLFSSL_SUCCESS;
-
- /* free existing store if it exists */
- wolfSSL_X509_STORE_free(ssl->x509_store_pt);
- if (str == ssl->ctx->x509_store_pt)
- ssl->x509_store_pt = NULL; /* if setting ctx store then just revert
- to using that instead */
- else
- ssl->x509_store_pt = str; /* take ownership of store and free it
- with SSL free */
- return WOLFSSL_SUCCESS;
- }
-
-
- int wolfSSL_set1_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str)
- {
- WOLFSSL_ENTER("wolfSSL_set1_verify_cert_store");
-
- if (ssl == NULL || str == NULL) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
-
- /* NO-OP when setting existing store */
- if (str == SSL_STORE(ssl))
- return WOLFSSL_SUCCESS;
-
- if (wolfSSL_X509_STORE_up_ref(str) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error");
- return WOLFSSL_FAILURE;
- }
-
- /* free existing store if it exists */
- wolfSSL_X509_STORE_free(ssl->x509_store_pt);
- if (str == ssl->ctx->x509_store_pt)
- ssl->x509_store_pt = NULL; /* if setting ctx store then just revert
- to using that instead */
- else
- ssl->x509_store_pt = str; /* take ownership of store and free it
- with SSL free */
- return WOLFSSL_SUCCESS;
- }
-#endif /* !NO_CERTS && (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) */
-
#ifdef WOLFSSL_ENCRYPTED_KEYS
void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX* ctx,
@@ -14975,78 +10253,6 @@ WOLF_STACK_OF(WOLFSSL_X509) *wolfSSL_get0_verified_chain(const WOLFSSL *ssl)
#endif /* KEEP_PEER_CERT */
#endif /* SESSION_CERTS && OPENSSL_EXTRA */
-#ifndef NO_CERTS
-
-/* OPENSSL_EXTRA is needed for wolfSSL_X509_d21 function
- KEEP_OUR_CERT is to insure ability for returning ssl certificate */
-#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
- defined(KEEP_OUR_CERT)
-WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl)
-{
- if (ssl == NULL) {
- return NULL;
- }
-
- if (ssl->buffers.weOwnCert) {
- if (ssl->ourCert == NULL) {
- if (ssl->buffers.certificate == NULL) {
- WOLFSSL_MSG("Certificate buffer not set!");
- return NULL;
- }
- #ifndef WOLFSSL_X509_STORE_CERTS
- ssl->ourCert = wolfSSL_X509_d2i_ex(NULL,
- ssl->buffers.certificate->buffer,
- (int)ssl->buffers.certificate->length,
- ssl->heap);
- #endif
- }
- return ssl->ourCert;
- }
- else { /* if cert not owned get parent ctx cert or return null */
- if (ssl->ctx) {
- if (ssl->ctx->ourCert == NULL) {
- if (ssl->ctx->certificate == NULL) {
- WOLFSSL_MSG("Ctx Certificate buffer not set!");
- return NULL;
- }
- #ifndef WOLFSSL_X509_STORE_CERTS
- ssl->ctx->ourCert = wolfSSL_X509_d2i_ex(NULL,
- ssl->ctx->certificate->buffer,
- (int)ssl->ctx->certificate->length,
- ssl->heap);
- #endif
- ssl->ctx->ownOurCert = 1;
- }
- return ssl->ctx->ourCert;
- }
- }
-
- return NULL;
-}
-
-WOLFSSL_X509* wolfSSL_CTX_get0_certificate(WOLFSSL_CTX* ctx)
-{
- if (ctx) {
- if (ctx->ourCert == NULL) {
- if (ctx->certificate == NULL) {
- WOLFSSL_MSG("Ctx Certificate buffer not set!");
- return NULL;
- }
- #ifndef WOLFSSL_X509_STORE_CERTS
- ctx->ourCert = wolfSSL_X509_d2i_ex(NULL,
- ctx->certificate->buffer,
- (int)ctx->certificate->length,
- ctx->heap);
- #endif
- ctx->ownOurCert = 1;
- }
- return ctx->ourCert;
- }
- return NULL;
-}
-#endif /* OPENSSL_EXTRA && KEEP_OUR_CERT */
-#endif /* NO_CERTS */
-
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
void wolfSSL_set_connect_state(WOLFSSL* ssl)
{
@@ -16299,201 +11505,6 @@ void wolfSSL_set_dynlock_destroy_callback(
}
-#endif /* OPENSSL_EXTRA */
-
-#ifdef OPENSSL_EXTRA
-#ifndef NO_CERTS
-
-#if !defined(NO_ASN) && !defined(NO_PWDBASED)
-/* Copies unencrypted DER key buffer into "der". If "der" is null then the size
- * of buffer needed is returned. If *der == NULL then it allocates a buffer.
- * NOTE: This also advances the "der" pointer to be at the end of buffer.
- *
- * Returns size of key buffer on success
- */
-int wolfSSL_i2d_PrivateKey(const WOLFSSL_EVP_PKEY* key, unsigned char** der)
-{
- return wolfSSL_EVP_PKEY_get_der(key, der);
-}
-
-int wolfSSL_i2d_PrivateKey_bio(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key)
-{
- int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
- int derSz = 0;
- byte* der = NULL;
-
- if (bio == NULL || key == NULL) {
- return WOLFSSL_FAILURE;
- }
-
- derSz = wolfSSL_i2d_PrivateKey(key, NULL);
- if (derSz <= 0) {
- WOLFSSL_MSG("wolfSSL_i2d_PrivateKey (for getting size) failed");
- return WOLFSSL_FAILURE;
- }
-
- der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (!der) {
- WOLFSSL_MSG("malloc failed");
- return WOLFSSL_FAILURE;
- }
-
- derSz = wolfSSL_i2d_PrivateKey(key, &der);
- if (derSz <= 0) {
- WOLFSSL_MSG("wolfSSL_i2d_PrivateKey failed");
- goto cleanup;
- }
-
- if (wolfSSL_BIO_write(bio, der, derSz) != derSz) {
- goto cleanup;
- }
-
- ret = WOLFSSL_SUCCESS;
-
-cleanup:
- XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return ret;
-}
-
-int wolfSSL_i2d_PublicKey(const WOLFSSL_EVP_PKEY *key, unsigned char **der)
-{
-#if !defined(NO_RSA) || defined(HAVE_ECC)
-#ifdef HAVE_ECC
- unsigned char *local_der = NULL;
- word32 local_derSz = 0;
- unsigned char *pub_der = NULL;
- ecc_key *eccKey = NULL;
- word32 inOutIdx = 0;
-#endif
- word32 pub_derSz = 0;
- int ret;
- int key_type = 0;
-
- if (key == NULL) {
- return WOLFSSL_FATAL_ERROR;
- }
-
- key_type = key->type;
- if ((key_type != WC_EVP_PKEY_EC) && (key_type != WC_EVP_PKEY_RSA)) {
- return WOLFSSL_FATAL_ERROR;
- }
-
-#ifndef NO_RSA
- if (key_type == WC_EVP_PKEY_RSA) {
- return wolfSSL_i2d_RSAPublicKey(key->rsa, der);
- }
-#endif
-
- /* Now that RSA is taken care of, we only need to consider the ECC case. */
-
-#ifdef HAVE_ECC
-
- /* We need to get the DER, then convert it to a public key. But what we get
- * might be a buffered private key so we need to decode it and then encode
- * the public part. */
- ret = wolfSSL_EVP_PKEY_get_der(key, &local_der);
- if (ret <= 0) {
- /* In this case, there was no buffered DER at all. This could be the
- * case where the key that was passed in was generated. So now we
- * have to create the local DER. */
- local_derSz = (word32)wolfSSL_i2d_ECPrivateKey(key->ecc, &local_der);
- if (local_derSz == 0) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- } else {
- local_derSz = (word32)ret;
- ret = 0;
- }
-
- if (ret == 0) {
- eccKey = (ecc_key *)XMALLOC(sizeof(*eccKey), NULL, DYNAMIC_TYPE_ECC);
- if (eccKey == NULL) {
- WOLFSSL_MSG("Failed to allocate key buffer.");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
-
- if (ret == 0) {
- ret = wc_ecc_init(eccKey);
- }
-
- if (ret == 0) {
- ret = wc_EccPublicKeyDecode(local_der, &inOutIdx, eccKey, local_derSz);
- if (ret < 0) {
- /* We now try again as x.963 [point type][x][opt y]. */
- ret = wc_ecc_import_x963(local_der, local_derSz, eccKey);
- }
- }
-
- if (ret == 0) {
- pub_derSz = (word32)wc_EccPublicKeyDerSize(eccKey, 1);
- if ((int)pub_derSz <= 0) {
- ret = WOLFSSL_FAILURE;
- }
- }
-
- if (ret == 0) {
- pub_der = (unsigned char*)XMALLOC(pub_derSz, NULL,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (pub_der == NULL) {
- WOLFSSL_MSG("Failed to allocate output buffer.");
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
-
- if (ret == 0) {
- pub_derSz = (word32)wc_EccPublicKeyToDer(eccKey, pub_der, pub_derSz, 1);
- if ((int)pub_derSz <= 0) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
-
- /* This block is for actually returning the DER of the public key */
- if ((ret == 0) && (der != NULL)) {
- if (*der == NULL) {
- *der = (unsigned char*)XMALLOC(pub_derSz, NULL,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (*der == NULL) {
- WOLFSSL_MSG("Failed to allocate output buffer.");
- ret = WOLFSSL_FATAL_ERROR;
- }
-
- if (ret == 0) {
- XMEMCPY(*der, pub_der, pub_derSz);
- }
- }
- else {
- XMEMCPY(*der, pub_der, pub_derSz);
- *der += pub_derSz;
- }
- }
-
- XFREE(pub_der, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- XFREE(local_der, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
-
- wc_ecc_free(eccKey);
- XFREE(eccKey, NULL, DYNAMIC_TYPE_ECC);
-
-#else
- ret = WOLFSSL_FATAL_ERROR;
-#endif /* HAVE_ECC */
-
- if (ret == 0) {
- return (int)pub_derSz;
- }
-
- return ret;
-#else
- return WOLFSSL_FATAL_ERROR;
-#endif /* !NO_RSA || HAVE_ECC */
-}
-#endif /* !NO_ASN && !NO_PWDBASED */
-
-#endif /* !NO_CERTS */
-#endif /* OPENSSL_EXTRA */
-
-#ifdef OPENSSL_EXTRA
-
/* Sets the DNS hostname to name.
* Hostname is cleared if name is NULL or empty. */
int wolfSSL_set1_host(WOLFSSL * ssl, const char* name)
@@ -17335,38 +12346,6 @@ long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg)
}
#endif /* HAVE_PK_CALLBACKS */
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
-long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type)
-{
- WOLFSSL_ENTER("wolfSSL_set_tlsext_status_type");
-
- if (s == NULL){
- return BAD_FUNC_ARG;
- }
-
- if (type == WOLFSSL_TLSEXT_STATUSTYPE_ocsp){
- int r = TLSX_UseCertificateStatusRequest(&s->extensions, (byte)type, 0,
- s, s->heap, s->devId);
- return (long)r;
- } else {
- WOLFSSL_MSG(
- "SSL_set_tlsext_status_type only supports TLSEXT_STATUSTYPE_ocsp type.");
- return WOLFSSL_FAILURE;
- }
-
-}
-
-long wolfSSL_get_tlsext_status_type(WOLFSSL *s)
-{
- TLSX* extension;
-
- if (s == NULL)
- return WOLFSSL_FATAL_ERROR;
- extension = TLSX_Find(s->extensions, TLSX_STATUS_REQUEST);
- return extension != NULL ? WOLFSSL_TLSEXT_STATUSTYPE_ocsp : WOLFSSL_FATAL_ERROR;
-}
-#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
-
#ifndef NO_WOLFSSL_STUB
long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg)
{
@@ -18773,374 +13752,6 @@ void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx)
#ifndef NO_CERTS
#ifdef HAVE_PK_CALLBACKS
-#ifdef HAVE_ECC
-void wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX* ctx, CallbackEccKeyGen cb)
-{
- if (ctx)
- ctx->EccKeyGenCb = cb;
-}
-void wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->EccKeyGenCtx = ctx;
-}
-void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->EccKeyGenCtx;
-
- return NULL;
-}
-void wolfSSL_CTX_SetEccSignCtx(WOLFSSL_CTX* ctx, void *userCtx)
-{
- if (ctx)
- ctx->EccSignCtx = userCtx;
-}
-void* wolfSSL_CTX_GetEccSignCtx(WOLFSSL_CTX* ctx)
-{
- if (ctx)
- return ctx->EccSignCtx;
-
- return NULL;
-}
-
-WOLFSSL_ABI
-void wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX* ctx, CallbackEccSign cb)
-{
- if (ctx)
- ctx->EccSignCb = cb;
-}
-void wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->EccSignCtx = ctx;
-}
-void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->EccSignCtx;
-
- return NULL;
-}
-
-void wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX* ctx, CallbackEccVerify cb)
-{
- if (ctx)
- ctx->EccVerifyCb = cb;
-}
-void wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->EccVerifyCtx = ctx;
-}
-void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->EccVerifyCtx;
-
- return NULL;
-}
-
-void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX* ctx,
- CallbackEccSharedSecret cb)
-{
- if (ctx)
- ctx->EccSharedSecretCb = cb;
-}
-void wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->EccSharedSecretCtx = ctx;
-}
-void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->EccSharedSecretCtx;
-
- return NULL;
-}
-#endif /* HAVE_ECC */
-
-#ifdef HAVE_ED25519
-void wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX* ctx, CallbackEd25519Sign cb)
-{
- if (ctx)
- ctx->Ed25519SignCb = cb;
-}
-void wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->Ed25519SignCtx = ctx;
-}
-void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->Ed25519SignCtx;
-
- return NULL;
-}
-
-void wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX* ctx, CallbackEd25519Verify cb)
-{
- if (ctx)
- ctx->Ed25519VerifyCb = cb;
-}
-void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->Ed25519VerifyCtx = ctx;
-}
-void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->Ed25519VerifyCtx;
-
- return NULL;
-}
-#endif /* HAVE_ED25519 */
-
-#ifdef HAVE_CURVE25519
-void wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX* ctx,
- CallbackX25519KeyGen cb)
-{
- if (ctx)
- ctx->X25519KeyGenCb = cb;
-}
-void wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->X25519KeyGenCtx = ctx;
-}
-void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->X25519KeyGenCtx;
-
- return NULL;
-}
-
-void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX* ctx,
- CallbackX25519SharedSecret cb)
-{
- if (ctx)
- ctx->X25519SharedSecretCb = cb;
-}
-void wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->X25519SharedSecretCtx = ctx;
-}
-void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->X25519SharedSecretCtx;
-
- return NULL;
-}
-#endif /* HAVE_CURVE25519 */
-
-#ifdef HAVE_ED448
-void wolfSSL_CTX_SetEd448SignCb(WOLFSSL_CTX* ctx, CallbackEd448Sign cb)
-{
- if (ctx)
- ctx->Ed448SignCb = cb;
-}
-void wolfSSL_SetEd448SignCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->Ed448SignCtx = ctx;
-}
-void* wolfSSL_GetEd448SignCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->Ed448SignCtx;
-
- return NULL;
-}
-
-void wolfSSL_CTX_SetEd448VerifyCb(WOLFSSL_CTX* ctx, CallbackEd448Verify cb)
-{
- if (ctx)
- ctx->Ed448VerifyCb = cb;
-}
-void wolfSSL_SetEd448VerifyCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->Ed448VerifyCtx = ctx;
-}
-void* wolfSSL_GetEd448VerifyCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->Ed448VerifyCtx;
-
- return NULL;
-}
-#endif /* HAVE_ED448 */
-
-#ifdef HAVE_CURVE448
-void wolfSSL_CTX_SetX448KeyGenCb(WOLFSSL_CTX* ctx,
- CallbackX448KeyGen cb)
-{
- if (ctx)
- ctx->X448KeyGenCb = cb;
-}
-void wolfSSL_SetX448KeyGenCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->X448KeyGenCtx = ctx;
-}
-void* wolfSSL_GetX448KeyGenCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->X448KeyGenCtx;
-
- return NULL;
-}
-
-void wolfSSL_CTX_SetX448SharedSecretCb(WOLFSSL_CTX* ctx,
- CallbackX448SharedSecret cb)
-{
- if (ctx)
- ctx->X448SharedSecretCb = cb;
-}
-void wolfSSL_SetX448SharedSecretCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->X448SharedSecretCtx = ctx;
-}
-void* wolfSSL_GetX448SharedSecretCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->X448SharedSecretCtx;
-
- return NULL;
-}
-#endif /* HAVE_CURVE448 */
-
-#ifndef NO_RSA
-void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb)
-{
- if (ctx)
- ctx->RsaSignCb = cb;
-}
-void wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb)
-{
- if (ctx)
- ctx->RsaSignCheckCb = cb;
-}
-void wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->RsaSignCtx = ctx;
-}
-void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->RsaSignCtx;
-
- return NULL;
-}
-
-
-void wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb)
-{
- if (ctx)
- ctx->RsaVerifyCb = cb;
-}
-void wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->RsaVerifyCtx = ctx;
-}
-void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->RsaVerifyCtx;
-
- return NULL;
-}
-
-#ifdef WC_RSA_PSS
-void wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX* ctx, CallbackRsaPssSign cb)
-{
- if (ctx)
- ctx->RsaPssSignCb = cb;
-}
-void wolfSSL_CTX_SetRsaPssSignCheckCb(WOLFSSL_CTX* ctx,
- CallbackRsaPssVerify cb)
-{
- if (ctx)
- ctx->RsaPssSignCheckCb = cb;
-}
-void wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->RsaPssSignCtx = ctx;
-}
-void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->RsaPssSignCtx;
-
- return NULL;
-}
-
-void wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb)
-{
- if (ctx)
- ctx->RsaPssVerifyCb = cb;
-}
-void wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->RsaPssVerifyCtx = ctx;
-}
-void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->RsaPssVerifyCtx;
-
- return NULL;
-}
-#endif /* WC_RSA_PSS */
-
-void wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX* ctx, CallbackRsaEnc cb)
-{
- if (ctx)
- ctx->RsaEncCb = cb;
-}
-void wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->RsaEncCtx = ctx;
-}
-void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->RsaEncCtx;
-
- return NULL;
-}
-
-void wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX* ctx, CallbackRsaDec cb)
-{
- if (ctx)
- ctx->RsaDecCb = cb;
-}
-void wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->RsaDecCtx = ctx;
-}
-void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->RsaDecCtx;
-
- return NULL;
-}
-#endif /* NO_RSA */
-
/* callback for premaster secret generation */
void wolfSSL_CTX_SetGenPreMasterCb(WOLFSSL_CTX* ctx, CallbackGenPreMaster cb)
{
@@ -19323,31 +13934,6 @@ void wolfSSL_CTX_SetPerformTlsRecordProcessingCb(WOLFSSL_CTX* ctx,
#endif /* HAVE_PK_CALLBACKS */
#endif /* NO_CERTS */
-#if defined(HAVE_PK_CALLBACKS) && !defined(NO_DH)
-void wolfSSL_CTX_SetDhGenerateKeyPair(WOLFSSL_CTX* ctx,
- CallbackDhGenerateKeyPair cb) {
- if (ctx)
- ctx->DhGenerateKeyPairCb = cb;
-}
-void wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX* ctx, CallbackDhAgree cb)
-{
- if (ctx)
- ctx->DhAgreeCb = cb;
-}
-void wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx)
-{
- if (ssl)
- ssl->DhAgreeCtx = ctx;
-}
-void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl)
-{
- if (ssl)
- return ssl->DhAgreeCtx;
-
- return NULL;
-}
-#endif /* HAVE_PK_CALLBACKS && !NO_DH */
-
#if defined(HAVE_PK_CALLBACKS) && defined(HAVE_HKDF)
void wolfSSL_CTX_SetHKDFExtractCb(WOLFSSL_CTX* ctx, CallbackHKDFExtract cb)
@@ -20644,114 +15230,9 @@ VerifyCallback wolfSSL_get_verify_callback(WOLFSSL* ssl)
return NULL;
}
-#ifndef NO_BIO
-/* Converts EVP_PKEY data from a bio buffer to a WOLFSSL_EVP_PKEY structure.
-Returns pointer to private EVP_PKEY struct upon success, NULL if there
-is a failure.*/
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO* bio,
- WOLFSSL_EVP_PKEY** out)
-{
- unsigned char* mem = NULL;
- int memSz = 0;
- WOLFSSL_EVP_PKEY* key = NULL;
- unsigned char* extraBioMem = NULL;
-
- WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_bio");
-
- if (bio == NULL) {
- return NULL;
- }
- (void)out;
-
- memSz = wolfSSL_BIO_get_len(bio);
- if (memSz <= 0) {
- WOLFSSL_MSG("wolfSSL_BIO_get_len() failure");
- return NULL;
- }
-
- mem = (unsigned char*)XMALLOC((size_t)memSz, bio->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (mem == NULL) {
- WOLFSSL_MSG("Malloc failure");
- return NULL;
- }
-
- if (wolfSSL_BIO_read(bio, (unsigned char*)mem, memSz) == memSz) {
- int extraBioMemSz;
- int derLength;
-
- /* Determines key type and returns the new private EVP_PKEY object */
- if ((key = wolfSSL_d2i_PrivateKey_EVP(NULL, &mem, (long)memSz)) ==
- NULL) {
- WOLFSSL_MSG("wolfSSL_d2i_PrivateKey_EVP() failure");
- XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
-
- /* Write extra data back into bio object if necessary. */
- derLength = key->pkey_sz;
- extraBioMemSz = (memSz - derLength);
- if (extraBioMemSz > 0) {
- int i;
- int j = 0;
-
- extraBioMem = (unsigned char *)XMALLOC((size_t)extraBioMemSz, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (extraBioMem == NULL) {
- WOLFSSL_MSG("Malloc failure");
- XFREE((unsigned char*)extraBioMem, bio->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
-
- for (i = derLength; i < memSz; i++) {
- *(extraBioMem + j) = *(mem + i);
- j++;
- }
-
- wolfSSL_BIO_write(bio, extraBioMem, extraBioMemSz);
- if (wolfSSL_BIO_get_len(bio) <= 0) {
- WOLFSSL_MSG("Failed to write memory to bio");
- XFREE((unsigned char*)extraBioMem, bio->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return NULL;
- }
- XFREE((unsigned char*)extraBioMem, bio->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- }
-
- if (out != NULL) {
- *out = key;
- }
- }
- XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return key;
-}
-#endif /* !NO_BIO */
-
#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT */
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \
- defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX) || \
- defined(WOLFSSL_QT) || defined(WOLFSSL_WPAS_SMALL)
-
-/* Converts a DER encoded private key to a WOLFSSL_EVP_PKEY structure.
- * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL
- * on fail */
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** out,
- unsigned char** in, long inSz)
-{
- WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_EVP");
- return d2iGenericKey(out, (const unsigned char**)in, inSz, 1);
-}
-
-#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT ||
- * WOLFSSL_WPAS_SMALL*/
-
-
/* stunnel compatibility functions*/
#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \
(defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
@@ -22046,182 +16527,6 @@ long wolfSSL_CTX_set_tlsext_ticket_keys(WOLFSSL_CTX *ctx,
}
#endif
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-#ifdef HAVE_OCSP
-/* Not an OpenSSL API. */
-int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response)
-{
- *response = ssl->ocspCsrResp[0].buffer;
- return ssl->ocspCsrResp[0].length;
-}
-
-/* Not an OpenSSL API. */
-char* wolfSSL_get_ocsp_url(WOLFSSL* ssl)
-{
- return ssl->url;
-}
-
-/* Not an OpenSSL API. */
-int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url)
-{
- if (ssl == NULL)
- return WOLFSSL_FAILURE;
-
- ssl->url = url;
- return WOLFSSL_SUCCESS;
-}
-#endif /* OCSP */
-#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
-
-#if defined(HAVE_OCSP) && !defined(NO_ASN_TIME)
-int wolfSSL_get_ocsp_producedDate(
- WOLFSSL *ssl,
- byte *producedDate,
- size_t producedDate_space,
- int *producedDateFormat)
-{
- if ((ssl->ocspProducedDateFormat != ASN_UTC_TIME) &&
- (ssl->ocspProducedDateFormat != ASN_GENERALIZED_TIME))
- return BAD_FUNC_ARG;
-
- if ((producedDate == NULL) || (producedDateFormat == NULL))
- return BAD_FUNC_ARG;
-
- if (XSTRLEN((char *)ssl->ocspProducedDate) >= producedDate_space)
- return BUFFER_E;
-
- XSTRNCPY((char *)producedDate, (const char *)ssl->ocspProducedDate,
- producedDate_space);
- *producedDateFormat = ssl->ocspProducedDateFormat;
-
- return 0;
-}
-
-int wolfSSL_get_ocsp_producedDate_tm(WOLFSSL *ssl, struct tm *produced_tm) {
- int idx = 0;
-
- if ((ssl->ocspProducedDateFormat != ASN_UTC_TIME) &&
- (ssl->ocspProducedDateFormat != ASN_GENERALIZED_TIME))
- return BAD_FUNC_ARG;
-
- if (produced_tm == NULL)
- return BAD_FUNC_ARG;
-
- if (ExtractDate(ssl->ocspProducedDate,
- (unsigned char)ssl->ocspProducedDateFormat, produced_tm, &idx,
- MAX_DATE_SZ))
- return 0;
- else
- return ASN_PARSE_E;
-}
-#endif
-
-#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
-int wolfSSL_CTX_get_tlsext_status_cb(WOLFSSL_CTX* ctx, tlsextStatusCb* cb)
-{
- if (ctx == NULL || ctx->cm == NULL || cb == NULL)
- return WOLFSSL_FAILURE;
-
-#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
- if (ctx->cm->ocsp_stapling == NULL)
- return WOLFSSL_FAILURE;
-
- *cb = ctx->cm->ocsp_stapling->statusCb;
-#else
- (void)cb;
- *cb = NULL;
-#endif
-
- return WOLFSSL_SUCCESS;
-
-}
-
-int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, tlsextStatusCb cb)
-{
- if (ctx == NULL || ctx->cm == NULL)
- return WOLFSSL_FAILURE;
-
-#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
- /* Ensure stapling is on for callback to be used. */
- wolfSSL_CTX_EnableOCSPStapling(ctx);
-
- if (ctx->cm->ocsp_stapling == NULL)
- return WOLFSSL_FAILURE;
-
- ctx->cm->ocsp_stapling->statusCb = cb;
-#else
- (void)cb;
-#endif
-
- return WOLFSSL_SUCCESS;
-}
-
-long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg)
-{
- if (ctx == NULL || ctx->cm == NULL)
- return WOLFSSL_FAILURE;
-
-#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
- /* Ensure stapling is on for callback to be used. */
- wolfSSL_CTX_EnableOCSPStapling(ctx);
-
- if (ctx->cm->ocsp_stapling == NULL)
- return WOLFSSL_FAILURE;
-
- ctx->cm->ocsp_stapling->statusCbArg = arg;
-#else
- (void)arg;
-#endif
-
- return WOLFSSL_SUCCESS;
-}
-
-long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *ssl, unsigned char **resp)
-{
- if (ssl == NULL || resp == NULL)
- return 0;
-
- *resp = ssl->ocspCsrResp[0].buffer;
- return (long)ssl->ocspCsrResp[0].length;
-}
-
-long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *ssl, unsigned char *resp,
- int len)
-{
- return wolfSSL_set_tlsext_status_ocsp_resp_multi(ssl, resp, len, 0);
-}
-
-int wolfSSL_set_tlsext_status_ocsp_resp_multi(WOLFSSL* ssl, unsigned char *resp,
- int len, word32 idx)
-{
- if (ssl == NULL || idx >= XELEM_CNT(ssl->ocspCsrResp) || len < 0)
- return WOLFSSL_FAILURE;
- if (!((resp == NULL) ^ (len > 0)))
- return WOLFSSL_FAILURE;
-
- XFREE(ssl->ocspCsrResp[idx].buffer, NULL, 0);
- ssl->ocspCsrResp[idx].buffer = resp;
- ssl->ocspCsrResp[idx].length = (word32)len;
-
- return WOLFSSL_SUCCESS;
-}
-
-#ifndef NO_WOLFSSL_SERVER
-void wolfSSL_CTX_set_ocsp_status_verify_cb(WOLFSSL_CTX* ctx,
- ocspVerifyStatusCb cb, void* cbArg)
-{
- if (ctx != NULL) {
- ctx->ocspStatusVerifyCb = cb;
- ctx->ocspStatusVerifyCbArg = cbArg;
- }
-}
-#endif
-#endif
-
#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx,
@@ -23745,144 +18050,6 @@ void wolfSSL_ERR_remove_state(unsigned long id)
#endif /* OPENSSL_EXTRA */
-#ifdef OPENSSL_ALL
-
-#if !defined(NO_BIO) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8)
-
-static int bio_get_data(WOLFSSL_BIO* bio, byte** data)
-{
- int ret = 0;
- byte* mem = NULL;
-
- ret = wolfSSL_BIO_get_len(bio);
- if (ret > 0) {
- mem = (byte*)XMALLOC((size_t)ret, bio->heap, DYNAMIC_TYPE_OPENSSL);
- if (mem == NULL) {
- WOLFSSL_MSG("Memory error");
- ret = MEMORY_E;
- }
- if (ret >= 0) {
- if ((ret = wolfSSL_BIO_read(bio, mem, ret)) <= 0) {
- XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
- ret = MEMORY_E;
- mem = NULL;
- }
- }
- }
-
- *data = mem;
-
- return ret;
-}
-
-/* DER data is PKCS#8 encrypted. */
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PKCS8PrivateKey_bio(WOLFSSL_BIO* bio,
- WOLFSSL_EVP_PKEY** pkey,
- wc_pem_password_cb* cb,
- void* ctx)
-{
- int ret;
- byte* der;
- int len;
- byte* p;
- word32 algId;
- WOLFSSL_EVP_PKEY* key;
-
- if ((len = bio_get_data(bio, &der)) < 0)
- return NULL;
-
- if (cb != NULL) {
- char password[NAME_SZ];
- int passwordSz = cb(password, sizeof(password), PEM_PASS_READ, ctx);
- if (passwordSz < 0) {
- XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL);
- return NULL;
- }
- #ifdef WOLFSSL_CHECK_MEM_ZERO
- wc_MemZero_Add("wolfSSL_d2i_PKCS8PrivateKey_bio password", password,
- passwordSz);
- #endif
-
- ret = ToTraditionalEnc(der, (word32)len, password, passwordSz, &algId);
- if (ret < 0) {
- XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL);
- return NULL;
- }
-
- ForceZero(password, (word32)passwordSz);
- #ifdef WOLFSSL_CHECK_MEM_ZERO
- wc_MemZero_Check(password, passwordSz);
- #endif
- }
-
- p = der;
- key = wolfSSL_d2i_PrivateKey_EVP(pkey, &p, len);
- XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL);
- return key;
-}
-
-#endif /* !NO_BIO && !NO_PWDBASED && HAVE_PKCS8 */
-
-/* Detect which type of key it is before decoding. */
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey(WOLFSSL_EVP_PKEY** pkey,
- const unsigned char** pp,
- long length)
-{
- int ret;
- WOLFSSL_EVP_PKEY* key = NULL;
- const byte* der = *pp;
- word32 idx = 0;
- int len = 0;
- int cnt = 0;
- word32 algId;
- word32 keyLen = (word32)length;
-
- /* Take off PKCS#8 wrapper if found. */
- if ((len = ToTraditionalInline_ex(der, &idx, keyLen, &algId)) >= 0) {
- der += idx;
- keyLen = (word32)len;
- }
- idx = 0;
- len = 0;
-
- /* Use the number of elements in the outer sequence to determine key type.
- */
- ret = GetSequence(der, &idx, &len, keyLen);
- if (ret >= 0) {
- word32 end = idx + (word32)len;
- while (ret >= 0 && idx < end) {
- /* Skip type */
- idx++;
- /* Get length and skip over - keeping count */
- len = 0;
- ret = GetLength(der, &idx, &len, keyLen);
- if (ret >= 0) {
- if (idx + (word32)len > end)
- ret = ASN_PARSE_E;
- else {
- idx += (word32)len;
- cnt++;
- }
- }
- }
- }
-
- if (ret >= 0) {
- int type;
- /* ECC includes version, private[, curve][, public key] */
- if (cnt >= 2 && cnt <= 4)
- type = WC_EVP_PKEY_EC;
- else
- type = WC_EVP_PKEY_RSA;
-
- key = wolfSSL_d2i_PrivateKey(type, pkey, &der, keyLen);
- *pp = der;
- }
-
- return key;
-}
-#endif /* OPENSSL_ALL */
-
#ifdef WOLFSSL_STATIC_EPHEMERAL
int wolfSSL_StaticEphemeralKeyLoad(WOLFSSL* ssl, int keyAlgo, void* keyPtr)
{
diff --git a/src/ssl_api_cert.c b/src/ssl_api_cert.c
new file mode 100644
index 0000000000..5871525dc4
--- /dev/null
+++ b/src/ssl_api_cert.c
@@ -0,0 +1,1740 @@
+/* ssl_api_cert.c
+ *
+ * Copyright (C) 2006-2025 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#include
+
+#if !defined(WOLFSSL_SSL_API_CERT_INCLUDED)
+ #ifndef WOLFSSL_IGNORE_FILE_WARN
+ #warning ssl_api_cert.c is not compiled separately from ssl.c
+ #endif
+#else
+
+#ifndef NO_CERTS
+
+/* Set whether mutual authentication is required for connections.
+ * Server side only.
+ *
+ * @param [in] ctx The SSL/TLS CTX object.
+ * @param [in] req 1 to indicate required and 0 when not.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when ctx is NULL.
+ * @return SIDE_ERROR when not a server.
+ */
+int wolfSSL_CTX_mutual_auth(WOLFSSL_CTX* ctx, int req)
+{
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+ if (ctx->method->side != WOLFSSL_SERVER_END)
+ return SIDE_ERROR;
+
+ ctx->mutualAuth = (byte)req;
+
+ return 0;
+}
+
+/* Set whether mutual authentication is required for the connection.
+ * Server side only.
+ *
+ * @param [in] ssl The SSL/TLS object.
+ * @param [in] req 1 to indicate required and 0 when not.
+ * @return 0 on success.
+ * @return BAD_FUNC_ARG when ssl is NULL.
+ * @return SIDE_ERROR when not a server
+ */
+int wolfSSL_mutual_auth(WOLFSSL* ssl, int req)
+{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+ if (ssl->options.side != WOLFSSL_SERVER_END)
+ return SIDE_ERROR;
+
+ ssl->options.mutualAuth = (word16)req;
+
+ return 0;
+}
+
+/* Get the certificate manager from the WOLFSSL_CTX.
+ *
+ * @param [in] ctx SSL/TLS CTX object.
+ * @return Certificate manager object on success.
+ * @return NULL when ctx is NULL.
+ */
+WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_CERT_MANAGER* cm = NULL;
+
+ if (ctx)
+ cm = ctx->cm;
+
+ return cm;
+}
+
+/* Sets the max chain depth when verifying a certificate chain.
+ *
+ * Default depth is set to MAX_CHAIN_DEPTH.
+ *
+ * @param [in] ctx WOLFSSL_CTX structure to set depth in
+ * @param [in] depth max depth
+ */
+void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth");
+
+ if ((ctx == NULL) || (depth < 0) || (depth > MAX_CHAIN_DEPTH)) {
+ WOLFSSL_MSG("Bad depth argument, too large or less than 0");
+ }
+ else {
+ ctx->verifyDepth = (byte)depth;
+ }
+}
+
+
+/* Get certificate chaining depth of SSL/TLS context object
+ *
+ * @param [in] ctx SSL/TLS context object.
+ * @return Verification depth on success.
+ * @return BAD_FUNC_ARG when ctx is NULL.
+ */
+long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx)
+{
+ long ret;
+
+ if (ctx == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ #ifndef OPENSSL_EXTRA
+ ret = MAX_CHAIN_DEPTH;
+ #else
+ ret = ctx->verifyDepth;
+ #endif
+ }
+
+ return ret;
+}
+
+/* Get certificate chaining depth of SSL/TLS object
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Verification depth on success.
+ * @return BAD_FUNC_ARG when ssl is NULL.
+ */
+long wolfSSL_get_verify_depth(WOLFSSL* ssl)
+{
+ long ret;
+
+ if (ssl == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ #ifndef OPENSSL_EXTRA
+ ret = MAX_CHAIN_DEPTH;
+ #else
+ ret = ssl->options.verifyDepth;
+ #endif
+ }
+
+ return ret;
+}
+
+#if defined(HAVE_RPK)
+/* TODO: Change this to use a bitfield. */
+
+/* Confirm that all the byte data in the buffer is unique.
+ *
+ * @param [in] buf Buffer to check.
+ * @param [in] len Length of buffer in bytes.
+ * @return 1 if all the byte data in the buffer is unique.
+ * @return 0 otherwise.
+ */
+static int isArrayUnique(const char* buf, size_t len)
+{
+ size_t i;
+ /* check the array is unique */
+ for (i = 0; i < len - 1; ++i) {
+ size_t j;
+ for (j = i + 1; j < len; ++j) {
+ if (buf[i] == buf[j]) {
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+/* Set user preference for the {client,server}_cert_type extension.
+ *
+ * Takes byte array containing cert types the caller can provide to its peer.
+ * Cert types are in preferred order in the array.
+ *
+ * @param [in] cfg Raw Public Key configuration.
+ * @param [in] client Indicates whether this is the client side.
+ * @param [in] buf List of certificate types.
+ * @param [in] len Length of certificate types.
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when cfg is NULL.
+ * @return BAD_FUNC_ARG when len is too long.
+ * @return BAD_FUNC_ARG when buffer values are not unique.
+ * @return BAD_FUNC_ARG when buffer contains unrecognized certificate type.
+ */
+static int set_cert_type(RpkConfig* cfg, int client, const char* buf,
+ int len)
+{
+ int i;
+ byte* certTypeCnt;
+ byte* certTypes;
+
+ /* Validate parameters. */
+ if ((cfg == NULL) || (len > (client ? MAX_CLIENT_CERT_TYPE_CNT :
+ MAX_SERVER_CERT_TYPE_CNT))) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* Get preferred certificate types for side. */
+ if (client) {
+ certTypeCnt = &cfg->preferred_ClientCertTypeCnt;
+ certTypes = cfg->preferred_ClientCertTypes;
+ }
+ else {
+ certTypeCnt = &cfg->preferred_ServerCertTypeCnt;
+ certTypes = cfg->preferred_ServerCertTypes;
+ }
+ /* If no buffer or empty buffer passed in, set the defaults. */
+ if ((buf == NULL) || (len == 0)) {
+ *certTypeCnt = 1;
+ for (i = 0; i < 2; i++) {
+ certTypes[i] = WOLFSSL_CERT_TYPE_X509;
+ }
+ return 1;
+ }
+
+ /* Check that the certificate types set are unique. */
+ if (!isArrayUnique(buf, (size_t)len))
+ return BAD_FUNC_ARG;
+
+ /* Check that the certificate types being set are known and then set. */
+ for (i = 0; i < len; i++) {
+ if ((buf[i] != WOLFSSL_CERT_TYPE_RPK) &&
+ (buf[i] != WOLFSSL_CERT_TYPE_X509)) {
+ return BAD_FUNC_ARG;
+ }
+ certTypes[i] = (byte)buf[i];
+ }
+ *certTypeCnt = len;
+
+ return 1;
+}
+/* Set the client certificate types against the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context object.
+ * @param [in] buf List of certificate types.
+ * @param [in] len Length of certificate types.
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ctx is NULL.
+ * @return BAD_FUNC_ARG when len is too long.
+ * @return BAD_FUNC_ARG when buffer values are not unique.
+ * @return BAD_FUNC_ARG when buffer contains unrecognized certificate type.
+ */
+int wolfSSL_CTX_set_client_cert_type(WOLFSSL_CTX* ctx, const char* buf, int len)
+{
+ int ret;
+
+ if (ctx == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ ret = set_cert_type(&ctx->rpkConfig, 1, buf, len);
+ }
+
+ return ret;
+}
+/* Set the server certificate types against the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context object.
+ * @param [in] buf List of certificate types.
+ * @param [in] len Length of certificate types.
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ctx is NULL.
+ * @return BAD_FUNC_ARG when len is too long.
+ * @return BAD_FUNC_ARG when buffer values are not unique.
+ * @return BAD_FUNC_ARG when buffer contains unrecognized certificate type.
+ */
+int wolfSSL_CTX_set_server_cert_type(WOLFSSL_CTX* ctx, const char* buf, int len)
+{
+ int ret;
+
+ if (ctx == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ ret = set_cert_type(&ctx->rpkConfig, 0, buf, len);
+ }
+
+ return ret;
+}
+/* Set the client certificate types against the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] buf List of certificate types.
+ * @param [in] len Length of certificate types.
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ssl is NULL.
+ * @return BAD_FUNC_ARG when len is too long.
+ * @return BAD_FUNC_ARG when buffer values are not unique.
+ * @return BAD_FUNC_ARG when buffer contains unrecognized certificate type.
+ */
+int wolfSSL_set_client_cert_type(WOLFSSL* ssl, const char* buf, int len)
+{
+ int ret;
+
+ if (ssl == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ ret = set_cert_type(&ssl->options.rpkConfig, 1, buf, len);
+ }
+
+ return ret;
+}
+/* Set the server certificate types against the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] buf List of certificate types.
+ * @param [in] len Length of certificate types.
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ssl is NULL.
+ * @return BAD_FUNC_ARG when len is too long.
+ * @return BAD_FUNC_ARG when buffer values are not unique.
+ * @return BAD_FUNC_ARG when buffer contains unrecognized certificate type.
+ */
+int wolfSSL_set_server_cert_type(WOLFSSL* ssl, const char* buf, int len)
+{
+ int ret;
+
+ if (ssl == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ ret = set_cert_type(&ssl->options.rpkConfig, 0, buf, len);
+ }
+
+ return ret;
+}
+
+/* Get negotiated client certificate type value.
+ *
+ * WOLFSSL_CERT_TYPE_UNKNOWN returned when no negotiation has been performed.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [out] tp Certificate type. One of:
+ * -1: WOLFSSL_CERT_TYPE_UNKNOWN
+ * 0: WOLFSSL_CERT_TYPE_X509
+ * 2: WOLFSSL_CERT_TYPE_RPK
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ssl or tp is NULL.
+ */
+int wolfSSL_get_negotiated_client_cert_type(WOLFSSL* ssl, int* tp)
+{
+ int ret = 1;
+
+ /* Validate parameters. */
+ if ((ssl == NULL) || (tp == NULL)) {
+ ret = BAD_FUNC_ARG;
+ }
+ /* Check side. */
+ else if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ /* Check certificate type negotiated. */
+ if (ssl->options.rpkState.received_ClientCertTypeCnt == 1) {
+ *tp = ssl->options.rpkState.received_ClientCertTypes[0];
+ }
+ else {
+ *tp = WOLFSSL_CERT_TYPE_UNKNOWN;
+ }
+ }
+ /* Check certificate type negotiated. */
+ else if (ssl->options.rpkState.sending_ClientCertTypeCnt == 1) {
+ *tp = ssl->options.rpkState.sending_ClientCertTypes[0];
+ }
+ else {
+ *tp = WOLFSSL_CERT_TYPE_UNKNOWN;
+ }
+
+ return ret;
+}
+
+/* Get negotiated server certificate type value.
+ *
+ * WOLFSSL_CERT_TYPE_UNKNOWN returned when no negotiation has been performed.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [out] tp Certificate type. One of:
+ * -1: WOLFSSL_CERT_TYPE_UNKNOWN
+ * 0: WOLFSSL_CERT_TYPE_X509
+ * 2: WOLFSSL_CERT_TYPE_RPK
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ssl or tp is NULL.
+ */
+int wolfSSL_get_negotiated_server_cert_type(WOLFSSL* ssl, int* tp)
+{
+ int ret = 1;
+
+ /* Validate parameters. */
+ if ((ssl == NULL) || (tp == NULL)) {
+ ret = BAD_FUNC_ARG;
+ }
+ /* Check side. */
+ else if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ /* Check certificate type negotiated. */
+ if (ssl->options.rpkState.received_ServerCertTypeCnt == 1) {
+ *tp = ssl->options.rpkState.received_ServerCertTypes[0];
+ }
+ else {
+ *tp = WOLFSSL_CERT_TYPE_UNKNOWN;
+ }
+ }
+ /* Check certificate type negotiated. */
+ else if (ssl->options.rpkState.sending_ServerCertTypeCnt == 1) {
+ *tp = ssl->options.rpkState.sending_ServerCertTypes[0];
+ }
+ else {
+ *tp = WOLFSSL_CERT_TYPE_UNKNOWN;
+ }
+ return ret;
+}
+#endif /* HAVE_RPK */
+
+/* Certificate verification options. */
+typedef struct {
+ /* Verify the peer certificate. */
+ byte verifyPeer:1;
+ /* No peer certificate verification. */
+ byte verifyNone:1;
+ /* Fail when no peer certificate seen. */
+ byte failNoCert:1;
+ /* Fail when no peer certificate except when PSK handshake performed. */
+ byte failNoCertxPSK:1;
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+ /* Verify peer certificate post handshake. */
+ byte verifyPostHandshake:1;
+#endif
+} SetVerifyOptions;
+
+/* Convert the mode flags into certificate verification options.
+ *
+ * @param [in] mode Certificate verification mode flags.
+ * @return Certificate verification options.
+ */
+static SetVerifyOptions ModeToVerifyOptions(int mode)
+{
+ SetVerifyOptions opts;
+
+ /* Set the options to the default - none set. */
+ XMEMSET(&opts, 0, sizeof(SetVerifyOptions));
+
+ /* When the mode is not default - set the options. */
+ if (mode != WOLFSSL_VERIFY_DEFAULT) {
+ opts.verifyNone = (mode == WOLFSSL_VERIFY_NONE);
+ /* When not no verification, set the chosen options. */
+ if (!opts.verifyNone) {
+ opts.verifyPeer =
+ (mode & WOLFSSL_VERIFY_PEER) != 0;
+ opts.failNoCertxPSK =
+ (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) != 0;
+ opts.failNoCert =
+ (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT) != 0;
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+ opts.verifyPostHandshake =
+ (mode & WOLFSSL_VERIFY_POST_HANDSHAKE) != 0;
+#endif
+ }
+ }
+
+ return opts;
+}
+
+/* Set the verification options against the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context object.
+ * @param [in] mode Verification mode options.
+ * @param [in] verify_callback Verification callback.
+ */
+WOLFSSL_ABI void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode,
+ VerifyCallback verify_callback)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_set_verify");
+
+ /* Ensure we have an SSL/TLS context to work with. */
+ if (ctx != NULL) {
+ SetVerifyOptions opts = ModeToVerifyOptions(mode);
+
+ /* Set the bitfield options. */
+ ctx->verifyNone = opts.verifyNone;
+ ctx->verifyPeer = opts.verifyPeer;
+ ctx->failNoCert = opts.failNoCert;
+ ctx->failNoCertxPSK = opts.failNoCertxPSK;
+ #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+ ctx->verifyPostHandshake = opts.verifyPostHandshake;
+ #endif
+
+ /* Store the user verification callback against the context. */
+ ctx->verifyCallback = verify_callback;
+ }
+}
+
+#ifdef OPENSSL_ALL
+/* Set certificate verification callback and context against SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context object.
+ * @param [in] cb Certificate verification callback.
+ * @param [in] arg Context for certification verification callback.
+ */
+void wolfSSL_CTX_set_cert_verify_callback(WOLFSSL_CTX* ctx,
+ CertVerifyCallback cb, void* arg)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_set_cert_verify_callback");
+
+ /* Ensure we have an SSL/TLS context to work with. */
+ if (ctx != NULL) {
+ ctx->verifyCertCb = cb;
+ ctx->verifyCertCbArg = arg;
+ }
+}
+#endif
+
+/* Set the verification options against the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] mode Verification mode options.
+ * @param [in] verify_callback Verification callback.
+ */
+void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback verify_callback)
+{
+ WOLFSSL_ENTER("wolfSSL_set_verify");
+
+ /* Ensure we have an SSL/TLS object to work with. */
+ if (ssl != NULL) {
+ SetVerifyOptions opts = ModeToVerifyOptions(mode);
+
+ /* Set the bitfield options. */
+ ssl->options.verifyNone = opts.verifyNone;
+ ssl->options.verifyPeer = opts.verifyPeer;
+ ssl->options.failNoCert = opts.failNoCert;
+ ssl->options.failNoCertxPSK = opts.failNoCertxPSK;
+ #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+ ssl->options.verifyPostHandshake = opts.verifyPostHandshake;
+ #endif
+
+ /* Store the user verification callback against the object. */
+ ssl->verifyCallback = verify_callback;
+ }
+}
+
+/* Set the certificate verification result for the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] v Verification result.
+ */
+void wolfSSL_set_verify_result(WOLFSSL *ssl, long v)
+{
+ WOLFSSL_ENTER("wolfSSL_set_verify_result");
+
+ /* Ensure we have an SSL/TLS object to work with. */
+ if (ssl != NULL) {
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ ssl->peerVerifyRet = (unsigned long)v;
+ #else
+ WOLFSSL_STUB("wolfSSL_set_verify_result");
+ (void)v;
+ #endif
+ }
+}
+
+/* Store user ctx for verify callback into SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] userCtx User context for verify callback.
+ */
+void wolfSSL_CTX_SetCertCbCtx(WOLFSSL_CTX* ctx, void* userCtx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_SetCertCbCtx");
+
+ /* Validate parameters. */
+ if (ctx != NULL) {
+ ctx->verifyCbCtx = userCtx;
+ }
+}
+
+/* Store user ctx for verify callback into SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx User context for verify callback.
+ */
+void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_SetCertCbCtx");
+
+ /* Validate parameters. */
+ if (ssl != NULL) {
+ ssl->verifyCbCtx = ctx;
+ }
+}
+
+
+
+/* Store context CA Cache addition callback into SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] userCtx User context for verify callback.
+ */
+void wolfSSL_CTX_SetCACb(WOLFSSL_CTX* ctx, CallbackCACache cb)
+{
+ /* Validate parameters. */
+ if ((ctx != NULL) && (ctx->cm != NULL)) {
+ ctx->cm->caCacheCallback = cb;
+ }
+}
+
+#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_TLS13) && \
+ defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+/* For TLS v1.3, send authentication messages after handshake completes.
+ *
+ * @return 1 on success.
+ * @return UNSUPPORTED_PROTO_VERSION when not a TLSv1.3 handshake.
+ * @return 0 on other failure.
+ */
+int wolfSSL_verify_client_post_handshake(WOLFSSL* ssl)
+{
+ int ret;
+
+ /* Do request of certificate. */
+ ret = wolfSSL_request_certificate(ssl);
+ if (ret != 1) {
+ /* Special logging for wrong protocol version. */
+ if ((ssl != NULL) && !IsAtLeastTLSv1_3(ssl->version)) {
+ WOLFSSL_ERROR(UNSUPPORTED_PROTO_VERSION);
+ }
+ else {
+ /* Other errors - return 0. */
+ WOLFSSL_ERROR(ret);
+ }
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/* Set whether handshakes from this SSL/TLS context allow auth post handshake.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] val Whether to allow post handshake authentication.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_CTX_set_post_handshake_auth(WOLFSSL_CTX* ctx, int val)
+{
+ int ret;
+
+ /* Try to allow - really just checking conditions. */
+ if (wolfSSL_CTX_allow_post_handshake_auth(ctx) == 0) {
+ /* Set value as a bit. */
+ ctx->postHandshakeAuth = (val != 0);
+ ret = 1;
+ }
+ else {
+ ret = 0;
+ }
+
+ return ret;
+}
+/* Set whether handshakes with this SSL/TLS object allow auth post handshake.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] val Whether to allow post handshake authentication.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_set_post_handshake_auth(WOLFSSL* ssl, int val)
+{
+ int ret;
+
+ /* Try to allow - really just checking conditions. */
+ if (wolfSSL_allow_post_handshake_auth(ssl) == 0) {
+ /* Set value as a bit. */
+ ssl->options.postHandshakeAuth = (val != 0);
+ ret = 1;
+ }
+ else {
+ ret = 0;
+ }
+
+ return ret;
+}
+#endif /* OPENSSL_EXTRA && WOLFSSL_TLS13 && WOLFSSL_POST_HANDSHAKE_AUTH */
+
+#if defined(PERSIST_CERT_CACHE)
+
+#if !defined(NO_FILESYSTEM)
+
+/* Persist certificate cache in SSL/TLS context to file.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] fname Filename so store certificate cache to.
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ctx or fname is NULL.
+ * @return Other values on failure.
+ */
+int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_save_cert_cache");
+
+ /* Validate parameters. */
+ if ((ctx == NULL) || (fname == NULL)) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Save certificate cache. */
+ ret = CM_SaveCertCache(ctx->cm, fname);
+ }
+
+ return ret;
+}
+
+
+/* Load certificate cache into SSL/TLS context from file.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] fname Filename so store certificate cache to.
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ctx or fname is NULL.
+ * @return Other values on failure.
+ */
+int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_restore_cert_cache");
+
+ /* Validate parameters. */
+ if ((ctx == NULL) || (fname == NULL)) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Restore certificate cache. */
+ ret = CM_RestoreCertCache(ctx->cm, fname);
+ }
+
+ return ret;
+}
+
+#endif /* NO_FILESYSTEM */
+
+/* Persist certificate cache in SSL/TLS context to memory.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] mem Memory to fill with certificate cache.
+ * @param [in] sz Size of memory to fill in bytes.
+ * @param [out] used The number of bytes of memory used.
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ctx, mem or used is NULL.
+ * @return BAD_FUNC_ARG when sz is less than or equal to zero.
+ * @return Other values on failure.
+ */
+int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX* ctx, void* mem,
+ int sz, int* used)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_memsave_cert_cache");
+
+ /* Validate parameters. */
+ if ((ctx == NULL) || (mem == NULL) || (used == NULL) || (sz <= 0)) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Persist certificate change to memory. */
+ ret = CM_MemSaveCertCache(ctx->cm, mem, sz, used);
+ }
+
+ return ret;
+}
+
+
+/* Load certificate cache into SSL/TLS context from memory.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] mem Memory with certificate cache.
+ * @param [in] sz Size of certificate cache in bytes
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ctx or mem is NULL.
+ * @return BAD_FUNC_ARG when sz is less than or equal to zero.
+ * @return Other values on failure.
+ */
+int wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX* ctx, const void* mem, int sz)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_memrestore_cert_cache");
+
+ /* Validate parameters. */
+ if ((ctx == NULL) || (mem == NULL) || (sz <= 0)) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Restore certificate cache. */
+ ret = CM_MemRestoreCertCache(ctx->cm, mem, sz);
+ }
+
+ return ret;
+}
+
+
+/* Get size of certificate cache when persisted.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @return Size of certificate cache when pesisted in bytes.
+ * @return BAD_FUNC_ARG when ctx is NULL.
+ */
+int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX* ctx)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_get_cert_cache_memsize");
+
+ /* Validate parameter. */
+ if (ctx == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Get size. */
+ ret = CM_GetCertCacheMemSize(ctx->cm);
+ }
+
+ return ret;
+}
+
+#endif /* PERSIST_CERT_CACHE */
+
+/* Unload certificates and keys that the SSL/TLS object owns.
+ *
+ * The WOLFSSL_CTX referenced is untouched.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ssl is NULL.
+ */
+int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl)
+{
+ int ret = 1;
+
+ /* Validate parameter. */
+ if (ssl == NULL) {
+ WOLFSSL_MSG("Null function arg");
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ if (ssl->buffers.weOwnCert && !ssl->keepCert) {
+ WOLFSSL_MSG("Unloading cert");
+ FreeDer(&ssl->buffers.certificate);
+ #ifdef KEEP_OUR_CERT
+ wolfSSL_X509_free(ssl->ourCert);
+ ssl->ourCert = NULL;
+ #endif
+ ssl->buffers.weOwnCert = 0;
+ }
+
+ if (ssl->buffers.weOwnCertChain) {
+ WOLFSSL_MSG("Unloading cert chain");
+ FreeDer(&ssl->buffers.certChain);
+ ssl->buffers.weOwnCertChain = 0;
+ }
+
+ if (ssl->buffers.weOwnKey) {
+ WOLFSSL_MSG("Unloading key");
+ ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length);
+ FreeDer(&ssl->buffers.key);
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ FreeDer(&ssl->buffers.keyMask);
+ #endif
+ ssl->buffers.weOwnKey = 0;
+ }
+
+ #ifdef WOLFSSL_DUAL_ALG_CERTS
+ if (ssl->buffers.weOwnAltKey) {
+ WOLFSSL_MSG("Unloading alt key");
+ ForceZero(ssl->buffers.altKey->buffer, ssl->buffers.altKey->length);
+ FreeDer(&ssl->buffers.altKey);
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ FreeDer(&ssl->buffers.altKeyMask);
+ #endif
+ ssl->buffers.weOwnAltKey = 0;
+ }
+ #endif /* WOLFSSL_DUAL_ALG_CERTS */
+ }
+
+ return ret;
+}
+
+/* Unload CAs from the certificate manager of the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ctx or ctx->cm is NULL.
+ * @return BAD_MUTEX_E when locking fails.
+ */
+int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_UnloadCAs");
+
+ /* Validate parameter. */
+ if (ctx == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ ret = wolfSSL_CertManagerUnloadCAs(ctx->cm);
+ }
+
+ return ret;
+}
+
+/* Unload Intermediate CAs from the certificate manager of the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ctx or ctx->cm is NULL.
+ * @return BAD_MUTEX_E when locking fails.
+ */
+int wolfSSL_CTX_UnloadIntermediateCerts(WOLFSSL_CTX* ctx)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_UnloadIntermediateCerts");
+
+ /* Validate parameter. */
+ if (ctx == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ /* Lock reference count. */
+ else if ((ret = wolfSSL_RefWithMutexLock(&ctx->ref)) == 0) {
+ /* Must not have another reference for this operation to be done. */
+ if (ctx->ref.count > 1) {
+ WOLFSSL_MSG("ctx object must have a ref count of 1 before "
+ "unloading intermediate certs");
+ ret = BAD_STATE_E;
+ }
+ else {
+ ret = wolfSSL_CertManagerUnloadIntermediateCerts(ctx->cm);
+ }
+
+ /* Unlock reference count. */
+ if (wolfSSL_RefWithMutexUnlock(&ctx->ref) != 0) {
+ WOLFSSL_MSG("Failed to unlock mutex!");
+ }
+ }
+
+ return ret;
+}
+
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* Unload trusted peers from the certificate manager of the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ctx or ctx->cm is NULL.
+ * @return BAD_MUTEX_E when locking fails.
+ */
+int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers");
+
+ /* Validate parameter. */
+ if (ctx == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ ret = wolfSSL_CertManagerUnload_trust_peers(ctx->cm);
+ }
+
+ return ret;
+}
+
+#ifdef WOLFSSL_LOCAL_X509_STORE
+/* Unload trusted peers from the certificate manager of the SSL/TLS object.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ssl is NULL.
+ * @return BAD_MUTEX_E when locking fails.
+ */
+int wolfSSL_Unload_trust_peers(WOLFSSL* ssl)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers");
+
+ /* Validate parameter. */
+ if (ssl == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Output message when certificate manager for object. */
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerUnload_trust_peers(SSL_CM(ssl));
+ }
+
+ return ret;
+}
+#endif /* WOLFSSL_LOCAL_X509_STORE */
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+#ifndef WOLFSSL_NO_CA_NAMES
+/* Add a CA certificate to the list of CA names.
+ *
+ * @param [in, out] ca_names List of CA certificate subject names.
+ * @param [in] x509 X509 certificate.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+static int add_to_ca_names_list(WOLFSSL_STACK* ca_names, WOLFSSL_X509* x509)
+{
+ int ret = 1;
+ WOLFSSL_X509_NAME *nameCopy = NULL;
+
+ nameCopy = wolfSSL_X509_NAME_dup(wolfSSL_X509_get_subject_name(x509));
+ if (nameCopy == NULL) {
+ WOLFSSL_MSG("wolfSSL_X509_NAME_dup error");
+ ret = 0;
+ }
+ else if (wolfSSL_sk_X509_NAME_push(ca_names, nameCopy) <= 0) {
+ WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error");
+ wolfSSL_X509_NAME_free(nameCopy);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/* Add a client's CA to SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] x509 X509 certificate.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA");
+
+ /* Validate parameters. */
+ if ((ctx == NULL) || (x509 == NULL)) {
+ WOLFSSL_MSG("Bad argument");
+ ret = 0;
+ }
+ /* Create a stack of names if not present. */
+ else if (ctx->client_ca_names == NULL) {
+ ctx->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL);
+ if (ctx->client_ca_names == NULL) {
+ WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
+ ret = 0;
+ }
+ }
+ if (ret == 1) {
+ /* Add certificate's subject name to client CA name list. */
+ ret = add_to_ca_names_list(ctx->client_ca_names, x509);
+ }
+
+ return ret;
+}
+
+/* Add a client's CA to SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] x509 X509 certificate.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_add_client_CA(WOLFSSL* ssl, WOLFSSL_X509* x509)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("wolfSSL_add_client_CA");
+
+ /* Validate parameters. */
+ if ((ssl == NULL) || (x509 == NULL)) {
+ WOLFSSL_MSG("Bad argument");
+ ret = 0;
+ }
+ /* Create a stack of names if not present. */
+ else if (ssl->client_ca_names == NULL) {
+ ssl->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL);
+ if (ssl->client_ca_names == NULL) {
+ WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
+ ret = 0;
+ }
+ }
+ if (ret == 1) {
+ /* Add certificate's subject name to client CA name list. */
+ ret = add_to_ca_names_list(ssl->client_ca_names, x509);
+ }
+
+ return ret;
+}
+
+/* Add a CA to SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] x509 X509 certificate.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_CTX_add1_to_CA_list(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_add1_to_CA_list");
+
+ /* Validate parameters. */
+ if ((ctx == NULL) || (x509 == NULL)) {
+ WOLFSSL_MSG("Bad argument");
+ ret = 0;
+ }
+ /* Create a stack of names if not present. */
+ else if (ctx->ca_names == NULL) {
+ ctx->ca_names = wolfSSL_sk_X509_NAME_new(NULL);
+ if (ctx->ca_names == NULL) {
+ WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
+ ret = 0;
+ }
+ }
+ if (ret == 1) {
+ /* Add certificate's subject name to CA name list. */
+ ret = add_to_ca_names_list(ctx->ca_names, x509);
+ }
+
+ return ret;
+}
+
+/* Add a CA to SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] x509 X509 certificate.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_add1_to_CA_list(WOLFSSL* ssl, WOLFSSL_X509* x509)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("wolfSSL_add1_to_CA_list");
+
+ /* Validate parameters. */
+ if ((ssl == NULL) || (x509 == NULL)) {
+ WOLFSSL_MSG("Bad argument");
+ ret = 0;
+ }
+ /* Create a stack of names if not present. */
+ else if (ssl->ca_names == NULL) {
+ ssl->ca_names = wolfSSL_sk_X509_NAME_new(NULL);
+ if (ssl->ca_names == NULL) {
+ WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
+ ret = 0;
+ }
+ }
+ if (ret == 1) {
+ /* Add certificate's subject name to CA name list. */
+ ret = add_to_ca_names_list(ssl->ca_names, x509);
+ }
+
+ return ret;
+}
+
+/* Set the client CA list into SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] names List of CA subject names.
+ */
+void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx,
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_set_client_CA_list");
+
+ /* Validate parameters. */
+ if (ctx != NULL) {
+ /* Dispose of any existing list. */
+ wolfSSL_sk_X509_NAME_pop_free(ctx->client_ca_names, NULL);
+ /* Take ownership of names list. */
+ ctx->client_ca_names = names;
+ }
+}
+
+/* Set the client CA list into SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] names List of CA subject names.
+ */
+void wolfSSL_set_client_CA_list(WOLFSSL* ssl,
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
+{
+ WOLFSSL_ENTER("wolfSSL_set_client_CA_list");
+
+ /* Validate parameters. */
+ if (ssl != NULL) {
+ /* Dispose of any existing list if the object owns it. */
+ if (ssl->client_ca_names != ssl->ctx->client_ca_names) {
+ wolfSSL_sk_X509_NAME_pop_free(ssl->client_ca_names, NULL);
+ }
+ /* Take ownership of names list. */
+ ssl->client_ca_names = names;
+ }
+}
+
+/* Set the CA list into SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] names List of CA subject names.
+ */
+void wolfSSL_CTX_set0_CA_list(WOLFSSL_CTX* ctx,
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_set0_CA_list");
+
+ /* Validate parameters. */
+ if (ctx != NULL) {
+ /* Dispose of any existing list. */
+ wolfSSL_sk_X509_NAME_pop_free(ctx->ca_names, NULL);
+ /* Take ownership of names list. */
+ ctx->ca_names = names;
+ }
+}
+
+/* Set the client CA list into SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] names List of CA subject names.
+ */
+void wolfSSL_set0_CA_list(WOLFSSL* ssl,
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
+{
+ WOLFSSL_ENTER("wolfSSL_set0_CA_list");
+
+ /* Validate parameters. */
+ if (ssl != NULL) {
+ /* Dispose of any existing list if the object owns it. */
+ if (ssl->ca_names != ssl->ctx->ca_names) {
+ wolfSSL_sk_X509_NAME_pop_free(ssl->ca_names, NULL);
+ }
+ /* Take ownership of names list. */
+ ssl->ca_names = names;
+ }
+}
+
+/* Get the list of client CA subject names from the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @return List of CA subject names on success.
+ * @return NULL when ctx is NULL or no names set.
+ */
+WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get_client_CA_list(
+ const WOLFSSL_CTX *ctx)
+{
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_get_client_CA_list");
+
+ /* Validate parameter. */
+ if (ctx == NULL) {
+ WOLFSSL_MSG("Bad argument passed to wolfSSL_CTX_get_client_CA_list");
+ ret = NULL;
+ }
+ else {
+ ret = ctx->client_ca_names;
+ }
+
+ return ret;
+}
+
+/* Get the list of client CA subject names from the SSL/TLS object.
+ *
+ * On server side: returns the CAs set via *_set_client_CA_list();
+ * On client side: returns the CAs received from server -- same as
+ * wolfSSL_get0_peer_CA_list().
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return List of CA subject names on success.
+ * @return NULL when ssl is NULL or no names set.
+ */
+WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list(const WOLFSSL* ssl)
+{
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret;
+
+ WOLFSSL_ENTER("wolfSSL_get_client_CA_list");
+
+ /* Validate parameter. */
+ if (ssl == NULL) {
+ WOLFSSL_MSG("Bad argument passed to wolfSSL_get_client_CA_list");
+ ret = NULL;
+ }
+ /* Client side return peer CA names. */
+ else if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ ret = ssl->peer_ca_names;
+ }
+ /* Server side return client CA names. */
+ else {
+ ret = SSL_CLIENT_CA_NAMES(ssl);
+ }
+
+ return ret;
+}
+
+/* Get the list of CA subject names from the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @return List of CA subject names on success.
+ * @return NULL when ctx is NULL or no names set.
+ */
+WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get0_CA_list(
+ const WOLFSSL_CTX *ctx)
+{
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_get0_CA_list");
+
+ /* Validate parameter. */
+ if (ctx == NULL) {
+ WOLFSSL_MSG("Bad argument passed to wolfSSL_CTX_get0_CA_list");
+ ret = NULL;
+ }
+ else {
+ /* Return list directly. */
+ ret = ctx->ca_names;
+ }
+
+ return ret;
+}
+
+/* Get the list of CA subject names from the SSL/TLS object.
+ *
+ * Always returns the CA's set via *_set0_CA_list.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return List of CA subject names on success.
+ * @return NULL when ssl is NULL or no names set.
+ */
+WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get0_CA_list(const WOLFSSL *ssl)
+{
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret;
+
+ WOLFSSL_ENTER("wolfSSL_get0_CA_list");
+
+ /* Validate parameter. */
+ if (ssl == NULL) {
+ WOLFSSL_MSG("Bad argument passed to wolfSSL_get0_CA_list");
+ ret = NULL;
+ }
+ else {
+ /* Return list directly from object, if available, or context. */
+ ret = SSL_CA_NAMES(ssl);
+ }
+
+ return ret;
+}
+
+/* Get the list of peer CA subject names from the SSL/TLS object.
+ *
+ * Always returns the CA's received from the peer.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return List of CA subject names on success.
+ * @return NULL when ssl is NULL or no names set.
+ */
+WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get0_peer_CA_list(const WOLFSSL* ssl)
+{
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret;
+
+ WOLFSSL_ENTER("wolfSSL_get0_peer_CA_list");
+
+ /* Validate parameter. */
+ if (ssl == NULL) {
+ WOLFSSL_MSG("Bad argument passed to wolfSSL_get0_peer_CA_list");
+ ret = NULL;
+ }
+ else {
+ /* Return list directly from object. */
+ ret = ssl->peer_ca_names;
+ }
+
+ return ret;
+}
+
+#ifndef NO_BIO
+/* Load the client CA subject names from file.
+ *
+ * @param [in] fname Name of file containing client CA certificates.
+ * @return A list of certificate names on success.
+ * @return NULL on error.
+ */
+WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname)
+{
+ /* The webserver build is using this to load a CA into the server
+ * for client authentication as an option. Have this return NULL in
+ * that case. If OPENSSL_EXTRA is enabled, go ahead and include
+ * the function. */
+#ifdef OPENSSL_EXTRA
+ WOLFSSL_STACK *list = NULL;
+ WOLFSSL_BIO* bio = NULL;
+ WOLFSSL_X509 *cert = NULL;
+ int err = 0;
+ unsigned long error;
+
+ WOLFSSL_ENTER("wolfSSL_load_client_CA_file");
+
+ /* Create a file BIO to read. */
+ bio = wolfSSL_BIO_new_file(fname, "rb");
+ if (bio == NULL) {
+ WOLFSSL_MSG("wolfSSL_BIO_new_file error");
+ err = 1;
+ }
+
+ if (!err) {
+ /* Create an empty list of certificate names - default compare cb. */
+ list = wolfSSL_sk_X509_NAME_new(NULL);
+ if (list == NULL) {
+ WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
+ err = 1;
+ }
+ }
+
+ /* Read each certificate in the chain out of the file. */
+ while (!err && wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) {
+ WOLFSSL_X509_NAME *nameCopy;
+
+ /* Need a persistent copy of the subject name. */
+ nameCopy = wolfSSL_X509_NAME_dup(wolfSSL_X509_get_subject_name(cert));
+ if (nameCopy == NULL) {
+ WOLFSSL_MSG("wolfSSL_X509_NAME_dup error");
+ err = 1;
+ }
+ else {
+ /* Original certificate will be freed - clear reference to it. */
+ nameCopy->x509 = NULL;
+
+ if (wolfSSL_sk_X509_NAME_push(list, nameCopy) <= 0) {
+ WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error");
+ /* Name not stored - free now as only place needing to. */
+ wolfSSL_X509_NAME_free(nameCopy);
+ err = 1;
+ }
+ }
+
+ /* Dispose of certificate read. */
+ wolfSSL_X509_free(cert);
+ cert = NULL;
+ }
+
+ /* Clear any error due to no more certificates. */
+ CLEAR_ASN_NO_PEM_HEADER_ERROR(error);
+
+ if (err) {
+ /* Error occurred so return NULL. */
+ wolfSSL_sk_X509_NAME_pop_free(list, NULL);
+ list = NULL;
+ }
+ wolfSSL_BIO_free(bio);
+ return list;
+#else
+ (void)fname;
+ return NULL;
+#endif
+}
+#endif /* !NO_BIO */
+#endif /* WOLFSSL_NO_CA_NAMES */
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+/* Get the certificate store of the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @return X509 certificate store on success.
+ * @return NULL when ctx is NULL.
+ */
+WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(const WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_X509_STORE* ret;
+
+ /* Validate parameter. */
+ if (ctx == NULL) {
+ ret = NULL;
+ }
+ /* Use pointer to external store if set. */
+ else if (ctx->x509_store_pt != NULL) {
+ ret = ctx->x509_store_pt;
+ }
+ else {
+ /* Return reference to store that is part of the context. */
+ ret = (WOLFSSL_X509_STORE*)&ctx->x509_store;
+ }
+
+ return ret;
+}
+
+/* Set the certificate store of the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @return X509 certificate store on success.
+ * @return NULL when ctx is NULL.
+ */
+void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_set_cert_store");
+
+ /* Validate parameters. */
+ if ((ctx == NULL) || (str == NULL) || (ctx->cm == str->cm)) {
+ WOLFSSL_MSG("Invalid parameters");
+ }
+ else if (wolfSSL_CertManager_up_ref(str->cm) != 1) {
+ WOLFSSL_MSG("wolfSSL_CertManager_up_ref error");
+ }
+ else {
+ /* Free any cert manager. */
+ wolfSSL_CertManagerFree(ctx->cm);
+ /* Free any external store. */
+ wolfSSL_X509_STORE_free(ctx->x509_store_pt);
+ /* Set the certificate manager into context. */
+ ctx->cm = str->cm;
+ ctx->x509_store.cm = str->cm;
+ ctx->x509_store.cache = str->cache;
+ /* Take ownership of store and free it with context free. */
+ ctx->x509_store_pt = str;
+ /* Context has ownership and free it with context free. */
+ ctx->cm->x509_store_p = ctx->x509_store_pt;
+ }
+}
+
+#ifdef OPENSSL_ALL
+/* Set certificate store into SSL/TLS context but don't take ownership.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] str Certificate store.
+ * @return 1 on success.
+ * @return 0 when ctx or str is NULL or on other error.
+ */
+int wolfSSL_CTX_set1_verify_cert_store(WOLFSSL_CTX* ctx,
+ WOLFSSL_X509_STORE* str)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_set1_verify_cert_store");
+
+ /* Validate parameters. */
+ if ((ctx == NULL) || (str == NULL)) {
+ WOLFSSL_MSG("Bad parameter");
+ ret = 0;
+ }
+ /* Nothing to do when store being set is the same as existing in context. */
+ else if (str == CTX_STORE(ctx)) {
+ ret = 1;
+ }
+ /* Increase ref so we can store pointer and free it with context free. */
+ else if (wolfSSL_X509_STORE_up_ref(str) != 1) {
+ WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error");
+ ret = 0;
+ }
+ else {
+ /* Free any external store. */
+ wolfSSL_X509_STORE_free(ctx->x509_store_pt);
+ /* Ref count increased - store pointer and free with context free. */
+ ctx->x509_store_pt = str;
+ ret = 1;
+ }
+
+ return ret;
+}
+#endif
+
+
+/* Set certificate store into SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] str Certificate store.
+ * @param [in] ref Take a reference to passed in certificate store.
+ * @return 1 on success.
+ * @return 0 when ssl or str is NULL or on other error.
+ */
+static int wolfssl_set_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str,
+ int ref)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfssl_set_verify_cert_store");
+
+ /* Validate parameters. */
+ if ((ssl == NULL) || (str == NULL)) {
+ WOLFSSL_MSG("Bad parameter");
+ ret = 0;
+ }
+ /* Nothing to do when store being set is the same as existing in object. */
+ else if (str == SSL_STORE(ssl)) {
+ ret = 1;
+ }
+ else if (ref && (wolfSSL_X509_STORE_up_ref(str) != 1)) {
+ WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error");
+ ret = 0;
+ }
+ else {
+ /* Free any external store. */
+ wolfSSL_X509_STORE_free(ssl->x509_store_pt);
+ if (str == ssl->ctx->x509_store_pt) {
+ /* Setting ctx store - just revert to using that instead. */
+ ssl->x509_store_pt = NULL;
+ }
+ else {
+ /* Ref count increased - store pointer and free with object free. */
+ ssl->x509_store_pt = str;
+ }
+ ret = 1;
+ }
+
+ return ret;
+}
+
+/* Set certificate store into SSL/TLS object and take ownership.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] str Certificate store.
+ * @return 1 on success.
+ * @return 0 when ssl or str is NULL or on other error.
+ */
+int wolfSSL_set0_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str)
+{
+ WOLFSSL_ENTER("wolfSSL_set0_verify_cert_store");
+
+ return wolfssl_set_verify_cert_store(ssl, str, 0);
+}
+
+/* Set certificate store into SSL/TLS object but don't take ownership.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] str Certificate store.
+ * @return 1 on success.
+ * @return 0 when ssl or str is NULL or on other error.
+ */
+int wolfSSL_set1_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str)
+{
+ WOLFSSL_ENTER("wolfSSL_set1_verify_cert_store");
+
+ return wolfssl_set_verify_cert_store(ssl, str, 1);
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+
+/* OPENSSL_EXTRA is needed for wolfSSL_X509_d21 function
+ KEEP_OUR_CERT is to ensure ability to return ssl certificate */
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+ defined(KEEP_OUR_CERT)
+/* Get the certificate in the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @return Certificate being sent to peer.
+ * @return NULL when ctx is NULL, no certificate set or on other error.
+ */
+WOLFSSL_X509* wolfSSL_CTX_get0_certificate(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_X509* ret = NULL;
+
+ /* Validate parameters. */
+ if (ctx == NULL) {
+ WOLFSSL_MSG("Invalid parameter");
+ }
+ else {
+ /* Check if we already have a certificate allocated. */
+ if (ctx->ourCert == NULL) {
+ /* Check if there is a raw certificate. */
+ if (ctx->certificate == NULL) {
+ WOLFSSL_MSG("Ctx Certificate buffer not set!");
+ }
+ #ifndef WOLFSSL_X509_STORE_CERTS
+ else {
+ /* Create a certificate object from raw data. */
+ ctx->ourCert = wolfSSL_X509_d2i_ex(NULL,
+ ctx->certificate->buffer, (int)ctx->certificate->length,
+ ctx->heap);
+ ctx->ownOurCert = 1;
+ }
+ #endif
+ }
+ /* Return certificate cached against SSL/TLS context. */
+ ret = ctx->ourCert;
+ }
+
+ return ret;
+}
+
+/* Get the certificate in the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Certificate being sent to peer.
+ * @return NULL when ssl is NULL, no certificate set or on other error.
+ */
+WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl)
+{
+ WOLFSSL_X509* ret = NULL;
+
+ /* Validate parameters. */
+ if (ssl == NULL) {
+ WOLFSSL_MSG("Invalid parameter");
+ }
+ /* Use certificate in SSL/TLS object if we own it. */
+ else if (ssl->buffers.weOwnCert) {
+ /* Check if we already have a certificate allocated. */
+ if (ssl->ourCert == NULL) {
+ /* We own certificate so this should never happen. */
+ if (ssl->buffers.certificate == NULL) {
+ WOLFSSL_MSG("Certificate buffer not set!");
+ }
+ #ifndef WOLFSSL_X509_STORE_CERTS
+ else {
+ /* Create a certificate object from raw data. */
+ ssl->ourCert = wolfSSL_X509_d2i_ex(NULL,
+ ssl->buffers.certificate->buffer,
+ (int)ssl->buffers.certificate->length, ssl->heap);
+ }
+ #endif
+ }
+ /* Return certificate cached against SSL/TLS object. */
+ ret = ssl->ourCert;
+ }
+ else {
+ /* Use any certificate in SSL/TLS context instead. */
+ ret = wolfSSL_CTX_get0_certificate(ssl->ctx);
+ }
+
+ return ret;
+}
+#endif /* (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) && KEEP_OUR_CERT */
+
+#endif /* !NO_CERTS */
+
+#endif /* !WOLFSSL_SSL_API_CERT_INCLUDED */
diff --git a/src/ssl_api_crl_ocsp.c b/src/ssl_api_crl_ocsp.c
new file mode 100644
index 0000000000..b0791dc6a9
--- /dev/null
+++ b/src/ssl_api_crl_ocsp.c
@@ -0,0 +1,634 @@
+/* ssl_api_crl_ocsp.c
+ *
+ * Copyright (C) 2006-2025 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#include
+
+#if !defined(WOLFSSL_SSL_API_CRL_OCSP_INCLUDED)
+ #ifndef WOLFSSL_IGNORE_FILE_WARN
+ #warning ssl_api_crl_ocsp.c is not compiled separately from ssl.c
+ #endif
+#else
+
+#ifndef NO_CERTS
+
+#ifdef HAVE_CRL
+
+int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
+ long sz, int type)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_LoadCRLBuffer");
+
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+
+ return wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, buff, sz, type);
+}
+
+
+int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff,
+ long sz, int type)
+{
+ WOLFSSL_ENTER("wolfSSL_LoadCRLBuffer");
+
+ if (ssl == NULL || ssl->ctx == NULL)
+ return BAD_FUNC_ARG;
+
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerLoadCRLBuffer(SSL_CM(ssl), buff, sz, type);
+}
+
+int wolfSSL_EnableCRL(WOLFSSL* ssl, int options)
+{
+ WOLFSSL_ENTER("wolfSSL_EnableCRL");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerEnableCRL(SSL_CM(ssl), options);
+ }
+ else
+ return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_DisableCRL(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_DisableCRL");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerDisableCRL(SSL_CM(ssl));
+ }
+ else
+ return BAD_FUNC_ARG;
+}
+
+#ifndef NO_FILESYSTEM
+int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor)
+{
+ WOLFSSL_ENTER("wolfSSL_LoadCRL");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerLoadCRL(SSL_CM(ssl), path, type, monitor);
+ }
+ else
+ return BAD_FUNC_ARG;
+}
+
+int wolfSSL_LoadCRLFile(WOLFSSL* ssl, const char* file, int type)
+{
+ WOLFSSL_ENTER("wolfSSL_LoadCRLFile");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerLoadCRLFile(SSL_CM(ssl), file, type);
+ }
+ else
+ return BAD_FUNC_ARG;
+}
+#endif
+
+int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb)
+{
+ WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerSetCRL_Cb(SSL_CM(ssl), cb);
+ }
+ else
+ return BAD_FUNC_ARG;
+}
+
+int wolfSSL_SetCRL_ErrorCb(WOLFSSL* ssl, crlErrorCb cb, void* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerSetCRL_ErrorCb(SSL_CM(ssl), cb, ctx);
+ }
+ else
+ return BAD_FUNC_ARG;
+}
+
+#ifdef HAVE_CRL_IO
+int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb)
+{
+ WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerSetCRL_IOCb(SSL_CM(ssl), cb);
+ }
+ else
+ return BAD_FUNC_ARG;
+}
+#endif
+
+int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_EnableCRL");
+ if (ctx)
+ return wolfSSL_CertManagerEnableCRL(ctx->cm, options);
+ else
+ return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_DisableCRL");
+ if (ctx)
+ return wolfSSL_CertManagerDisableCRL(ctx->cm);
+ else
+ return BAD_FUNC_ARG;
+}
+
+
+#ifndef NO_FILESYSTEM
+int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path,
+ int type, int monitor)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL");
+ if (ctx)
+ return wolfSSL_CertManagerLoadCRL(ctx->cm, path, type, monitor);
+ else
+ return BAD_FUNC_ARG;
+}
+
+int wolfSSL_CTX_LoadCRLFile(WOLFSSL_CTX* ctx, const char* file,
+ int type)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL");
+ if (ctx)
+ return wolfSSL_CertManagerLoadCRLFile(ctx->cm, file, type);
+ else
+ return BAD_FUNC_ARG;
+}
+#endif
+
+
+int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_Cb");
+ if (ctx)
+ return wolfSSL_CertManagerSetCRL_Cb(ctx->cm, cb);
+ else
+ return BAD_FUNC_ARG;
+}
+
+int wolfSSL_CTX_SetCRL_ErrorCb(WOLFSSL_CTX* ctx, crlErrorCb cb, void* cbCtx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_ErrorCb");
+ if (ctx)
+ return wolfSSL_CertManagerSetCRL_ErrorCb(ctx->cm, cb, cbCtx);
+ else
+ return BAD_FUNC_ARG;
+}
+
+#ifdef HAVE_CRL_IO
+int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX* ctx, CbCrlIO cb)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_IOCb");
+ if (ctx)
+ return wolfSSL_CertManagerSetCRL_IOCb(ctx->cm, cb);
+ else
+ return BAD_FUNC_ARG;
+}
+#endif
+
+#endif /* HAVE_CRL */
+
+
+#ifdef HAVE_OCSP
+int wolfSSL_EnableOCSP(WOLFSSL* ssl, int options)
+{
+ WOLFSSL_ENTER("wolfSSL_EnableOCSP");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerEnableOCSP(SSL_CM(ssl), options);
+ }
+ else
+ return BAD_FUNC_ARG;
+}
+
+int wolfSSL_DisableOCSP(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_DisableOCSP");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerDisableOCSP(SSL_CM(ssl));
+ }
+ else
+ return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_EnableOCSPStapling(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_EnableOCSPStapling");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerEnableOCSPStapling(SSL_CM(ssl));
+ }
+ else
+ return BAD_FUNC_ARG;
+}
+
+int wolfSSL_DisableOCSPStapling(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_DisableOCSPStapling");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerDisableOCSPStapling(SSL_CM(ssl));
+ }
+ else
+ return BAD_FUNC_ARG;
+}
+int wolfSSL_SetOCSP_OverrideURL(WOLFSSL* ssl, const char* url)
+{
+ WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerSetOCSPOverrideURL(SSL_CM(ssl), url);
+ }
+ else
+ return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_SetOCSP_Cb(WOLFSSL* ssl,
+ CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx)
+{
+ WOLFSSL_ENTER("wolfSSL_SetOCSP_Cb");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ ssl->ocspIOCtx = ioCbCtx; /* use SSL specific ioCbCtx */
+ return wolfSSL_CertManagerSetOCSP_Cb(SSL_CM(ssl),
+ ioCb, respFreeCb, NULL);
+ }
+ else
+ return BAD_FUNC_ARG;
+}
+
+int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX* ctx, int options)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSP");
+ if (ctx)
+ return wolfSSL_CertManagerEnableOCSP(ctx->cm, options);
+ else
+ return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSP");
+ if (ctx)
+ return wolfSSL_CertManagerDisableOCSP(ctx->cm);
+ else
+ return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX* ctx, const char* url)
+{
+ WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL");
+ if (ctx)
+ return wolfSSL_CertManagerSetOCSPOverrideURL(ctx->cm, url);
+ else
+ return BAD_FUNC_ARG;
+}
+
+
+int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX* ctx, CbOCSPIO ioCb,
+ CbOCSPRespFree respFreeCb, void* ioCbCtx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_SetOCSP_Cb");
+ if (ctx)
+ return wolfSSL_CertManagerSetOCSP_Cb(ctx->cm, ioCb,
+ respFreeCb, ioCbCtx);
+ else
+ return BAD_FUNC_ARG;
+}
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPStapling");
+ if (ctx)
+ return wolfSSL_CertManagerEnableOCSPStapling(ctx->cm);
+ else
+ return BAD_FUNC_ARG;
+}
+
+int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPStapling");
+ if (ctx)
+ return wolfSSL_CertManagerDisableOCSPStapling(ctx->cm);
+ else
+ return BAD_FUNC_ARG;
+}
+int wolfSSL_CTX_EnableOCSPMustStaple(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPMustStaple");
+ if (ctx)
+ return wolfSSL_CertManagerEnableOCSPMustStaple(ctx->cm);
+ else
+ return BAD_FUNC_ARG;
+}
+
+int wolfSSL_CTX_DisableOCSPMustStaple(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPMustStaple");
+ if (ctx)
+ return wolfSSL_CertManagerDisableOCSPMustStaple(ctx->cm);
+ else
+ return BAD_FUNC_ARG;
+}
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST || \
+ * HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+/* Not an OpenSSL API. */
+int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response)
+{
+ *response = ssl->ocspCsrResp[0].buffer;
+ return ssl->ocspCsrResp[0].length;
+}
+
+/* Not an OpenSSL API. */
+char* wolfSSL_get_ocsp_url(WOLFSSL* ssl)
+{
+ return ssl->url;
+}
+
+/* Not an OpenSSL API. */
+int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url)
+{
+ if (ssl == NULL)
+ return WOLFSSL_FAILURE;
+
+ ssl->url = url;
+ return WOLFSSL_SUCCESS;
+}
+#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
+#if !defined(NO_ASN_TIME)
+int wolfSSL_get_ocsp_producedDate(
+ WOLFSSL *ssl,
+ byte *producedDate,
+ size_t producedDate_space,
+ int *producedDateFormat)
+{
+ if ((ssl->ocspProducedDateFormat != ASN_UTC_TIME) &&
+ (ssl->ocspProducedDateFormat != ASN_GENERALIZED_TIME))
+ return BAD_FUNC_ARG;
+
+ if ((producedDate == NULL) || (producedDateFormat == NULL))
+ return BAD_FUNC_ARG;
+
+ if (XSTRLEN((char *)ssl->ocspProducedDate) >= producedDate_space)
+ return BUFFER_E;
+
+ XSTRNCPY((char *)producedDate, (const char *)ssl->ocspProducedDate,
+ producedDate_space);
+ *producedDateFormat = ssl->ocspProducedDateFormat;
+
+ return 0;
+}
+
+int wolfSSL_get_ocsp_producedDate_tm(WOLFSSL *ssl, struct tm *produced_tm) {
+ int idx = 0;
+
+ if ((ssl->ocspProducedDateFormat != ASN_UTC_TIME) &&
+ (ssl->ocspProducedDateFormat != ASN_GENERALIZED_TIME))
+ return BAD_FUNC_ARG;
+
+ if (produced_tm == NULL)
+ return BAD_FUNC_ARG;
+
+ if (ExtractDate(ssl->ocspProducedDate,
+ (unsigned char)ssl->ocspProducedDateFormat, produced_tm, &idx,
+ MAX_DATE_SZ))
+ return 0;
+ else
+ return ASN_PARSE_E;
+}
+#endif /* !NO_ASN_TIME */
+#endif /* HAVE_OCSP */
+
+#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT)
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+
+int wolfSSL_UseOCSPStapling(WOLFSSL* ssl, byte status_type, byte options)
+{
+ WOLFSSL_ENTER("wolfSSL_UseOCSPStapling");
+
+ if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END)
+ return BAD_FUNC_ARG;
+
+ return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type,
+ options, NULL, ssl->heap, ssl->devId);
+}
+
+
+int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx, byte status_type,
+ byte options)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_UseOCSPStapling");
+
+ if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
+ return BAD_FUNC_ARG;
+
+ return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type,
+ options, NULL, ctx->heap, ctx->devId);
+}
+
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
+
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+
+int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl, byte status_type, byte options)
+{
+ if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END)
+ return BAD_FUNC_ARG;
+
+ return TLSX_UseCertificateStatusRequestV2(&ssl->extensions, status_type,
+ options, ssl->heap, ssl->devId);
+}
+
+
+int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, byte status_type,
+ byte options)
+{
+ if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END)
+ return BAD_FUNC_ARG;
+
+ return TLSX_UseCertificateStatusRequestV2(&ctx->extensions, status_type,
+ options, ctx->heap, ctx->devId);
+}
+
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+#endif /* !NO_TLS && !NO_WOLFSSL_CLIENT */
+
+#ifdef OPENSSL_EXTRA
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type)
+{
+ WOLFSSL_ENTER("wolfSSL_set_tlsext_status_type");
+
+ if (s == NULL){
+ return BAD_FUNC_ARG;
+ }
+
+ if (type == WOLFSSL_TLSEXT_STATUSTYPE_ocsp){
+ int r = TLSX_UseCertificateStatusRequest(&s->extensions, (byte)type, 0,
+ s, s->heap, s->devId);
+ return (long)r;
+ } else {
+ WOLFSSL_MSG(
+ "SSL_set_tlsext_status_type only supports TLSEXT_STATUSTYPE_ocsp type.");
+ return WOLFSSL_FAILURE;
+ }
+
+}
+
+long wolfSSL_get_tlsext_status_type(WOLFSSL *s)
+{
+ TLSX* extension;
+
+ if (s == NULL)
+ return WOLFSSL_FATAL_ERROR;
+ extension = TLSX_Find(s->extensions, TLSX_STATUS_REQUEST);
+ return (extension != NULL) ? WOLFSSL_TLSEXT_STATUSTYPE_ocsp :
+ WOLFSSL_FATAL_ERROR;
+}
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
+#endif /* OPENSSL_EXTRA */
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+ defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+int wolfSSL_CTX_get_tlsext_status_cb(WOLFSSL_CTX* ctx, tlsextStatusCb* cb)
+{
+ if (ctx == NULL || ctx->cm == NULL || cb == NULL)
+ return WOLFSSL_FAILURE;
+
+#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
+ if (ctx->cm->ocsp_stapling == NULL)
+ return WOLFSSL_FAILURE;
+
+ *cb = ctx->cm->ocsp_stapling->statusCb;
+#else
+ (void)cb;
+ *cb = NULL;
+#endif
+
+ return WOLFSSL_SUCCESS;
+
+}
+
+int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, tlsextStatusCb cb)
+{
+ if (ctx == NULL || ctx->cm == NULL)
+ return WOLFSSL_FAILURE;
+
+#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
+ /* Ensure stapling is on for callback to be used. */
+ wolfSSL_CTX_EnableOCSPStapling(ctx);
+
+ if (ctx->cm->ocsp_stapling == NULL)
+ return WOLFSSL_FAILURE;
+
+ ctx->cm->ocsp_stapling->statusCb = cb;
+#else
+ (void)cb;
+#endif
+
+ return WOLFSSL_SUCCESS;
+}
+
+long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg)
+{
+ if (ctx == NULL || ctx->cm == NULL)
+ return WOLFSSL_FAILURE;
+
+#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
+ /* Ensure stapling is on for callback to be used. */
+ wolfSSL_CTX_EnableOCSPStapling(ctx);
+
+ if (ctx->cm->ocsp_stapling == NULL)
+ return WOLFSSL_FAILURE;
+
+ ctx->cm->ocsp_stapling->statusCbArg = arg;
+#else
+ (void)arg;
+#endif
+
+ return WOLFSSL_SUCCESS;
+}
+
+long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *ssl, unsigned char **resp)
+{
+ if (ssl == NULL || resp == NULL)
+ return 0;
+
+ *resp = ssl->ocspCsrResp[0].buffer;
+ return (long)ssl->ocspCsrResp[0].length;
+}
+
+long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *ssl, unsigned char *resp,
+ int len)
+{
+ return wolfSSL_set_tlsext_status_ocsp_resp_multi(ssl, resp, len, 0);
+}
+
+int wolfSSL_set_tlsext_status_ocsp_resp_multi(WOLFSSL* ssl, unsigned char *resp,
+ int len, word32 idx)
+{
+ if (ssl == NULL || idx >= XELEM_CNT(ssl->ocspCsrResp) || len < 0)
+ return WOLFSSL_FAILURE;
+ if (!((resp == NULL) ^ (len > 0)))
+ return WOLFSSL_FAILURE;
+
+ XFREE(ssl->ocspCsrResp[idx].buffer, NULL, 0);
+ ssl->ocspCsrResp[idx].buffer = resp;
+ ssl->ocspCsrResp[idx].length = (word32)len;
+
+ return WOLFSSL_SUCCESS;
+}
+
+#ifndef NO_WOLFSSL_SERVER
+void wolfSSL_CTX_set_ocsp_status_verify_cb(WOLFSSL_CTX* ctx,
+ ocspVerifyStatusCb cb, void* cbArg)
+{
+ if (ctx != NULL) {
+ ctx->ocspStatusVerifyCb = cb;
+ ctx->ocspStatusVerifyCbArg = cbArg;
+ }
+}
+#endif /* NO_WOLFSSL_SERVER */
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST ||
+ * HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+
+#endif /* !NO_CERTS */
+
+#endif /* !WOLFSSL_SSL_API_CRL_OCSP_INCLUDED */
+
diff --git a/src/ssl_api_pk.c b/src/ssl_api_pk.c
new file mode 100644
index 0000000000..92bdd522c1
--- /dev/null
+++ b/src/ssl_api_pk.c
@@ -0,0 +1,1611 @@
+/* ssl_api_pk.c
+ *
+ * Copyright (C) 2006-2025 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#include
+
+#if !defined(WOLFSSL_SSL_API_PK_INCLUDED)
+ #ifndef WOLFSSL_IGNORE_FILE_WARN
+ #warning ssl_api_pk.c is not compiled separately from ssl.c
+ #endif
+#else
+
+#ifndef NO_CERTS
+
+#ifndef NO_CHECK_PRIVATE_KEY
+
+#ifdef WOLF_PRIVATE_KEY_ID
+/* Check priv against pub for match using external device with given devId
+ *
+ * @param [in] keyOID Public key OID.
+ * @param [in] privKey Private key data.
+ * @param [in] privSz Length of private key data in bytes.
+ * @param [in] pubKey Public key data.
+ * @param [in] pubSz Length of public key data in bytes.
+ * @param [in] label Key data is a hardware label.
+ * @param [in] id Key data is a hardware id.
+ * @param [in] heap Heap hint for dynamic memory allocation.
+ * @param [in] devId Device Id.
+ * @return 0 on success.
+ * @return MISSING_KEY when privKey is NULL.
+ * @return Other negative value on error.
+ */
+static int check_cert_key_dev(word32 keyOID, byte* privKey, word32 privSz,
+ const byte* pubKey, word32 pubSz, int label, int id, void* heap, int devId)
+{
+ int ret = 0;
+ int type;
+ void *pkey = NULL;
+
+ if (privKey == NULL) {
+ ret = MISSING_KEY;
+ }
+ else {
+ switch (keyOID) {
+ #ifndef NO_RSA
+ case RSAk:
+ #ifdef WC_RSA_PSS
+ case RSAPSSk:
+ #endif
+ type = DYNAMIC_TYPE_RSA;
+ break;
+ #endif
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ type = DYNAMIC_TYPE_ECC;
+ break;
+ #endif
+ #if defined(HAVE_DILITHIUM)
+ case ML_DSA_LEVEL2k:
+ case ML_DSA_LEVEL3k:
+ case ML_DSA_LEVEL5k:
+ #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
+ case DILITHIUM_LEVEL2k:
+ case DILITHIUM_LEVEL3k:
+ case DILITHIUM_LEVEL5k:
+ #endif
+ type = DYNAMIC_TYPE_DILITHIUM;
+ break;
+ #endif
+ #if defined(HAVE_FALCON)
+ case FALCON_LEVEL1k:
+ case FALCON_LEVEL5k:
+ type = DYNAMIC_TYPE_FALCON;
+ break;
+ #endif
+ default:
+ type = 0;
+ }
+
+ ret = CreateDevPrivateKey(&pkey, privKey, privSz, type, label, id, heap,
+ devId);
+ }
+#ifdef WOLF_CRYPTO_CB
+ if (ret == 0) {
+ switch (keyOID) {
+ #ifndef NO_RSA
+ case RSAk:
+ #ifdef WC_RSA_PSS
+ case RSAPSSk:
+ #endif
+ ret = wc_CryptoCb_RsaCheckPrivKey((RsaKey*)pkey, pubKey, pubSz);
+ break;
+ #endif
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ ret = wc_CryptoCb_EccCheckPrivKey((ecc_key*)pkey, pubKey,
+ pubSz);
+ break;
+ #endif
+ #if defined(HAVE_DILITHIUM)
+ case ML_DSA_LEVEL2k:
+ case ML_DSA_LEVEL3k:
+ case ML_DSA_LEVEL5k:
+ #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
+ case DILITHIUM_LEVEL2k:
+ case DILITHIUM_LEVEL3k:
+ case DILITHIUM_LEVEL5k:
+ #endif
+ ret = wc_CryptoCb_PqcSignatureCheckPrivKey(pkey,
+ WC_PQC_SIG_TYPE_DILITHIUM, pubKey, pubSz);
+ break;
+ #endif
+ #if defined(HAVE_FALCON)
+ case FALCON_LEVEL1k:
+ case FALCON_LEVEL5k:
+ ret = wc_CryptoCb_PqcSignatureCheckPrivKey(pkey,
+ WC_PQC_SIG_TYPE_FALCON, pubKey, pubSz);
+ break;
+ #endif
+ default:
+ ret = 0;
+ }
+ }
+#else
+ /* devId was set, don't check, for now */
+ /* TODO: Add callback for private key check? */
+ (void) pubKey;
+ (void) pubSz;
+#endif
+
+ switch (keyOID) {
+#ifndef NO_RSA
+ case RSAk:
+ #ifdef WC_RSA_PSS
+ case RSAPSSk:
+ #endif
+ wc_FreeRsaKey((RsaKey*)pkey);
+ break;
+#endif
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ wc_ecc_free((ecc_key*)pkey);
+ break;
+ #endif
+#if defined(HAVE_DILITHIUM)
+ case ML_DSA_LEVEL2k:
+ case ML_DSA_LEVEL3k:
+ case ML_DSA_LEVEL5k:
+ #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
+ case DILITHIUM_LEVEL2k:
+ case DILITHIUM_LEVEL3k:
+ case DILITHIUM_LEVEL5k:
+ #endif
+ wc_dilithium_free((dilithium_key*)pkey);
+ break;
+#endif
+ #if defined(HAVE_FALCON)
+ case FALCON_LEVEL1k:
+ case FALCON_LEVEL5k:
+ wc_falcon_free((falcon_key*)pkey);
+ break;
+ #endif
+ default:
+ WC_DO_NOTHING;
+ }
+ XFREE(pkey, heap, type);
+
+ return ret;
+}
+#endif /* WOLF_PRIVATE_KEY_ID */
+
+/* Check private against public in certificate for match.
+ *
+ * @param [in] cert DER encoded certificate.
+ * @param [in] key DER encoded private key.
+ * @param [in] altKey Alternative DER encoded key.
+ * @param [in] heap Heap hint for dynamic memory allocation.
+ * @param [in] devId Device Id.
+ * @param [in] isKeyLabel Whether key is label.
+ * @param [in] isKeyId Whether key is an id.
+ * @param [in] altDevId Alternative key's device id.
+ * @param [in] isAltKeyLabel Is alternative key a label.
+ * @param [in] isAltKeyId Is alternative key an id.
+ * @return 1 on success.
+ * @return 0 on failure.
+ * @return MEMORY_E when memory allocation fails.
+ */
+static int check_cert_key(const DerBuffer* cert, const DerBuffer* key,
+ const DerBuffer* altKey, void* heap, int devId, int isKeyLabel, int isKeyId,
+ int altDevId, int isAltKeyLabel, int isAltKeyId)
+{
+ WC_DECLARE_VAR(der, DecodedCert, 1, 0);
+ word32 size;
+ byte* buff;
+ int ret = 1;
+
+ WOLFSSL_ENTER("check_cert_key");
+
+ /* Validate parameters. */
+ if ((cert == NULL) || (key == NULL)) {
+ return 0;
+ }
+ if (ret == 1) {
+ /* Make a decoded certificate object available. */
+ WC_ALLOC_VAR_EX(der, DecodedCert, 1, heap, DYNAMIC_TYPE_DCERT,
+ return MEMORY_E);
+ }
+
+ if (ret == 1) {
+ /* Decode certificate. */
+ InitDecodedCert_ex(der, cert->buffer, cert->length, heap, devId);
+ /* Parse certificate. */
+ if (ParseCertRelative(der, CERT_TYPE, NO_VERIFY, NULL, NULL) != 0) {
+ WC_FREE_VAR_EX(der, heap, DYNAMIC_TYPE_DCERT);
+ ret = 0;
+ }
+ }
+
+ if (ret == 1) {
+ buff = key->buffer;
+ size = key->length;
+ #ifdef WOLF_PRIVATE_KEY_ID
+ if (devId != INVALID_DEVID) {
+ ret = check_cert_key_dev(der->keyOID, buff, size, der->publicKey,
+ der->pubKeySize, isKeyLabel, isKeyId, heap, devId);
+ if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
+ ret = (ret == 0) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE;
+ }
+ }
+ else {
+ /* fall through if unavailable */
+ ret = CRYPTOCB_UNAVAILABLE;
+ }
+
+ if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
+ #endif /* WOLF_PRIVATE_KEY_ID */
+ {
+ ret = wc_CheckPrivateKeyCert(buff, size, der, 0, heap);
+ if (ret != 1) {
+ ret = 0;
+ }
+ }
+
+ #ifdef WOLFSSL_DUAL_ALG_CERTS
+ if ((ret == 1) && der->extSapkiSet && (der->sapkiDer != NULL)) {
+ /* Certificate contains an alternative public key. Hence, we also
+ * need an alternative private key. */
+ if (altKey == NULL) {
+ ret = MISSING_KEY;
+ buff = NULL;
+ size = 0;
+ }
+ else {
+ size = altKey->length;
+ buff = altKey->buffer;
+ }
+ #ifdef WOLF_PRIVATE_KEY_ID
+ if (altDevId != INVALID_DEVID) {
+ /* We have to decode the public key first */
+ /* Default to max pub key size. */
+ word32 pubKeyLen = MAX_PUBLIC_KEY_SZ;
+ byte* decodedPubKey = (byte*)XMALLOC(pubKeyLen, heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (decodedPubKey == NULL) {
+ ret = MEMORY_E;
+ }
+ if (ret == WOLFSSL_SUCCESS) {
+ if ((der->sapkiOID == RSAk) || (der->sapkiOID == ECDSAk)) {
+ /* Simply copy the data */
+ XMEMCPY(decodedPubKey, der->sapkiDer, der->sapkiLen);
+ pubKeyLen = der->sapkiLen;
+ ret = 0;
+ }
+ else {
+ #if defined(WC_ENABLE_ASYM_KEY_IMPORT)
+ word32 idx = 0;
+ ret = DecodeAsymKeyPublic(der->sapkiDer, &idx,
+ der->sapkiLen, decodedPubKey,
+ &pubKeyLen, der->sapkiOID);
+ #else
+ ret = NOT_COMPILED_IN;
+ #endif /* WC_ENABLE_ASYM_KEY_IMPORT */
+ }
+ }
+ if (ret == 0) {
+ ret = check_cert_key_dev(der->sapkiOID, buff, size,
+ decodedPubKey, pubKeyLen, isAltKeyLabel, isAltKeyId,
+ heap, altDevId);
+ }
+ XFREE(decodedPubKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
+ ret = (ret == 0) ? 1: 0;
+ }
+ }
+ else {
+ /* fall through if unavailable */
+ ret = CRYPTOCB_UNAVAILABLE;
+ }
+
+ if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
+ #else
+ if (ret == 1)
+ #endif /* WOLF_PRIVATE_KEY_ID */
+ {
+ ret = wc_CheckPrivateKeyCert(buff, size, der, 1, heap);
+ if (ret != 1) {
+ ret = 0;
+ }
+ }
+ }
+ #endif /* WOLFSSL_DUAL_ALG_CERTS */
+ }
+
+ FreeDecodedCert(der);
+ WC_FREE_VAR_EX(der, heap, DYNAMIC_TYPE_DCERT);
+
+ (void)devId;
+ (void)isKeyLabel;
+ (void)isKeyId;
+ (void)altKey;
+ (void)altDevId;
+ (void)isAltKeyLabel;
+ (void)isAltKeyId;
+
+ return ret;
+}
+
+/* Check private against public in certificate for match
+ *
+ * @param [in] ctx SSL/TLS context with a private key and certificate.
+ *
+ * @return 1 on good private key
+ * @return 0 if mismatched.
+ */
+int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx)
+{
+ int res = 1;
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ DerBuffer *privateKey;
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+ DerBuffer *altPrivateKey;
+#endif
+#else
+ const DerBuffer *privateKey;
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+ const DerBuffer *altPrivateKey;
+#endif
+#endif
+
+ /* Validate parameter. */
+ if (ctx == NULL) {
+ res = 0;
+ }
+ else {
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ /* Unblind private keys. */
+ privateKey = wolfssl_priv_der_unblind(ctx->privateKey,
+ ctx->privateKeyMask);
+ if (privateKey == NULL) {
+ res = 0;
+ }
+ if (ctx->altPrivateKey != NULL) {
+ altPrivateKey = wolfssl_priv_der_unblind(ctx->altPrivateKey,
+ ctx->altPrivateKeyMask);
+ if (altPrivateKey == NULL) {
+ res = 0;
+ }
+ }
+ else {
+ altPrivateKey = NULL;
+ }
+ #else
+ privateKey = ctx->privateKey;
+ altPrivateKey = ctx->altPrivateKey;
+ #endif
+ if (res == 1) {
+ /* Check certificate and private keys. */
+ res = check_cert_key(ctx->certificate, privateKey, altPrivateKey,
+ ctx->heap, ctx->privateKeyDevId, ctx->privateKeyLabel,
+ ctx->privateKeyId, ctx->altPrivateKeyDevId,
+ ctx->altPrivateKeyLabel, ctx->altPrivateKeyId) != 0;
+ }
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ /* Dispose of the unblinded buffers. */
+ wolfssl_priv_der_unblind_free(privateKey);
+ wolfssl_priv_der_unblind_free(altPrivateKey);
+ #endif
+#else
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ /* Unblind private key. */
+ privateKey = wolfssl_priv_der_unblind(ctx->privateKey,
+ ctx->privateKeyMask);
+ if (privateKey == NULL) {
+ res = 0;
+ }
+ #else
+ privateKey = ctx->privateKey;
+ #endif
+ if (res == WOLFSSL_SUCCESS) {
+ /* Check certificate and private key. */
+ res = check_cert_key(ctx->certificate, privateKey, NULL, ctx->heap,
+ ctx->privateKeyDevId, ctx->privateKeyLabel, ctx->privateKeyId,
+ INVALID_DEVID, 0, 0);
+ }
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ /* Dispose of the unblinded buffer. */
+ wolfssl_priv_der_unblind_free(privateKey);
+ #endif
+#endif
+ }
+
+ /* Place error into queue for Python port. */
+ if (res != 1) {
+ WOLFSSL_ERROR(WC_KEY_MISMATCH_E);
+ }
+
+ return res;
+}
+
+#ifdef OPENSSL_EXTRA
+/* Check private against public in certificate for match.
+ *
+ * @param [in] ssl SSL/TLS object with a private key and certificate.
+ *
+ * @return 1 on good private key
+ * @return 0 if mismatched.
+ */
+int wolfSSL_check_private_key(const WOLFSSL* ssl)
+{
+ int res = 1;
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ DerBuffer *privateKey;
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+ DerBuffer *altPrivateKey;
+#endif
+#else
+ const DerBuffer *privateKey;
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+ const DerBuffer *altPrivateKey;
+#endif
+#endif
+
+ /* Validate parameter. */
+ if (ssl == NULL) {
+ res = 0;
+ }
+ else {
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ /* Unblind private keys. */
+ privateKey = wolfssl_priv_der_unblind(ssl->buffers.key,
+ ssl->buffers.keyMask);
+ if (privateKey == NULL) {
+ res = 0;
+ }
+ if (ssl->buffers.altKey != NULL) {
+ altPrivateKey = wolfssl_priv_der_unblind(ssl->buffers.altKey,
+ ssl->buffers.altKeyMask);
+ if (altPrivateKey == NULL) {
+ res = 0;
+ }
+ }
+ else {
+ altPrivateKey = NULL;
+ }
+ #else
+ privateKey = ssl->buffers.key;
+ altPrivateKey = ssl->buffers.altKey;
+ #endif
+ if (res == 1) {
+ /* Check certificate and private keys. */
+ res = check_cert_key(ssl->buffers.certificate, privateKey,
+ altPrivateKey, ssl->heap, ssl->buffers.keyDevId,
+ ssl->buffers.keyLabel, ssl->buffers.keyId,
+ ssl->buffers.altKeyDevId, ssl->buffers.altKeyLabel,
+ ssl->buffers.altKeyId);
+ }
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ /* Dispose of the unblinded buffers. */
+ wolfssl_priv_der_unblind_free(privateKey);
+ wolfssl_priv_der_unblind_free(altPrivateKey);
+ #endif
+#else
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ /* Unblind private key. */
+ privateKey = wolfssl_priv_der_unblind(ssl->buffers.key,
+ ssl->buffers.keyMask);
+ if (privateKey == NULL) {
+ res = 0;
+ }
+ #else
+ privateKey = ssl->buffers.key;
+ #endif
+ if (res == 1) {
+ /* Check certificate and private key. */
+ res = check_cert_key(ssl->buffers.certificate, privateKey, NULL,
+ ssl->heap, ssl->buffers.keyDevId, ssl->buffers.keyLabel,
+ ssl->buffers.keyId, INVALID_DEVID, 0, 0);
+ }
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ /* Dispose of the unblinded buffer. */
+ wolfssl_priv_der_unblind_free(privateKey);
+ #endif
+#endif
+ }
+
+ return res;
+}
+#endif /* OPENSSL_EXTRA */
+#endif /* !NO_CHECK_PRIVATE_KEY */
+
+
+#ifdef OPENSSL_ALL
+/**
+ * Return the private key of the SSL/TLS context.
+ *
+ * The caller doesn *NOT*` free the returned object.
+ *
+ * Note, even though the supplied ctx pointer is designated const, on success
+ * ctx->privateKeyPKey is changed by this call. The change is done safely using
+ * a hardware-synchronized store.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @return A WOFLSSL_EVP_PKEY on success.
+ * @return NULL on error.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_CTX_get0_privatekey(const WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_EVP_PKEY* res = NULL;
+ const unsigned char *key;
+ int type = WC_EVP_PKEY_NONE;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_get0_privatekey");
+
+ if ((ctx == NULL) || (ctx->privateKey == NULL) ||
+ (ctx->privateKey->buffer == NULL)) {
+ WOLFSSL_MSG("Bad parameter or key not set");
+ }
+ else {
+ switch (ctx->privateKeyType) {
+ #ifndef NO_RSA
+ case rsa_sa_algo:
+ type = WC_EVP_PKEY_RSA;
+ break;
+ #endif
+ #ifdef HAVE_ECC
+ case ecc_dsa_sa_algo:
+ type = WC_EVP_PKEY_EC;
+ break;
+ #endif
+ #ifdef WOLFSSL_SM2
+ case sm2_sa_algo:
+ type = WC_EVP_PKEY_EC;
+ break;
+ #endif
+ default:
+ /* Other key types not supported either as ssl private keys
+ * or in the EVP layer */
+ WOLFSSL_MSG("Unsupported key type");
+ }
+ }
+
+ if (type != WC_EVP_PKEY_NONE) {
+ if (ctx->privateKeyPKey != NULL) {
+ res = ctx->privateKeyPKey;
+ }
+ else {
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ DerBuffer* unblinded_privateKey = wolfssl_priv_der_unblind(
+ ctx->privateKey, ctx->privateKeyMask);
+ if (unblinded_privateKey != NULL) {
+ key = unblinded_privateKey->buffer;
+ }
+ else {
+ key = NULL;
+ }
+ #else
+ key = ctx->privateKey->buffer;
+ #endif
+ if (key != NULL) {
+ res = wolfSSL_d2i_PrivateKey(type, NULL, &key,
+ (long)ctx->privateKey->length);
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ wolfssl_priv_der_unblind_free(unblinded_privateKey);
+ #endif
+ }
+ if (res != NULL) {
+ #ifdef WOLFSSL_ATOMIC_OPS
+ WOLFSSL_EVP_PKEY *current_pkey = NULL;
+ if (!wolfSSL_Atomic_Ptr_CompareExchange(
+ (void * volatile *)&ctx->privateKeyPKey,
+ (void **)¤t_pkey, res)) {
+ wolfSSL_EVP_PKEY_free(res);
+ res = current_pkey;
+ }
+ #else
+ ((WOLFSSL_CTX *)ctx)->privateKeyPKey = res;
+ #endif
+ }
+ }
+ }
+
+ return res;
+}
+#endif /* OPENSSL_ALL */
+
+#ifdef HAVE_ECC
+
+/* Set size, in bytes, of temporary ECDHE key into SSL/TLS context.
+ *
+ * Values can be: 14 - 66 (112 - 521 bit)
+ * Uses the private key length if sz is 0.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] sz Size of EC key in bytes.
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ctx is NULL or sz is invalid.
+ */
+int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX* ctx, word16 sz)
+{
+ int ret = 0;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_SetTmpEC_DHE_Sz");
+
+ /* Validate parameters. */
+ if (ctx == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ /* If size is 0 then get value from loaded private key. */
+ else if (sz == 0) {
+ /* Applies only to ECDSA. */
+ if (ctx->privateKeyType != ecc_dsa_sa_algo) {
+ ret = 1;
+ }
+ /* Must have a key set. */
+ else if (ctx->privateKeySz == 0) {
+ WOLFSSL_MSG("Must set private key/cert first");
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ sz = (word16)ctx->privateKeySz;
+ }
+ }
+ if (ret == 0) {
+ /* Check size against bounds. */
+ #if ECC_MIN_KEY_SZ > 0
+ if (sz < ECC_MINSIZE) {
+ ret = BAD_FUNC_ARG;
+ }
+ #endif
+ else if (sz > ECC_MAXSIZE) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Store the size requested. */
+ ctx->eccTempKeySz = sz;
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
+
+
+/* Set size, in bytes, of temporary ECDHE key into SSL/TLS object.
+ *
+ * Values can be: 14 - 66 (112 - 521 bit)
+ * Uses the private key length if sz is 0.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] sz Size of EC key in bytes.
+ * @return 1 on success.
+ * @return BAD_FUNC_ARG when ssl is NULL or sz is invalid.
+ */
+int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL* ssl, word16 sz)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("wolfSSL_SetTmpEC_DHE_Sz");
+
+ /* Validate parameters. */
+ if (ssl == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ /* Check size against bounds. */
+#if ECC_MIN_KEY_SZ > 0
+ else if (sz < ECC_MINSIZE) {
+ ret = BAD_FUNC_ARG;
+ }
+#endif
+ else if (sz > ECC_MAXSIZE) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Store the size requested. */
+ ssl->eccTempKeySz = sz;
+ }
+
+ return ret;
+}
+
+#endif /* HAVE_ECC */
+
+#ifdef HAVE_PK_CALLBACKS
+
+#ifdef HAVE_ECC
+/* Set the ECC key generation callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb ECC key generation callback.
+ */
+void wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX* ctx, CallbackEccKeyGen cb)
+{
+ if (ctx != NULL) {
+ ctx->EccKeyGenCb = cb;
+ }
+}
+/* Set the context for ECC key generation callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for ECC key generation callback.
+ */
+void wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->EccKeyGenCtx = ctx;
+ }
+}
+/* Get the context for ECC key generation callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for ECC key generation callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->EccKeyGenCtx;
+ }
+
+ return ret;
+}
+/* Set the context for ECC sign callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] userCtx Context for ECC sign callback.
+ */
+void wolfSSL_CTX_SetEccSignCtx(WOLFSSL_CTX* ctx, void *userCtx)
+{
+ if (ctx != NULL) {
+ ctx->EccSignCtx = userCtx;
+ }
+}
+/* Get the context for ECC sign callback from the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @return Context for ECC sign for callback.
+ * @return NULL when ctx is NULL.
+ */
+void* wolfSSL_CTX_GetEccSignCtx(WOLFSSL_CTX* ctx)
+{
+ void* ret;
+
+ if (ctx == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ctx->EccSignCtx;
+ }
+
+ return ret;
+}
+
+/* Set the ECC sign callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb ECC sign callback.
+ */
+WOLFSSL_ABI void wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX* ctx, CallbackEccSign cb)
+{
+ if (ctx != NULL) {
+ ctx->EccSignCb = cb;
+ }
+}
+/* Set the context for ECC sign callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for ECC sign callback.
+ */
+void wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->EccSignCtx = ctx;
+ }
+}
+/* Get the context for ECC sign callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for ECC sign for callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->EccSignCtx;
+ }
+
+ return ret;
+}
+
+/* Set the ECC verify callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb ECC verify callback.
+ */
+void wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX* ctx, CallbackEccVerify cb)
+{
+ if (ctx != NULL) {
+ ctx->EccVerifyCb = cb;
+ }
+}
+/* Set the context for ECC verify callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for ECC verify callback.
+ */
+void wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->EccVerifyCtx = ctx;
+ }
+}
+/* Get the context for ECC verify callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for ECC verify for callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->EccVerifyCtx;
+ }
+
+ return ret;
+}
+
+/* Set the ECC shared secret callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb ECC shared secret callback.
+ */
+void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX* ctx,
+ CallbackEccSharedSecret cb)
+{
+ if (ctx != NULL) {
+ ctx->EccSharedSecretCb = cb;
+ }
+}
+/* Set the context for ECC shared secret callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for ECC shared secret callback.
+ */
+void wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->EccSharedSecretCtx = ctx;
+ }
+}
+/* Get the context for ECC shared secret callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for ECC shared secret callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->EccSharedSecretCtx;
+ }
+
+ return ret;
+}
+#endif /* HAVE_ECC */
+
+#ifdef HAVE_ED25519
+/* Set the Ed25519 sign callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb Ed25519 sign callback.
+ */
+void wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX* ctx, CallbackEd25519Sign cb)
+{
+ if (ctx != NULL) {
+ ctx->Ed25519SignCb = cb;
+ }
+}
+/* Set the context for Ed25519 sign callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for Ed25519 sign callback.
+ */
+void wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->Ed25519SignCtx = ctx;
+ }
+}
+/* Get the context for Ed25519 sign callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for Ed25519 sign callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->Ed25519SignCtx;
+ }
+
+ return ret;
+}
+
+/* Set the Ed25519 verify callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb Ed25519 verify callback.
+ */
+void wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX* ctx, CallbackEd25519Verify cb)
+{
+ if (ctx != NULL) {
+ ctx->Ed25519VerifyCb = cb;
+ }
+}
+/* Set the context for Ed25519 verify callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for Ed25519 verify callback.
+ */
+void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->Ed25519VerifyCtx = ctx;
+ }
+}
+/* Get the context for Ed25519 verify callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for Ed25519 verify callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->Ed25519VerifyCtx;
+ }
+
+ return ret;
+}
+#endif /* HAVE_ED25519 */
+
+#ifdef HAVE_CURVE25519
+/* Set the X25519 key generation callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb X25519 key generation callback.
+ */
+void wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX* ctx, CallbackX25519KeyGen cb)
+{
+ if (ctx != NULL) {
+ ctx->X25519KeyGenCb = cb;
+ }
+}
+/* Set the context for X25519 key generation callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for X25519 key generation callback.
+ */
+void wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->X25519KeyGenCtx = ctx;
+ }
+}
+/* Get the context for X25519 key generation callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for X25519 key generation callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->X25519KeyGenCtx;
+ }
+
+ return ret;
+}
+
+/* Set the X25519 shared secret callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb X25519 shared secret callback.
+ */
+void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX* ctx,
+ CallbackX25519SharedSecret cb)
+{
+ if (ctx != NULL) {
+ ctx->X25519SharedSecretCb = cb;
+ }
+}
+/* Set the context for X25519 shared secret callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for X25519 shared secret callback.
+ */
+void wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->X25519SharedSecretCtx = ctx;
+ }
+}
+/* Get the context for X25519 shared secret callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for X25519 shared secret callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->X25519SharedSecretCtx;
+ }
+
+ return ret;
+}
+#endif /* HAVE_CURVE25519 */
+
+#ifdef HAVE_ED448
+/* Set the Ed448 sign callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb Ed448 sign callback.
+ */
+void wolfSSL_CTX_SetEd448SignCb(WOLFSSL_CTX* ctx, CallbackEd448Sign cb)
+{
+ if (ctx != NULL) {
+ ctx->Ed448SignCb = cb;
+ }
+}
+/* Set the context for Ed448 sign callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for Ed448 sign callback.
+ */
+void wolfSSL_SetEd448SignCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->Ed448SignCtx = ctx;
+ }
+}
+/* Get the context for Ed448 sign callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for Ed448 sign callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetEd448SignCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->Ed448SignCtx;
+ }
+
+ return ret;
+}
+
+/* Set the Ed448 verify callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb Ed448 verify callback.
+ */
+void wolfSSL_CTX_SetEd448VerifyCb(WOLFSSL_CTX* ctx, CallbackEd448Verify cb)
+{
+ if (ctx != NULL) {
+ ctx->Ed448VerifyCb = cb;
+ }
+}
+/* Set the context for Ed448 verify callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for Ed448 verify callback.
+ */
+void wolfSSL_SetEd448VerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->Ed448VerifyCtx = ctx;
+ }
+}
+/* Get the context for Ed448 verify callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for Ed448 verify callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetEd448VerifyCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->Ed448VerifyCtx;
+ }
+
+ return ret;
+}
+#endif /* HAVE_ED448 */
+
+#ifdef HAVE_CURVE448
+/* Set the X448 key generation callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb X448 key generation callback.
+ */
+void wolfSSL_CTX_SetX448KeyGenCb(WOLFSSL_CTX* ctx,
+ CallbackX448KeyGen cb)
+{
+ if (ctx != NULL) {
+ ctx->X448KeyGenCb = cb;
+ }
+}
+/* Set the context for X448 key generation callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for X448 key generation callback.
+ */
+void wolfSSL_SetX448KeyGenCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->X448KeyGenCtx = ctx;
+ }
+}
+/* Get the context for X448 key generation callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for X448 key generation callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetX448KeyGenCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->X448KeyGenCtx;
+ }
+
+ return ret;
+}
+
+/* Set the X448 shared secret callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb X448 shared secret callback.
+ */
+void wolfSSL_CTX_SetX448SharedSecretCb(WOLFSSL_CTX* ctx,
+ CallbackX448SharedSecret cb)
+{
+ if (ctx != NULL) {
+ ctx->X448SharedSecretCb = cb;
+ }
+}
+/* Set the context for X448 shared secret callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for X448 shared secret callback.
+ */
+void wolfSSL_SetX448SharedSecretCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->X448SharedSecretCtx = ctx;
+ }
+}
+/* Get the context for X448 shared secret callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for X448 shared secret callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetX448SharedSecretCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->X448SharedSecretCtx;
+ }
+
+ return ret;
+}
+#endif /* HAVE_CURVE448 */
+
+#ifndef NO_RSA
+/* Set the RSA sign callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb RSA sign callback.
+ */
+void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb)
+{
+ if (ctx != NULL) {
+ ctx->RsaSignCb = cb;
+ }
+}
+/* Set the RSA sign check callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb RSA sign check callback.
+ */
+void wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb)
+{
+ if (ctx != NULL) {
+ ctx->RsaSignCheckCb = cb;
+ }
+}
+/* Set the context for RSA sign callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for RSA sign callback.
+ */
+void wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->RsaSignCtx = ctx;
+ }
+}
+/* Get the context for RSA sign callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for RSA sign callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->RsaSignCtx;
+ }
+
+ return ret;
+}
+
+/* Set the RSA verify callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb RSA verify callback.
+ */
+void wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb)
+{
+ if (ctx != NULL) {
+ ctx->RsaVerifyCb = cb;
+ }
+}
+/* Set the context for RSA verify callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for RSA verify callback.
+ */
+void wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->RsaVerifyCtx = ctx;
+ }
+}
+/* Get the context for RSA verify callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for RSA verify callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->RsaVerifyCtx;
+ }
+
+ return ret;
+}
+
+#ifdef WC_RSA_PSS
+/* Set the RSA PSS sign callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb RSA PSS sign callback.
+ */
+void wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX* ctx, CallbackRsaPssSign cb)
+{
+ if (ctx != NULL) {
+ ctx->RsaPssSignCb = cb;
+ }
+}
+/* Set the RSA PSS sign check callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb RSA PSS sign check callback.
+ */
+void wolfSSL_CTX_SetRsaPssSignCheckCb(WOLFSSL_CTX* ctx,
+ CallbackRsaPssVerify cb)
+{
+ if (ctx != NULL) {
+ ctx->RsaPssSignCheckCb = cb;
+ }
+}
+/* Set the context for RSA PSS sign callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for RSA PSS sign callback.
+ */
+void wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->RsaPssSignCtx = ctx;
+ }
+}
+/* Get the context for RSA PSS sign callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for RSA PSS sign callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->RsaPssSignCtx;
+ }
+
+ return ret;
+}
+
+/* Set the RSA PSS verify callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb RSA PSS verify callback.
+ */
+void wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb)
+{
+ if (ctx != NULL) {
+ ctx->RsaPssVerifyCb = cb;
+ }
+}
+/* Set the context for RSA PSS verify callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for RSA PSS verify callback.
+ */
+void wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->RsaPssVerifyCtx = ctx;
+ }
+}
+/* Get the context for RSA PSS verify callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for RSA PSS verify callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->RsaPssVerifyCtx;
+ }
+
+ return ret;
+}
+#endif /* WC_RSA_PSS */
+
+/* Set the RSA encrypt callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb RSA encrypt callback.
+ */
+void wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX* ctx, CallbackRsaEnc cb)
+{
+ if (ctx != NULL) {
+ ctx->RsaEncCb = cb;
+ }
+}
+/* Set the context for RSA encrypt callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for RSA encrypt callback.
+ */
+void wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->RsaEncCtx = ctx;
+ }
+}
+/* Get the context for RSA encrypt callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for RSA encrypt callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->RsaEncCtx;
+ }
+
+ return ret;
+}
+
+/* Set the RSA decrypt callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb RSA decrypt callback.
+ */
+void wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX* ctx, CallbackRsaDec cb)
+{
+ if (ctx != NULL) {
+ ctx->RsaDecCb = cb;
+ }
+}
+/* Set the context for RSA decrypt callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for RSA decrypt callback.
+ */
+void wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->RsaDecCtx = ctx;
+ }
+}
+/* Get the context for RSA decrypt callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for RSA decrypt callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->RsaDecCtx;
+ }
+
+ return ret;
+}
+#endif /* NO_RSA */
+
+#endif /* HAVE_PK_CALLBACKS */
+
+#endif /* !NO_CERTS */
+
+#if defined(HAVE_PK_CALLBACKS) && !defined(NO_DH)
+/* Set the DH key pair generation callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb DH key pair generation callback.
+ */
+void wolfSSL_CTX_SetDhGenerateKeyPair(WOLFSSL_CTX* ctx,
+ CallbackDhGenerateKeyPair cb)
+{
+ if (ctx != NULL) {
+ ctx->DhGenerateKeyPairCb = cb;
+ }
+}
+/* Set the DH key agree callback into the SSL/TLS context.
+ *
+ * @param [in] ctx SSL/TLS context.
+ * @param [in] cb DH key agree callback.
+ */
+void wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX* ctx, CallbackDhAgree cb)
+{
+ if (ctx != NULL) {
+ ctx->DhAgreeCb = cb;
+ }
+}
+/* Set the context for DH key agree callback into the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @param [in] ctx Context for DH key agree callback.
+ */
+void wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl != NULL) {
+ ssl->DhAgreeCtx = ctx;
+ }
+}
+/* Get the context for DH key ageww callback from the SSL/TLS object.
+ *
+ * @param [in] ssl SSL/TLS object.
+ * @return Context for DH key agree callback.
+ * @return NULL when ssl is NULL.
+ */
+void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl)
+{
+ void* ret;
+
+ if (ssl == NULL) {
+ ret = NULL;
+ }
+ else {
+ ret = ssl->DhAgreeCtx;
+ }
+
+ return ret;
+}
+#endif /* HAVE_PK_CALLBACKS && !NO_DH */
+
+#endif /* !WOLFSSL_SSL_API_PK_INCLUDED */
diff --git a/src/ssl_asn1.c b/src/ssl_asn1.c
index 2fe3cab470..e9c43ca53e 100644
--- a/src/ssl_asn1.c
+++ b/src/ssl_asn1.c
@@ -3334,7 +3334,8 @@ const char* wolfSSL_ASN1_tag2str(int tag)
const char* str = "(unknown)";
/* Clear negative flag. */
- if ((tag == WOLFSSL_V_ASN1_NEG_INTEGER) || (tag == WOLFSSL_V_ASN1_NEG_ENUMERATED)) {
+ if ((tag == WOLFSSL_V_ASN1_NEG_INTEGER) ||
+ (tag == WOLFSSL_V_ASN1_NEG_ENUMERATED)) {
tag &= ~WOLFSSL_V_ASN1_NEG;
}
/* Check for known basic types. */
@@ -4194,7 +4195,8 @@ char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, char* buf, int len)
}
/* Get time as human readable string. */
- if ((buf != NULL) && !GetTimeString(t->data, t->type, buf, len, t->length)) {
+ if ((buf != NULL) && !GetTimeString(t->data, t->type, buf, len,
+ t->length)) {
buf = NULL;
}
@@ -4717,9 +4719,11 @@ void wolfSSL_ASN1_TYPE_set(WOLFSSL_ASN1_TYPE *a, int type, void *value)
int wolfSSL_ASN1_TYPE_get(const WOLFSSL_ASN1_TYPE *a)
{
- if (a != NULL && (a->type == WOLFSSL_V_ASN1_BOOLEAN || a->type == WOLFSSL_V_ASN1_NULL
- || a->value.ptr != NULL))
+ if (a != NULL && (a->type == WOLFSSL_V_ASN1_BOOLEAN ||
+ a->type == WOLFSSL_V_ASN1_NULL ||
+ a->value.ptr != NULL)) {
return a->type;
+ }
return 0;
}
diff --git a/src/ssl_certman.c b/src/ssl_certman.c
index 2fbab23fc4..5073ba044c 100644
--- a/src/ssl_certman.c
+++ b/src/ssl_certman.c
@@ -25,7 +25,7 @@
#if !defined(WOLFSSL_SSL_CERTMAN_INCLUDED)
#ifndef WOLFSSL_IGNORE_FILE_WARN
- #warning ssl_certman.c does not need to be compiled separately from ssl.c
+ #warning ssl_certman.c not to be compiled separately from ssl.c
#endif
#else
@@ -2142,8 +2142,8 @@ int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options)
/* Initialize the OCSP object. */
if (InitOCSP(cm->ocsp, cm) != 0) {
WOLFSSL_MSG("Init OCSP failed");
- /* Dispose of OCSP object - indicating dynamically allocated.
- */
+ /* Dispose of OCSP object - indicating dynamically
+ * allocated. */
FreeOCSP(cm->ocsp, 1);
cm->ocsp = NULL;
ret = 0;
@@ -2533,6 +2533,821 @@ int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER* cm, CbOCSPIO ioCb,
#endif /* HAVE_OCSP */
+/******************************************************************************
+ * Internal APIs that use WOLFSSL_CERT_MANAGER
+ ******************************************************************************/
+
+/* hash is the SHA digest of name, just use first 32 bits as hash */
+static WC_INLINE word32 HashSigner(const byte* hash)
+{
+ return MakeWordFromHash(hash) % CA_TABLE_SIZE;
+}
+
+
+/* does CA already exist on signer list */
+int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash)
+{
+ Signer* signers;
+ int ret = 0;
+ word32 row;
+
+ if (cm == NULL || hash == NULL) {
+ return ret;
+ }
+
+ row = HashSigner(hash);
+
+ if (wc_LockMutex(&cm->caLock) != 0) {
+ return ret;
+ }
+ signers = cm->caTable[row];
+ while (signers) {
+ byte* subjectHash;
+
+ #ifndef NO_SKID
+ subjectHash = signers->subjectKeyIdHash;
+ #else
+ subjectHash = signers->subjectNameHash;
+ #endif
+
+ if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
+ ret = 1; /* success */
+ break;
+ }
+ signers = signers->next;
+ }
+ wc_UnLockMutex(&cm->caLock);
+
+ return ret;
+}
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* hash is the SHA digest of name, just use first 32 bits as hash */
+static WC_INLINE word32 TrustedPeerHashSigner(const byte* hash)
+{
+ return MakeWordFromHash(hash) % TP_TABLE_SIZE;
+}
+
+/* does trusted peer already exist on signer list */
+int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DecodedCert* cert)
+{
+ TrustedPeerCert* tp;
+ int ret = 0;
+ word32 row = TrustedPeerHashSigner(cert->subjectHash);
+
+ if (wc_LockMutex(&cm->tpLock) != 0)
+ return ret;
+ tp = cm->tpTable[row];
+ while (tp) {
+ if ((XMEMCMP(cert->subjectHash, tp->subjectNameHash,
+ SIGNER_DIGEST_SIZE) == 0)
+ #ifndef WOLFSSL_NO_ISSUERHASH_TDPEER
+ && (XMEMCMP(cert->issuerHash, tp->issuerHash,
+ SIGNER_DIGEST_SIZE) == 0)
+ #endif
+ )
+ ret = 1;
+ #ifndef NO_SKID
+ if (cert->extSubjKeyIdSet) {
+ /* Compare SKID as well if available */
+ if (ret == 1 && XMEMCMP(cert->extSubjKeyId, tp->subjectKeyIdHash,
+ SIGNER_DIGEST_SIZE) != 0)
+ ret = 0;
+ }
+ #endif
+ if (ret == 1)
+ break;
+ tp = tp->next;
+ }
+ wc_UnLockMutex(&cm->tpLock);
+
+ return ret;
+}
+
+/* return Trusted Peer if found, otherwise NULL
+ type is what to match on
+ */
+TrustedPeerCert* GetTrustedPeer(void* vp, DecodedCert* cert)
+{
+ WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
+ TrustedPeerCert* ret = NULL;
+ TrustedPeerCert* tp = NULL;
+ word32 row;
+
+ if (cm == NULL || cert == NULL)
+ return NULL;
+
+ row = TrustedPeerHashSigner(cert->subjectHash);
+
+ if (wc_LockMutex(&cm->tpLock) != 0)
+ return ret;
+
+ tp = cm->tpTable[row];
+ while (tp) {
+ if ((XMEMCMP(cert->subjectHash, tp->subjectNameHash,
+ SIGNER_DIGEST_SIZE) == 0)
+ #ifndef WOLFSSL_NO_ISSUERHASH_TDPEER
+ && (XMEMCMP(cert->issuerHash, tp->issuerHash,
+ SIGNER_DIGEST_SIZE) == 0)
+ #endif
+ )
+ ret = tp;
+ #ifndef NO_SKID
+ if (cert->extSubjKeyIdSet) {
+ /* Compare SKID as well if available */
+ if (ret != NULL && XMEMCMP(cert->extSubjKeyId, tp->subjectKeyIdHash,
+ SIGNER_DIGEST_SIZE) != 0)
+ ret = NULL;
+ }
+ #endif
+ if (ret != NULL)
+ break;
+ tp = tp->next;
+ }
+ wc_UnLockMutex(&cm->tpLock);
+
+ return ret;
+}
+
+
+int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert)
+{
+ if (tp == NULL || cert == NULL)
+ return BAD_FUNC_ARG;
+
+ /* subject key id or subject hash has been compared when searching
+ tpTable for the cert from function GetTrustedPeer */
+
+ /* compare signatures */
+ if (tp->sigLen == cert->sigLength) {
+ if (XMEMCMP(tp->sig, cert->signature, cert->sigLength)) {
+ return WOLFSSL_FAILURE;
+ }
+ }
+ else {
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+/* return CA if found, otherwise NULL */
+Signer* GetCA(void* vp, byte* hash)
+{
+ WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
+ Signer* ret = NULL;
+ Signer* signers;
+ word32 row = 0;
+
+ if (cm == NULL || hash == NULL)
+ return NULL;
+
+ row = HashSigner(hash);
+
+ if (wc_LockMutex(&cm->caLock) != 0)
+ return ret;
+
+ signers = cm->caTable[row];
+ while (signers) {
+ byte* subjectHash;
+ #ifndef NO_SKID
+ subjectHash = signers->subjectKeyIdHash;
+ #else
+ subjectHash = signers->subjectNameHash;
+ #endif
+ if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
+ ret = signers;
+ break;
+ }
+ signers = signers->next;
+ }
+ wc_UnLockMutex(&cm->caLock);
+
+ return ret;
+}
+
+#if defined(HAVE_OCSP)
+Signer* GetCAByKeyHash(void* vp, const byte* keyHash)
+{
+ WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
+ Signer* ret = NULL;
+ Signer* signers;
+ int row;
+
+ if (cm == NULL || keyHash == NULL)
+ return NULL;
+
+ /* try lookup using keyHash as subjKeyID first */
+ ret = GetCA(vp, (byte*)keyHash);
+ if (ret != NULL && XMEMCMP(ret->subjectKeyHash, keyHash, KEYID_SIZE) == 0) {
+ return ret;
+ }
+
+ /* if we can't find the cert, we have to scan the full table */
+ if (wc_LockMutex(&cm->caLock) != 0)
+ return NULL;
+
+ /* Unfortunately we need to look through the entire table */
+ for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
+ for (signers = cm->caTable[row]; signers != NULL;
+ signers = signers->next) {
+ if (XMEMCMP(signers->subjectKeyHash, keyHash, KEYID_SIZE) == 0) {
+ ret = signers;
+ break;
+ }
+ }
+ }
+
+ wc_UnLockMutex(&cm->caLock);
+ return ret;
+}
+#endif
+#ifdef WOLFSSL_AKID_NAME
+Signer* GetCAByAKID(void* vp, const byte* issuer, word32 issuerSz,
+ const byte* serial, word32 serialSz)
+{
+ WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
+ Signer* ret = NULL;
+ Signer* signers;
+ byte nameHash[SIGNER_DIGEST_SIZE];
+ byte serialHash[SIGNER_DIGEST_SIZE];
+ word32 row;
+
+ if (cm == NULL || issuer == NULL || issuerSz == 0 ||
+ serial == NULL || serialSz == 0)
+ return NULL;
+
+ if (CalcHashId(issuer, issuerSz, nameHash) != 0 ||
+ CalcHashId(serial, serialSz, serialHash) != 0)
+ return NULL;
+
+ if (wc_LockMutex(&cm->caLock) != 0)
+ return ret;
+
+ /* Unfortunately we need to look through the entire table */
+ for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
+ for (signers = cm->caTable[row]; signers != NULL;
+ signers = signers->next) {
+ if (XMEMCMP(signers->issuerNameHash, nameHash, SIGNER_DIGEST_SIZE)
+ == 0 && XMEMCMP(signers->serialHash, serialHash,
+ SIGNER_DIGEST_SIZE) == 0) {
+ ret = signers;
+ break;
+ }
+ }
+ }
+
+ wc_UnLockMutex(&cm->caLock);
+
+ return ret;
+}
+#endif
+
+#ifndef NO_SKID
+/* return CA if found, otherwise NULL. Walk through hash table. */
+Signer* GetCAByName(void* vp, byte* hash)
+{
+ WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
+ Signer* ret = NULL;
+ Signer* signers;
+ word32 row;
+
+ if (cm == NULL)
+ return NULL;
+
+ if (wc_LockMutex(&cm->caLock) != 0)
+ return ret;
+
+ for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
+ signers = cm->caTable[row];
+ while (signers && ret == NULL) {
+ if (XMEMCMP(hash, signers->subjectNameHash,
+ SIGNER_DIGEST_SIZE) == 0) {
+ ret = signers;
+ }
+ signers = signers->next;
+ }
+ }
+ wc_UnLockMutex(&cm->caLock);
+
+ return ret;
+}
+#endif
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* add a trusted peer cert to linked list */
+int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify)
+{
+ int ret = 0;
+ int row = 0;
+ TrustedPeerCert* peerCert;
+ DecodedCert* cert;
+ DerBuffer* der = *pDer;
+
+ WOLFSSL_MSG("Adding a Trusted Peer Cert");
+
+ cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
+ DYNAMIC_TYPE_DCERT);
+ if (cert == NULL) {
+ FreeDer(&der);
+ return MEMORY_E;
+ }
+
+ InitDecodedCert(cert, der->buffer, der->length, cm->heap);
+ if ((ret = ParseCert(cert, TRUSTED_PEER_TYPE, verify, cm)) != 0) {
+ FreeDecodedCert(cert);
+ XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+ FreeDer(&der);
+ return ret;
+ }
+ WOLFSSL_MSG("\tParsed new trusted peer cert");
+
+ peerCert = (TrustedPeerCert*)XMALLOC(sizeof(TrustedPeerCert), cm->heap,
+ DYNAMIC_TYPE_CERT);
+ if (peerCert == NULL) {
+ FreeDecodedCert(cert);
+ XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+ FreeDer(&der);
+ return MEMORY_E;
+ }
+ XMEMSET(peerCert, 0, sizeof(TrustedPeerCert));
+
+ #ifndef IGNORE_NAME_CONSTRAINTS
+ if (peerCert->permittedNames)
+ FreeNameSubtrees(peerCert->permittedNames, cm->heap);
+ if (peerCert->excludedNames)
+ FreeNameSubtrees(peerCert->excludedNames, cm->heap);
+ #endif
+
+ if (AlreadyTrustedPeer(cm, cert)) {
+ WOLFSSL_MSG("\tAlready have this CA, not adding again");
+ FreeTrustedPeer(peerCert, cm->heap);
+ (void)ret;
+ }
+ else {
+ /* add trusted peer signature */
+ peerCert->sigLen = cert->sigLength;
+ peerCert->sig = (byte *)XMALLOC(cert->sigLength, cm->heap,
+ DYNAMIC_TYPE_SIGNATURE);
+ if (peerCert->sig == NULL) {
+ FreeDecodedCert(cert);
+ XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+ FreeTrustedPeer(peerCert, cm->heap);
+ FreeDer(&der);
+ return MEMORY_E;
+ }
+ XMEMCPY(peerCert->sig, cert->signature, cert->sigLength);
+
+ /* add trusted peer name */
+ peerCert->nameLen = cert->subjectCNLen;
+ peerCert->name = cert->subjectCN;
+ #ifndef IGNORE_NAME_CONSTRAINTS
+ peerCert->permittedNames = cert->permittedNames;
+ peerCert->excludedNames = cert->excludedNames;
+ #endif
+
+ /* add SKID when available and hash of name */
+ #ifndef NO_SKID
+ XMEMCPY(peerCert->subjectKeyIdHash, cert->extSubjKeyId,
+ SIGNER_DIGEST_SIZE);
+ #endif
+ XMEMCPY(peerCert->subjectNameHash, cert->subjectHash,
+ SIGNER_DIGEST_SIZE);
+ #ifndef WOLFSSL_NO_ISSUERHASH_TDPEER
+ XMEMCPY(peerCert->issuerHash, cert->issuerHash,
+ SIGNER_DIGEST_SIZE);
+ #endif
+ /* If Key Usage not set, all uses valid. */
+ peerCert->next = NULL;
+ cert->subjectCN = 0;
+ #ifndef IGNORE_NAME_CONSTRAINTS
+ cert->permittedNames = NULL;
+ cert->excludedNames = NULL;
+ #endif
+
+ row = (int)TrustedPeerHashSigner(peerCert->subjectNameHash);
+
+ if (wc_LockMutex(&cm->tpLock) == 0) {
+ peerCert->next = cm->tpTable[row];
+ cm->tpTable[row] = peerCert; /* takes ownership */
+ wc_UnLockMutex(&cm->tpLock);
+ }
+ else {
+ WOLFSSL_MSG("\tTrusted Peer Cert Mutex Lock failed");
+ FreeDecodedCert(cert);
+ XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+ FreeTrustedPeer(peerCert, cm->heap);
+ FreeDer(&der);
+ return BAD_MUTEX_E;
+ }
+ }
+
+ WOLFSSL_MSG("\tFreeing parsed trusted peer cert");
+ FreeDecodedCert(cert);
+ XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
+ WOLFSSL_MSG("\tFreeing der trusted peer cert");
+ FreeDer(&der);
+ WOLFSSL_MSG("\t\tOK Freeing der trusted peer cert");
+ WOLFSSL_LEAVE("AddTrustedPeer", ret);
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+
+int AddSigner(WOLFSSL_CERT_MANAGER* cm, Signer *s)
+{
+ byte* subjectHash;
+ Signer* signers;
+ word32 row;
+
+ if (cm == NULL || s == NULL)
+ return BAD_FUNC_ARG;
+
+#ifndef NO_SKID
+ subjectHash = s->subjectKeyIdHash;
+#else
+ subjectHash = s->subjectNameHash;
+#endif
+
+ if (AlreadySigner(cm, subjectHash)) {
+ FreeSigner(s, cm->heap);
+ return 0;
+ }
+
+ row = HashSigner(subjectHash);
+
+ if (wc_LockMutex(&cm->caLock) != 0)
+ return BAD_MUTEX_E;
+
+ signers = cm->caTable[row];
+ s->next = signers;
+ cm->caTable[row] = s;
+
+ wc_UnLockMutex(&cm->caLock);
+ return 0;
+}
+
+/* owns der, internal now uses too */
+/* type flag ids from user or from chain received during verify
+ don't allow chain ones to be added w/o isCA extension */
+int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
+{
+ int ret;
+ Signer* signer = NULL;
+ word32 row;
+ byte* subjectHash;
+ WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
+ DerBuffer* der = *pDer;
+
+ WOLFSSL_MSG_CERT_LOG("Adding a CA");
+
+ if (cm == NULL) {
+ FreeDer(pDer);
+ return BAD_FUNC_ARG;
+ }
+
+ #ifdef WOLFSSL_SMALL_STACK
+ cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
+ if (cert == NULL) {
+ FreeDer(pDer);
+ return MEMORY_E;
+ }
+ #endif
+
+ InitDecodedCert(cert, der->buffer, der->length, cm->heap);
+
+#ifdef WC_ASN_UNKNOWN_EXT_CB
+ if (cm->unknownExtCallback != NULL) {
+ wc_SetUnknownExtCallback(cert, cm->unknownExtCallback);
+ }
+#endif
+
+ WOLFSSL_MSG_CERT("\tParsing new CA");
+ ret = ParseCert(cert, CA_TYPE, verify, cm);
+
+ WOLFSSL_MSG("\tParsed new CA");
+#ifdef WOLFSSL_DEBUG_CERTS
+ {
+ const char* err_msg;
+ if (ret == 0) {
+ WOLFSSL_MSG_CERT_EX(WOLFSSL_MSG_CERT_INDENT "issuer: '%s'",
+ cert->issuer);
+ WOLFSSL_MSG_CERT_EX(WOLFSSL_MSG_CERT_INDENT "subject: '%s'",
+ cert->subject);
+ }
+ else {
+ WOLFSSL_MSG_CERT(
+ WOLFSSL_MSG_CERT_INDENT "Failed during parse of new CA");
+ err_msg = wc_GetErrorString(ret);
+ WOLFSSL_MSG_CERT_EX(WOLFSSL_MSG_CERT_INDENT "error ret: %d; %s",
+ ret, err_msg);
+ }
+ }
+#endif /* WOLFSSL_DEBUG_CERTS */
+
+#ifndef NO_SKID
+ subjectHash = cert->extSubjKeyId;
+#else
+ subjectHash = cert->subjectHash;
+#endif
+
+ /* check CA key size */
+ if (verify && (ret == 0 )) {
+ switch (cert->keyOID) {
+ #ifndef NO_RSA
+ #ifdef WC_RSA_PSS
+ case RSAPSSk:
+ #endif
+ case RSAk:
+ if (cm->minRsaKeySz < 0 ||
+ cert->pubKeySize < (word16)cm->minRsaKeySz) {
+ ret = RSA_KEY_SIZE_E;
+ WOLFSSL_MSG_CERT_LOG("\tCA RSA key size error");
+ WOLFSSL_MSG_CERT_EX("\tCA RSA pubKeySize = %d; "
+ "minRsaKeySz = %d",
+ cert->pubKeySize, cm->minRsaKeySz);
+ }
+ break;
+ #endif /* !NO_RSA */
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ if (cm->minEccKeySz < 0 ||
+ cert->pubKeySize < (word16)cm->minEccKeySz) {
+ ret = ECC_KEY_SIZE_E;
+ WOLFSSL_MSG_CERT_LOG("\tCA ECC key size error");
+ WOLFSSL_MSG_CERT_EX("\tCA ECC pubKeySize = %d; "
+ "minEccKeySz = %d",
+ cert->pubKeySize, cm->minEccKeySz);
+ }
+ break;
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ if (cm->minEccKeySz < 0 ||
+ ED25519_KEY_SIZE < (word16)cm->minEccKeySz) {
+ ret = ECC_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA ECC key size error");
+ }
+ break;
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_ED448
+ case ED448k:
+ if (cm->minEccKeySz < 0 ||
+ ED448_KEY_SIZE < (word16)cm->minEccKeySz) {
+ ret = ECC_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA ECC key size error");
+ }
+ break;
+ #endif /* HAVE_ED448 */
+ #if defined(HAVE_FALCON)
+ case FALCON_LEVEL1k:
+ if (cm->minFalconKeySz < 0 ||
+ FALCON_LEVEL1_KEY_SIZE < (word16)cm->minFalconKeySz) {
+ ret = FALCON_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA Falcon level 1 key size error");
+ }
+ break;
+ case FALCON_LEVEL5k:
+ if (cm->minFalconKeySz < 0 ||
+ FALCON_LEVEL5_KEY_SIZE < (word16)cm->minFalconKeySz) {
+ ret = FALCON_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA Falcon level 5 key size error");
+ }
+ break;
+ #endif /* HAVE_FALCON */
+ #if defined(HAVE_DILITHIUM)
+ #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
+ case DILITHIUM_LEVEL2k:
+ if (cm->minDilithiumKeySz < 0 ||
+ DILITHIUM_LEVEL2_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
+ ret = DILITHIUM_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA Dilithium level 2 key size error");
+ }
+ break;
+ case DILITHIUM_LEVEL3k:
+ if (cm->minDilithiumKeySz < 0 ||
+ DILITHIUM_LEVEL3_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
+ ret = DILITHIUM_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA Dilithium level 3 key size error");
+ }
+ break;
+ case DILITHIUM_LEVEL5k:
+ if (cm->minDilithiumKeySz < 0 ||
+ DILITHIUM_LEVEL5_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
+ ret = DILITHIUM_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA Dilithium level 5 key size error");
+ }
+ break;
+ #endif /* WOLFSSL_DILITHIUM_FIPS204_DRAFT */
+ case ML_DSA_LEVEL2k:
+ if (cm->minDilithiumKeySz < 0 ||
+ ML_DSA_LEVEL2_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
+ ret = DILITHIUM_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA Dilithium level 2 key size error");
+ }
+ break;
+ case ML_DSA_LEVEL3k:
+ if (cm->minDilithiumKeySz < 0 ||
+ ML_DSA_LEVEL3_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
+ ret = DILITHIUM_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA Dilithium level 3 key size error");
+ }
+ break;
+ case ML_DSA_LEVEL5k:
+ if (cm->minDilithiumKeySz < 0 ||
+ ML_DSA_LEVEL5_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
+ ret = DILITHIUM_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA Dilithium level 5 key size error");
+ }
+ break;
+ #endif /* HAVE_DILITHIUM */
+
+ default:
+ WOLFSSL_MSG("\tNo key size check done on CA");
+ break; /* no size check if key type is not in switch */
+ }
+ }
+
+ if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA &&
+ type != WOLFSSL_TEMP_CA) {
+ WOLFSSL_MSG("\tCan't add as CA if not actually one");
+ ret = NOT_CA_ERROR;
+ }
+#ifndef ALLOW_INVALID_CERTSIGN
+ else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA &&
+ type != WOLFSSL_TEMP_CA && !cert->selfSigned &&
+ (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) {
+ /* Intermediate CA certs are required to have the keyCertSign
+ * extension set. User loaded root certs are not. */
+ WOLFSSL_MSG("\tDoesn't have key usage certificate signing");
+ ret = NOT_CA_ERROR;
+ }
+#endif
+ else if (ret == 0 && AlreadySigner(cm, subjectHash)) {
+ WOLFSSL_MSG("\tAlready have this CA, not adding again");
+ (void)ret;
+ }
+ else if (ret == 0) {
+ /* take over signer parts */
+ signer = MakeSigner(cm->heap);
+ if (!signer)
+ ret = MEMORY_ERROR;
+ }
+ if (ret == 0 && signer != NULL) {
+ ret = FillSigner(signer, cert, type, der);
+
+ if (ret == 0){
+ #ifndef NO_SKID
+ row = HashSigner(signer->subjectKeyIdHash);
+ #else
+ row = HashSigner(signer->subjectNameHash);
+ #endif
+ }
+
+ #if defined(WOLFSSL_RENESAS_TSIP_TLS) || defined(WOLFSSL_RENESAS_FSPSM_TLS)
+ /* Verify CA by TSIP so that generated tsip key is going to */
+ /* be able to be used for peer's cert verification */
+ /* TSIP is only able to handle USER CA, and only one CA. */
+ /* Therefore, it doesn't need to call TSIP again if there is already */
+ /* verified CA. */
+ if ( ret == 0 && signer != NULL ) {
+ signer->cm_idx = row;
+ if (type == WOLFSSL_USER_CA) {
+ if ((ret = wc_Renesas_cmn_RootCertVerify(cert->source,
+ cert->maxIdx,
+ cert->sigCtx.CertAtt.pubkey_n_start,
+ cert->sigCtx.CertAtt.pubkey_n_len - 1,
+ cert->sigCtx.CertAtt.pubkey_e_start,
+ cert->sigCtx.CertAtt.pubkey_e_len - 1,
+ row/* cm index */))
+ < 0)
+ WOLFSSL_MSG("Renesas_RootCertVerify() failed");
+ else
+ WOLFSSL_MSG("Renesas_RootCertVerify() succeed or skipped");
+ }
+ }
+ #endif /* TSIP or SCE */
+
+ if (ret == 0 && wc_LockMutex(&cm->caLock) == 0) {
+ signer->next = cm->caTable[row];
+ cm->caTable[row] = signer; /* takes ownership */
+ wc_UnLockMutex(&cm->caLock);
+ if (cm->caCacheCallback)
+ cm->caCacheCallback(der->buffer, (int)der->length, type);
+ }
+ else {
+ WOLFSSL_MSG("\tCA Mutex Lock failed");
+ ret = BAD_MUTEX_E;
+ }
+ }
+
+ WOLFSSL_MSG("\tFreeing Parsed CA");
+ FreeDecodedCert(cert);
+ if (ret != 0 && signer != NULL)
+ FreeSigner(signer, cm->heap);
+ WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
+ WOLFSSL_MSG("\tFreeing der CA");
+ FreeDer(pDer);
+ WOLFSSL_MSG("\t\tOK Freeing der CA");
+
+ WOLFSSL_LEAVE("AddCA", ret);
+
+ return ret == 0 ? WOLFSSL_SUCCESS : ret;
+}
+
+/* Removes the CA with the passed in subject hash from the
+ cert manager's CA cert store. */
+int RemoveCA(WOLFSSL_CERT_MANAGER* cm, byte* hash, int type)
+{
+ Signer* current;
+ Signer** prev;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
+ word32 row;
+
+ WOLFSSL_MSG("Removing a CA");
+
+ if (cm == NULL || hash == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ row = HashSigner(hash);
+
+ if (wc_LockMutex(&cm->caLock) != 0) {
+ return BAD_MUTEX_E;
+ }
+ current = cm->caTable[row];
+ prev = &cm->caTable[row];
+ while (current) {
+ byte* subjectHash;
+
+ #ifndef NO_SKID
+ subjectHash = current->subjectKeyIdHash;
+ #else
+ subjectHash = current->subjectNameHash;
+ #endif
+
+ if ((current->type == type) &&
+ (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0)) {
+ *prev = current->next;
+ FreeSigner(current, cm->heap);
+ ret = WOLFSSL_SUCCESS;
+ break;
+ }
+ prev = ¤t->next;
+ current = current->next;
+ }
+ wc_UnLockMutex(&cm->caLock);
+
+ WOLFSSL_LEAVE("RemoveCA", ret);
+
+ return ret;
+}
+
+/* Sets the CA with the passed in subject hash
+ to the provided type. */
+int SetCAType(WOLFSSL_CERT_MANAGER* cm, byte* hash, int type)
+{
+ Signer* current;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
+ word32 row;
+
+ WOLFSSL_MSG_EX("Setting CA to type %d", type);
+
+ if (cm == NULL || hash == NULL ||
+ type < WOLFSSL_USER_CA || type > WOLFSSL_USER_INTER) {
+ return ret;
+ }
+
+ row = HashSigner(hash);
+
+ if (wc_LockMutex(&cm->caLock) != 0) {
+ return ret;
+ }
+ current = cm->caTable[row];
+ while (current) {
+ byte* subjectHash;
+
+ #ifndef NO_SKID
+ subjectHash = current->subjectKeyIdHash;
+ #else
+ subjectHash = current->subjectNameHash;
+ #endif
+
+ if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
+ current->type = (byte)type;
+ ret = WOLFSSL_SUCCESS;
+ break;
+ }
+ current = current->next;
+ }
+ wc_UnLockMutex(&cm->caLock);
+
+ WOLFSSL_LEAVE("SetCAType", ret);
+
+ return ret;
+}
+
#endif /* NO_CERTS */
#endif /* !WOLFSSL_SSL_CERTMAN_INCLUDED */
diff --git a/src/ssl_crypto.c b/src/ssl_crypto.c
index 167f71cc88..477c9a9971 100644
--- a/src/ssl_crypto.c
+++ b/src/ssl_crypto.c
@@ -3071,8 +3071,8 @@ void wolfSSL_AES_decrypt(const unsigned char* input, unsigned char* output,
WOLFSSL_MSG("Null argument passed in");
}
else
-#if !defined(HAVE_SELFTEST) && \
- (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION3_GE(5,3,0)))
+#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
+ (defined(FIPS_VERSION_GE) && FIPS_VERSION3_GE(5,3,0)))
/* Decrypt a block with wolfCrypt AES. */
if (wc_AesDecryptDirect((Aes*)key, output, input) != 0) {
WOLFSSL_MSG("wc_AesDecryptDirect failed");
@@ -3203,7 +3203,8 @@ void wolfSSL_AES_cbc_encrypt(const unsigned char *in, unsigned char* out,
* AES_ENCRPT for encryption, AES_DECRYPTION for decryption.
*/
void wolfSSL_AES_cfb128_encrypt(const unsigned char *in, unsigned char* out,
- size_t len, WOLFSSL_AES_KEY *key, unsigned char* iv, int* num, const int enc)
+ size_t len, WOLFSSL_AES_KEY *key, unsigned char* iv, int* num,
+ const int enc)
{
#ifndef WOLFSSL_AES_CFB
WOLFSSL_MSG("CFB mode not enabled please use macro WOLFSSL_AES_CFB");
@@ -3435,13 +3436,15 @@ size_t wolfSSL_CRYPTO_cts128_decrypt(const unsigned char *in,
* Use 0 buffer as IV to do straight decryption.
* This places the Cn-1 block at lastBlk */
XMEMSET(lastBlk, 0, WOLFSSL_CTS128_BLOCK_SZ);
- (*cbc)(in, prevBlk, WOLFSSL_CTS128_BLOCK_SZ, key, lastBlk, AES_DECRYPTION);
+ (*cbc)(in, prevBlk, WOLFSSL_CTS128_BLOCK_SZ, key, lastBlk,
+ AES_DECRYPTION);
/* RFC2040: Append the tail (BB minus Ln) bytes of Xn to Cn
* to create En. */
XMEMCPY(prevBlk, in + WOLFSSL_CTS128_BLOCK_SZ, lastBlkLen);
/* Cn and Cn-1 can now be decrypted */
(*cbc)(prevBlk, out, WOLFSSL_CTS128_BLOCK_SZ, key, iv, AES_DECRYPTION);
- (*cbc)(lastBlk, lastBlk, WOLFSSL_CTS128_BLOCK_SZ, key, iv, AES_DECRYPTION);
+ (*cbc)(lastBlk, lastBlk, WOLFSSL_CTS128_BLOCK_SZ, key, iv,
+ AES_DECRYPTION);
XMEMCPY(out + WOLFSSL_CTS128_BLOCK_SZ, lastBlk, lastBlkLen);
}
diff --git a/src/ssl_ech.c b/src/ssl_ech.c
new file mode 100644
index 0000000000..d27522c862
--- /dev/null
+++ b/src/ssl_ech.c
@@ -0,0 +1,738 @@
+/* ssl_ech.c
+ *
+ * Copyright (C) 2006-2025 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#include
+
+#if !defined(WOLFSSL_SSL_ECH_INCLUDED)
+ #ifndef WOLFSSL_IGNORE_FILE_WARN
+ #warning ssl_ech.c does not need to be compiled separately from ssl.c
+ #endif
+#else
+
+#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
+
+/* create the hpke key and ech config to send to clients */
+int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx, const char* publicName,
+ word16 kemId, word16 kdfId, word16 aeadId)
+{
+ int ret = 0;
+ word16 encLen = DHKEM_X25519_ENC_LEN;
+ WOLFSSL_EchConfig* newConfig;
+ WOLFSSL_EchConfig* parentConfig;
+#ifdef WOLFSSL_SMALL_STACK
+ Hpke* hpke = NULL;
+ WC_RNG* rng;
+#else
+ Hpke hpke[1];
+ WC_RNG rng[1];
+#endif
+
+ if (ctx == NULL || publicName == NULL)
+ return BAD_FUNC_ARG;
+
+ WC_ALLOC_VAR_EX(rng, WC_RNG, 1, ctx->heap, DYNAMIC_TYPE_RNG,
+ return MEMORY_E);
+ ret = wc_InitRng(rng);
+ if (ret != 0) {
+ WC_FREE_VAR_EX(rng, ctx->heap, DYNAMIC_TYPE_RNG);
+ return ret;
+ }
+
+ newConfig = (WOLFSSL_EchConfig*)XMALLOC(sizeof(WOLFSSL_EchConfig),
+ ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (newConfig == NULL)
+ ret = MEMORY_E;
+ else
+ XMEMSET(newConfig, 0, sizeof(WOLFSSL_EchConfig));
+
+ /* set random config id */
+ if (ret == 0)
+ ret = wc_RNG_GenerateByte(rng, &newConfig->configId);
+
+ /* if 0 is selected for algorithms use default, may change with draft */
+ if (kemId == 0)
+ kemId = DHKEM_X25519_HKDF_SHA256;
+
+ if (kdfId == 0)
+ kdfId = HKDF_SHA256;
+
+ if (aeadId == 0)
+ aeadId = HPKE_AES_128_GCM;
+
+ if (ret == 0) {
+ /* set the kem id */
+ newConfig->kemId = kemId;
+
+ /* set the cipher suite, only 1 for now */
+ newConfig->numCipherSuites = 1;
+ newConfig->cipherSuites =
+ (EchCipherSuite*)XMALLOC(sizeof(EchCipherSuite), ctx->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+
+ if (newConfig->cipherSuites == NULL) {
+ ret = MEMORY_E;
+ }
+ else {
+ newConfig->cipherSuites[0].kdfId = kdfId;
+ newConfig->cipherSuites[0].aeadId = aeadId;
+ }
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ if (ret == 0) {
+ hpke = (Hpke*)XMALLOC(sizeof(Hpke), ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (hpke == NULL)
+ ret = MEMORY_E;
+ }
+#endif
+
+ if (ret == 0)
+ ret = wc_HpkeInit(hpke, kemId, kdfId, aeadId, ctx->heap);
+
+ /* generate the receiver private key */
+ if (ret == 0)
+ ret = wc_HpkeGenerateKeyPair(hpke, &newConfig->receiverPrivkey, rng);
+
+ /* done with RNG */
+ wc_FreeRng(rng);
+
+ /* serialize the receiver key */
+ if (ret == 0)
+ ret = wc_HpkeSerializePublicKey(hpke, newConfig->receiverPrivkey,
+ newConfig->receiverPubkey, &encLen);
+
+ if (ret == 0) {
+ newConfig->publicName = (char*)XMALLOC(XSTRLEN(publicName) + 1,
+ ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (newConfig->publicName == NULL) {
+ ret = MEMORY_E;
+ }
+ else {
+ XMEMCPY(newConfig->publicName, publicName,
+ XSTRLEN(publicName) + 1);
+ }
+ }
+
+ if (ret != 0) {
+ if (newConfig) {
+ XFREE(newConfig->cipherSuites, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(newConfig->publicName, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(newConfig, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ }
+ else {
+ parentConfig = ctx->echConfigs;
+
+ if (parentConfig == NULL) {
+ ctx->echConfigs = newConfig;
+ }
+ else {
+ while (parentConfig->next != NULL) {
+ parentConfig = parentConfig->next;
+ }
+
+ parentConfig->next = newConfig;
+ }
+ }
+
+ if (ret == 0)
+ ret = WOLFSSL_SUCCESS;
+
+ WC_FREE_VAR_EX(hpke, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ WC_FREE_VAR_EX(rng, ctx->heap, DYNAMIC_TYPE_RNG);
+
+ return ret;
+}
+
+int wolfSSL_CTX_SetEchConfigsBase64(WOLFSSL_CTX* ctx, const char* echConfigs64,
+ word32 echConfigs64Len)
+{
+ int ret = 0;
+ word32 decodedLen = echConfigs64Len * 3 / 4 + 1;
+ byte* decodedConfigs;
+
+ if (ctx == NULL || echConfigs64 == NULL || echConfigs64Len == 0)
+ return BAD_FUNC_ARG;
+
+ decodedConfigs = (byte*)XMALLOC(decodedLen, ctx->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+
+ if (decodedConfigs == NULL)
+ return MEMORY_E;
+
+ decodedConfigs[decodedLen - 1] = 0;
+
+ /* decode the echConfigs */
+ ret = Base64_Decode((const byte*)echConfigs64, echConfigs64Len,
+ decodedConfigs, &decodedLen);
+
+ if (ret != 0) {
+ XFREE(decodedConfigs, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+
+ ret = wolfSSL_CTX_SetEchConfigs(ctx, decodedConfigs, decodedLen);
+
+ XFREE(decodedConfigs, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return ret;
+}
+
+int wolfSSL_CTX_SetEchConfigs(WOLFSSL_CTX* ctx, const byte* echConfigs,
+ word32 echConfigsLen)
+{
+ int ret;
+
+ if (ctx == NULL || echConfigs == NULL || echConfigsLen == 0)
+ return BAD_FUNC_ARG;
+
+ FreeEchConfigs(ctx->echConfigs, ctx->heap);
+ ctx->echConfigs = NULL;
+ ret = SetEchConfigsEx(&ctx->echConfigs, ctx->heap, echConfigs,
+ echConfigsLen);
+
+ if (ret == 0)
+ return WOLFSSL_SUCCESS;
+
+ return ret;
+}
+
+/* get the ech configs that the server context is using */
+int wolfSSL_CTX_GetEchConfigs(WOLFSSL_CTX* ctx, byte* output,
+ word32* outputLen) {
+ if (ctx == NULL || outputLen == NULL)
+ return BAD_FUNC_ARG;
+
+ /* if we don't have ech configs */
+ if (ctx->echConfigs == NULL)
+ return WOLFSSL_FATAL_ERROR;
+
+ return GetEchConfigsEx(ctx->echConfigs, output, outputLen);
+}
+
+void wolfSSL_CTX_SetEchEnable(WOLFSSL_CTX* ctx, byte enable)
+{
+ if (ctx != NULL) {
+ ctx->disableECH = !enable;
+ if (ctx->disableECH) {
+ TLSX_Remove(&ctx->extensions, TLSX_ECH, ctx->heap);
+ FreeEchConfigs(ctx->echConfigs, ctx->heap);
+ ctx->echConfigs = NULL;
+ }
+ }
+}
+
+/* set the ech config from base64 for our client ssl object, base64 is the
+ * format ech configs are sent using dns records */
+int wolfSSL_SetEchConfigsBase64(WOLFSSL* ssl, char* echConfigs64,
+ word32 echConfigs64Len)
+{
+ int ret = 0;
+ word32 decodedLen = echConfigs64Len * 3 / 4 + 1;
+ byte* decodedConfigs;
+
+ if (ssl == NULL || echConfigs64 == NULL || echConfigs64Len == 0)
+ return BAD_FUNC_ARG;
+
+ /* already have ech configs */
+ if (ssl->options.useEch == 1) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ decodedConfigs = (byte*)XMALLOC(decodedLen, ssl->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+
+ if (decodedConfigs == NULL)
+ return MEMORY_E;
+
+ decodedConfigs[decodedLen - 1] = 0;
+
+ /* decode the echConfigs */
+ ret = Base64_Decode((byte*)echConfigs64, echConfigs64Len,
+ decodedConfigs, &decodedLen);
+
+ if (ret != 0) {
+ XFREE(decodedConfigs, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+
+ ret = wolfSSL_SetEchConfigs(ssl, decodedConfigs, decodedLen);
+
+ XFREE(decodedConfigs, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return ret;
+}
+
+/* set the ech config from a raw buffer, this is the format ech configs are
+ * sent using retry_configs from the ech server */
+int wolfSSL_SetEchConfigs(WOLFSSL* ssl, const byte* echConfigs,
+ word32 echConfigsLen)
+{
+ int ret;
+
+ if (ssl == NULL || echConfigs == NULL || echConfigsLen == 0)
+ return BAD_FUNC_ARG;
+
+ /* already have ech configs */
+ if (ssl->options.useEch == 1) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ ret = SetEchConfigsEx(&ssl->echConfigs, ssl->heap, echConfigs,
+ echConfigsLen);
+
+ /* if we found valid configs */
+ if (ret == 0) {
+ ssl->options.useEch = 1;
+ return WOLFSSL_SUCCESS;
+ }
+
+ return ret;
+}
+
+/* get the raw ech config from our struct */
+int GetEchConfig(WOLFSSL_EchConfig* config, byte* output, word32* outputLen)
+{
+ int i;
+ word16 totalLen = 0;
+
+ if (config == NULL || (output == NULL && outputLen == NULL))
+ return BAD_FUNC_ARG;
+
+ /* 2 for version */
+ totalLen += 2;
+ /* 2 for length */
+ totalLen += 2;
+ /* 1 for configId */
+ totalLen += 1;
+ /* 2 for kemId */
+ totalLen += 2;
+ /* 2 for hpke_len */
+ totalLen += 2;
+
+ /* hpke_pub_key */
+ switch (config->kemId) {
+ case DHKEM_P256_HKDF_SHA256:
+ totalLen += DHKEM_P256_ENC_LEN;
+ break;
+ case DHKEM_P384_HKDF_SHA384:
+ totalLen += DHKEM_P384_ENC_LEN;
+ break;
+ case DHKEM_P521_HKDF_SHA512:
+ totalLen += DHKEM_P521_ENC_LEN;
+ break;
+ case DHKEM_X25519_HKDF_SHA256:
+ totalLen += DHKEM_X25519_ENC_LEN;
+ break;
+ case DHKEM_X448_HKDF_SHA512:
+ totalLen += DHKEM_X448_ENC_LEN;
+ break;
+ }
+
+ /* cipherSuitesLen */
+ totalLen += 2;
+ /* cipherSuites */
+ totalLen += config->numCipherSuites * 4;
+ /* public name len */
+ totalLen += 2;
+
+ /* public name */
+ totalLen += XSTRLEN(config->publicName);
+ /* trailing zeros */
+ totalLen += 2;
+
+ if (output == NULL) {
+ *outputLen = totalLen;
+ return WC_NO_ERR_TRACE(LENGTH_ONLY_E);
+ }
+
+ if (totalLen > *outputLen) {
+ *outputLen = totalLen;
+ return INPUT_SIZE_E;
+ }
+
+ /* version */
+ c16toa(TLSX_ECH, output);
+ output += 2;
+
+ /* length - 4 for version and length itself */
+ c16toa(totalLen - 4, output);
+ output += 2;
+
+ /* configId */
+ *output = config->configId;
+ output++;
+ /* kemId */
+ c16toa(config->kemId, output);
+ output += 2;
+
+ /* length and key itself */
+ switch (config->kemId) {
+ case DHKEM_P256_HKDF_SHA256:
+ c16toa(DHKEM_P256_ENC_LEN, output);
+ output += 2;
+ XMEMCPY(output, config->receiverPubkey, DHKEM_P256_ENC_LEN);
+ output += DHKEM_P256_ENC_LEN;
+ break;
+ case DHKEM_P384_HKDF_SHA384:
+ c16toa(DHKEM_P384_ENC_LEN, output);
+ output += 2;
+ XMEMCPY(output, config->receiverPubkey, DHKEM_P384_ENC_LEN);
+ output += DHKEM_P384_ENC_LEN;
+ break;
+ case DHKEM_P521_HKDF_SHA512:
+ c16toa(DHKEM_P521_ENC_LEN, output);
+ output += 2;
+ XMEMCPY(output, config->receiverPubkey, DHKEM_P521_ENC_LEN);
+ output += DHKEM_P521_ENC_LEN;
+ break;
+ case DHKEM_X25519_HKDF_SHA256:
+ c16toa(DHKEM_X25519_ENC_LEN, output);
+ output += 2;
+ XMEMCPY(output, config->receiverPubkey, DHKEM_X25519_ENC_LEN);
+ output += DHKEM_X25519_ENC_LEN;
+ break;
+ case DHKEM_X448_HKDF_SHA512:
+ c16toa(DHKEM_X448_ENC_LEN, output);
+ output += 2;
+ XMEMCPY(output, config->receiverPubkey, DHKEM_X448_ENC_LEN);
+ output += DHKEM_X448_ENC_LEN;
+ break;
+ }
+
+ /* cipherSuites len */
+ c16toa(config->numCipherSuites * 4, output);
+ output += 2;
+
+ /* cipherSuites */
+ for (i = 0; i < config->numCipherSuites; i++) {
+ c16toa(config->cipherSuites[i].kdfId, output);
+ output += 2;
+ c16toa(config->cipherSuites[i].aeadId, output);
+ output += 2;
+ }
+
+ /* set maximum name length to 0 */
+ *output = 0;
+ output++;
+
+ /* publicName len */
+ *output = XSTRLEN(config->publicName);
+ output++;
+
+ /* publicName */
+ XMEMCPY(output, config->publicName,
+ XSTRLEN(config->publicName));
+ output += XSTRLEN(config->publicName);
+
+ /* terminating zeros */
+ c16toa(0, output);
+ /* output += 2; */
+
+ *outputLen = totalLen;
+
+ return 0;
+}
+
+/* wrapper function to get ech configs from application code */
+int wolfSSL_GetEchConfigs(WOLFSSL* ssl, byte* output, word32* outputLen)
+{
+ if (ssl == NULL || outputLen == NULL)
+ return BAD_FUNC_ARG;
+
+ /* if we don't have ech configs */
+ if (ssl->options.useEch != 1) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ return GetEchConfigsEx(ssl->echConfigs, output, outputLen);
+}
+
+void wolfSSL_SetEchEnable(WOLFSSL* ssl, byte enable)
+{
+ if (ssl != NULL) {
+ ssl->options.disableECH = !enable;
+ if (ssl->options.disableECH) {
+ TLSX_Remove(&ssl->extensions, TLSX_ECH, ssl->heap);
+ FreeEchConfigs(ssl->echConfigs, ssl->heap);
+ ssl->echConfigs = NULL;
+ }
+ }
+}
+
+int SetEchConfigsEx(WOLFSSL_EchConfig** outputConfigs, void* heap,
+ const byte* echConfigs, word32 echConfigsLen)
+{
+ int ret = 0;
+ int i;
+ int j;
+ word16 totalLength;
+ word16 version;
+ word16 length;
+ word16 hpkePubkeyLen;
+ word16 cipherSuitesLen;
+ word16 publicNameLen;
+ WOLFSSL_EchConfig* configList = NULL;
+ WOLFSSL_EchConfig* workingConfig = NULL;
+ WOLFSSL_EchConfig* lastConfig = NULL;
+ byte* echConfig = NULL;
+
+ if (outputConfigs == NULL || echConfigs == NULL || echConfigsLen == 0)
+ return BAD_FUNC_ARG;
+
+ /* check that the total length is well formed */
+ ato16(echConfigs, &totalLength);
+
+ if (totalLength != echConfigsLen - 2) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* skip the total length uint16_t */
+ i = 2;
+
+ do {
+ echConfig = (byte*)echConfigs + i;
+ ato16(echConfig, &version);
+ ato16(echConfig + 2, &length);
+
+ /* if the version does not match */
+ if (version != TLSX_ECH) {
+ /* we hit the end of the configs */
+ if ( (word32)i + 2 >= echConfigsLen ) {
+ break;
+ }
+
+ /* skip this config, +4 for version and length */
+ i += length + 4;
+ continue;
+ }
+
+ /* check if the length will overrun the buffer */
+ if ((word32)i + length + 4 > echConfigsLen) {
+ break;
+ }
+
+ if (workingConfig == NULL) {
+ workingConfig =
+ (WOLFSSL_EchConfig*)XMALLOC(sizeof(WOLFSSL_EchConfig), heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ configList = workingConfig;
+ if (workingConfig != NULL) {
+ workingConfig->next = NULL;
+ }
+ }
+ else {
+ lastConfig = workingConfig;
+ workingConfig->next =
+ (WOLFSSL_EchConfig*)XMALLOC(sizeof(WOLFSSL_EchConfig),
+ heap, DYNAMIC_TYPE_TMP_BUFFER);
+ workingConfig = workingConfig->next;
+ }
+
+ if (workingConfig == NULL) {
+ ret = MEMORY_E;
+ break;
+ }
+
+ XMEMSET(workingConfig, 0, sizeof(WOLFSSL_EchConfig));
+
+ /* rawLen */
+ workingConfig->rawLen = length + 4;
+
+ /* raw body */
+ workingConfig->raw = (byte*)XMALLOC(workingConfig->rawLen,
+ heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (workingConfig->raw == NULL) {
+ ret = MEMORY_E;
+ break;
+ }
+
+ XMEMCPY(workingConfig->raw, echConfig, workingConfig->rawLen);
+
+ /* skip over version and length */
+ echConfig += 4;
+
+ /* configId, 1 byte */
+ workingConfig->configId = *(echConfig);
+ echConfig++;
+ /* kemId, 2 bytes */
+ ato16(echConfig, &workingConfig->kemId);
+ echConfig += 2;
+ /* hpke public_key length, 2 bytes */
+ ato16(echConfig, &hpkePubkeyLen);
+ echConfig += 2;
+ /* hpke public_key */
+ XMEMCPY(workingConfig->receiverPubkey, echConfig, hpkePubkeyLen);
+ echConfig += hpkePubkeyLen;
+ /* cipherSuitesLen */
+ ato16(echConfig, &cipherSuitesLen);
+
+ workingConfig->cipherSuites = (EchCipherSuite*)XMALLOC(cipherSuitesLen,
+ heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (workingConfig->cipherSuites == NULL) {
+ ret = MEMORY_E;
+ break;
+ }
+
+ echConfig += 2;
+ workingConfig->numCipherSuites = cipherSuitesLen / 4;
+ /* cipherSuites */
+ for (j = 0; j < workingConfig->numCipherSuites; j++) {
+ ato16(echConfig + j * 4, &workingConfig->cipherSuites[j].kdfId);
+ ato16(echConfig + j * 4 + 2,
+ &workingConfig->cipherSuites[j].aeadId);
+ }
+ echConfig += cipherSuitesLen;
+ /* ignore the maximum name length */
+ echConfig++;
+ /* publicNameLen */
+ publicNameLen = *(echConfig);
+ workingConfig->publicName = (char*)XMALLOC(publicNameLen + 1,
+ heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (workingConfig->publicName == NULL) {
+ ret = MEMORY_E;
+ break;
+ }
+ echConfig++;
+ /* publicName */
+ XMEMCPY(workingConfig->publicName, echConfig, publicNameLen);
+ /* null terminated */
+ workingConfig->publicName[publicNameLen] = 0;
+
+ /* add length to go to next config, +4 for version and length */
+ i += length + 4;
+
+ /* check that we support this config */
+ for (j = 0; j < HPKE_SUPPORTED_KEM_LEN; j++) {
+ if (hpkeSupportedKem[j] == workingConfig->kemId)
+ break;
+ }
+
+ /* if we don't support the kem or at least one cipher suite */
+ if (j >= HPKE_SUPPORTED_KEM_LEN ||
+ EchConfigGetSupportedCipherSuite(workingConfig) < 0)
+ {
+ XFREE(workingConfig->cipherSuites, heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(workingConfig->publicName, heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(workingConfig->raw, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ workingConfig = lastConfig;
+ }
+ } while ((word32)i < echConfigsLen);
+
+ /* if we found valid configs */
+ if (ret == 0 && configList != NULL) {
+ *outputConfigs = configList;
+
+ return ret;
+ }
+
+ workingConfig = configList;
+
+ while (workingConfig != NULL) {
+ lastConfig = workingConfig;
+ workingConfig = workingConfig->next;
+
+ XFREE(lastConfig->cipherSuites, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(lastConfig->publicName, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(lastConfig->raw, heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ XFREE(lastConfig, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+
+ if (ret == 0)
+ return WOLFSSL_FATAL_ERROR;
+
+ return ret;
+}
+
+/* get the raw ech configs from our linked list of ech config structs */
+int GetEchConfigsEx(WOLFSSL_EchConfig* configs, byte* output, word32* outputLen)
+{
+ int ret = 0;
+ WOLFSSL_EchConfig* workingConfig = NULL;
+ byte* outputStart = output;
+ word32 totalLen = 2;
+ word32 workingOutputLen = 0;
+
+ if (configs == NULL || outputLen == NULL ||
+ (output != NULL && *outputLen < totalLen)) {
+ return BAD_FUNC_ARG;
+ }
+
+
+ /* skip over total length which we fill in later */
+ if (output != NULL) {
+ workingOutputLen = *outputLen - totalLen;
+ output += 2;
+ }
+ else {
+ /* caller getting the size only, set current 2 byte length size */
+ *outputLen = totalLen;
+ }
+
+ workingConfig = configs;
+
+ while (workingConfig != NULL) {
+ /* get this config */
+ ret = GetEchConfig(workingConfig, output, &workingOutputLen);
+
+ if (output != NULL)
+ output += workingOutputLen;
+
+ /* add this config's length to the total length */
+ totalLen += workingOutputLen;
+
+ if (totalLen > *outputLen)
+ workingOutputLen = 0;
+ else
+ workingOutputLen = *outputLen - totalLen;
+
+ /* only error we break on, other 2 we need to keep finding length */
+ if (ret == WC_NO_ERR_TRACE(BAD_FUNC_ARG))
+ return BAD_FUNC_ARG;
+
+ workingConfig = workingConfig->next;
+ }
+
+ if (output == NULL) {
+ *outputLen = totalLen;
+ return WC_NO_ERR_TRACE(LENGTH_ONLY_E);
+ }
+
+ if (totalLen > *outputLen) {
+ *outputLen = totalLen;
+ return INPUT_SIZE_E;
+ }
+
+ /* total size -2 for size itself */
+ c16toa(totalLen - 2, outputStart);
+
+ *outputLen = totalLen;
+
+ return WOLFSSL_SUCCESS;
+}
+
+#endif /* WOLFSSL_TLS13 && HAVE_ECH */
+
+#endif /* !WOLFSSL_SSL_ECH_INCLUDED */
+
diff --git a/src/ssl_load.c b/src/ssl_load.c
index e9e6862955..240d72e268 100644
--- a/src/ssl_load.c
+++ b/src/ssl_load.c
@@ -928,7 +928,8 @@ static int ProcessBufferTryDecodeDilithium(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
if (ret == 0) {
/* Decode as a Dilithium private key. */
idx = 0;
- ret = wc_Dilithium_PrivateKeyDecode(der->buffer, &idx, key, der->length);
+ ret = wc_Dilithium_PrivateKeyDecode(der->buffer, &idx, key,
+ der->length);
if (ret == 0) {
ret = dilithium_get_oid_sum(key, &keyFormatTemp);
if (ret == 0) {
@@ -1079,11 +1080,9 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
}
#ifdef WC_RSA_PSS
if((ret == 0) && (*keyFormat == RSAPSSk)) {
- /*
- Require logic to verify that the der is RSAPSSk (when *keyFormat == RSAPSSK),
- and to detect that the der is RSAPSSk (when *keyFormat == 0).
- */
-
+ /* Require logic to verify that the der is RSAPSSk
+ * (when *keyFormat == RSAPSSK), and to detect that the der is RSAPSSk
+ * (when *keyFormat == 0). */
matchAnyKey = 1;
}
#endif /* WC_RSA_PSS */
@@ -2138,7 +2137,8 @@ static int ProcessBufferCertHandleDer(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
* certificates so we can inject them at verification time */
if (ret == 1 && ctx->doAppleNativeCertValidationFlag == 1) {
WOLFSSL_MSG("ANCV Test: Appending CA to cert list");
- ret = wolfSSL_TestAppleNativeCertValidation_AppendCA(ctx, derBuf, (int)derLen);
+ ret = wolfSSL_TestAppleNativeCertValidation_AppendCA(ctx, derBuf,
+ (int)derLen);
if (ret == WOLFSSL_SUCCESS) {
WOLFSSL_MSG("ANCV Test: Clearing CA table");
/* Clear the CA table so we can ensure they won't be used for
@@ -2949,8 +2949,8 @@ int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX* ctx, const char* file,
NULL, verify);
#else
/* Load the DER formatted CA file */
- ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_ASN1, CA_TYPE, NULL, 0,
- NULL, verify);
+ ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_ASN1, CA_TYPE, NULL,
+ 0, NULL, verify);
#endif
#ifndef NO_WOLFSSL_DIR
if (ret == 1) {
@@ -3234,8 +3234,8 @@ int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX* ctx, const char* file)
ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, NULL, 1, NULL,
GET_VERIFY_SETTING_CTX(ctx));
#else
- ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_ASN1, CERT_TYPE, NULL, 1, NULL,
- GET_VERIFY_SETTING_CTX(ctx));
+ ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_ASN1, CERT_TYPE, NULL, 1,
+ NULL, GET_VERIFY_SETTING_CTX(ctx));
#endif
/* Return 1 on success or 0 on failure. */
@@ -4157,6 +4157,8 @@ int wolfSSL_CTX_use_PrivateKey_Id(WOLFSSL_CTX* ctx, const unsigned char* id,
{
int ret = 1;
+ WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_Id");
+
/* Dispose of old private key and allocate and copy in id. */
FreeDer(&ctx->privateKey);
if (AllocCopyDer(&ctx->privateKey, id, (word32)sz, PRIVATEKEY_TYPE,
@@ -4182,6 +4184,7 @@ int wolfSSL_CTX_use_PrivateKey_Id(WOLFSSL_CTX* ctx, const unsigned char* id,
#endif
}
+ WOLFSSL_LEAVE("wolfSSL_CTX_use_PrivateKey_Id", ret);
return ret;
}
@@ -4198,12 +4201,17 @@ int wolfSSL_CTX_use_PrivateKey_Id(WOLFSSL_CTX* ctx, const unsigned char* id,
int wolfSSL_CTX_use_PrivateKey_id(WOLFSSL_CTX* ctx, const unsigned char* id,
long sz, int devId, long keySz)
{
- int ret = wolfSSL_CTX_use_PrivateKey_Id(ctx, id, sz, devId);
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_id");
+
+ ret = wolfSSL_CTX_use_PrivateKey_Id(ctx, id, sz, devId);
if (ret == 1) {
/* Set the key size which normally is calculated during decoding. */
ctx->privateKeySz = (int)keySz;
}
+ WOLFSSL_LEAVE("wolfSSL_CTX_use_PrivateKey_id", ret);
return ret;
}
@@ -4221,6 +4229,8 @@ int wolfSSL_CTX_use_PrivateKey_Label(WOLFSSL_CTX* ctx, const char* label,
int ret = 1;
word32 sz = (word32)XSTRLEN(label) + 1;
+ WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_Label");
+
/* Dispose of old private key and allocate and copy in label. */
FreeDer(&ctx->privateKey);
if (AllocCopyDer(&ctx->privateKey, (const byte*)label, (word32)sz,
@@ -4246,6 +4256,7 @@ int wolfSSL_CTX_use_PrivateKey_Label(WOLFSSL_CTX* ctx, const char* label,
#endif
}
+ WOLFSSL_LEAVE("wolfSSL_CTX_use_PrivateKey_Label", ret);
return ret;
}
@@ -4255,6 +4266,8 @@ int wolfSSL_CTX_use_AltPrivateKey_Id(WOLFSSL_CTX* ctx, const unsigned char* id,
{
int ret = 1;
+ WOLFSSL_ENTER("wolfSSL_CTX_use_AltPrivateKey_Id");
+
if ((ctx == NULL) || (id == NULL)) {
ret = 0;
}
@@ -4277,17 +4290,23 @@ int wolfSSL_CTX_use_AltPrivateKey_Id(WOLFSSL_CTX* ctx, const unsigned char* id,
}
}
+ WOLFSSL_LEAVE("wolfSSL_CTX_use_AltPrivateKey_Id", ret);
return ret;
}
int wolfSSL_CTX_use_AltPrivateKey_id(WOLFSSL_CTX* ctx, const unsigned char* id,
long sz, int devId, long keySz)
{
- int ret = wolfSSL_CTX_use_AltPrivateKey_Id(ctx, id, sz, devId);
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_use_AltPrivateKey_id");
+
+ ret = wolfSSL_CTX_use_AltPrivateKey_Id(ctx, id, sz, devId);
if (ret == 1) {
ctx->altPrivateKeySz = (word32)keySz;
}
+ WOLFSSL_LEAVE("wolfSSL_CTX_use_AltPrivateKey_id", ret);
return ret;
}
@@ -4297,6 +4316,8 @@ int wolfSSL_CTX_use_AltPrivateKey_Label(WOLFSSL_CTX* ctx, const char* label,
int ret = 1;
word32 sz;
+ WOLFSSL_ENTER("wolfSSL_CTX_use_AltPrivateKey_Label");
+
if ((ctx == NULL) || (label == NULL)) {
ret = 0;
}
@@ -4320,6 +4341,7 @@ int wolfSSL_CTX_use_AltPrivateKey_Label(WOLFSSL_CTX* ctx, const char* label,
}
}
+ WOLFSSL_LEAVE("wolfSSL_CTX_use_AltPrivateKey_Label", ret);
return ret;
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
@@ -4871,7 +4893,8 @@ static int wolfssl_ctx_add_to_chain(WOLFSSL_CTX* ctx, const byte* der,
if (res == 1) {
/* Add chain to DER buffer. */
- res = wolfssl_add_to_chain(&ctx->certChain, 1, der, (word32)derSz, ctx->heap);
+ res = wolfssl_add_to_chain(&ctx->certChain, 1, der, (word32)derSz,
+ ctx->heap);
#ifdef WOLFSSL_TLS13
/* Update count of certificates. */
ctx->certChainCnt++;
@@ -5417,7 +5440,8 @@ int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx)
}
#else
/* OpenSSL's implementation of this API does not require loading the
- system CA cert directory. Allow skipping this without erroring out. */
+ * system CA cert directory. Allow skipping this without erroring out.
+ */
ret = 1;
#endif
}
@@ -5538,8 +5562,10 @@ int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz,
if (ret == 1) {
/* Allocate buffers for p and g to be assigned into SSL. */
- pAlloc = (byte*)XMALLOC((size_t)pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- gAlloc = (byte*)XMALLOC((size_t)gSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ pAlloc = (byte*)XMALLOC((size_t)pSz, ssl->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ gAlloc = (byte*)XMALLOC((size_t)gSz, ssl->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
if ((pAlloc == NULL) || (gAlloc == NULL)) {
/* Memory will be freed below in the (ret != 1) block */
ret = MEMORY_E;
@@ -5590,7 +5616,8 @@ static int wolfssl_check_dh_key(unsigned char* p, int pSz, unsigned char* g,
/* Initialize a DH object. */
if ((ret = wc_InitDhKey(checkKey)) == 0) {
/* Check DH parameters. */
- ret = wc_DhSetCheckKey(checkKey, p, (word32)pSz, g, (word32)gSz, NULL, 0, 0, &rng);
+ ret = wc_DhSetCheckKey(checkKey, p, (word32)pSz, g, (word32)gSz,
+ NULL, 0, 0, &rng);
/* Dispose of DH object. */
wc_FreeDhKey(checkKey);
}
@@ -5686,8 +5713,10 @@ int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz,
if (ret == 1) {
/* Allocate buffers for p and g to be assigned into SSL context. */
- pAlloc = (byte*)XMALLOC((size_t)pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- gAlloc = (byte*)XMALLOC((size_t)gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ pAlloc = (byte*)XMALLOC((size_t)pSz, ctx->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ gAlloc = (byte*)XMALLOC((size_t)gSz, ctx->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
if ((pAlloc == NULL) || (gAlloc == NULL)) {
ret = MEMORY_E;
}
diff --git a/src/ssl_p7p12.c b/src/ssl_p7p12.c
index 7fc44a4b97..0b43d71e6d 100644
--- a/src/ssl_p7p12.c
+++ b/src/ssl_p7p12.c
@@ -1029,7 +1029,8 @@ int wolfSSL_PEM_write_bio_PKCS7(WOLFSSL_BIO* bio, PKCS7* p7)
XMEMSET(pem, 0, pemSz);
- if (wc_DerToPemEx(output, outputSz, pem, (word32)pemSz, NULL, CERT_TYPE) < 0) {
+ if (wc_DerToPemEx(output, outputSz, pem, (word32)pemSz, NULL,CERT_TYPE)
+ < 0) {
goto error;
}
if ((wolfSSL_BIO_write(bio, pem, pemSz) == pemSz)) {
@@ -1368,8 +1369,8 @@ PKCS7* wolfSSL_SMIME_read_PKCS7(WOLFSSL_BIO* in,
WOLFSSL_MSG("Error base64 decoding S/MIME message.");
goto error;
}
- pkcs7 = wolfSSL_d2i_PKCS7_only(NULL, (const unsigned char**)&out, (int)outLen,
- bcontMem, (word32)bcontMemSz);
+ pkcs7 = wolfSSL_d2i_PKCS7_only(NULL, (const unsigned char**)&out,
+ (int)outLen, bcontMem, (word32)bcontMemSz);
wc_MIME_free_hdrs(allHdrs);
XFREE(outHead, NULL, DYNAMIC_TYPE_PKCS7);
@@ -1912,7 +1913,8 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
DYNAMIC_TYPE_X509);
InitX509(x509, 1, heap);
InitDecodedCert(DeCert, current->buffer, current->bufferSz, heap);
- if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL, NULL) != 0) {
+ if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL, NULL)
+ != 0) {
WOLFSSL_MSG("Issue with parsing certificate");
FreeDecodedCert(DeCert);
wolfSSL_X509_free(x509);
diff --git a/src/ssl_sess.c b/src/ssl_sess.c
index ac368c9b66..cff0046289 100644
--- a/src/ssl_sess.c
+++ b/src/ssl_sess.c
@@ -968,7 +968,8 @@ WOLFSSL_SESSION* wolfSSL_GetSessionClient(WOLFSSL* ssl, const byte* id, int len)
}
/* start from most recently used */
- count = (int)min((word32)ClientCache[row].totalCount, CLIENT_SESSIONS_PER_ROW);
+ count = (int)min((word32)ClientCache[row].totalCount,
+ CLIENT_SESSIONS_PER_ROW);
idx = ClientCache[row].nextIdx - 1;
if (idx < 0 || idx >= CLIENT_SESSIONS_PER_ROW) {
/* if back to front, the previous was end */
@@ -997,7 +998,8 @@ WOLFSSL_SESSION* wolfSSL_GetSessionClient(WOLFSSL* ssl, const byte* id, int len)
#else
current = &sessRow->Sessions[clSess[idx].serverIdx];
#endif
- if (current && XMEMCMP(current->serverID, id, (unsigned long)len) == 0) {
+ if (current && XMEMCMP(current->serverID, id,
+ (unsigned long)len) == 0) {
WOLFSSL_MSG("Found a serverid match for client");
if (LowResTimer() < (current->bornOn + current->timeout)) {
WOLFSSL_MSG("Session valid");
@@ -1265,8 +1267,8 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
#endif
if (output->ticketLenAlloc)
XFREE(output->ticket, output->heap, DYNAMIC_TYPE_SESSION_TICK);
- output->ticket = tmpTicket; /* cppcheck-suppress autoVariables
- */
+ /* cppcheck-suppress autoVariables */
+ output->ticket = tmpTicket;
output->ticketLenAlloc = PREALLOC_SESSION_TICKET_LEN;
output->ticketLen = 0;
tmpBufSet = 1;
@@ -1394,7 +1396,8 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
output->ticketLen = 0;
}
if (error == WOLFSSL_SUCCESS) {
- XMEMCPY(output->ticket, tmpTicket, output->ticketLen); /* cppcheck-suppress uninitvar */
+ /* cppcheck-suppress uninitvar */
+ XMEMCPY(output->ticket, tmpTicket, output->ticketLen);
}
}
WC_FREE_VAR_EX(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER);
@@ -1839,8 +1842,9 @@ int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession,
if (SESSION_ROW_WR_LOCK(sessRow) != 0) {
#ifdef HAVE_SESSION_TICKET
XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK);
- #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
- (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
+ #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
+ (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && \
+ FIPS_VERSION_GE(5,3)))
XFREE(preallocNonce, addSession->heap, DYNAMIC_TYPE_SESSION_TICK);
#endif
#endif
@@ -1879,8 +1883,9 @@ int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession,
if (cacheSession == NULL) {
#ifdef HAVE_SESSION_TICKET
XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK);
- #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
- (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
+ #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
+ (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && \
+ FIPS_VERSION_GE(5,3)))
XFREE(preallocNonce, addSession->heap, DYNAMIC_TYPE_SESSION_TICK);
#endif
#endif
@@ -2028,8 +2033,8 @@ int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession,
#ifndef NO_CLIENT_CACHE
if (ret == 0 && clientCacheEntry != NULL) {
- ClientSession* clientCache = AddSessionToClientCache(side, row, (int)idx,
- addSession->serverID, addSession->idLen, id, useTicket);
+ ClientSession* clientCache = AddSessionToClientCache(side, row,
+ (int)idx, addSession->serverID, addSession->idLen, id, useTicket);
if (clientCache != NULL)
*clientCacheEntry = clientCache;
}
@@ -4088,7 +4093,8 @@ void wolfSSL_FreeSession(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session)
ForceZero(session->sessionID, ID_LEN);
if (session->type == WOLFSSL_SESSION_TYPE_HEAP) {
- XFREE(session, session->heap, DYNAMIC_TYPE_SESSION); /* // NOLINT(clang-analyzer-unix.Malloc) */
+ /* // NOLINTNEXTLINE(clang-analyzer-unix.Malloc) */
+ XFREE(session, session->heap, DYNAMIC_TYPE_SESSION);
}
}
diff --git a/src/ssl_sk.c b/src/ssl_sk.c
index 9696a820aa..aeefa5a95b 100644
--- a/src/ssl_sk.c
+++ b/src/ssl_sk.c
@@ -259,6 +259,50 @@ int wolfSSL_sk_push_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* node)
return ret;
}
+/* Pushes the node onto the back of the stack.
+ *
+ * If *stack is NULL, node becomes the head.
+ *
+ * @param [in, out] stack Stack of nodes.
+ * @param [in] node Node to append.
+ *
+ * @return WOLFSSL_SUCCESS on success
+ * @return WOLFSSL_FAILURE when stack or node is NULL.
+ */
+int wolfSSL_sk_push_back_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* node)
+{
+ int ret = WOLFSSL_SUCCESS;
+
+ /* Validate parameters. */
+ if (stack == NULL || node == NULL) {
+ ret = WOLFSSL_FAILURE;
+ }
+ if (ret == WOLFSSL_SUCCESS) {
+ node->next = NULL;
+ /* Tail node has num of 1, indicating 1 node till the end */
+ node->num = 1;
+
+ if (*stack == NULL) {
+ /* First node. */
+ *stack = node;
+ }
+ else {
+ /* Walk to the end and append. Each node's num field holds the
+ * count of nodes from that node to the tail (inclusive), so
+ * every existing node's num increases by one. */
+ WOLFSSL_STACK* cur = *stack;
+ while (cur->next != NULL) {
+ cur->num++;
+ cur = cur->next;
+ }
+ cur->num++;
+ cur->next = node;
+ }
+ }
+
+ return ret;
+}
+
/* Removes the node at the index from the stack and returns data.
*
* This is an internal API.
diff --git a/src/tls.c b/src/tls.c
index 7d7dcea86c..843d16f461 100644
--- a/src/tls.c
+++ b/src/tls.c
@@ -9894,7 +9894,7 @@ static int TLSX_KeyShareEntry_Parse(const WOLFSSL* ssl, const byte* input,
ato16(&input[offset], &keLen);
offset += OPAQUE16_LEN;
if (keLen == 0)
- return INVALID_PARAMETER;
+ return BUFFER_ERROR;
if (keLen > length - offset)
return BUFFER_ERROR;
diff --git a/src/tls13.c b/src/tls13.c
index 5b0f098507..b9e06896f9 100644
--- a/src/tls13.c
+++ b/src/tls13.c
@@ -5497,8 +5497,8 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
suite[1] = ssl->options.cipherSuite;
if (!FindSuiteSSL(ssl, suite)) {
WOLFSSL_MSG("Cipher suite not supported on client");
- WOLFSSL_ERROR_VERBOSE(MATCH_SUITE_ERROR);
- return MATCH_SUITE_ERROR;
+ WOLFSSL_ERROR_VERBOSE(INVALID_PARAMETER);
+ return INVALID_PARAMETER;
}
#if defined(HAVE_ECH)
diff --git a/src/x509.c b/src/x509.c
index 291cd37ba2..ef9794829b 100644
--- a/src/x509.c
+++ b/src/x509.c
@@ -14986,41 +14986,109 @@ int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *name,
void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk)
{
- WOLFSSL_STACK *curr;
+ wolfSSL_sk_pop_free(sk, NULL);
+}
- while (sk != NULL) {
- curr = sk;
- sk = sk->next;
+static int x509_aia_append_string(WOLFSSL_STACK** head,
+ const byte* uri, word32 uriSz)
+{
+ WOLFSSL_STACK* node;
+ char* url;
- XFREE(curr, NULL, DYNAMIC_TYPE_OPENSSL);
+ url = (char*)XMALLOC(uriSz + 1, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (url == NULL)
+ return WOLFSSL_FAILURE;
+
+ XMEMCPY(url, uri, uriSz);
+ url[uriSz] = '\0';
+
+ node = wolfSSL_sk_new_node(*head != NULL ? (*head)->heap : NULL);
+ if (node == NULL) {
+ XFREE(url, NULL, DYNAMIC_TYPE_OPENSSL);
+ return WOLFSSL_FAILURE;
}
+
+ 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;
+}
+
+static WOLFSSL_STACK* x509_get1_aia_by_method(WOLFSSL_X509* x, word32 method,
+ const byte* fallback, int fallbackSz)
+{
+ WOLFSSL_STACK* head = 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. */
+ if (x->authInfoListSz > 0) {
+ for (i = 0; i < x->authInfoListSz; i++) {
+ if (x->authInfoList[i].method != method ||
+ x->authInfoList[i].uri == NULL ||
+ x->authInfoList[i].uriSz == 0) {
+ continue;
+ }
+
+ if (x509_aia_append_string(&head, x->authInfoList[i].uri,
+ x->authInfoList[i].uriSz) != WOLFSSL_SUCCESS) {
+ wolfSSL_sk_pop_free(head, NULL);
+ 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);
+ return NULL;
+ }
+ }
+
+ return head;
}
WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x)
{
- WOLFSSL_STACK* list = NULL;
- char* url;
-
- if (x == NULL || x->authInfoSz == 0)
+ if (x == NULL)
return NULL;
-
- list = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK) + x->authInfoSz + 1,
- NULL, DYNAMIC_TYPE_OPENSSL);
- if (list == NULL)
- return NULL;
-
- url = (char*)list;
- url += sizeof(WOLFSSL_STACK);
- XMEMCPY(url, x->authInfo, x->authInfoSz);
- url[x->authInfoSz] = '\0';
-
- list->data.string = url;
- list->next = NULL;
- list->num = 1;
-
- return list;
+ return x509_get1_aia_by_method(x, AIA_OCSP_OID, x->authInfo, x->authInfoSz);
}
+int wolfSSL_X509_get_aia_overflow(WOLFSSL_X509 *x)
+{
+ int overflow = 0;
+
+ WOLFSSL_ENTER("wolfSSL_X509_get_aia_overflow");
+
+ if (x != NULL) {
+ overflow = x->authInfoListOverflow;
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_X509_get_aia_overflow", overflow);
+
+ return overflow;
+}
+
+#ifdef WOLFSSL_ASN_CA_ISSUER
+WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ca_issuers(WOLFSSL_X509 *x)
+{
+ if (x == NULL)
+ return NULL;
+ return x509_get1_aia_by_method(x, AIA_CA_ISSUER_OID, x->authInfoCaIssuer,
+ x->authInfoCaIssuerSz);
+}
+#endif /* WOLFSSL_ASN_CA_ISSUER */
+
int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, WOLFSSL_X509 *subject)
{
WOLFSSL_X509_NAME *issuerName = wolfSSL_X509_get_issuer_name(subject);
diff --git a/tests/api.c b/tests/api.c
index 95b5f37713..7083040296 100644
--- a/tests/api.c
+++ b/tests/api.c
@@ -19199,6 +19199,109 @@ static int test_wolfSSL_OCSP_REQ_CTX(void)
return EXPECT_RESULT();
}
+static int test_wolfSSL_X509_get1_ca_issuers(void)
+{
+ EXPECT_DECLS;
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \
+ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) && \
+ defined(WOLFSSL_ASN_CA_ISSUER) && !defined(NO_FILESYSTEM) && \
+ !defined(NO_RSA)
+ X509* cert = NULL;
+ STACK_OF(WOLFSSL_STRING) *skStr = NULL;
+ WOLFSSL_STRING url = NULL;
+ const char* expected = "http://example.com/ca.pem";
+
+ ExpectNull(wolfSSL_X509_get1_ca_issuers(NULL));
+ ExpectNotNull(cert = wolfSSL_X509_load_certificate_file(
+ "certs/aia/ca-issuers-cert.pem", WOLFSSL_FILETYPE_PEM));
+ ExpectNotNull(skStr = wolfSSL_X509_get1_ca_issuers(cert));
+ ExpectIntEQ(wolfSSL_sk_WOLFSSL_STRING_num(skStr), 1);
+ ExpectNotNull(url = wolfSSL_sk_WOLFSSL_STRING_value(skStr, 0));
+ ExpectIntEQ(XSTRCMP(url, expected), 0);
+
+ wolfSSL_X509_email_free(skStr);
+ wolfSSL_X509_free(cert);
+#endif
+ return EXPECT_RESULT();
+}
+
+static int test_wolfSSL_X509_get1_aia_multi(void)
+{
+ EXPECT_DECLS;
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \
+ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) && \
+ defined(WOLFSSL_ASN_CA_ISSUER) && !defined(NO_FILESYSTEM) && \
+ !defined(NO_RSA)
+ X509* cert = NULL;
+ STACK_OF(WOLFSSL_STRING) *ocsp = NULL;
+ STACK_OF(WOLFSSL_STRING) *ca = NULL;
+ const char* ocspExp1 = "http://127.0.0.1:22221";
+ const char* ocspExp2 = "http://127.0.0.1:22222";
+ const char* caExp1 = "http://www.wolfssl.com/ca.pem";
+ const char* caExp2 = "https://www.wolfssl.com/ca2.pem";
+ int i;
+ int ocspFound1 = 0, ocspFound2 = 0;
+ int caFound1 = 0, caFound2 = 0;
+
+ ExpectNotNull(cert = wolfSSL_X509_load_certificate_file(
+ "certs/aia/multi-aia-cert.pem", WOLFSSL_FILETYPE_PEM));
+ ExpectIntEQ(wolfSSL_X509_get_aia_overflow(cert), 0);
+
+ ExpectNotNull(ocsp = wolfSSL_X509_get1_ocsp(cert));
+ ExpectIntEQ(wolfSSL_sk_WOLFSSL_STRING_num(ocsp), 2);
+ for (i = 0; i < wolfSSL_sk_WOLFSSL_STRING_num(ocsp); i++) {
+ WOLFSSL_STRING url = wolfSSL_sk_WOLFSSL_STRING_value(ocsp, i);
+ if (url == NULL)
+ continue;
+ if (XSTRCMP(url, ocspExp1) == 0) ocspFound1 = 1;
+ if (XSTRCMP(url, ocspExp2) == 0) ocspFound2 = 1;
+ }
+ ExpectIntEQ(ocspFound1, 1);
+ ExpectIntEQ(ocspFound2, 1);
+
+ ExpectNotNull(ca = wolfSSL_X509_get1_ca_issuers(cert));
+ ExpectIntEQ(wolfSSL_sk_WOLFSSL_STRING_num(ca), 2);
+ for (i = 0; i < wolfSSL_sk_WOLFSSL_STRING_num(ca); i++) {
+ WOLFSSL_STRING url = wolfSSL_sk_WOLFSSL_STRING_value(ca, i);
+ if (url == NULL)
+ continue;
+ if (XSTRCMP(url, caExp1) == 0) caFound1 = 1;
+ if (XSTRCMP(url, caExp2) == 0) caFound2 = 1;
+ }
+ ExpectIntEQ(caFound1, 1);
+ ExpectIntEQ(caFound2, 1);
+
+ wolfSSL_X509_email_free(ocsp);
+ wolfSSL_X509_email_free(ca);
+ wolfSSL_X509_free(cert);
+#endif
+ return EXPECT_RESULT();
+}
+
+static int test_wolfSSL_X509_get1_aia_overflow(void)
+{
+ EXPECT_DECLS;
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \
+ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) && \
+ !defined(NO_FILESYSTEM) && !defined(NO_RSA)
+ X509* cert = NULL;
+ STACK_OF(WOLFSSL_STRING) *ocsp = NULL;
+ int count;
+
+ ExpectNotNull(cert = wolfSSL_X509_load_certificate_file(
+ "certs/aia/overflow-aia-cert.pem", WOLFSSL_FILETYPE_PEM));
+
+ ExpectNotNull(ocsp = wolfSSL_X509_get1_ocsp(cert));
+ count = wolfSSL_sk_WOLFSSL_STRING_num(ocsp);
+ ExpectIntEQ(count, 8);
+ ExpectIntEQ(wolfSSL_X509_get_aia_overflow(cert), 1);
+
+ wolfSSL_X509_email_free(ocsp);
+ wolfSSL_X509_free(cert);
+#endif
+ return EXPECT_RESULT();
+}
+
static int test_no_op_functions(void)
{
EXPECT_DECLS;
@@ -31666,6 +31769,9 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wolfSSL_OCSP_resp_get0),
TEST_DECL(test_wolfSSL_OCSP_parse_url),
TEST_DECL(test_wolfSSL_OCSP_REQ_CTX),
+ TEST_DECL(test_wolfSSL_X509_get1_ca_issuers),
+ TEST_DECL(test_wolfSSL_X509_get1_aia_multi),
+ TEST_DECL(test_wolfSSL_X509_get1_aia_overflow),
TEST_DECL(test_wolfSSL_PEM_read),
diff --git a/tests/api/test_aes.c b/tests/api/test_aes.c
index fd56d26585..ab921e7ce3 100644
--- a/tests/api/test_aes.c
+++ b/tests/api/test_aes.c
@@ -5222,3 +5222,742 @@ int test_wc_AesEaxDecryptAuth(void)
* (!HAVE_FIPS || FIPS_VERSION_GE(5, 3)) && !HAVE_SELFTEST
*/
+/*----------------------------------------------------------------------------*
+ | CryptoCB AES SetKey Test
+ *----------------------------------------------------------------------------*/
+
+#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_AES_SETKEY) && \
+ !defined(NO_AES) && defined(HAVE_AESGCM)
+
+#include
+
+#define TEST_CRYPTOCB_AES_DEVID 7
+
+/* Test state tracking */
+static int cryptoCbAesSetKeyCalled = 0;
+static int cryptoCbAesFreeCalled = 0;
+
+/* Simulated SE key storage - in real SE this would be in secure hardware */
+typedef struct {
+ byte key[AES_256_KEY_SIZE];
+ word32 keySz;
+ int valid;
+} MockSeKeySlot;
+
+static MockSeKeySlot mockSeKey = {0};
+
+/* Mock handle pointing to our key slot */
+static void* cryptoCbAesMockHandle = (void*)&mockSeKey;
+
+/* Test CryptoCB callback for AES key import operations
+ * This emulates a Secure Element by:
+ * - Storing the key on SetKey (simulating SE key import)
+ * - Using stored key for encrypt/decrypt (simulating SE crypto)
+ * - Clearing key on Free (simulating SE key deletion)
+ */
+static int test_CryptoCb_Aes_Cb(int devId, wc_CryptoInfo* info, void* ctx)
+{
+ (void)ctx;
+
+ if (devId != TEST_CRYPTOCB_AES_DEVID)
+ return CRYPTOCB_UNAVAILABLE;
+
+ /* AES SetKey operation - simulate SE key import */
+ if (info->algo_type == WC_ALGO_TYPE_CIPHER &&
+ info->cipher.type == WC_CIPHER_AES &&
+ info->cipher.aessetkey.aes != NULL) {
+
+ Aes* aes = info->cipher.aessetkey.aes;
+ const byte* key = info->cipher.aessetkey.key;
+ word32 keySz = info->cipher.aessetkey.keySz;
+
+ /* Validate key */
+ if (key == NULL || keySz == 0 || keySz > AES_256_KEY_SIZE) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* "Import" key to simulated SE storage */
+ XMEMCPY(mockSeKey.key, key, keySz);
+ mockSeKey.keySz = keySz;
+ mockSeKey.valid = 1;
+
+ /* Store handle in aes->devCtx - this is what wolfSSL will use */
+ aes->devCtx = cryptoCbAesMockHandle;
+
+
+ cryptoCbAesSetKeyCalled++;
+
+ return 0;
+ }
+
+ /* AES-GCM Encrypt - simulate SE encryption using stored key */
+ if (info->algo_type == WC_ALGO_TYPE_CIPHER &&
+ info->cipher.type == WC_CIPHER_AES_GCM &&
+ info->cipher.enc) {
+
+ Aes* aes = info->cipher.aesgcm_enc.aes;
+ MockSeKeySlot* slot;
+ Aes tempAes;
+ int ret;
+
+ /* Verify handle points to our key slot */
+ if (aes == NULL || aes->devCtx != cryptoCbAesMockHandle) {
+ return BAD_FUNC_ARG;
+ }
+
+ slot = (MockSeKeySlot*)aes->devCtx;
+ if (!slot->valid) {
+ return BAD_STATE_E;
+ }
+
+ /* Initialize a temporary Aes for software crypto (simulating SE internal operation) */
+ XMEMSET(&tempAes, 0, sizeof(tempAes));
+ ret = wc_AesInit(&tempAes, NULL, INVALID_DEVID); /* No CryptoCB for internal use */
+ if (ret != 0) return ret;
+
+ ret = wc_AesGcmSetKey(&tempAes, slot->key, slot->keySz);
+ if (ret != 0) {
+ wc_AesFree(&tempAes);
+ return ret;
+ }
+
+ /* Perform the actual encryption */
+ ret = wc_AesGcmEncrypt(&tempAes,
+ info->cipher.aesgcm_enc.out,
+ info->cipher.aesgcm_enc.in,
+ info->cipher.aesgcm_enc.sz,
+ info->cipher.aesgcm_enc.iv,
+ info->cipher.aesgcm_enc.ivSz,
+ info->cipher.aesgcm_enc.authTag,
+ info->cipher.aesgcm_enc.authTagSz,
+ info->cipher.aesgcm_enc.authIn,
+ info->cipher.aesgcm_enc.authInSz);
+
+ wc_AesFree(&tempAes);
+
+ return ret;
+ }
+
+ /* AES-GCM Decrypt - simulate SE decryption using stored key */
+ if (info->algo_type == WC_ALGO_TYPE_CIPHER &&
+ info->cipher.type == WC_CIPHER_AES_GCM &&
+ !info->cipher.enc) {
+
+ Aes* aes = info->cipher.aesgcm_dec.aes;
+ MockSeKeySlot* slot;
+ Aes tempAes;
+ int ret;
+
+ /* Verify handle points to our key slot */
+ if (aes == NULL || aes->devCtx != cryptoCbAesMockHandle) {
+ return BAD_FUNC_ARG;
+ }
+
+ slot = (MockSeKeySlot*)aes->devCtx;
+ if (!slot->valid) {
+ return BAD_STATE_E;
+ }
+
+ /* Initialize a temporary Aes for software crypto (simulating SE internal operation) */
+ XMEMSET(&tempAes, 0, sizeof(tempAes));
+ ret = wc_AesInit(&tempAes, NULL, INVALID_DEVID);
+ if (ret != 0) return ret;
+
+ ret = wc_AesGcmSetKey(&tempAes, slot->key, slot->keySz);
+ if (ret != 0) {
+ wc_AesFree(&tempAes);
+ return ret;
+ }
+
+ /* Perform the actual decryption */
+ ret = wc_AesGcmDecrypt(&tempAes,
+ info->cipher.aesgcm_dec.out,
+ info->cipher.aesgcm_dec.in,
+ info->cipher.aesgcm_dec.sz,
+ info->cipher.aesgcm_dec.iv,
+ info->cipher.aesgcm_dec.ivSz,
+ info->cipher.aesgcm_dec.authTag,
+ info->cipher.aesgcm_dec.authTagSz,
+ info->cipher.aesgcm_dec.authIn,
+ info->cipher.aesgcm_dec.authInSz);
+
+ wc_AesFree(&tempAes);
+
+ return ret;
+ }
+
+#ifdef WOLF_CRYPTO_CB_FREE
+ /* Free operation - simulate SE key deletion */
+ if (info->algo_type == WC_ALGO_TYPE_FREE &&
+ info->free.algo == WC_ALGO_TYPE_CIPHER &&
+ info->free.type == WC_CIPHER_AES) {
+
+ Aes* aes = (Aes*)info->free.obj;
+
+ if (aes != NULL && aes->devCtx == cryptoCbAesMockHandle) {
+ /* "Delete" key from simulated SE */
+ ForceZero(&mockSeKey, sizeof(mockSeKey));
+ cryptoCbAesFreeCalled++;
+ }
+
+ return 0;
+ }
+#endif
+
+ return CRYPTOCB_UNAVAILABLE;
+}
+
+/*
+ * Test: CryptoCB AES SetKey hook for key import / secure element support
+ */
+int test_wc_CryptoCb_AesSetKey(void)
+{
+ EXPECT_DECLS;
+#ifdef WOLFSSL_SMALL_STACK
+ Aes* aes = NULL;
+ byte* key = NULL;
+ byte* iv = NULL;
+ byte* plain = NULL;
+ byte* cipher = NULL;
+ byte* decrypted = NULL;
+ byte* authTag = NULL;
+#else
+ Aes aes[1];
+ byte key[AES_128_KEY_SIZE];
+ byte iv[GCM_NONCE_MID_SZ];
+ byte plain[16];
+ byte cipher[16];
+ byte decrypted[16];
+ byte authTag[AES_BLOCK_SIZE];
+#endif
+ int ret;
+
+#ifdef WOLFSSL_SMALL_STACK
+ aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ key = (byte*)XMALLOC(AES_128_KEY_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ iv = (byte*)XMALLOC(GCM_NONCE_MID_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ plain = (byte*)XMALLOC(16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ cipher = (byte*)XMALLOC(16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ decrypted = (byte*)XMALLOC(16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ authTag = (byte*)XMALLOC(AES_BLOCK_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ if (aes == NULL || key == NULL || iv == NULL || plain == NULL ||
+ cipher == NULL || decrypted == NULL || authTag == NULL) {
+ ret = MEMORY_E;
+ goto out;
+ }
+#endif
+
+ /* Initialize key, iv, plain arrays */
+ {
+ static const byte keyData[AES_128_KEY_SIZE] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+ static const byte plainData[16] = {
+ 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77,
+ 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x21, 0x00
+ };
+ XMEMCPY(key, keyData, AES_128_KEY_SIZE);
+ XMEMSET(iv, 0, GCM_NONCE_MID_SZ);
+ XMEMCPY(plain, plainData, 16);
+ }
+
+ XMEMSET(aes, 0, sizeof(Aes));
+ XMEMSET(&mockSeKey, 0, sizeof(mockSeKey));
+
+ /* Reset test state */
+ cryptoCbAesSetKeyCalled = 0;
+ cryptoCbAesFreeCalled = 0;
+
+ /* Register test callback */
+ ret = wc_CryptoCb_RegisterDevice(TEST_CRYPTOCB_AES_DEVID,
+ test_CryptoCb_Aes_Cb, NULL);
+ ExpectIntEQ(ret, 0);
+
+ /* Initialize Aes with device ID */
+ ret = wc_AesInit(aes, NULL, TEST_CRYPTOCB_AES_DEVID);
+ ExpectIntEQ(ret, 0);
+ ExpectIntEQ(aes->devId, TEST_CRYPTOCB_AES_DEVID);
+
+ /* Set key - should trigger CryptoCB and "import" to mock SE */
+ ret = wc_AesGcmSetKey(aes, key, sizeof(key));
+ ExpectIntEQ(ret, 0);
+
+ /* Verify callback was invoked */
+ ExpectIntEQ(cryptoCbAesSetKeyCalled, 1);
+
+ /* Verify handle stored in devCtx */
+ ExpectPtrEq(aes->devCtx, cryptoCbAesMockHandle);
+
+ /* Verify key was "imported" to mock SE */
+ ExpectIntEQ(mockSeKey.valid, 1);
+ ExpectIntEQ(mockSeKey.keySz, (int)sizeof(key));
+
+ /* Verify keylen metadata stored in Aes struct */
+ ExpectIntEQ(aes->keylen, (int)sizeof(key));
+
+ /* After SetKey succeeds via CryptoCB, verify key NOT in devKey */
+ {
+ byte zeroKey[AES_128_KEY_SIZE] = {0};
+ /* Key should NOT be copied to devKey - SE owns it */
+ ExpectIntEQ(XMEMCMP(aes->devKey, zeroKey, sizeof(key)), 0);
+ }
+
+ /* Test encrypt - callback performs crypto using stored key */
+ ret = wc_AesGcmEncrypt(aes, cipher, plain, sizeof(plain),
+ iv, sizeof(iv), authTag, sizeof(authTag),
+ NULL, 0);
+ ExpectIntEQ(ret, 0);
+
+ /* Test decrypt - callback performs crypto using stored key */
+ ret = wc_AesGcmDecrypt(aes, decrypted, cipher, sizeof(cipher),
+ iv, sizeof(iv), authTag, sizeof(authTag),
+ NULL, 0);
+ ExpectIntEQ(ret, 0);
+
+ /* Verify round-trip */
+ ExpectIntEQ(XMEMCMP(plain, decrypted, sizeof(plain)), 0);
+
+#ifdef WOLF_CRYPTO_CB_FREE
+ /* Free should trigger callback and "delete" key from mock SE */
+ cryptoCbAesFreeCalled = 0;
+ wc_AesFree(aes);
+
+ /* Verify free callback invoked */
+ ExpectIntEQ(cryptoCbAesFreeCalled, 1);
+
+ /* Verify devCtx cleared */
+ ExpectPtrEq(aes->devCtx, NULL);
+
+ /* Verify key was "deleted" from mock SE */
+ ExpectIntEQ(mockSeKey.valid, 0);
+#else
+ wc_AesFree(aes);
+#endif
+
+ /* Cleanup */
+ wc_CryptoCb_UnRegisterDevice(TEST_CRYPTOCB_AES_DEVID);
+
+ /* Test software path (no devId) still works */
+ XMEMSET(aes, 0, sizeof(Aes));
+ cryptoCbAesSetKeyCalled = 0;
+
+ ret = wc_AesInit(aes, NULL, INVALID_DEVID);
+ ExpectIntEQ(ret, 0);
+
+ ret = wc_AesGcmSetKey(aes, key, sizeof(key));
+ ExpectIntEQ(ret, 0);
+
+ /* Callback should NOT have been invoked */
+ ExpectIntEQ(cryptoCbAesSetKeyCalled, 0);
+
+ /* devCtx should be NULL */
+ ExpectPtrEq(aes->devCtx, NULL);
+
+ wc_AesFree(aes);
+
+#ifdef WOLFSSL_SMALL_STACK
+out:
+ XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(iv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(cipher, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(decrypted, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(authTag, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+ return EXPECT_RESULT();
+}
+
+#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_AES_SETKEY && !NO_AES && HAVE_AESGCM */
+
+/*----------------------------------------------------------------------------*
+ | CryptoCB AES-GCM End-to-End Offload Test
+ *----------------------------------------------------------------------------*/
+
+#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_AES_SETKEY) && \
+ !defined(NO_AES) && defined(HAVE_AESGCM)
+
+#define TEST_CRYPTOCB_AESGCM_OFFLOAD_DEVID 8
+
+/* Test state tracking for end-to-end offload test */
+static int cryptoCbAesGcmSetKeyCalled = 0;
+static int cryptoCbAesGcmEncryptCalled = 0;
+static int cryptoCbAesGcmDecryptCalled = 0;
+static int cryptoCbAesGcmFreeCalled = 0;
+
+/* Mock SE key storage for offload test */
+typedef struct {
+ byte key[AES_256_KEY_SIZE];
+ word32 keySz;
+ int valid;
+} MockSeKeySlotOffload;
+
+static MockSeKeySlotOffload mockSeKeyOffload = {0};
+
+/* Mock handle pointing to our key slot */
+static void* cryptoCbAesGcmMockHandle = (void*)&mockSeKeyOffload;
+
+/* Mock CryptoCB callback for end-to-end AES-GCM offload test
+ * This emulates a Secure Element that:
+ * - Stores the key on SetKey (simulating SE key import)
+ * - Performs encryption/decryption using stored key (simulating SE crypto)
+ * - Tracks all callback invocations to verify offload is working
+ * - Uses software AES internally (simulating SE internal operation)
+ */
+static int test_CryptoCb_AesGcm_Offload_Cb(int devId, wc_CryptoInfo* info, void* ctx)
+{
+ (void)ctx;
+
+ if (devId != TEST_CRYPTOCB_AESGCM_OFFLOAD_DEVID)
+ return CRYPTOCB_UNAVAILABLE;
+
+ /* AES SetKey operation - simulate SE key import */
+ if (info->algo_type == WC_ALGO_TYPE_CIPHER &&
+ info->cipher.type == WC_CIPHER_AES &&
+ info->cipher.aessetkey.aes != NULL) {
+
+ Aes* aes = info->cipher.aessetkey.aes;
+ const byte* key = info->cipher.aessetkey.key;
+ word32 keySz = info->cipher.aessetkey.keySz;
+
+ /* Validate key */
+ if (key == NULL || keySz == 0 || keySz > AES_256_KEY_SIZE) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* "Import" key to simulated SE storage */
+ XMEMCPY(mockSeKeyOffload.key, key, keySz);
+ mockSeKeyOffload.keySz = keySz;
+ mockSeKeyOffload.valid = 1;
+
+ /* Store handle in aes->devCtx - this is what wolfSSL will use */
+ aes->devCtx = cryptoCbAesGcmMockHandle;
+
+
+ cryptoCbAesGcmSetKeyCalled++;
+
+ return 0;
+ }
+
+ /* AES-GCM Encrypt - simulate SE encryption using stored key */
+ if (info->algo_type == WC_ALGO_TYPE_CIPHER &&
+ info->cipher.type == WC_CIPHER_AES_GCM &&
+ info->cipher.enc) {
+
+ Aes* aes = info->cipher.aesgcm_enc.aes;
+ MockSeKeySlotOffload* slot;
+ Aes tempAes;
+ int ret;
+
+ /* Verify handle points to our key slot */
+ if (aes == NULL || aes->devCtx != cryptoCbAesGcmMockHandle) {
+ return BAD_FUNC_ARG;
+ }
+
+ slot = (MockSeKeySlotOffload*)aes->devCtx;
+ if (!slot->valid) {
+ return BAD_STATE_E;
+ }
+
+ /* Track that encrypt callback was invoked */
+ cryptoCbAesGcmEncryptCalled++;
+
+ /* Initialize a temporary Aes for software crypto (simulating SE internal operation) */
+ XMEMSET(&tempAes, 0, sizeof(tempAes));
+ ret = wc_AesInit(&tempAes, NULL, INVALID_DEVID); /* No CryptoCB for internal use */
+ if (ret != 0) return ret;
+
+ ret = wc_AesGcmSetKey(&tempAes, slot->key, slot->keySz);
+ if (ret != 0) {
+ wc_AesFree(&tempAes);
+ return ret;
+ }
+
+ /* Perform the actual encryption using software AES (simulating SE internal operation) */
+ ret = wc_AesGcmEncrypt(&tempAes,
+ info->cipher.aesgcm_enc.out,
+ info->cipher.aesgcm_enc.in,
+ info->cipher.aesgcm_enc.sz,
+ info->cipher.aesgcm_enc.iv,
+ info->cipher.aesgcm_enc.ivSz,
+ info->cipher.aesgcm_enc.authTag,
+ info->cipher.aesgcm_enc.authTagSz,
+ info->cipher.aesgcm_enc.authIn,
+ info->cipher.aesgcm_enc.authInSz);
+
+ wc_AesFree(&tempAes);
+
+ return ret;
+ }
+
+ /* AES-GCM Decrypt - simulate SE decryption using stored key */
+ if (info->algo_type == WC_ALGO_TYPE_CIPHER &&
+ info->cipher.type == WC_CIPHER_AES_GCM &&
+ !info->cipher.enc) {
+
+ Aes* aes = info->cipher.aesgcm_dec.aes;
+ MockSeKeySlotOffload* slot;
+ Aes tempAes;
+ int ret;
+
+ /* Verify handle points to our key slot */
+ if (aes == NULL || aes->devCtx != cryptoCbAesGcmMockHandle) {
+ return BAD_FUNC_ARG;
+ }
+
+ slot = (MockSeKeySlotOffload*)aes->devCtx;
+ if (!slot->valid) {
+ return BAD_STATE_E;
+ }
+
+ /* Track that decrypt callback was invoked */
+ cryptoCbAesGcmDecryptCalled++;
+
+ /* Initialize a temporary Aes for software crypto (simulating SE internal operation) */
+ XMEMSET(&tempAes, 0, sizeof(tempAes));
+ ret = wc_AesInit(&tempAes, NULL, INVALID_DEVID);
+ if (ret != 0) return ret;
+
+ ret = wc_AesGcmSetKey(&tempAes, slot->key, slot->keySz);
+ if (ret != 0) {
+ wc_AesFree(&tempAes);
+ return ret;
+ }
+
+ /* Perform the actual decryption using software AES (simulating SE internal operation) */
+ ret = wc_AesGcmDecrypt(&tempAes,
+ info->cipher.aesgcm_dec.out,
+ info->cipher.aesgcm_dec.in,
+ info->cipher.aesgcm_dec.sz,
+ info->cipher.aesgcm_dec.iv,
+ info->cipher.aesgcm_dec.ivSz,
+ info->cipher.aesgcm_dec.authTag,
+ info->cipher.aesgcm_dec.authTagSz,
+ info->cipher.aesgcm_dec.authIn,
+ info->cipher.aesgcm_dec.authInSz);
+
+ wc_AesFree(&tempAes);
+
+ return ret;
+ }
+
+#ifdef WOLF_CRYPTO_CB_FREE
+ /* Free operation - simulate SE key deletion */
+ if (info->algo_type == WC_ALGO_TYPE_FREE &&
+ info->free.algo == WC_ALGO_TYPE_CIPHER &&
+ info->free.type == WC_CIPHER_AES) {
+
+ Aes* aes = (Aes*)info->free.obj;
+
+ if (aes != NULL && aes->devCtx == cryptoCbAesGcmMockHandle) {
+ /* "Delete" key from simulated SE */
+ ForceZero(&mockSeKeyOffload, sizeof(mockSeKeyOffload));
+ cryptoCbAesGcmFreeCalled++;
+ }
+
+ return 0;
+ }
+#endif
+
+ return CRYPTOCB_UNAVAILABLE;
+}
+
+/*
+ * Test: End-to-End AES-GCM Offload via CryptoCB
+ * This test verifies that:
+ * - AES-GCM encryption/decryption operations are routed through CryptoCb
+ * - Software AES is bypassed when offload is enabled
+ * - Encrypted output and auth tag are correct
+ * - Decryption via CryptoCb restores the original plaintext
+ */
+int test_wc_CryptoCb_AesGcm_EncryptDecrypt(void)
+{
+ EXPECT_DECLS;
+#ifdef WOLFSSL_SMALL_STACK
+ Aes* aes = NULL;
+ byte* key = NULL;
+ byte* iv = NULL;
+ byte* aad = NULL;
+ byte* plaintext = NULL;
+ byte* ciphertext = NULL;
+ byte* decrypted = NULL;
+ byte* authTag = NULL;
+#else
+ Aes aes[1];
+ byte key[AES_128_KEY_SIZE];
+ byte iv[GCM_NONCE_MID_SZ];
+ byte aad[16];
+ byte plaintext[32];
+ byte ciphertext[32];
+ byte decrypted[32];
+ byte authTag[AES_BLOCK_SIZE];
+#endif
+ int ret;
+ int i;
+ int hasNonZero = 0;
+
+#ifdef WOLFSSL_SMALL_STACK
+ aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ key = (byte*)XMALLOC(AES_128_KEY_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ iv = (byte*)XMALLOC(GCM_NONCE_MID_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ aad = (byte*)XMALLOC(16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ plaintext = (byte*)XMALLOC(32, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ ciphertext = (byte*)XMALLOC(32, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ decrypted = (byte*)XMALLOC(32, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ authTag = (byte*)XMALLOC(AES_BLOCK_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ if (aes == NULL || key == NULL || iv == NULL || aad == NULL ||
+ plaintext == NULL || ciphertext == NULL || decrypted == NULL ||
+ authTag == NULL) {
+ ret = MEMORY_E;
+ goto out;
+ }
+#endif
+
+ /* Initialize key, iv, aad, plaintext arrays */
+ {
+ static const byte keyData[AES_128_KEY_SIZE] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+ static const byte ivData[GCM_NONCE_MID_SZ] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b
+ };
+ static const byte aadData[16] = {
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
+ };
+ static const byte plaintextData[32] = {
+ 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77,
+ 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x21, 0x00,
+ 0x54, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x20, 0x32, 0x21, 0x00
+ };
+ XMEMCPY(key, keyData, AES_128_KEY_SIZE);
+ XMEMCPY(iv, ivData, GCM_NONCE_MID_SZ);
+ XMEMCPY(aad, aadData, 16);
+ XMEMCPY(plaintext, plaintextData, 32);
+ }
+
+ XMEMSET(aes, 0, sizeof(Aes));
+ XMEMSET(&mockSeKeyOffload, 0, sizeof(mockSeKeyOffload));
+ XMEMSET(ciphertext, 0, 32);
+ XMEMSET(decrypted, 0, 32);
+ XMEMSET(authTag, 0, AES_BLOCK_SIZE);
+
+ /* Reset test state */
+ cryptoCbAesGcmSetKeyCalled = 0;
+ cryptoCbAesGcmEncryptCalled = 0;
+ cryptoCbAesGcmDecryptCalled = 0;
+ cryptoCbAesGcmFreeCalled = 0;
+
+ /* Register test callback */
+ ret = wc_CryptoCb_RegisterDevice(TEST_CRYPTOCB_AESGCM_OFFLOAD_DEVID,
+ test_CryptoCb_AesGcm_Offload_Cb, NULL);
+ ExpectIntEQ(ret, 0);
+
+ /* Initialize Aes with device ID */
+ ret = wc_AesInit(aes, NULL, TEST_CRYPTOCB_AESGCM_OFFLOAD_DEVID);
+ ExpectIntEQ(ret, 0);
+ ExpectIntEQ(aes->devId, TEST_CRYPTOCB_AESGCM_OFFLOAD_DEVID);
+
+ /* Set key - should trigger CryptoCB and "import" to mock SE */
+ ret = wc_AesGcmSetKey(aes, key, sizeof(key));
+ ExpectIntEQ(ret, 0);
+
+ /* Verify SetKey callback was invoked */
+ ExpectIntEQ(cryptoCbAesGcmSetKeyCalled, 1);
+
+ /* Verify handle stored in devCtx */
+ ExpectPtrEq(aes->devCtx, cryptoCbAesGcmMockHandle);
+
+ /* Verify key was "imported" to mock SE */
+ ExpectIntEQ(mockSeKeyOffload.valid, 1);
+ ExpectIntEQ(mockSeKeyOffload.keySz, (int)sizeof(key));
+
+ /* Verify keylen metadata stored in Aes struct */
+ ExpectIntEQ(aes->keylen, (int)sizeof(key));
+
+ /* Encrypt via wolfCrypt API - should route through CryptoCb */
+ ret = wc_AesGcmEncrypt(aes, ciphertext, plaintext, 32,
+ iv, sizeof(iv), authTag, sizeof(authTag),
+ aad, 16);
+ ExpectIntEQ(ret, 0);
+
+ /* Assert: Encrypt callback was invoked */
+ ExpectIntEQ(cryptoCbAesGcmEncryptCalled, 1);
+
+ /* Assert: Ciphertext is different from plaintext */
+ ExpectIntNE(XMEMCMP(plaintext, ciphertext, 32), 0);
+
+ /* Assert: Auth tag is non-zero */
+ hasNonZero = 0;
+ for (i = 0; i < (int)sizeof(authTag); i++) {
+ if (authTag[i] != 0) {
+ hasNonZero = 1;
+ break;
+ }
+ }
+ ExpectIntEQ(hasNonZero, 1);
+
+ /* Decrypt via wolfCrypt API - should route through CryptoCb */
+ ret = wc_AesGcmDecrypt(aes, decrypted, ciphertext, 32,
+ iv, sizeof(iv), authTag, sizeof(authTag),
+ aad, 16);
+ ExpectIntEQ(ret, 0);
+
+ /* Assert: Decrypt callback was invoked */
+ ExpectIntEQ(cryptoCbAesGcmDecryptCalled, 1);
+
+ /* Assert: Decrypted plaintext matches original */
+ ExpectIntEQ(XMEMCMP(plaintext, decrypted, 32), 0);
+
+#ifdef WOLF_CRYPTO_CB_FREE
+ /* Free should trigger callback and "delete" key from mock SE */
+ cryptoCbAesGcmFreeCalled = 0;
+ wc_AesFree(aes);
+
+ /* Verify free callback invoked */
+ ExpectIntEQ(cryptoCbAesGcmFreeCalled, 1);
+
+ /* Verify devCtx cleared */
+ ExpectPtrEq(aes->devCtx, NULL);
+
+ /* Verify key was "deleted" from mock SE */
+ ExpectIntEQ(mockSeKeyOffload.valid, 0);
+#else
+ wc_AesFree(aes);
+#endif
+
+ /* Cleanup */
+ wc_CryptoCb_UnRegisterDevice(TEST_CRYPTOCB_AESGCM_OFFLOAD_DEVID);
+
+ /* Verify lifecycle: SetKey -> Encrypt -> Decrypt -> Free */
+ ExpectIntEQ(cryptoCbAesGcmSetKeyCalled, 1);
+ ExpectIntEQ(cryptoCbAesGcmEncryptCalled, 1);
+ ExpectIntEQ(cryptoCbAesGcmDecryptCalled, 1);
+#ifdef WOLF_CRYPTO_CB_FREE
+ ExpectIntEQ(cryptoCbAesGcmFreeCalled, 1);
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+out:
+ XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(iv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(aad, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(plaintext, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(ciphertext, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(decrypted, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(authTag, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+ return EXPECT_RESULT();
+}
+
+#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_AES_SETKEY && !NO_AES && HAVE_AESGCM */
+
diff --git a/tests/api/test_aes.h b/tests/api/test_aes.h
index 99265f3331..261f0484ad 100644
--- a/tests/api/test_aes.h
+++ b/tests/api/test_aes.h
@@ -53,6 +53,19 @@ int test_wc_AesEaxDecryptAuth(void);
int test_wc_GmacSetKey(void);
int test_wc_GmacUpdate(void);
+#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_AES_SETKEY) && \
+ !defined(NO_AES) && defined(HAVE_AESGCM)
+int test_wc_CryptoCb_AesSetKey(void);
+int test_wc_CryptoCb_AesGcm_EncryptDecrypt(void);
+#endif
+
+#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_AES_SETKEY) && \
+ !defined(NO_AES) && defined(HAVE_AESGCM)
+#define TEST_CRYPTOCB_AES_SETKEY_DECL , TEST_DECL_GROUP("aes", test_wc_CryptoCb_AesSetKey), \
+ TEST_DECL_GROUP("aes", test_wc_CryptoCb_AesGcm_EncryptDecrypt)
+#else
+#define TEST_CRYPTOCB_AES_SETKEY_DECL
+#endif
#define TEST_AES_DECLS \
TEST_DECL_GROUP("aes", test_wc_AesSetKey), \
@@ -74,7 +87,8 @@ int test_wc_GmacUpdate(void);
TEST_DECL_GROUP("aes", test_wc_AesCcmEncryptDecrypt), \
TEST_DECL_GROUP("aes", test_wc_AesXtsSetKey), \
TEST_DECL_GROUP("aes", test_wc_AesXtsEncryptDecrypt_Sizes), \
- TEST_DECL_GROUP("aes", test_wc_AesXtsEncryptDecrypt)
+ TEST_DECL_GROUP("aes", test_wc_AesXtsEncryptDecrypt) \
+ TEST_CRYPTOCB_AES_SETKEY_DECL
#if defined(WOLFSSL_AES_EAX) && defined(WOLFSSL_AES_256) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 3)) && !defined(HAVE_SELFTEST)
diff --git a/tests/api/test_ossl_x509_str.c b/tests/api/test_ossl_x509_str.c
index 79f1ce5581..d628e08b37 100644
--- a/tests/api/test_ossl_x509_str.c
+++ b/tests/api/test_ossl_x509_str.c
@@ -36,9 +36,8 @@
#include
#include
-#if defined(OPENSSL_ALL) && \
- !defined(NO_RSA) && !defined(NO_FILESYSTEM)
-
+#if defined(OPENSSL_ALL) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) && \
+ !defined(NO_ASN_TIME)
static int last_errcodes[10];
static int last_errdepths[10];
static int err_index = 0;
@@ -187,8 +186,7 @@ int test_wolfSSL_X509_STORE_check_time(void)
wolfSSL_X509_free(cert);
cert = NULL;
-#if defined(OPENSSL_ALL) && \
- !defined(NO_RSA) && !defined(NO_FILESYSTEM)
+#if defined(OPENSSL_ALL) && !defined(NO_RSA) && !defined(NO_FILESYSTEM)
err_index = 0;
diff --git a/tests/api/test_pkcs7.c b/tests/api/test_pkcs7.c
index d60e3abb67..eeaeec1cf6 100644
--- a/tests/api/test_pkcs7.c
+++ b/tests/api/test_pkcs7.c
@@ -388,12 +388,15 @@ int test_wc_PKCS7_EncodeData(void)
#if defined(HAVE_PKCS7) && defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && \
!defined(NO_RSA) && !defined(NO_SHA256)
-/* RSA sign raw digest callback */
+/* RSA sign raw digest callback
+ * This callback demonstrates HSM/secure element use case where the private
+ * key is not passed through PKCS7 structure but obtained independently.
+ */
static int rsaSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz,
byte* out, word32 outSz, byte* privateKey,
word32 privateKeySz, int devid, int hashOID)
{
- /* specific DigestInfo ASN.1 encoding prefix for a SHA2565 digest */
+ /* specific DigestInfo ASN.1 encoding prefix for a SHA256 digest */
byte digInfoEncoding[] = {
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
@@ -407,6 +410,11 @@ static int rsaSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz,
word32 idx = 0;
RsaKey rsa;
+ /* privateKey may be NULL in HSM/secure element use case - we load it
+ * independently in this callback to simulate that scenario */
+ (void)privateKey;
+ (void)privateKeySz;
+
/* SHA-256 required only for this example callback due to above
* digInfoEncoding[] */
if (pkcs7 == NULL || digest == NULL || out == NULL ||
@@ -427,7 +435,33 @@ static int rsaSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz,
return ret;
}
- ret = wc_RsaPrivateKeyDecode(privateKey, &idx, &rsa, privateKeySz);
+ /* Load key from test buffer - simulates HSM/secure element access */
+#if defined(USE_CERT_BUFFERS_2048)
+ ret = wc_RsaPrivateKeyDecode(client_key_der_2048, &idx, &rsa,
+ sizeof_client_key_der_2048);
+#elif defined(USE_CERT_BUFFERS_1024)
+ ret = wc_RsaPrivateKeyDecode(client_key_der_1024, &idx, &rsa,
+ sizeof_client_key_der_1024);
+#else
+ {
+ XFILE fp;
+ byte keyBuf[ONEK_BUF];
+ int keySz;
+
+ fp = XFOPEN("./certs/client-key.der", "rb");
+ if (fp == XBADFILE) {
+ wc_FreeRsaKey(&rsa);
+ return -1;
+ }
+ keySz = (int)XFREAD(keyBuf, 1, sizeof(keyBuf), fp);
+ XFCLOSE(fp);
+ if (keySz <= 0) {
+ wc_FreeRsaKey(&rsa);
+ return -1;
+ }
+ ret = wc_RsaPrivateKeyDecode(keyBuf, &idx, &rsa, (word32)keySz);
+ }
+#endif
/* sign DigestInfo */
if (ret == 0) {
@@ -451,6 +485,102 @@ static int rsaSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz,
}
#endif
+#if defined(HAVE_PKCS7) && defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && \
+ defined(HAVE_ECC) && !defined(NO_SHA256)
+/* ECC sign raw digest callback
+ * This callback demonstrates HSM/secure element use case where the private
+ * key is not passed through PKCS7 structure but obtained independently.
+ * Note: This example callback is hash-agnostic and will work with any
+ * hash algorithm. The hashOID parameter can be used to validate or select
+ * different signing behavior if needed.
+ */
+static int eccSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz,
+ byte* out, word32 outSz, byte* privateKey,
+ word32 privateKeySz, int devid, int hashOID)
+{
+ int ret;
+ word32 idx = 0;
+ word32 sigSz = outSz;
+#ifdef WOLFSSL_SMALL_STACK
+ ecc_key* ecc = NULL;
+#else
+ ecc_key ecc[1];
+#endif
+
+ /* privateKey may be NULL in HSM/secure element use case - we load it
+ * independently in this callback to simulate that scenario */
+ (void)privateKey;
+ (void)privateKeySz;
+ (void)hashOID;
+
+ if (pkcs7 == NULL || digest == NULL || out == NULL) {
+ return -1;
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ ecc = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, DYNAMIC_TYPE_ECC);
+ if (ecc == NULL) {
+ return MEMORY_E;
+ }
+#endif
+
+ /* set up ECC key */
+ ret = wc_ecc_init_ex(ecc, pkcs7->heap, devid);
+ if (ret != 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(ecc, pkcs7->heap, DYNAMIC_TYPE_ECC);
+ #endif
+ return ret;
+ }
+
+ /* Load key from test buffer - simulates HSM/secure element access */
+#if defined(USE_CERT_BUFFERS_256)
+ ret = wc_EccPrivateKeyDecode(ecc_clikey_der_256, &idx, ecc,
+ sizeof_ecc_clikey_der_256);
+#else
+ {
+ XFILE fp;
+ byte keyBuf[ONEK_BUF];
+ int keySz;
+
+ fp = XFOPEN("./certs/client-ecc-key.der", "rb");
+ if (fp == XBADFILE) {
+ wc_ecc_free(ecc);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(ecc, pkcs7->heap, DYNAMIC_TYPE_ECC);
+ #endif
+ return -1;
+ }
+ keySz = (int)XFREAD(keyBuf, 1, sizeof(keyBuf), fp);
+ XFCLOSE(fp);
+ if (keySz <= 0) {
+ wc_ecc_free(ecc);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(ecc, pkcs7->heap, DYNAMIC_TYPE_ECC);
+ #endif
+ return -1;
+ }
+ ret = wc_EccPrivateKeyDecode(keyBuf, &idx, ecc, (word32)keySz);
+ }
+#endif
+
+ /* sign digest */
+ if (ret == 0) {
+ ret = wc_ecc_sign_hash(digest, digestSz, out, &sigSz, pkcs7->rng, ecc);
+ if (ret == 0) {
+ ret = (int)sigSz;
+ }
+ }
+
+ wc_ecc_free(ecc);
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(ecc, pkcs7->heap, DYNAMIC_TYPE_ECC);
+#endif
+
+ return ret;
+}
+#endif
+
#if defined(HAVE_PKCS7) && defined(ASN_BER_TO_DER)
typedef struct encodeSignedDataStream {
byte out[FOURK_BUF*3];
@@ -757,8 +887,7 @@ int test_wc_PKCS7_EncodeSignedData(void)
if (pkcs7 != NULL) {
pkcs7->content = data;
pkcs7->contentSz = (word32)sizeof(data);
- pkcs7->privateKey = key;
- pkcs7->privateKeySz = (word32)sizeof(key);
+ /* privateKey not set - callback simulates HSM/secure element access */
pkcs7->encryptOID = RSAk;
pkcs7->hashOID = SHA256h;
pkcs7->rng = &rng;
@@ -769,6 +898,47 @@ int test_wc_PKCS7_EncodeSignedData(void)
ExpectIntGT(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), 0);
#endif
+#if defined(HAVE_PKCS7) && defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && \
+ defined(HAVE_ECC) && !defined(NO_SHA256)
+ /* test ECC sign raw digest callback, if using ECC and compiled in.
+ * Example callback assumes SHA-256, so only run test if compiled in. */
+ {
+ #if defined(USE_CERT_BUFFERS_256)
+ byte eccCert[sizeof(cliecc_cert_der_256)];
+ word32 eccCertSz = (word32)sizeof(eccCert);
+ XMEMCPY(eccCert, cliecc_cert_der_256, eccCertSz);
+ #else
+ byte eccCert[ONEK_BUF];
+ int eccCertSz;
+ XFILE eccFp = XBADFILE;
+
+ ExpectTrue((eccFp = XFOPEN("./certs/client-ecc-cert.der", "rb")) !=
+ XBADFILE);
+ ExpectIntGT(eccCertSz = (int)XFREAD(eccCert, 1, ONEK_BUF, eccFp), 0);
+ if (eccFp != XBADFILE)
+ XFCLOSE(eccFp);
+ #endif
+
+ wc_PKCS7_Free(pkcs7);
+ pkcs7 = NULL;
+ ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
+ ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, eccCert, (word32)eccCertSz), 0);
+
+ if (pkcs7 != NULL) {
+ pkcs7->content = data;
+ pkcs7->contentSz = (word32)sizeof(data);
+ /* privateKey not set - callback simulates HSM/secure element access */
+ pkcs7->encryptOID = ECDSAk;
+ pkcs7->hashOID = SHA256h;
+ pkcs7->rng = &rng;
+ }
+
+ ExpectIntEQ(wc_PKCS7_SetEccSignRawDigestCb(pkcs7, eccSignRawDigestCb), 0);
+
+ ExpectIntGT(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), 0);
+ }
+#endif
+
wc_PKCS7_Free(pkcs7);
DoExpectIntEQ(wc_FreeRng(&rng), 0);
diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c
index 3e1dcf050f..f6e2615e99 100644
--- a/wolfcrypt/benchmark/benchmark.c
+++ b/wolfcrypt/benchmark/benchmark.c
@@ -2683,9 +2683,9 @@ static WC_INLINE void bench_stats_start(int* count, double* start)
#endif
}
-#ifdef WOLFSSL_USE_SAVE_VECTOR_REGISTERS
+#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS)
#define bench_stats_start(count, start) do { \
- SAVE_VECTOR_REGISTERS(pr_err( \
+ SAVE_VECTOR_REGISTERS(WOLFSSL_DEBUG_PRINTF( \
"ERROR: SAVE_VECTOR_REGISTERS failed for benchmark run."); \
return; ); \
bench_stats_start(count, start); \
@@ -3161,7 +3161,7 @@ static void bench_stats_sym_finish(const char* desc, int useDeviceID,
(void)useDeviceID;
(void)ret;
-#ifdef WOLFSSL_USE_SAVE_VECTOR_REGISTERS
+#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS)
RESTORE_VECTOR_REGISTERS();
#elif defined(WOLFSSL_LINUXKM)
kernel_fpu_end();
@@ -3559,7 +3559,7 @@ static void bench_stats_asym_finish_ex(const char* algo, int strength,
(void)useDeviceID;
(void)ret;
-#ifdef WOLFSSL_USE_SAVE_VECTOR_REGISTERS
+#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS)
RESTORE_VECTOR_REGISTERS();
#elif defined(WOLFSSL_LINUXKM)
kernel_fpu_end();
@@ -16024,6 +16024,20 @@ void bench_sphincsKeySign(byte level, byte optim)
return (double)ns / 1000000000.0;
}
+#elif defined(WOLFSSL_BSDKM)
+
+ #include
+ double current_time(int reset)
+ {
+ (void)reset;
+ struct timespec ts;
+ int64_t result = 0;
+
+ getnanouptime(&ts);
+ result = (int64_t) ts.tv_sec + (int64_t) ts.tv_nsec / NANOSECOND;
+ return (double)result;
+ }
+
#elif defined(WOLFSSL_GAISLER_BCC)
#include
diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c
index 8abec2905f..7217c7f871 100644
--- a/wolfcrypt/src/aes.c
+++ b/wolfcrypt/src/aes.c
@@ -4365,6 +4365,24 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(
#ifdef WOLF_CRYPTO_CB
if (aes->devId != INVALID_DEVID) {
+ #ifdef WOLF_CRYPTO_CB_AES_SETKEY
+ int ret = wc_CryptoCb_AesSetKey(aes, userKey, keylen);
+ if (ret == 0) {
+ /* Callback succeeded - SE owns the key */
+ aes->keylen = (int)keylen;
+ if (iv != NULL)
+ XMEMCPY(aes->reg, iv, WC_AES_BLOCK_SIZE);
+ else
+ XMEMSET(aes->reg, 0, WC_AES_BLOCK_SIZE);
+ return 0;
+ }
+ else if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
+ aes->devCtx = NULL;
+ return ret;
+ }
+ /* CRYPTOCB_UNAVAILABLE: continue to software setup */
+ #endif
+ /* Standard CryptoCB path - copy key to devKey for encrypt/decrypt offload */
if (keylen > sizeof(aes->devKey)) {
return BAD_FUNC_ARG;
}
@@ -4791,6 +4809,33 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir)
return BAD_FUNC_ARG;
}
+ #ifdef WOLF_CRYPTO_CB
+ if (aes->devId != INVALID_DEVID) {
+ #ifdef WOLF_CRYPTO_CB_AES_SETKEY
+ ret = wc_CryptoCb_AesSetKey(aes, userKey, keylen);
+ if (ret == 0) {
+ /* Callback succeeded - SE owns the key */
+ aes->keylen = (int)keylen;
+ if (iv != NULL)
+ XMEMCPY(aes->reg, iv, WC_AES_BLOCK_SIZE);
+ else
+ XMEMSET(aes->reg, 0, WC_AES_BLOCK_SIZE);
+ return 0;
+ }
+ else if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
+ aes->devCtx = NULL;
+ return ret;
+ }
+ /* CRYPTOCB_UNAVAILABLE: continue to software setup */
+ #endif
+ /* Standard CryptoCB path - copy key to devKey */
+ if (keylen > sizeof(aes->devKey)) {
+ return BAD_FUNC_ARG;
+ }
+ XMEMCPY(aes->devKey, userKey, keylen);
+ }
+ #endif
+
#ifdef WOLFSSL_MAXQ10XX_CRYPTO
if (wc_MAXQ10XX_AesSetKey(aes, userKey, keylen) != 0) {
return WC_HW_E;
@@ -7454,46 +7499,55 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
}
#else
#if !defined(FREESCALE_LTC_AES_GCM) && !defined(WOLFSSL_PSOC6_CRYPTO)
+
+
+#ifdef WOLF_CRYPTO_CB_AES_SETKEY
+ if ((ret == 0) && (aes->devId != INVALID_DEVID && aes->devCtx != NULL)) {
+ /* SE owns key - skip H and M table generation */
+ }
+ else
+#endif
if (ret == 0) {
VECTOR_REGISTERS_PUSH;
- /* AES-NI code generates its own H value, but generate it here too, to
- * assure pure-C fallback is always usable.
- */
+
+ /* Generate H = AES_Encrypt(key, 0^128) */
ret = wc_AesEncrypt(aes, iv, aes->gcm.H);
if (ret == 0) {
- #if defined(GCM_TABLE) || defined(GCM_TABLE_4BIT)
+#if defined(GCM_TABLE) || defined(GCM_TABLE_4BIT)
#if defined(WOLFSSL_AESNI) && defined(GCM_TABLE_4BIT)
if (aes->use_aesni) {
#if defined(WC_C_DYNAMIC_FALLBACK)
#ifdef HAVE_INTEL_AVX2
if (IS_INTEL_AVX2(intel_flags)) {
- GCM_generate_m0_avx2(aes->gcm.H, (byte*)aes->gcm.M0);
+ GCM_generate_m0_avx2(aes->gcm.H,
+ (byte*)aes->gcm.M0);
}
else
#endif
#if defined(HAVE_INTEL_AVX1)
if (IS_INTEL_AVX1(intel_flags)) {
- GCM_generate_m0_avx1(aes->gcm.H, (byte*)aes->gcm.M0);
+ GCM_generate_m0_avx1(aes->gcm.H,
+ (byte*)aes->gcm.M0);
}
else
#endif
{
- GCM_generate_m0_aesni(aes->gcm.H, (byte*)aes->gcm.M0);
+ GCM_generate_m0_aesni(aes->gcm.H,
+ (byte*)aes->gcm.M0);
}
- #endif
+ #endif /* WC_C_DYNAMIC_FALLBACK */
}
else
- #endif
+ #endif /* AESNI */
{
GenerateM0(&aes->gcm);
}
- #endif /* GCM_TABLE || GCM_TABLE_4BIT */
+#endif /* GCM_TABLE || GCM_TABLE_4BIT */
}
VECTOR_REGISTERS_POP;
}
-
#endif /* !FREESCALE_LTC_AES_GCM && !WOLFSSL_PSOC6_CRYPTO */
#endif
@@ -7503,7 +7557,15 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
#ifdef WOLF_CRYPTO_CB
if (aes->devId != INVALID_DEVID) {
- XMEMCPY(aes->devKey, key, len);
+ #ifdef WOLF_CRYPTO_CB_AES_SETKEY
+ if (aes->devCtx != NULL) {
+ /* SE owns key - don't copy to devKey */
+ }
+ else
+ #endif
+ {
+ XMEMCPY(aes->devKey, key, len);
+ }
}
#endif
@@ -13302,6 +13364,7 @@ int wc_AesInit(Aes* aes, void* heap, int devId)
#if defined(WOLF_CRYPTO_CB) || defined(WOLFSSL_STM32U5_DHUK)
aes->devId = devId;
+ aes->devCtx = NULL;
#else
(void)devId;
#endif
@@ -13383,10 +13446,6 @@ int wc_AesInit_Label(Aes* aes, const char* label, void* heap, int devId)
/* Free Aes resources */
void wc_AesFree(Aes* aes)
{
-#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE)
- int ret = 0;
-#endif
-
if (aes == NULL) {
return;
}
@@ -13396,19 +13455,17 @@ void wc_AesFree(Aes* aes)
if (aes->devId != INVALID_DEVID)
#endif
{
- ret = wc_CryptoCb_Free(aes->devId, WC_ALGO_TYPE_CIPHER,
- WC_CIPHER_AES, (void*)aes);
- /* If they want the standard free, they can call it themselves */
- /* via their callback setting devId to INVALID_DEVID */
- /* otherwise assume the callback handled it */
+ int ret = wc_CryptoCb_Free(aes->devId, WC_ALGO_TYPE_CIPHER,
+ WC_CIPHER_AES, aes);
+ #ifdef WOLF_CRYPTO_CB_AES_SETKEY
+ aes->devCtx = NULL; /* Clear device context handle */
+ #endif
+ /* If callback wants standard free, it can set devId to INVALID_DEVID.
+ * Otherwise assume the callback handled cleanup. */
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return;
/* fall-through when unavailable */
}
-
- /* silence compiler warning */
- (void)ret;
-
#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_FREE */
#ifdef WC_DEBUG_CIPHER_LIFECYCLE
diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c
index 4ea0743ce6..c2f48e98d2 100644
--- a/wolfcrypt/src/asn.c
+++ b/wolfcrypt/src/asn.c
@@ -13839,7 +13839,18 @@ static int StoreEccKey(DecodedCert* cert, const byte* source, word32* srcIdx,
ret = ASN_PARSE_E;
#endif
}
-
+ #if defined(WOLFSSL_RENESAS_FSPSM_TLS) || defined(WOLFSSL_RENESAS_TSIP_TLS)
+ cert->sigCtx.CertAtt.pubkey_n_start =
+ cert->sigCtx.CertAtt.pubkey_e_start =
+ GetASNItem_DataIdx(
+ dataASN[ECCCERTKEYASN_IDX_SUBJPUBKEY], source) + 1;
+ cert->sigCtx.CertAtt.pubkey_n_len =
+ ((dataASN[ECCCERTKEYASN_IDX_SUBJPUBKEY].data.ref.length - 1) >> 1);
+ cert->sigCtx.CertAtt.pubkey_e_start +=
+ cert->sigCtx.CertAtt.pubkey_n_len;
+ cert->sigCtx.CertAtt.pubkey_e_len =
+ cert->sigCtx.CertAtt.pubkey_n_len;
+ #endif
#ifdef WOLFSSL_MAXQ10XX_TLS
cert->publicKeyIndex =
GetASNItem_DataIdx(dataASN[ECCCERTKEYASN_IDX_SUBJPUBKEY], source)
@@ -21195,6 +21206,7 @@ static int DecodeAuthInfo(const byte* input, word32 sz, DecodedCert* cert)
int length = 0;
byte b = 0;
word32 oid;
+ int aiaIdx;
WOLFSSL_ENTER("DecodeAuthInfo");
@@ -21219,14 +21231,29 @@ static int DecodeAuthInfo(const byte* input, word32 sz, DecodedCert* cert)
if (GetLength(input, &idx, &length, sz) < 0)
return ASN_PARSE_E;
- /* Set ocsp entry */
+ if (b == GENERALNAME_URI) {
+ /* Add to AIA list if space. */
+ aiaIdx = cert->extAuthInfoListSz;
+ if (aiaIdx < WOLFSSL_MAX_AIA_ENTRIES) {
+ cert->extAuthInfoList[aiaIdx].method = oid;
+ cert->extAuthInfoList[aiaIdx].uri = input + idx;
+ cert->extAuthInfoList[aiaIdx].uriSz = (word32)length;
+ cert->extAuthInfoListSz++;
+ }
+ else {
+ cert->extAuthInfoListOverflow = 1;
+ WOLFSSL_MSG("AIA list overflow");
+ }
+ }
+
+ /* Set first ocsp entry */
if (b == GENERALNAME_URI && oid == AIA_OCSP_OID &&
cert->extAuthInfo == NULL) {
cert->extAuthInfoSz = length;
cert->extAuthInfo = input + idx;
}
#ifdef WOLFSSL_ASN_CA_ISSUER
- /* Set CaIssuers entry */
+ /* Set first CaIssuers entry */
else if ((b == GENERALNAME_URI) && oid == AIA_CA_ISSUER_OID &&
cert->extAuthInfoCaIssuer == NULL)
{
@@ -21242,6 +21269,7 @@ static int DecodeAuthInfo(const byte* input, word32 sz, DecodedCert* cert)
word32 idx = 0;
int length = 0;
int ret = 0;
+ int aiaIdx;
WOLFSSL_ENTER("DecodeAuthInfo");
@@ -21263,27 +21291,41 @@ static int DecodeAuthInfo(const byte* input, word32 sz, DecodedCert* cert)
if (ret == 0) {
word32 sz32;
- /* Check we have OCSP and URI. */
- if ((dataASN[ACCESSDESCASN_IDX_METH].data.oid.sum == AIA_OCSP_OID) &&
- (dataASN[ACCESSDESCASN_IDX_LOC].tag == GENERALNAME_URI) &&
- (cert->extAuthInfo == NULL)) {
- /* Store URI for OCSP lookup. */
- GetASN_GetConstRef(&dataASN[ACCESSDESCASN_IDX_LOC],
- &cert->extAuthInfo, &sz32);
- cert->extAuthInfoSz = (int)sz32;
+ if (dataASN[ACCESSDESCASN_IDX_LOC].tag == GENERALNAME_URI) {
+ const byte* uri = NULL;
+
+ GetASN_GetConstRef(&dataASN[ACCESSDESCASN_IDX_LOC], &uri, &sz32);
+
+ /* Add to AIA list if space. */
+ aiaIdx = cert->extAuthInfoListSz;
+ if (aiaIdx < WOLFSSL_MAX_AIA_ENTRIES) {
+ cert->extAuthInfoList[aiaIdx].method =
+ dataASN[ACCESSDESCASN_IDX_METH].data.oid.sum;
+ cert->extAuthInfoList[aiaIdx].uri = uri;
+ cert->extAuthInfoList[aiaIdx].uriSz = sz32;
+ cert->extAuthInfoListSz++;
+ }
+ else {
+ cert->extAuthInfoListOverflow = 1;
+ WOLFSSL_MSG("AIA list overflow");
+ }
+
+ /* Set first OCSP entry. */
+ if ((dataASN[ACCESSDESCASN_IDX_METH].data.oid.sum ==
+ AIA_OCSP_OID) && (cert->extAuthInfo == NULL)) {
+ cert->extAuthInfo = uri;
+ cert->extAuthInfoSz = (int)sz32;
+ }
+ #ifdef WOLFSSL_ASN_CA_ISSUER
+ /* Set first CA Issuer entry. */
+ else if ((dataASN[ACCESSDESCASN_IDX_METH].data.oid.sum ==
+ AIA_CA_ISSUER_OID) &&
+ (cert->extAuthInfoCaIssuer == NULL)) {
+ cert->extAuthInfoCaIssuer = uri;
+ cert->extAuthInfoCaIssuerSz = (int)sz32;
+ }
+ #endif
}
- #ifdef WOLFSSL_ASN_CA_ISSUER
- /* Check we have CA Issuer and URI. */
- else if ((dataASN[ACCESSDESCASN_IDX_METH].data.oid.sum ==
- AIA_CA_ISSUER_OID) &&
- (dataASN[ACCESSDESCASN_IDX_LOC].tag == GENERALNAME_URI) &&
- (cert->extAuthInfoCaIssuer == NULL)) {
- /* Set CaIssuers entry */
- GetASN_GetConstRef(&dataASN[ACCESSDESCASN_IDX_LOC],
- &cert->extAuthInfoCaIssuer, &sz32);
- cert->extAuthInfoCaIssuerSz = (int)sz32;
- }
- #endif
/* Otherwise skip. */
}
}
diff --git a/wolfcrypt/src/cpuid.c b/wolfcrypt/src/cpuid.c
index 5c3e333ffe..9d9b458e8a 100644
--- a/wolfcrypt/src/cpuid.c
+++ b/wolfcrypt/src/cpuid.c
@@ -113,7 +113,11 @@
static WC_INLINE void cpuid_set_flags(void)
{
+ #ifdef WOLFSSL_BSDKM
+ if (WOLFSSL_ATOMIC_LOAD_UINT(cpuid_flags) == WC_CPUID_INITIALIZER) {
+ #else
if (WOLFSSL_ATOMIC_LOAD(cpuid_flags) == WC_CPUID_INITIALIZER) {
+ #endif
cpuid_flags_t new_cpuid_flags = 0,
old_cpuid_flags = WC_CPUID_INITIALIZER;
if (cpuid_flag(1, 0, ECX, 28)) { new_cpuid_flags |= CPUID_AVX1 ; }
diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c
index 04051041bd..bb56894214 100644
--- a/wolfcrypt/src/cryptocb.c
+++ b/wolfcrypt/src/cryptocb.c
@@ -1537,6 +1537,36 @@ int wc_CryptoCb_AesEcbDecrypt(Aes* aes, byte* out,
return wc_CryptoCb_TranslateErrorCode(ret);
}
#endif /* HAVE_AES_ECB */
+
+#ifdef WOLF_CRYPTO_CB_AES_SETKEY
+int wc_CryptoCb_AesSetKey(Aes* aes, const byte* key, word32 keySz)
+{
+ int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
+ CryptoCb* dev;
+
+ if (aes == NULL || key == NULL)
+ return BAD_FUNC_ARG;
+
+ if (aes->devId == INVALID_DEVID)
+ return CRYPTOCB_UNAVAILABLE;
+
+ /* locate registered callback */
+ dev = wc_CryptoCb_FindDevice(aes->devId, WC_ALGO_TYPE_CIPHER);
+ if (dev && dev->cb) {
+ wc_CryptoInfo cryptoInfo;
+ XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
+ cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER;
+ cryptoInfo.cipher.type = WC_CIPHER_AES;
+ cryptoInfo.cipher.aessetkey.aes = aes;
+ cryptoInfo.cipher.aessetkey.key = key;
+ cryptoInfo.cipher.aessetkey.keySz = keySz;
+
+ ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
+ }
+
+ return wc_CryptoCb_TranslateErrorCode(ret);
+}
+#endif /* WOLF_CRYPTO_CB_AES_SETKEY */
#endif /* !NO_AES */
#ifndef NO_DES3
diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c
index da309eb2ab..c34e140d6b 100644
--- a/wolfcrypt/src/ecc.c
+++ b/wolfcrypt/src/ecc.c
@@ -13214,7 +13214,7 @@ int ecc_mul2add(ecc_point* A, mp_int* kA,
err = add_entry(idx1, A);
}
}
- if (err == MP_OKAY && idx1 != -1) {
+ if (err == MP_OKAY && idx1 != -1 && fp_cache[idx1].lru_count < (INT_MAX-1)) {
/* increment LRU */
++(fp_cache[idx1].lru_count);
}
@@ -13231,7 +13231,7 @@ int ecc_mul2add(ecc_point* A, mp_int* kA,
}
}
- if (err == MP_OKAY && idx2 != -1) {
+ if (err == MP_OKAY && idx2 != -1 && fp_cache[idx2].lru_count < (INT_MAX-1)) {
/* increment LRU */
++(fp_cache[idx2].lru_count);
}
@@ -13368,7 +13368,7 @@ int wc_ecc_mulmod_ex(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
if (idx >= 0)
err = add_entry(idx, G);
}
- if (err == MP_OKAY && idx >= 0) {
+ if (err == MP_OKAY && idx >= 0 && fp_cache[idx].lru_count < (INT_MAX-1)) {
/* increment LRU */
++(fp_cache[idx].lru_count);
}
@@ -13539,7 +13539,7 @@ int wc_ecc_mulmod_ex2(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
if (idx >= 0)
err = add_entry(idx, G);
}
- if (err == MP_OKAY && idx >= 0) {
+ if (err == MP_OKAY && idx >= 0 && fp_cache[idx].lru_count < (INT_MAX-1)) {
/* increment LRU */
++(fp_cache[idx].lru_count);
}
diff --git a/wolfcrypt/src/evp_pk.c b/wolfcrypt/src/evp_pk.c
new file mode 100644
index 0000000000..27801f010c
--- /dev/null
+++ b/wolfcrypt/src/evp_pk.c
@@ -0,0 +1,1909 @@
+/* evp_pk.c
+ *
+ * Copyright (C) 2006-2025 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#include
+
+#if !defined(WOLFSSL_EVP_PK_INCLUDED)
+ #ifndef WOLFSSL_IGNORE_FILE_WARN
+ #warning evp_pk.c does not need to be compiled separately from ssl.c
+ #endif
+#elif defined(WOLFCRYPT_ONLY)
+#else
+
+/*******************************************************************************
+ * START OF d2i APIs
+ ******************************************************************************/
+
+#ifndef NO_CERTS
+
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+/**
+ * Make an EVP PKEY and put data and type in.
+ *
+ * @param [in, out] out On in, an EVP PKEY or NULL.
+ * On out, an EVP PKEY or NULL.
+ * @param [in] mem Memory containing key data.
+ * @param [in] memSz Size of key data in bytes.
+ * @param [in] priv 1 means private key, 0 means public key.
+ * @param [in] type The type of public/private key.
+ * @return 1 on success.
+ * @return 0 otherwise.
+ */
+static int d2i_make_pkey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
+ word32 memSz, int priv, int type)
+{
+ WOLFSSL_EVP_PKEY* pkey;
+ int ret = 1;
+
+ /* Get or create the EVP PKEY object. */
+ if (*out != NULL) {
+ pkey = *out;
+ }
+ else {
+ pkey = wolfSSL_EVP_PKEY_new();
+ if (pkey == NULL) {
+ WOLFSSL_MSG("wolfSSL_EVP_PKEY_new error");
+ return 0;
+ }
+ }
+
+ /* Set the size and allocate memory for key data to be copied into. */
+ pkey->pkey_sz = (int)memSz;
+ pkey->pkey.ptr = (char*)XMALLOC((size_t)memSz, NULL,
+ priv ? DYNAMIC_TYPE_PRIVATE_KEY : DYNAMIC_TYPE_PUBLIC_KEY);
+ if (pkey->pkey.ptr == NULL) {
+ ret = 0;
+ }
+ if (ret == 1) {
+ /* Copy in key data, set key type passed in and return object. */
+ XMEMCPY(pkey->pkey.ptr, mem, memSz);
+ pkey->type = type;
+ *out = pkey;
+ }
+ if ((ret == 0) && (*out == NULL)) {
+ /* Dispose of object allocated in this function. */
+ wolfSSL_EVP_PKEY_free(pkey);
+ }
+
+ return ret;
+}
+
+#if !defined(NO_RSA)
+/**
+ * Try to make an RSA EVP PKEY from data.
+ *
+ * @param [in, out] out On in, an EVP PKEY or NULL.
+ * On out, an EVP PKEY or NULL.
+ * @param [in] mem Memory containing key data.
+ * @param [in] memSz Size of key data in bytes.
+ * @param [in] priv 1 means private key, 0 means public key.
+ * @return 1 on success.
+ * @return 0 otherwise.
+ */
+static int d2iTryRsaKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
+ long memSz, int priv)
+{
+ WOLFSSL_RSA* rsaObj = NULL;
+ word32 keyIdx = 0;
+ int isRsaKey;
+ int ret = 1;
+ WC_DECLARE_VAR(rsa, RsaKey, 1, NULL);
+
+ WC_ALLOC_VAR_EX(rsa, RsaKey, 1, NULL, DYNAMIC_TYPE_RSA, return 0);
+
+ XMEMSET(rsa, 0, sizeof(RsaKey));
+
+ if (wc_InitRsaKey(rsa, NULL) != 0) {
+ WC_FREE_VAR_EX(rsa, NULL, DYNAMIC_TYPE_RSA);
+ return 0;
+ }
+ /* Try decoding data as an RSA private/public key. */
+ if (priv) {
+ isRsaKey =
+ (wc_RsaPrivateKeyDecode(mem, &keyIdx, rsa, (word32)memSz) == 0);
+ }
+ else {
+ isRsaKey =
+ (wc_RsaPublicKeyDecode(mem, &keyIdx, rsa, (word32)memSz) == 0);
+ }
+ wc_FreeRsaKey(rsa);
+ WC_FREE_VAR_EX(rsa, NULL, DYNAMIC_TYPE_RSA);
+
+ if (!isRsaKey) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Create RSA key object from data. */
+ rsaObj = wolfssl_rsa_d2i(NULL, mem, keyIdx,
+ priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC);
+ if (rsaObj == NULL) {
+ ret = 0;
+ }
+ if (ret == 1) {
+ /* Create an EVP PKEY object. */
+ ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_RSA);
+ }
+ if (ret == 1) {
+ /* Put RSA key object into EVP PKEY object. */
+ (*out)->ownRsa = 1;
+ (*out)->rsa = rsaObj;
+ }
+ if (ret == 0) {
+ wolfSSL_RSA_free(rsaObj);
+ }
+
+ return ret;
+}
+#endif /* !NO_RSA */
+
+#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA)
+/**
+ * Try to make an ECC EVP PKEY from data.
+ *
+ * @param [in, out] out On in, an EVP PKEY or NULL.
+ * On out, an EVP PKEY or NULL.
+ * @param [in] mem Memory containing key data.
+ * @param [in] memSz Size of key data in bytes.
+ * @param [in] priv 1 means private key, 0 means public key.
+ * @return 1 on success.
+ * @return 0 otherwise.
+ */
+static int d2iTryEccKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
+ long memSz, int priv)
+{
+ WOLFSSL_EC_KEY* ec = NULL;
+ word32 keyIdx = 0;
+ int isEccKey;
+ int ret = 1;
+ WC_DECLARE_VAR(ecc, ecc_key, 1, NULL);
+
+ WC_ALLOC_VAR_EX(ecc, ecc_key, 1, NULL, DYNAMIC_TYPE_ECC, return 0);
+
+ XMEMSET(ecc, 0, sizeof(ecc_key));
+
+ if (wc_ecc_init(ecc) != 0) {
+ WC_FREE_VAR_EX(ecc, NULL, DYNAMIC_TYPE_ECC);
+ return 0;
+ }
+
+ /* Try decoding data as an ECC private/public key. */
+ if (priv) {
+ isEccKey =
+ (wc_EccPrivateKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0);
+ }
+ else {
+ isEccKey =
+ (wc_EccPublicKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0);
+ }
+ wc_ecc_free(ecc);
+ WC_FREE_VAR_EX(ecc, NULL, DYNAMIC_TYPE_ECC);
+
+ if (!isEccKey) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Create EC key object from data. */
+ ec = wolfSSL_EC_KEY_new();
+ if (ec == NULL) {
+ ret = 0;
+ }
+ if ((ret == 1) && (wolfSSL_EC_KEY_LoadDer_ex(ec, mem, keyIdx,
+ priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC) != 1)) {
+ ret = 0;
+ }
+ if (ret == 1) {
+ /* Create an EVP PKEY object. */
+ ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_EC);
+ }
+ if (ret == 1) {
+ /* Put RSA key object into EVP PKEY object. */
+ (*out)->ownEcc = 1;
+ (*out)->ecc = ec;
+ }
+ if (ret == 0) {
+ wolfSSL_EC_KEY_free(ec);
+ }
+
+ return ret;
+}
+#endif /* HAVE_ECC && OPENSSL_EXTRA */
+
+#if !defined(NO_DSA)
+/**
+ * Try to make a DSA EVP PKEY from data.
+ *
+ * @param [in, out] out On in, an EVP PKEY or NULL.
+ * On out, an EVP PKEY or NULL.
+ * @param [in] mem Memory containing key data.
+ * @param [in] memSz Size of key data in bytes.
+ * @param [in] priv 1 means private key, 0 means public key.
+ * @return 1 on success.
+ * @return 0 otherwise.
+ */
+static int d2iTryDsaKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
+ long memSz, int priv)
+{
+ WOLFSSL_DSA* dsaObj;
+ word32 keyIdx = 0;
+ int isDsaKey;
+ int ret = 1;
+ WC_DECLARE_VAR(dsa, DsaKey, 1, NULL);
+
+ WC_ALLOC_VAR_EX(dsa, DsaKey, 1, NULL, DYNAMIC_TYPE_DSA, return 0);
+
+ XMEMSET(dsa, 0, sizeof(DsaKey));
+
+ if (wc_InitDsaKey(dsa) != 0) {
+ WC_FREE_VAR_EX(dsa, NULL, DYNAMIC_TYPE_DSA);
+ return 0;
+ }
+
+ /* Try decoding data as a DSA private/public key. */
+ if (priv) {
+ isDsaKey =
+ (wc_DsaPrivateKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0);
+ }
+ else {
+ isDsaKey =
+ (wc_DsaPublicKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0);
+ }
+ wc_FreeDsaKey(dsa);
+ WC_FREE_VAR_EX(dsa, NULL, DYNAMIC_TYPE_DSA);
+
+ /* test if DSA key */
+ if (!isDsaKey) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Create DSA key object from data. */
+ dsaObj = wolfSSL_DSA_new();
+ if (dsaObj == NULL) {
+ ret = 0;
+ }
+ if ((ret == 1) && (wolfSSL_DSA_LoadDer_ex(dsaObj, mem, keyIdx,
+ priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC) != 1)) {
+ ret = 0;
+ }
+ if (ret == 1) {
+ /* Create an EVP PKEY object. */
+ ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_DSA);
+ }
+ if (ret == 1) {
+ /* Put RSA key object into EVP PKEY object. */
+ (*out)->ownDsa = 1;
+ (*out)->dsa = dsaObj;
+ }
+ if (ret == 0) {
+ wolfSSL_DSA_free(dsaObj);
+ }
+
+ return ret;
+}
+#endif /* NO_DSA */
+
+#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
+ (HAVE_FIPS_VERSION > 2))
+/**
+ * Try to make a DH EVP PKEY from data.
+ *
+ * @param [in, out] out On in, an EVP PKEY or NULL.
+ * On out, an EVP PKEY or NULL.
+ * @param [in] mem Memory containing key data.
+ * @param [in] memSz Size of key data in bytes.
+ * @param [in] priv 1 means private key, 0 means public key.
+ * @return 1 on success.
+ * @return 0 otherwise.
+ */
+static int d2iTryDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
+ long memSz, int priv)
+{
+ WOLFSSL_DH* dhObj;
+ int isDhKey;
+ word32 keyIdx = 0;
+ int ret = 1;
+ WC_DECLARE_VAR(dh, DhKey, 1, NULL);
+
+ WC_ALLOC_VAR_EX(dh, DhKey, 1, NULL, DYNAMIC_TYPE_DH, return 0);
+
+ XMEMSET(dh, 0, sizeof(DhKey));
+
+ if (wc_InitDhKey(dh) != 0) {
+ WC_FREE_VAR_EX(dh, NULL, DYNAMIC_TYPE_DH);
+ return 0;
+ }
+
+ /* Try decoding data as a DH public key. */
+ isDhKey = (wc_DhKeyDecode(mem, &keyIdx, dh, (word32)memSz) == 0);
+ wc_FreeDhKey(dh);
+ WC_FREE_VAR_EX(dh, NULL, DYNAMIC_TYPE_DH);
+
+ /* test if DH key */
+ if (!isDhKey) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Create DH key object from data. */
+ dhObj = wolfSSL_DH_new();
+ if (dhObj == NULL) {
+ ret = 0;
+ }
+ if ((ret == 1) && (wolfSSL_DH_LoadDer(dhObj, mem, keyIdx) != 1)) {
+ ret = 0;
+ }
+ if (ret == 1) {
+ /* Create an EVP PKEY object. */
+ ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_DH);
+ }
+ if (ret == 1) {
+ /* Put RSA key object into EVP PKEY object. */
+ (*out)->ownDh = 1;
+ (*out)->dh = dhObj;
+ }
+ if (ret == 0) {
+ wolfSSL_DH_free(dhObj);
+ }
+
+ return ret;
+}
+#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
+#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */
+
+#if !defined(NO_DH) && defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA)
+#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
+ (HAVE_FIPS_VERSION > 2))
+/**
+ * Try to make a DH EVP PKEY from data.
+ *
+ * @param [in, out] out On in, an EVP PKEY or NULL.
+ * On out, an EVP PKEY or NULL.
+ * @param [in] mem Memory containing key data.
+ * @param [in] memSz Size of key data in bytes.
+ * @param [in] priv 1 means private key, 0 means public key.
+ * @return 1 on success.
+ * @return 0 otherwise.
+ */
+static int d2iTryAltDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
+ long memSz, int priv)
+{
+ WOLFSSL_DH* dhObj;
+ word32 keyIdx = 0;
+ DhKey* key = NULL;
+ int elements;
+ int ret = 1;
+
+ /* Create DH key object from data. */
+ dhObj = wolfSSL_DH_new();
+ if (dhObj == NULL) {
+ return 0;
+ }
+
+ key = (DhKey*)dhObj->internal;
+ /* Try decoding data as a DH public key. */
+ if (wc_DhKeyDecode(mem, &keyIdx, key, (word32)memSz) != 0) {
+ ret = 0;
+ }
+ if (ret == 1) {
+ /* DH key has data and is external to DH object. */
+ elements = ELEMENT_P | ELEMENT_G | ELEMENT_Q | ELEMENT_PUB;
+ if (priv) {
+ elements |= ELEMENT_PRV;
+ }
+ if (SetDhExternal_ex(dhObj, elements) != WOLFSSL_SUCCESS ) {
+ ret = 0;
+ }
+ }
+ if (ret == 1) {
+ /* Create an EVP PKEY object. */
+ ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_DH);
+ }
+ if (ret == 1) {
+ /* Put RSA key object into EVP PKEY object. */
+ (*out)->ownDh = 1;
+ (*out)->dh = dhObj;
+ }
+ if (ret == 0) {
+ wolfSSL_DH_free(dhObj);
+ }
+
+ return ret;
+}
+#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
+#endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */
+
+#ifdef HAVE_FALCON
+/**
+ * Attempt to import a private Falcon key at a specified level.
+ *
+ * @param [in] falcon Falcon key object.
+ * @param [in] level Level of Falcon key.
+ * @param [in] mem Memory containing key data.
+ * @param [in] memSz Size of key data in bytes.
+ * @return 1 on success.
+ * @return 0 otherwise.
+ */
+static int d2i_falcon_priv_key_level(falcon_key* falcon, byte level,
+ const unsigned char* mem, long memSz)
+{
+ return (wc_falcon_set_level(falcon, level) == 0) &&
+ (wc_falcon_import_private_only(mem, (word32)memSz, falcon) == 0);
+}
+
+/**
+ * Attempt to import a public Falcon key at a specified level.
+ *
+ * @param [in] falcon Falcon key object.
+ * @param [in] level Level of Falcon key.
+ * @param [in] mem Memory containing key data.
+ * @param [in] memSz Size of key data in bytes.
+ * @return 1 on success.
+ * @return 0 otherwise.
+ */
+static int d2i_falcon_pub_key_level(falcon_key* falcon, byte level,
+ const unsigned char* mem, long memSz)
+{
+ return (wc_falcon_set_level(falcon, level) == 0) &&
+ (wc_falcon_import_public(mem, (word32)memSz, falcon) == 0);
+}
+
+/**
+ * Try to make a Falcon EVP PKEY from data.
+ *
+ * @param [in, out] out On in, an EVP PKEY or NULL.
+ * On out, an EVP PKEY or NULL.
+ * @param [in] mem Memory containing key data.
+ * @param [in] memSz Size of key data in bytes.
+ * @param [in] priv 1 means private key, 0 means public key.
+ * @return 1 on success.
+ * @return 0 otherwise.
+ */
+static int d2iTryFalconKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
+ long memSz, int priv)
+{
+ int isFalcon = 0;
+ WC_DECLARE_VAR(falcon, falcon_key, 1, NULL);
+
+ WC_ALLOC_VAR_EX(falcon, falcon_key, 1, NULL, DYNAMIC_TYPE_FALCON,
+ return 0);
+
+ if (wc_falcon_init(falcon) != 0) {
+ WC_FREE_VAR_EX(falcon, NULL, DYNAMIC_TYPE_FALCON);
+ return 0;
+ }
+
+ /* Try decoding data as a Falcon private/public key. */
+ if (priv) {
+ /* Try level 1 */
+ isFalcon = d2i_falcon_priv_key_level(falcon, 1, mem, memSz);
+ if (!isFalcon) {
+ /* Try level 5 */
+ isFalcon = d2i_falcon_priv_key_level(falcon, 5, mem, memSz);
+ }
+ }
+ else {
+ /* Try level 1 */
+ isFalcon = d2i_falcon_pub_key_level(falcon, 1, mem, memSz);
+ if (!isFalcon) {
+ /* Try level 5 */
+ isFalcon = d2i_falcon_pub_key_level(falcon, 5, mem, memSz);
+ }
+ }
+ /* Dispose of any Falcon key created. */
+ wc_falcon_free(falcon);
+ WC_FREE_VAR_EX(falcon, NULL, DYNAMIC_TYPE_FALCON);
+
+ if (!isFalcon) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Create an EVP PKEY object. */
+ return d2i_make_pkey(out, NULL, 0, priv, WC_EVP_PKEY_FALCON);
+}
+#endif /* HAVE_FALCON */
+
+#ifdef HAVE_DILITHIUM
+/**
+ * Attempt to import a private Dilithium key at a specified level.
+ *
+ * @param [in] dilithium Dilithium key object.
+ * @param [in] level Level of Dilithium key.
+ * @param [in] mem Memory containing key data.
+ * @param [in] memSz Size of key data in bytes.
+ * @return 1 on success.
+ * @return 0 otherwise.
+ */
+static int d2i_dilithium_priv_key_level(dilithium_key* dilithium, byte level,
+ const unsigned char* mem, long memSz)
+{
+ return (wc_dilithium_set_level(dilithium, level) == 0) &&
+ (wc_dilithium_import_private(mem, (word32)memSz, dilithium) == 0);
+}
+
+/**
+ * Attempt to import a public Dilithium key at a specified level.
+ *
+ * @param [in] dilithium Dilithium key object.
+ * @param [in] level Level of Dilithium key.
+ * @param [in] mem Memory containing key data.
+ * @param [in] memSz Size of key data in bytes.
+ * @return 1 on success.
+ * @return 0 otherwise.
+ */
+static int d2i_dilithium_pub_key_level(dilithium_key* dilithium, byte level,
+ const unsigned char* mem, long memSz)
+{
+ return (wc_dilithium_set_level(dilithium, level) == 0) &&
+ (wc_dilithium_import_public(mem, (word32)memSz, dilithium) == 0);
+}
+
+/**
+ * Try to make a Dilithium EVP PKEY from data.
+ *
+ * @param [in, out] out On in, an EVP PKEY or NULL.
+ * On out, an EVP PKEY or NULL.
+ * @param [in] mem Memory containing key data.
+ * @param [in] memSz Size of key data in bytes.
+ * @param [in] priv 1 means private key, 0 means public key.
+ * @return 1 on success.
+ * @return 0 otherwise.
+ */
+static int d2iTryDilithiumKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
+ long memSz, int priv)
+{
+ int isDilithium = 0;
+ WC_DECLARE_VAR(dilithium, dilithium_key, 1, NULL);
+
+ WC_ALLOC_VAR_EX(dilithium, dilithium_key, 1, NULL, DYNAMIC_TYPE_DILITHIUM,
+ return 0);
+
+ if (wc_dilithium_init(dilithium) != 0) {
+ WC_FREE_VAR_EX(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM);
+ return 0;
+ }
+
+ /* Try decoding data as a Dilithium private/public key. */
+ if (priv) {
+ isDilithium = d2i_dilithium_priv_key_level(dilithium, WC_ML_DSA_44,
+ mem, memSz);
+ if (!isDilithium) {
+ isDilithium = d2i_dilithium_priv_key_level(dilithium, WC_ML_DSA_65,
+ mem, memSz);
+ }
+ if (!isDilithium) {
+ isDilithium = d2i_dilithium_priv_key_level(dilithium, WC_ML_DSA_87,
+ mem, memSz);
+ }
+ }
+ else {
+ isDilithium = d2i_dilithium_pub_key_level(dilithium, WC_ML_DSA_44,
+ mem, memSz);
+ if (!isDilithium) {
+ isDilithium = d2i_dilithium_pub_key_level(dilithium, WC_ML_DSA_65,
+ mem, memSz);
+ }
+ if (!isDilithium) {
+ isDilithium = d2i_dilithium_pub_key_level(dilithium, WC_ML_DSA_87,
+ mem, memSz);
+ }
+ }
+ /* Dispose of any Dilithium key created. */
+ wc_dilithium_free(dilithium);
+ WC_FREE_VAR_EX(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM);
+
+ if (!isDilithium) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Create an EVP PKEY object. */
+ return d2i_make_pkey(out, NULL, 0, priv, WC_EVP_PKEY_DILITHIUM);
+}
+#endif /* HAVE_DILITHIUM */
+
+/**
+ * Try to make a WOLFSSL_EVP_PKEY from data.
+ *
+ * @param [in, out] out On in, an EVP PKEY or NULL.
+ * On out, an EVP PKEY or NULL.
+ * @param [in] mem Memory containing key data.
+ * @param [in] memSz Size of key data in bytes.
+ * @param [in] priv 1 means private key, 0 means public key.
+ * @return 1 on success.
+ * @return 0 otherwise.
+ */
+static WOLFSSL_EVP_PKEY* d2i_evp_pkey_try(WOLFSSL_EVP_PKEY** out,
+ const unsigned char** in, long inSz, int priv)
+{
+ WOLFSSL_EVP_PKEY* pkey = NULL;
+
+ WOLFSSL_ENTER("d2i_evp_pkey_try");
+
+ if (in == NULL || *in == NULL || inSz < 0) {
+ WOLFSSL_MSG("Bad argument");
+ return NULL;
+ }
+
+ if ((out != NULL) && (*out != NULL)) {
+ pkey = *out;
+ }
+
+#if !defined(NO_RSA)
+ if (d2iTryRsaKey(&pkey, *in, inSz, priv) >= 0) {
+ ;
+ }
+ else
+#endif /* NO_RSA */
+#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA)
+ if (d2iTryEccKey(&pkey, *in, inSz, priv) >= 0) {
+ ;
+ }
+ else
+#endif /* HAVE_ECC && OPENSSL_EXTRA */
+#if !defined(NO_DSA)
+ if (d2iTryDsaKey(&pkey, *in, inSz, priv) >= 0) {
+ ;
+ }
+ else
+#endif /* NO_DSA */
+#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
+ (HAVE_FIPS_VERSION > 2))
+ if (d2iTryDhKey(&pkey, *in, inSz, priv) >= 0) {
+ ;
+ }
+ else
+#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
+#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */
+
+#if !defined(NO_DH) && defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA)
+#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
+ (HAVE_FIPS_VERSION > 2))
+ if (d2iTryAltDhKey(&pkey, *in, inSz, priv) >= 0) {
+ ;
+ }
+ else
+#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
+#endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */
+
+#ifdef HAVE_FALCON
+ if (d2iTryFalconKey(&pkey, *in, inSz, priv) >= 0) {
+ ;
+ }
+ else
+#endif /* HAVE_FALCON */
+#ifdef HAVE_DILITHIUM
+ if (d2iTryDilithiumKey(&pkey, *in, inSz, priv) >= 0) {
+ ;
+ }
+ else
+#endif /* HAVE_DILITHIUM */
+ {
+ WOLFSSL_MSG("d2i_evp_pkey_try couldn't determine key type");
+ }
+
+ if ((pkey != NULL) && (out != NULL)) {
+ *out = pkey;
+ }
+ return pkey;
+}
+#endif /* OPENSSL_EXTRA || WPA_SMALL */
+
+#ifdef OPENSSL_EXTRA
+/* Converts a DER encoded public key to a WOLFSSL_EVP_PKEY structure.
+ *
+ * @param [in, out] out Pointer to new WOLFSSL_EVP_PKEY structure.
+ * Can be NULL.
+ * @param [in, out] in DER buffer to convert.
+ * @param [in] inSz Size of in buffer.
+ * @return Pointer to a new WOLFSSL_EVP_PKEY structure on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out,
+ const unsigned char** in, long inSz)
+{
+ WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY");
+ return d2i_evp_pkey_try(out, in, inSz, 0);
+}
+
+#ifndef NO_BIO
+/* Converts a DER encoded public key in a BIO to a WOLFSSL_EVP_PKEY structure.
+ *
+ * @param [in] bio BIO to read DER from.
+ * @param [out] out New WOLFSSL_EVP_PKEY pointer when not NULL.
+ * @return Pointer to a new WOLFSSL_EVP_PKEY structure on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio,
+ WOLFSSL_EVP_PKEY** out)
+{
+ unsigned char* mem;
+ long memSz;
+ WOLFSSL_EVP_PKEY* pkey = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio");
+
+ /* Validate parameters. */
+ if (bio == NULL) {
+ return NULL;
+ }
+
+ /* Get length of data in BIO. */
+ memSz = wolfSSL_BIO_get_len(bio);
+ if (memSz <= 0) {
+ return NULL;
+ }
+ /* Allocate memory to read all of BIO data into. */
+ mem = (unsigned char*)XMALLOC((size_t)memSz, bio->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (mem == NULL) {
+ return NULL;
+ }
+ /* Read all data into allocated buffer. */
+ if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) {
+ /* Create a WOLFSSL_EVP_PKEY from data. */
+ pkey = wolfSSL_d2i_PUBKEY(NULL, (const unsigned char**)&mem, memSz);
+ if (out != NULL && pkey != NULL) {
+ /* Return new WOLFSSL_EVP_PKEY through parameter. */
+ *out = pkey;
+ }
+ }
+
+ /* Dispose of memory holding BIO data. */
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return pkey;
+}
+#endif /* !NO_BIO */
+#endif /* OPENSSL_EXTRA */
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \
+ defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX) || \
+ defined(WOLFSSL_QT) || defined(WOLFSSL_WPAS_SMALL)
+/* Converts a DER encoded private key to a WOLFSSL_EVP_PKEY structure.
+ *
+ * @param [in, out] out Pointer to new WOLFSSL_EVP_PKEY structure.
+ * Can be NULL.
+ * @param [in, out] in DER buffer to convert.
+ * @param [in] inSz Size of in buffer.
+ * @return Pointer to a new WOLFSSL_EVP_PKEY structure on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** out,
+ unsigned char** in, long inSz)
+{
+ WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_EVP");
+ return d2i_evp_pkey_try(out, (const unsigned char**)in, inSz, 1);
+}
+#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT ||
+ * WOLFSSL_WPAS_SMALL*/
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \
+ defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT)
+
+#ifndef NO_BIO
+/* Converts a DER encoded private key in a BIO to a WOLFSSL_EVP_PKEY structure.
+ *
+ * @param [in] bio BIO to read DER from.
+ * @param [out] out New WOLFSSL_EVP_PKEY pointer when not NULL.
+ * @return Pointer to a new WOLFSSL_EVP_PKEY structure on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO* bio,
+ WOLFSSL_EVP_PKEY** out)
+{
+ unsigned char* mem = NULL;
+ int memSz = 0;
+ WOLFSSL_EVP_PKEY* key = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_bio");
+
+ /* Validate parameters. */
+ if (bio == NULL) {
+ return NULL;
+ }
+
+ /* Get length of data in BIO. */
+ memSz = wolfSSL_BIO_get_len(bio);
+ if (memSz <= 0) {
+ WOLFSSL_MSG("wolfSSL_BIO_get_len() failure");
+ return NULL;
+ }
+ /* Allocate memory to read all of BIO data into. */
+ mem = (unsigned char*)XMALLOC((size_t)memSz, bio->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (mem == NULL) {
+ WOLFSSL_MSG("Malloc failure");
+ return NULL;
+ }
+
+ /* Read all of data. */
+ if (wolfSSL_BIO_read(bio, (unsigned char*)mem, memSz) == memSz) {
+ /* Determines key type and returns the new private EVP_PKEY object */
+ if ((key = wolfSSL_d2i_PrivateKey_EVP(NULL, &mem, (long)memSz)) ==
+ NULL) {
+ WOLFSSL_MSG("wolfSSL_d2i_PrivateKey_EVP() failure");
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return NULL;
+ }
+
+ /* Write extra data back into bio object if necessary. */
+ if (memSz > key->pkey_sz) {
+ wolfSSL_BIO_write(bio, mem + key->pkey_sz, memSz - key->pkey_sz);
+ if (wolfSSL_BIO_get_len(bio) <= 0) {
+ WOLFSSL_MSG("Failed to write memory to bio");
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return NULL;
+ }
+ }
+
+ /* Return key through parameter if required. */
+ if (out != NULL) {
+ *out = key;
+ }
+ }
+
+ /* Dispose of memory holding BIO data. */
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return key;
+}
+#endif /* !NO_BIO */
+
+#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_NGINX ||
+ * WOLFSSL_QT */
+
+#ifdef OPENSSL_EXTRA
+/* Reads in a DER format key. If PKCS8 headers are found they are stripped off.
+ *
+ * @param [in] type Type of key.
+ * @param [in, out] out Newly created WOLFSSL_EVP_PKEY structure.
+ * @param [in, out] in Pointer to input key DER.
+ * Pointer is advanced the same number of bytes read on
+ * success.
+ * @param [in] inSz Size of in buffer.
+ * @return A non null pointer on success.
+ * @return NULL on failure.
+ */
+static WOLFSSL_EVP_PKEY* d2i_evp_pkey(int type, WOLFSSL_EVP_PKEY** out,
+ const unsigned char **in, long inSz, int priv)
+{
+ int ret = 0;
+ word32 idx = 0, algId;
+ word16 pkcs8HeaderSz = 0;
+ WOLFSSL_EVP_PKEY* local;
+ const unsigned char* p;
+ int opt;
+
+ (void)opt;
+
+ /* Validate parameters. */
+ if (in == NULL || inSz < 0) {
+ WOLFSSL_MSG("Bad argument");
+ return NULL;
+ }
+
+ if (priv == 1) {
+ /* Check if input buffer has PKCS8 header. In the case that it does not
+ * have a PKCS8 header then do not error out. */
+ if ((ret = ToTraditionalInline_ex((const byte*)(*in), &idx,
+ (word32)inSz, &algId)) > 0) {
+ WOLFSSL_MSG("Found PKCS8 header");
+ pkcs8HeaderSz = (word16)idx;
+
+ /* Check header algorithm id matches algorithm type passed in. */
+ if ((type == WC_EVP_PKEY_RSA && algId != RSAk
+ #ifdef WC_RSA_PSS
+ && algId != RSAPSSk
+ #endif
+ ) ||
+ (type == WC_EVP_PKEY_EC && algId != ECDSAk) ||
+ (type == WC_EVP_PKEY_DSA && algId != DSAk) ||
+ (type == WC_EVP_PKEY_DH && algId != DHk)) {
+ WOLFSSL_MSG("PKCS8 does not match EVP key type");
+ return NULL;
+ }
+
+ (void)idx; /* not used */
+ }
+ /* Ensure no error occurred try to remove any PKCS#8 header. */
+ else if (ret != WC_NO_ERR_TRACE(ASN_PARSE_E)) {
+ WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header");
+ return NULL;
+ }
+ }
+
+ /* Dispose of any WOLFSSL_EVP_PKEY passed in. */
+ if (out != NULL && *out != NULL) {
+ wolfSSL_EVP_PKEY_free(*out);
+ *out = NULL;
+ }
+ /* Create a new WOLFSSL_EVP_PKEY and populate. */
+ local = wolfSSL_EVP_PKEY_new();
+ if (local == NULL) {
+ return NULL;
+ }
+ local->type = type;
+ local->pkey_sz = (int)inSz;
+ local->pkcs8HeaderSz = pkcs8HeaderSz;
+ local->pkey.ptr = (char*)XMALLOC((size_t)inSz, NULL,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (local->pkey.ptr == NULL) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ XMEMCPY(local->pkey.ptr, *in, (size_t)inSz);
+ p = (const unsigned char*)local->pkey.ptr;
+
+ /* Create an algorithm specific object into WOLFSSL_EVP_PKEY. */
+ switch (type) {
+#ifndef NO_RSA
+ case WC_EVP_PKEY_RSA:
+ /* Create a WOLFSSL_RSA object. */
+ local->ownRsa = 1;
+ opt = priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC;
+ local->rsa = wolfssl_rsa_d2i(NULL, p, local->pkey_sz, opt);
+ if (local->rsa == NULL) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ break;
+#endif /* NO_RSA */
+#ifdef HAVE_ECC
+ case WC_EVP_PKEY_EC:
+ /* Create a WOLFSSL_EC object. */
+ local->ownEcc = 1;
+ local->ecc = wolfSSL_EC_KEY_new();
+ if (local->ecc == NULL) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ opt = priv ? WOLFSSL_EC_KEY_LOAD_PRIVATE :
+ WOLFSSL_EC_KEY_LOAD_PUBLIC;
+ if (wolfSSL_EC_KEY_LoadDer_ex(local->ecc, p, local->pkey_sz, opt) !=
+ WOLFSSL_SUCCESS) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ break;
+#endif /* HAVE_ECC */
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)
+#ifndef NO_DSA
+ case WC_EVP_PKEY_DSA:
+ /* Create a WOLFSSL_DSA object. */
+ local->ownDsa = 1;
+ local->dsa = wolfSSL_DSA_new();
+ if (local->dsa == NULL) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ opt = priv ? WOLFSSL_DSA_LOAD_PRIVATE : WOLFSSL_DSA_LOAD_PUBLIC;
+ if (wolfSSL_DSA_LoadDer_ex(local->dsa, p, local->pkey_sz, opt) !=
+ WOLFSSL_SUCCESS) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ break;
+#endif /* NO_DSA */
+#ifndef NO_DH
+#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2))
+ case WC_EVP_PKEY_DH:
+ /* Create a WOLFSSL_DH object. */
+ local->ownDh = 1;
+ local->dh = wolfSSL_DH_new();
+ if (local->dh == NULL) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ if (wolfSSL_DH_LoadDer(local->dh, p, local->pkey_sz) !=
+ WOLFSSL_SUCCESS) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ break;
+#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
+#endif /* HAVE_DH */
+#endif /* WOLFSSL_QT || OPENSSL_ALL || WOLFSSL_OPENSSH */
+ default:
+ WOLFSSL_MSG("Unsupported key type");
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+
+ /* Advance pointer and return through parameter when required on success. */
+ if (local != NULL) {
+ if (local->pkey_sz <= (int)inSz) {
+ *in += local->pkey_sz;
+ }
+ if (out != NULL) {
+ *out = local;
+ }
+ }
+
+ /* Return newly allocated WOLFSSL_EVP_PKEY structure. */
+ return local;
+}
+
+/* Reads in a DER format key.
+ *
+ * @param [in] type Type of key.
+ * @param [in, out] out Newly created WOLFSSL_EVP_PKEY structure.
+ * @param [in, out] in Pointer to input key DER.
+ * Pointer is advanced the same number of bytes read on
+ * success.
+ * @param [in] inSz Size of in buffer.
+ * @return A non null pointer on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out,
+ const unsigned char **in, long inSz)
+{
+ WOLFSSL_ENTER("wolfSSL_d2i_PublicKey");
+
+ return d2i_evp_pkey(type, out, in, inSz, 0);
+}
+
+/* Reads in a DER format key. If PKCS8 headers are found they are stripped off.
+ *
+ * @param [in] type Type of key.
+ * @param [in, out] out Newly created WOLFSSL_EVP_PKEY structure.
+ * @param [in, out] in Pointer to input key DER.
+ * Pointer is advanced the same number of bytes read on
+ * success.
+ * @param [in] inSz Size of in buffer.
+ * @return A non null pointer on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out,
+ const unsigned char **in, long inSz)
+{
+ WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey");
+
+ return d2i_evp_pkey(type, out, in, inSz, 1);
+}
+#endif /* OPENSSL_EXTRA */
+
+#ifdef OPENSSL_ALL
+/* Detect RSA or EC key and decode private key DER.
+ *
+ * @param [in, out] pkey Newly created WOLFSSL_EVP_PKEY structure.
+ * @param [in, out] pp Pointer to private key DER data.
+ * @param [in] length Length in bytes of DER data.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey(WOLFSSL_EVP_PKEY** pkey,
+ const unsigned char** pp, long length)
+{
+ int ret;
+ WOLFSSL_EVP_PKEY* key = NULL;
+ const byte* der = *pp;
+ word32 idx = 0;
+ int len = 0;
+ int cnt = 0;
+ word32 algId;
+ word32 keyLen = (word32)length;
+
+ /* Take off PKCS#8 wrapper if found. */
+ if ((len = ToTraditionalInline_ex(der, &idx, keyLen, &algId)) >= 0) {
+ der += idx;
+ keyLen = (word32)len;
+ }
+
+ idx = 0;
+ len = 0;
+ /* Use the number of elements in the outer sequence to determine key type.
+ */
+ ret = GetSequence(der, &idx, &len, keyLen);
+ if (ret >= 0) {
+ word32 end = idx + (word32)len;
+ while (ret >= 0 && idx < end) {
+ /* Skip type */
+ idx++;
+ /* Get length and skip over - keeping count */
+ len = 0;
+ ret = GetLength(der, &idx, &len, keyLen);
+ if (ret >= 0) {
+ if (idx + (word32)len > end) {
+ ret = ASN_PARSE_E;
+ }
+ else {
+ idx += (word32)len;
+ cnt++;
+ }
+ }
+ }
+ }
+
+ if (ret >= 0) {
+ int type;
+ /* ECC includes version, private[, curve][, public key] */
+ if (cnt >= 2 && cnt <= 4) {
+ type = WC_EVP_PKEY_EC;
+ }
+ else {
+ type = WC_EVP_PKEY_RSA;
+ }
+
+ /* Decode the detected type of private key. */
+ key = wolfSSL_d2i_PrivateKey(type, pkey, &der, keyLen);
+ /* Update the pointer to after the DER data. */
+ *pp = der;
+ }
+
+ return key;
+}
+
+#if !defined(NO_BIO) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8)
+/* Read all of the BIO data into a newly allocated buffer.
+ *
+ * @param [in] bio BIO to read from.
+ * @param [out] data Allocated buffer holding all BIO data.
+ * @return Number of bytes allocated and read.
+ * @return MEMORY_E on dynamic memory allocation failure.
+ * @return Other negative on error.
+ */
+static int bio_get_data(WOLFSSL_BIO* bio, byte** data)
+{
+ int ret = 0;
+ byte* mem = NULL;
+
+ /* Get length of data in BIO. */
+ ret = wolfSSL_BIO_get_len(bio);
+ if (ret > 0) {
+ /* Allocate memory big enough to hold data in BIO. */
+ mem = (byte*)XMALLOC((size_t)ret, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ if (mem == NULL) {
+ WOLFSSL_MSG("Memory error");
+ ret = MEMORY_E;
+ }
+ if (ret >= 0) {
+ /* Read data from BIO. */
+ if ((ret = wolfSSL_BIO_read(bio, mem, ret)) <= 0) {
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ ret = MEMORY_E;
+ mem = NULL;
+ }
+ }
+ }
+
+ /* Return allocated buffer with data from BIO. */
+ *data = mem;
+ return ret;
+}
+
+/* Convert the algorithm id to a key type.
+ *
+ * @param [in] algId Algorithm Id.
+ * @return Key type on success.
+ * @return WC_EVP_PKEY_NONE when algorithm id not supported.
+ */
+static int wolfssl_i_alg_id_to_key_type(word32 algId)
+{
+ int type;
+
+ /* Convert algorithm id into EVP PKEY id. */
+ switch (algId) {
+#ifndef NO_RSA
+ case RSAk:
+ #ifdef WC_RSA_PSS
+ case RSAPSSk:
+ #endif
+ type = WC_EVP_PKEY_RSA;
+ break;
+#endif
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ type = WC_EVP_PKEY_EC;
+ break;
+ #endif
+ #ifndef NO_DSA
+ case DSAk:
+ type = WC_EVP_PKEY_DSA;
+ break;
+ #endif
+ #ifndef NO_DH
+ case DHk:
+ type = WC_EVP_PKEY_DH;
+ break;
+ #endif
+ default:
+ WOLFSSL_MSG("PKEY algorithm, from PKCS#8 header, not supported");
+ type = WC_EVP_PKEY_NONE;
+ break;
+ }
+
+ return type;
+}
+
+/* Creates an WOLFSSL_EVP_PKEY from PKCS#8 encrypted private DER in a BIO.
+ *
+ * Uses the PEM default password callback when cb is NULL.
+ *
+ * @param [in] bio BIO to read DER from.
+ * @param [in, out] pkey Newly created WOLFSSL_EVP_PKEY structure.
+ * @param [in] cb Password callback. May be NULL.
+ * @param [in] ctx Password callback context. May be NULL.
+ * @return A non null pointer on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PKCS8PrivateKey_bio(WOLFSSL_BIO* bio,
+ WOLFSSL_EVP_PKEY** pkey, wc_pem_password_cb* cb, void* ctx)
+{
+ int ret;
+ const byte* p;
+ byte* der = NULL;
+ int len;
+ word32 algId;
+ WOLFSSL_EVP_PKEY* key;
+ int type;
+ char password[NAME_SZ];
+ int passwordSz;
+
+ /* Get the data from the BIO into a newly allocated buffer. */
+ if ((len = bio_get_data(bio, &der)) < 0)
+ return NULL;
+
+ /* Use the PEM default callback if none supplied. */
+ if (cb == NULL) {
+ cb = wolfSSL_PEM_def_callback;
+ }
+ /* Get the password. */
+ passwordSz = cb(password, sizeof(password), PEM_PASS_READ, ctx);
+ if (passwordSz < 0) {
+ XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ return NULL;
+ }
+#ifdef WOLFSSL_CHECK_MEM_ZERO
+ wc_MemZero_Add("wolfSSL_d2i_PKCS8PrivateKey_bio password", password,
+ passwordSz);
+#endif
+
+ /* Decrypt the PKCS#8 encrypted private key and get algorithm. */
+ ret = ToTraditionalEnc(der, (word32)len, password, passwordSz, &algId);
+ ForceZero(password, (word32)passwordSz);
+#ifdef WOLFSSL_CHECK_MEM_ZERO
+ wc_MemZero_Check(password, passwordSz);
+#endif
+ if (ret < 0) {
+ XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ return NULL;
+ }
+
+ /* Get the key type from the algorithm id of the PKCS#8 header. */
+ if ((type = wolfssl_i_alg_id_to_key_type(algId)) == WC_EVP_PKEY_NONE) {
+ XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ return NULL;
+ }
+
+ /* Decode private key with the known type. */
+ p = der;
+ key = d2i_evp_pkey(type, pkey, &p, len, 1);
+
+ /* Dispose of memory holding BIO data. */
+ XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ return key;
+}
+#endif /* !NO_BIO && !NO_PWDBASED && HAVE_PKCS8 */
+#endif /* OPENSSL_ALL */
+
+#ifdef OPENSSL_EXTRA
+/* Reads in a PKCS#8 DER format key.
+ *
+ * @param [in, out] pkey Newly created WOLFSSL_PKCS8_PRIV_KEY_INFO structure.
+ * @param [in, out] keyBuf Pointer to input key DER.
+ * Pointer is advanced the same number of bytes read on
+ * success.
+ * @param [in] keyLen Number of bytes in keyBuf.
+ * @return A non null pointer on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY(
+ WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey, const unsigned char** keyBuf,
+ long keyLen)
+{
+ WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL;
+#ifdef WOLFSSL_PEM_TO_DER
+ int ret;
+ DerBuffer* pkcs8Der = NULL;
+ DerBuffer rawDer;
+ EncryptedInfo info;
+ int advanceLen = 0;
+
+ /* Clear the encryption information and DER buffer. */
+ XMEMSET(&info, 0, sizeof(info));
+ XMEMSET(&rawDer, 0, sizeof(rawDer));
+
+ /* Validate parameters. */
+ if ((keyBuf == NULL) || (*keyBuf == NULL) || (keyLen <= 0)) {
+ WOLFSSL_MSG("Bad key PEM/DER args");
+ return NULL;
+ }
+
+ /* Try to decode the PEM into DER. */
+ ret = PemToDer(*keyBuf, keyLen, PRIVATEKEY_TYPE, &pkcs8Der, NULL, &info,
+ NULL);
+ if (ret >= 0) {
+ /* Cache the amount of data in PEM formatted private key. */
+ advanceLen = (int)info.consumed;
+ }
+ else {
+ /* Not PEM - create a DerBuffer with the PKCS#8 DER data. */
+ WOLFSSL_MSG("Not PEM format");
+ ret = AllocDer(&pkcs8Der, (word32)keyLen, PRIVATEKEY_TYPE, NULL);
+ if (ret == 0) {
+ XMEMCPY(pkcs8Der->buffer, *keyBuf, keyLen);
+ }
+ }
+
+ if (ret == 0) {
+ /* Verify this is PKCS8 Key */
+ word32 inOutIdx = 0;
+ word32 algId;
+
+ ret = ToTraditionalInline_ex(pkcs8Der->buffer, &inOutIdx,
+ pkcs8Der->length, &algId);
+ if (ret >= 0) {
+ if (advanceLen == 0) {
+ /* Set only if not PEM */
+ advanceLen = (int)inOutIdx + ret;
+ }
+ if (algId == DHk) {
+ /* Special case for DH as we expect the DER buffer to be always
+ * be in PKCS8 format */
+ rawDer.buffer = pkcs8Der->buffer;
+ rawDer.length = inOutIdx + (word32)ret;
+ }
+ else {
+ rawDer.buffer = pkcs8Der->buffer + inOutIdx;
+ rawDer.length = (word32)ret;
+ }
+ ret = 0; /* good DER */
+ }
+ }
+
+ if (ret == 0) {
+ /* Create a WOLFSSL_EVP_PKEY for a WOLFSSL_PKCS8_PRIV_KEY_INFO. */
+ pkcs8 = wolfSSL_EVP_PKEY_new();
+ if (pkcs8 == NULL) {
+ ret = MEMORY_E;
+ }
+ }
+ if (ret == 0) {
+ /* Allocate memory to hold DER. */
+ pkcs8->pkey.ptr = (char*)XMALLOC(rawDer.length, NULL,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (pkcs8->pkey.ptr == NULL) {
+ ret = MEMORY_E;
+ }
+ }
+ if (ret == 0) {
+ /* Copy in DER data and size. */
+ XMEMCPY(pkcs8->pkey.ptr, rawDer.buffer, rawDer.length);
+ pkcs8->pkey_sz = (int)rawDer.length;
+ }
+
+ /* Dispose of PKCS#8 DER data - raw DER reference data in pkcs8Der. */
+ FreeDer(&pkcs8Der);
+ if (ret != 0) {
+ /* Dispose of WOLFSSL_PKCS8_PRIV_KEY_INFO object on error. */
+ wolfSSL_EVP_PKEY_free(pkcs8);
+ pkcs8 = NULL;
+ }
+ else {
+ /* Advance the buffer past the key on success. */
+ *keyBuf += advanceLen;
+ }
+ if (pkey != NULL) {
+ /* Return the WOLFSSL_PKCS8_PRIV_KEY_INFO object through parameter. */
+ *pkey = pkcs8;
+ }
+#else
+ (void)pkey;
+ (void)keyBuf;
+ (void)keyLen;
+#endif /* WOLFSSL_PEM_TO_DER */
+
+ /* Return new WOLFSSL_PKCS8_PRIV_KEY_INFO object. */
+ return pkcs8;
+}
+
+#ifndef NO_BIO
+/* Converts a DER format key read from BIO to a PKCS#8 structure.
+ *
+ * @param [in] bio Input BIO to read DER from.
+ * @param [out] pkey If not NULL then this pointer will be overwritten with a
+ * new PKCS8 structure.
+ * @return A WOLFSSL_PKCS8_PRIV_KEY_INFO pointer on success
+ * @return NULL on failure.
+ */
+WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(WOLFSSL_BIO* bio,
+ WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey)
+{
+ WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL;
+#ifdef WOLFSSL_PEM_TO_DER
+ unsigned char* mem = NULL;
+ int memSz;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_PKCS8_PKEY_bio");
+
+ /* Validate parameters. */
+ if (bio == NULL) {
+ return NULL;
+ }
+
+ /* Get the memory buffer from the BIO. */
+ if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) {
+ return NULL;
+ }
+
+ /* Decode the PKCS#8 key into a WOLFSSL_PKCS8_PRIV_KEY_INFO object. */
+ pkcs8 = wolfSSL_d2i_PKCS8_PKEY(pkey, (const unsigned char**)&mem, memSz);
+#else
+ (void)bio;
+ (void)pkey;
+#endif /* WOLFSSL_PEM_TO_DER */
+
+ /* Return new WOLFSSL_PKCS8_PRIV_KEY_INFO object. */
+ return pkcs8;
+}
+#endif /* !NO_BIO */
+
+#ifdef WOLF_PRIVATE_KEY_ID
+/* Create an EVP structure for use with crypto callbacks.
+ *
+ * @param [in] type Type of private key.
+ * @param [out] out WOLFSSL_EVP_PKEY object created.
+ * @param [in] heap Heap hint for dynamic memory allocation.
+ * @param [in] devId Device id.
+ * @return A new WOLFSSL_EVP_PKEY object on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_id(int type, WOLFSSL_EVP_PKEY** out,
+ void* heap, int devId)
+{
+ WOLFSSL_EVP_PKEY* local;
+
+ /* Dispose of any object passed in through out. */
+ if (out != NULL && *out != NULL) {
+ wolfSSL_EVP_PKEY_free(*out);
+ *out = NULL;
+ }
+
+ /* Create a local WOLFSSL_EVP_PKEY to be decoded into. */
+ local = wolfSSL_EVP_PKEY_new_ex(heap);
+ if (local == NULL) {
+ return NULL;
+ }
+ local->type = type;
+ local->pkey_sz = 0;
+ local->pkcs8HeaderSz = 0;
+
+ switch (type) {
+#ifndef NO_RSA
+ case WC_EVP_PKEY_RSA:
+ {
+ /* Create a WOLFSSL_RSA object into WOLFSSL_EVP_PKEY. */
+ local->rsa = wolfSSL_RSA_new_ex(heap, devId);
+ if (local->rsa == NULL) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ local->ownRsa = 1;
+ /* Algorithm specific object set into WOLFSL_EVP_PKEY. */
+ local->rsa->inSet = 1;
+ #ifdef WOLF_CRYPTO_CB
+ ((RsaKey*)local->rsa->internal)->devId = devId;
+ #endif
+ break;
+ }
+#endif /* !NO_RSA */
+#ifdef HAVE_ECC
+ case WC_EVP_PKEY_EC:
+ {
+ ecc_key* key;
+
+ /* Create a WOLFSSL_EC object into WOLFSSL_EVP_PKEY. */
+ local->ecc = wolfSSL_EC_KEY_new_ex(heap, devId);
+ if (local->ecc == NULL) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+ local->ownEcc = 1;
+ /* Algorithm specific object set into WOLFSL_EVP_PKEY. */
+ local->ecc->inSet = 1;
+
+ /* Get wolfSSL EC key and set fields. */
+ key = (ecc_key*)local->ecc->internal;
+ #ifdef WOLF_CRYPTO_CB
+ key->devId = devId;
+ #endif
+ key->type = ECC_PRIVATEKEY;
+ /* key is required to have a key size / curve set, although
+ * actual one used is determined by devId callback function. */
+ wc_ecc_set_curve(key, ECDHE_SIZE, ECC_CURVE_DEF);
+ break;
+ }
+#endif /* HAVE_ECC */
+ default:
+ WOLFSSL_MSG("Unsupported private key id type");
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+
+ /* Return new WOLFSSL_EVP_PKEY through parameter if required. */
+ if (local != NULL && out != NULL) {
+ *out = local;
+ }
+ /* Return new WOLFSSL_EVP_PKEY. */
+ return local;
+}
+#endif /* WOLF_PRIVATE_KEY_ID */
+#endif /* OPENSSL_EXTRA */
+
+/*******************************************************************************
+ * END OF d2i APIs
+ ******************************************************************************/
+
+/*******************************************************************************
+ * START OF i2d APIs
+ ******************************************************************************/
+
+#ifdef OPENSSL_ALL
+/* Encode PKCS#8 key as DER data.
+ *
+ * @param [in] key PKCS#8 private key to encode.
+ * @param [out] pp Pointer to buffer of encoded data.
+ * @return Length of DER encoded data on success.
+ * @return Less than zero on failure.
+ */
+int wolfSSL_i2d_PKCS8_PKEY(WOLFSSL_PKCS8_PRIV_KEY_INFO* key, unsigned char** pp)
+{
+ word32 keySz = 0;
+ unsigned char* out;
+ int len;
+
+ WOLFSSL_ENTER("wolfSSL_i2d_PKCS8_PKEY");
+
+ /* Validate parameters. */
+ if (key == NULL) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Get the length of DER encoding. */
+ if (pkcs8_encode(key, NULL, &keySz) != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+ len = (int)keySz;
+
+ /* Return the length when output parameter is NULL. */
+ if ((pp == NULL) || (len == 0)) {
+ return len;
+ }
+
+ /* Allocate memory for DER encoding if NULL passed in for output buffer. */
+ if (*pp == NULL) {
+ out = (unsigned char*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_ASN1);
+ if (out == NULL) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+ else {
+ /* Use buffer passed in - assume it is big enough. */
+ out = *pp;
+ }
+
+ /* Encode the PKCS#8 key into the output buffer. */
+ if (pkcs8_encode(key, out, &keySz) != len) {
+ if (*pp == NULL) {
+ XFREE(out, NULL, DYNAMIC_TYPE_ASN1);
+ }
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Return new output buffer or move pointer passed encoded data. */
+ if (*pp == NULL) {
+ *pp = out;
+ }
+ else {
+ *pp += len;
+ }
+
+ return len;
+}
+#endif
+
+#ifdef OPENSSL_EXTRA
+
+#if !defined(NO_ASN) && !defined(NO_PWDBASED)
+/* Get raw pointer to DER buffer from WOLFSSL_EVP_PKEY.
+ *
+ * Assumes der is large enough if passed in.
+ *
+ * @param [in] key WOLFSSL_EVP_PKEY to get DER buffer for.
+ * @param [out] der Buffer holding DER encoding. May be NULL.
+ * @return Size of DER encoding on success.
+ * @return Less than 0 on failure.
+ */
+static int wolfssl_i_evp_pkey_get_der(const WOLFSSL_EVP_PKEY* key,
+ unsigned char** der)
+{
+ int sz;
+ word16 pkcs8HeaderSz;
+
+ /* Validate parameters. */
+ if ((key == NULL) || (key->pkey_sz == 0)) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* If pkcs8HeaderSz is invalid, return all of the DER encoding. */
+ pkcs8HeaderSz = 0;
+ if (key->pkey_sz > key->pkcs8HeaderSz) {
+ pkcs8HeaderSz = key->pkcs8HeaderSz;
+ }
+ /* Calculate the size of the DER encoding to return. */
+ sz = key->pkey_sz - pkcs8HeaderSz;
+ /* Returning encoding when DER is not NULL. */
+ if (der != NULL) {
+ unsigned char* pt = (unsigned char*)key->pkey.ptr;
+ int bufferPassedIn = ((*der) != NULL);
+
+ if (!bufferPassedIn) {
+ /* Allocate buffer to hold DER encoding. */
+ *der = (unsigned char*)XMALLOC((size_t)sz, NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (*der == NULL) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+ /* Copy in non-PKCS#8 DER encoding. */
+ XMEMCPY(*der, pt + pkcs8HeaderSz, (size_t)sz);
+ /* Step past encoded key when buffer provided. */
+ if (bufferPassedIn) {
+ *der += sz;
+ }
+ }
+
+ /* Return size of DER encoded data. */
+ return sz;
+}
+
+/* Encode key as unencrypted DER data.
+ *
+ * @param [in] key PKCS#8 private key to encode.
+ * @param [out] der Pointer to buffer of encoded data.
+ * @return Length of DER encoded data on success.
+ * @return Less than zero on failure.
+ */
+int wolfSSL_i2d_PrivateKey(const WOLFSSL_EVP_PKEY* key, unsigned char** der)
+{
+ return wolfssl_i_evp_pkey_get_der(key, der);
+}
+
+#ifndef NO_BIO
+/* Encode key as unencrypted DER data and write to BIO.
+ *
+ * @param [in] bio BIO to write data to.
+ * @param [in] key PKCS#8 private key to encode.
+ * @return Length of DER encoded data on success.
+ * @return Less than zero on failure.
+ */
+int wolfSSL_i2d_PrivateKey_bio(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key)
+{
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
+ int derSz = 0;
+ byte* der = NULL;
+
+ if (bio == NULL || key == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+
+ derSz = wolfSSL_i2d_PrivateKey(key, &der);
+ if (derSz <= 0) {
+ WOLFSSL_MSG("wolfSSL_i2d_PrivateKey (for getting size) failed");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wolfSSL_BIO_write(bio, der, derSz) != derSz) {
+ goto cleanup;
+ }
+
+ ret = WOLFSSL_SUCCESS;
+
+cleanup:
+ XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL);
+ return ret;
+}
+#endif
+
+#ifdef HAVE_ECC
+/* Encode EC key as public key DER.
+ *
+ * @param [in] key WOLFSSL_EVP_KEY object to encode.
+ * @param [in] ec WOLFSSL_EC_KEY object to encode.
+ * @param [out] der Buffer with DER encoding of EC public key.
+ * @return Public key DER encoding size on success.
+ * @return WOLFSSL_FATAL_ERROR when dynamic memory allocation fails.
+ * @return WOLFSSL_FATAL_ERROR when encoding fails.
+ */
+static int wolfssl_i_i2d_ecpublickey(const WOLFSSL_EVP_PKEY* key,
+ const WOLFSSL_EC_KEY *ec, unsigned char **der)
+{
+ word32 pub_derSz = 0;
+ int ret;
+ unsigned char *local_der = NULL;
+ word32 local_derSz = 0;
+ unsigned char *pub_der = NULL;
+ ecc_key *eccKey = NULL;
+ word32 inOutIdx = 0;
+
+ /* We need to get the DER, then convert it to a public key. But what we get
+ * might be a buffered private key so we need to decode it and then encode
+ * the public part. */
+ ret = wolfssl_i_evp_pkey_get_der(key, &local_der);
+ if (ret <= 0) {
+ /* In this case, there was no buffered DER at all. This could be the
+ * case where the key that was passed in was generated. So now we
+ * have to create the local DER. */
+ local_derSz = (word32)wolfSSL_i2d_ECPrivateKey(ec, &local_der);
+ if (local_derSz == 0) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ } else {
+ local_derSz = (word32)ret;
+ ret = 0;
+ }
+
+ if (ret == 0) {
+ eccKey = (ecc_key *)XMALLOC(sizeof(*eccKey), NULL, DYNAMIC_TYPE_ECC);
+ if (eccKey == NULL) {
+ WOLFSSL_MSG("Failed to allocate key buffer.");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ /* Initialize a wolfCrypt ECC key. */
+ if (ret == 0) {
+ ret = wc_ecc_init(eccKey);
+ }
+ if (ret == 0) {
+ /* Decode the DER data with wolfCrypt ECC key. */
+ ret = wc_EccPublicKeyDecode(local_der, &inOutIdx, eccKey, local_derSz);
+ if (ret < 0) {
+ /* We now try again as x.963 [point type][x][opt y]. */
+ ret = wc_ecc_import_x963(local_der, local_derSz, eccKey);
+ }
+ }
+
+ if (ret == 0) {
+ /* Get the size of the encoding of the public key DER. */
+ pub_derSz = (word32)wc_EccPublicKeyDerSize(eccKey, 1);
+ if ((int)pub_derSz <= 0) {
+ ret = WOLFSSL_FAILURE;
+ }
+ }
+
+ if (ret == 0) {
+ /* Allocate memory for public key DER encoding. */
+ pub_der = (unsigned char*)XMALLOC(pub_derSz, NULL,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (pub_der == NULL) {
+ WOLFSSL_MSG("Failed to allocate output buffer.");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ if (ret == 0) {
+ /* Encode public key as DER. */
+ pub_derSz = (word32)wc_EccPublicKeyToDer(eccKey, pub_der, pub_derSz, 1);
+ if ((int)pub_derSz <= 0) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ /* This block is for actually returning the DER of the public key */
+ if ((ret == 0) && (der != NULL)) {
+ int bufferPassedIn = ((*der) != NULL);
+ if (!bufferPassedIn) {
+ *der = (unsigned char*)XMALLOC(pub_derSz, NULL,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (*der == NULL) {
+ WOLFSSL_MSG("Failed to allocate output buffer.");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+ if (ret == 0) {
+ XMEMCPY(*der, pub_der, pub_derSz);
+ if (bufferPassedIn) {
+ *der += pub_derSz;
+ }
+ }
+ }
+
+ /* Dispose of allocated objects. */
+ XFREE(pub_der, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ XFREE(local_der, NULL, DYNAMIC_TYPE_OPENSSL);
+ wc_ecc_free(eccKey);
+ XFREE(eccKey, NULL, DYNAMIC_TYPE_ECC);
+
+ /* Return error or the size of the DER encoded public key. */
+ if (ret == 0) {
+ ret = (int)pub_derSz;
+ }
+ return ret;
+}
+#endif
+
+/* Encode the WOLFSSL_EVP_PKEY object as public key DER.
+ *
+ * @param [in] key WOLFSLS_EVP_PKEY object to encode.
+ * @param [out] der Buffer with DER encoding of public key.
+ * @return Public key DER encoding size on success.
+ * @return WOLFSSL_FATAL_ERROR when key is NULL.
+ * @return WOLFSSL_FATAL_ERROR when key type not supported.
+ * @return WOLFSSL_FATAL_ERROR when dynamic memory allocation fails.
+ */
+int wolfSSL_i2d_PublicKey(const WOLFSSL_EVP_PKEY *key, unsigned char **der)
+{
+ int ret;
+
+ /* Validate parameters. */
+ if (key == NULL) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ /* Encode based on key type. */
+ switch (key->type) {
+ #ifndef NO_RSA
+ case WC_EVP_PKEY_RSA:
+ return wolfSSL_i2d_RSAPublicKey(key->rsa, der);
+ #endif
+ #ifdef HAVE_ECC
+ case WC_EVP_PKEY_EC:
+ return wolfssl_i_i2d_ecpublickey(key, key->ecc, der);
+ #endif
+ default:
+ ret = WOLFSSL_FATAL_ERROR;
+ break;
+ }
+
+ return ret;
+}
+
+/* Encode the WOLFSSL_EVP_PKEY object as public key DER.
+ *
+ * @param [in] key WOLFSLS_EVP_PKEY object to encode.
+ * @param [out] der Buffer with DER encoding of public key.
+ * @return Public key DER encoding size on success.
+ * @return WOLFSSL_FATAL_ERROR when key is NULL.
+ * @return WOLFSSL_FATAL_ERROR when key type not supported.
+ * @return WOLFSSL_FATAL_ERROR when dynamic memory allocation fails.
+ */
+int wolfSSL_i2d_PUBKEY(const WOLFSSL_EVP_PKEY *key, unsigned char **der)
+{
+ return wolfSSL_i2d_PublicKey(key, der);
+}
+#endif /* !NO_ASN && !NO_PWDBASED */
+
+#endif /* OPENSSL_EXTRA */
+
+#endif /* !NO_CERTS */
+
+/*******************************************************************************
+ * END OF i2d APIs
+ ******************************************************************************/
+
+#endif /* !WOLFSSL_EVP_PK_INCLUDED */
+
diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am
index a14ae1884c..bb8eea3f42 100644
--- a/wolfcrypt/src/include.am
+++ b/wolfcrypt/src/include.am
@@ -12,6 +12,7 @@ MAINTAINERCLEANFILES+= $(ASYNC_FILES)
EXTRA_DIST += wolfcrypt/src/misc.c
EXTRA_DIST += wolfcrypt/src/evp.c
+EXTRA_DIST += wolfcrypt/src/evp_pk.c
EXTRA_DIST += wolfcrypt/src/asm.c
EXTRA_DIST += wolfcrypt/src/aes_asm.asm
EXTRA_DIST += wolfcrypt/src/aes_gcm_asm.asm
diff --git a/wolfcrypt/src/kdf.c b/wolfcrypt/src/kdf.c
index beb9e79124..0f6bdd736e 100644
--- a/wolfcrypt/src/kdf.c
+++ b/wolfcrypt/src/kdf.c
@@ -896,8 +896,7 @@ static void wc_srtp_kdf_first_block(const byte* salt, word32 saltSz, int kdrIdx,
block[i] = 0;
}
XMEMCPY(block + WC_SRTP_MAX_SALT - saltSz, salt, saltSz);
- block[WC_SRTP_MAX_SALT] = 0;
- /* block[15] is counter. */
+ /* block[14-15] are counter. */
/* When kdrIdx is -1, don't XOR in index. */
if (kdrIdx >= 0) {
@@ -947,6 +946,7 @@ static int wc_srtp_kdf_derive_key(byte* block, int idxSz, byte label,
block[WC_SRTP_MAX_SALT - idxSz - 1] ^= label;
for (i = 0; (ret == 0) && (i < blocks); i++) {
/* Set counter. */
+ block[14] = (byte)(i >> 8);
block[15] = (byte)i;
/* Encrypt block into key buffer. */
ret = wc_AesEcbEncrypt(aes, key, block, WC_AES_BLOCK_SIZE);
@@ -959,6 +959,7 @@ static int wc_srtp_kdf_derive_key(byte* block, int idxSz, byte label,
if ((ret == 0) && (keySz > 0)) {
byte enc[WC_AES_BLOCK_SIZE];
/* Set counter. */
+ block[14] = (byte)(i >> 8);
block[15] = (byte)i;
/* Encrypt block into temporary. */
ret = wc_AesEcbEncrypt(aes, enc, block, WC_AES_BLOCK_SIZE);
diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c
index 677441e426..97d15a3937 100644
--- a/wolfcrypt/src/pkcs7.c
+++ b/wolfcrypt/src/pkcs7.c
@@ -1794,6 +1794,16 @@ static int wc_PKCS7_ImportRSA(wc_PKCS7* pkcs7, RsaKey* privKey)
}
#endif
}
+ #ifdef HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK
+ else if (pkcs7->rsaSignRawDigestCb != NULL && pkcs7->publicKeySz > 0) {
+ /* When using raw sign callback (e.g., HSM/secure element), private
+ * key may not be available. Use public key from signer certificate
+ * for signature size calculation. */
+ idx = 0;
+ ret = wc_RsaPublicKeyDecode(pkcs7->publicKey, &idx, privKey,
+ pkcs7->publicKeySz);
+ }
+ #endif
else if (pkcs7->devId == INVALID_DEVID) {
ret = BAD_FUNC_ARG;
}
@@ -1874,6 +1884,16 @@ static int wc_PKCS7_ImportECC(wc_PKCS7* pkcs7, ecc_key* privKey)
}
#endif
}
+ #ifdef HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK
+ else if (pkcs7->eccSignRawDigestCb != NULL && pkcs7->publicKeySz > 0) {
+ /* When using raw sign callback (e.g., HSM/secure element), private
+ * key may not be available. Use public key from signer certificate
+ * for signature size calculation. */
+ idx = 0;
+ ret = wc_EccPublicKeyDecode(pkcs7->publicKey, &idx, privKey,
+ pkcs7->publicKeySz);
+ }
+ #endif
else if (pkcs7->devId == INVALID_DEVID) {
ret = BAD_FUNC_ARG;
}
@@ -2398,6 +2418,28 @@ static int wc_PKCS7_SignedDataBuildSignature(wc_PKCS7* pkcs7,
#ifdef HAVE_ECC
case ECDSAk:
+ #ifdef HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK
+ if (pkcs7->eccSignRawDigestCb != NULL) {
+ /* get hash OID */
+ int eccHashOID = wc_HashGetOID(esd->hashType);
+ if (eccHashOID < 0) {
+ ret = eccHashOID;
+ break;
+ }
+
+ /* user signing plain digest */
+ ret = pkcs7->eccSignRawDigestCb(pkcs7,
+ esd->contentAttribsDigest, hashSz,
+ esd->encContentDigest, sizeof(esd->encContentDigest),
+ pkcs7->privateKey, pkcs7->privateKeySz, pkcs7->devId,
+ eccHashOID);
+ /* validate return value doesn't exceed buffer size */
+ if (ret > 0 && (word32)ret > sizeof(esd->encContentDigest)) {
+ ret = BUFFER_E;
+ }
+ break;
+ }
+ #endif
/* CMS with ECDSA does not sign DigestInfo structure
* like PKCS#7 with RSA does */
ret = wc_PKCS7_EcdsaSign(pkcs7, esd->contentAttribsDigest,
@@ -3986,6 +4028,30 @@ int wc_PKCS7_SetRsaSignRawDigestCb(wc_PKCS7* pkcs7, CallbackRsaSignRawDigest cb)
}
#endif
+#endif /* NO_RSA */
+
+
+#ifdef HAVE_ECC
+
+#ifdef HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK
+/* register raw ECC sign digest callback */
+int wc_PKCS7_SetEccSignRawDigestCb(wc_PKCS7* pkcs7, CallbackEccSignRawDigest cb)
+{
+ if (pkcs7 == NULL || cb == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ pkcs7->eccSignRawDigestCb = cb;
+
+ return 0;
+}
+#endif
+
+#endif /* HAVE_ECC */
+
+
+#ifndef NO_RSA
+
/* returns size of signature put into out, negative on error */
static int wc_PKCS7_RsaVerify(wc_PKCS7* pkcs7, byte* sig, int sigSz,
byte* hash, word32 hashSz)
diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c
index 4e4f4e2388..37c410b543 100644
--- a/wolfcrypt/src/random.c
+++ b/wolfcrypt/src/random.c
@@ -1147,7 +1147,7 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
rng->drbg_scratch = NULL;
#endif
}
- /* else swc_RNG_HealthTestLocal was successful */
+ /* else wc_RNG_HealthTestLocal was successful */
if (ret == DRBG_SUCCESS) {
#ifdef WOLFSSL_CHECK_MEM_ZERO
diff --git a/wolfcrypt/src/wc_pkcs11.c b/wolfcrypt/src/wc_pkcs11.c
index 3ac4911f25..8ad4049804 100644
--- a/wolfcrypt/src/wc_pkcs11.c
+++ b/wolfcrypt/src/wc_pkcs11.c
@@ -68,10 +68,6 @@
#endif
-/* Maximum length of the EC parameter string. */
-#define MAX_EC_PARAM_LEN 16
-
-
#if defined(HAVE_ECC) && !defined(NO_PKCS11_ECDH)
/* Pointer to false required for templates. */
static CK_BBOOL ckFalse = CK_FALSE;
@@ -110,7 +106,9 @@ typedef struct CK_AES_CTR_PARAMS {
} CK_AES_CTR_PARAMS;
#endif
+#if !defined(NO_CERTS)
static CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
+#endif
#ifdef WOLFSSL_DEBUG_PKCS11
/* Enable logging of PKCS#11 calls and return value. */
@@ -120,6 +118,9 @@ static CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
/* Enable logging of PKCS#11 template. */
#define PKCS11_DUMP_TEMPLATE(name, templ, cnt) \
pkcs11_dump_template(name, templ, cnt)
+/* Enable logging of PKCS#11 mechanism info. */
+#define PKCS11_DUMP_MECHANSIM(name, mechanism) \
+ pkcs11_dump_mechanism(name, mechanism)
/* Formats of template items - used to instruct how to log information. */
enum PKCS11_TYPE_FORMATS {
@@ -141,7 +142,7 @@ static struct PKCS11_TYPE_STR {
int format;
} typeStr[] = {
{ CKA_CLASS, "CKA_CLASS", PKCS11_FMT_CLASS },
- { CKA_TOKEN, "CKA_TOKEN", PKCS11_FMT_POINTER },
+ { CKA_TOKEN, "CKA_TOKEN", PKCS11_FMT_BOOLEAN },
{ CKA_PRIVATE, "CKA_PRIVATE", PKCS11_FMT_BOOLEAN },
{ CKA_LABEL, "CKA_LABEL", PKCS11_FMT_STRING },
{ CKA_VALUE, "CKA_VALUE", PKCS11_FMT_DATA },
@@ -327,6 +328,11 @@ static void pkcs11_dump_template(const char* name, CK_ATTRIBUTE* templ,
WOLFSSL_MSG(line);
break;
case PKCS11_FMT_DATA:
+ if (templ[i].ulValueLen == CK_UNAVAILABLE_INFORMATION) {
+ XSNPRINTF(line, sizeof(line), "%25s: unavailable", type);
+ WOLFSSL_MSG(line);
+ break;
+ }
XSNPRINTF(line, sizeof(line), "%25s: %ld", type,
templ[i].ulValueLen);
WOLFSSL_MSG(line);
@@ -340,7 +346,7 @@ static void pkcs11_dump_template(const char* name, CK_ATTRIBUTE* templ,
char hex[6];
XSNPRINTF(hex, sizeof(hex), "0x%02x,",
((byte*)templ[i].pValue)[j]);
- XSTRNCAT(line, hex, 5);
+ XSTRNCAT(line, hex, sizeof(line) - XSTRLEN(line) - 1);
if ((j % 8) == 7) {
WOLFSSL_MSG(line);
XSNPRINTF(line, sizeof(line), "%27s", "");
@@ -365,6 +371,64 @@ static void pkcs11_dump_template(const char* name, CK_ATTRIBUTE* templ,
}
}
+/* Information for logging a mechanism */
+static struct PKCS11_MECHANISM_STR {
+ /** Mechanism. */
+ CK_MECHANISM_TYPE mech;
+ /** String to log corresponding mechanism. */
+ const char* str;
+} mechStr[] = {
+ { CKM_RSA_PKCS_KEY_PAIR_GEN, "CKM_RSA_PKCS_KEY_PAIR_GEN" },
+ { CKM_RSA_X_509, "CKM_RSA_X_509" },
+ { CKM_DH_PKCS_KEY_PAIR_GEN, "CKM_DH_PKCS_KEY_PAIR_GEN" },
+ { CKM_DH_PKCS_DERIVE, "CKM_DH_PKCS_DERIVE" },
+ { CKM_MD5_HMAC, "CKM_MD5_HMAC" },
+ { CKM_SHA_1_HMAC, "CKM_SHA_1_HMAC" },
+ { CKM_SHA256_HMAC, "CKM_SHA256_HMAC" },
+ { CKM_SHA224_HMAC, "CKM_SHA224_HMAC" },
+ { CKM_SHA384_HMAC, "CKM_SHA384_HMAC" },
+ { CKM_SHA512_HMAC, "CKM_SHA512_HMAC" },
+ { CKM_GENERIC_SECRET_KEY_GEN, "CKM_GENERIC_SECRET_KEY_GEN" },
+ { CKM_EC_KEY_PAIR_GEN, "CKM_EC_KEY_PAIR_GEN" },
+ { CKM_ECDSA, "CKM_ECDSA" },
+ { CKM_ECDH1_DERIVE, "CKM_ECDH1_DERIVE" },
+ { CKM_ECDH1_COFACTOR_DERIVE, "CKM_ECDH1_COFACTOR_DERIVE" },
+ { CKM_AES_KEY_GEN, "CKM_AES_KEY_GEN" },
+ { CKM_AES_CBC, "CKM_AES_CBC" },
+ { CKM_AES_GCM, "CKM_AES_GCM" },
+};
+/* Count of known mechanism for logging. */
+#define PKCS11_MECH_STR_CNT ((int)(sizeof(mechStr) / sizeof(*mechStr)))
+
+/*
+ * Dump/log the PKCS #11 mechanism.
+ *
+ * This is only for debugging purposes. Only the values needed are recognised.
+ *
+ * @param [in] op PKCS #11 operation that was attempted.
+ * @param [in] mech PKCS #11 mechanism to dump.
+ */
+static void pkcs11_dump_mechanism(const char* op, CK_MECHANISM_TYPE mech)
+{
+ char line[80];
+ const char *mechName = NULL;
+ int i;
+
+ for (i = 0; i < PKCS11_MECH_STR_CNT; i++) {
+ if (mech == mechStr[i].mech) {
+ mechName = mechStr[i].str;
+ break;
+ }
+ }
+ if (i == PKCS11_TYPE_STR_CNT) {
+ mechName = "UNKNOWN";
+ }
+
+ XSNPRINTF(line, 80, "%s: %s", op, mechName);
+
+ WOLFSSL_MSG(line);
+}
+
/*
* Log a PKCS #11 return value with the name of function called.
*
@@ -416,6 +480,8 @@ static void pkcs11_val(const char* op, CK_ULONG val)
#define PKCS11_VAL(op, val) WC_DO_NOTHING
/* Disable logging of PKCS#11 template. */
#define PKCS11_DUMP_TEMPLATE(name, templ, cnt) WC_DO_NOTHING
+/* Disable logging of PKCS#11 mechanism info. */
+#define PKCS11_DUMP_MECHANSIM(name, mechanism) WC_DO_NOTHING
#endif
/**
@@ -432,7 +498,7 @@ static void pkcs11_val(const char* op, CK_ULONG val)
*/
int wc_Pkcs11_Initialize(Pkcs11Dev* dev, const char* library, void* heap)
{
- return wc_Pkcs11_Initialize_ex(dev, library, heap, NULL);
+ return wc_Pkcs11_Initialize_v3(dev, library, heap, NULL, NULL, NULL);
}
/**
@@ -451,52 +517,270 @@ int wc_Pkcs11_Initialize(Pkcs11Dev* dev, const char* library, void* heap)
*/
int wc_Pkcs11_Initialize_ex(Pkcs11Dev* dev, const char* library, void* heap,
CK_RV* rvp)
+{
+ return wc_Pkcs11_Initialize_v3(dev, library, heap, NULL, NULL, rvp);
+}
+
+/**
+ * Load library, get function list and initialize PKCS#11.
+ *
+ * @param [in] dev Device object.
+ * @param [in] library Library name including path.
+ * @param [in] heap Heap hint.
+ * @param [in,out] version On in, desired version of interface.
+ * On out, actual obtained version of interface.
+ * @param [in] interfaceName Name of the interface to use.
+ * @param [out] rvp PKCS#11 return value. Last return value seen.
+ * May be NULL.
+ * @return BAD_FUNC_ARG when dev or library are NULL pointers.
+ * @return BAD_PATH_ERROR when dynamic library cannot be opened.
+ * @return WC_INIT_E when the initialization PKCS#11 fails.
+ * @return WC_HW_E when unable to get PKCS#11 function list.
+ * @return 0 on success.
+ */
+int wc_Pkcs11_Initialize_v3(Pkcs11Dev* dev, const char* library,
+ void* heap, int* version, const char* interfaceName, CK_RV* rvp)
{
int ret = 0;
CK_RV rv = CKR_OK;
-#ifndef HAVE_PKCS11_STATIC
+#if !defined(HAVE_PKCS11_STATIC) && !defined(HAVE_PKCS11_V3_STATIC)
void* func;
#endif
CK_C_INITIALIZE_ARGS args;
+ CK_VERSION_PTR version_ptr = NULL;
- if (dev == NULL || library == NULL)
+ if (dev == NULL)
ret = BAD_FUNC_ARG;
+#if !defined(HAVE_PKCS11_STATIC) && !defined(HAVE_PKCS11_V3_STATIC)
+ if (library == NULL)
+ ret = BAD_FUNC_ARG;
+#endif
+
if (ret == 0) {
dev->heap = heap;
-#ifndef HAVE_PKCS11_STATIC
+#if defined(HAVE_PKCS11_V3_STATIC)
+ CK_INTERFACE_PTR interface = NULL;
+ CK_VERSION pkcs11_version = {0, 0};
+
+ if (version != NULL) {
+ if (*version == WC_PCKS11VERSION_2_20) {
+ pkcs11_version.major = 2;
+ pkcs11_version.minor = 20;
+ }
+ else if (*version == WC_PCKS11VERSION_2_20) {
+ pkcs11_version.major = 2;
+ pkcs11_version.minor = 40;
+ }
+ else if (*version == WC_PCKS11VERSION_3_0) {
+ pkcs11_version.major = 3;
+ pkcs11_version.minor = 0;
+ }
+ else if (*version == WC_PCKS11VERSION_3_1) {
+ pkcs11_version.major = 3;
+ pkcs11_version.minor = 1;
+ }
+ else if (*version == WC_PCKS11VERSION_3_2) {
+ pkcs11_version.major = 3;
+ pkcs11_version.minor = 2;
+ }
+ version_ptr = &pkcs11_version;
+ }
+ else {
+ version_ptr = NULL;
+ }
+
+ rv = C_GetInterface((CK_UTF8CHAR_PTR) interfaceName, version_ptr,
+ &interface, 0);
+
+ if (rv == CKR_OK) {
+ dev->func = interface->pFunctionList;
+ version_ptr = (CK_VERSION_PTR) interface->pFunctionList;
+ if (version_ptr->major == 2 && version_ptr->minor == 20) {
+ dev->version = WC_PCKS11VERSION_2_20;
+ }
+ else if (version_ptr->major == 2 &&
+ version_ptr->minor == 40) {
+ dev->version = WC_PCKS11VERSION_2_40;
+ }
+ else if (version_ptr->major == 3 &&
+ version_ptr->minor == 0) {
+ dev->version = WC_PCKS11VERSION_3_0;
+ }
+ else if (version_ptr->major == 3 &&
+ version_ptr->minor == 1) {
+ dev->version = WC_PCKS11VERSION_3_1;
+ }
+ else if (version_ptr->major == 3 &&
+ version_ptr->minor == 2) {
+ dev->version = WC_PCKS11VERSION_3_2;
+ }
+ else {
+ WOLFSSL_MSG_EX("Unsupported PKCS#11 version: %d.%d",
+ version_ptr->major, version_ptr->minor);
+ ret = WC_HW_E;
+ }
+ }
+ else {
+ PKCS11_RV("CK_C_GetInterface", rv);
+ ret = WC_HW_E;
+ }
+#elif defined(HAVE_PKCS11_STATIC)
+ rv = C_GetFunctionList(&dev->func);
+ if (rv == CKR_OK) {
+ version_ptr = (CK_VERSION_PTR) dev->func;
+ if (version_ptr->major == 2 &&
+ version_ptr->minor == 20) {
+ dev->version = WC_PCKS11VERSION_2_20;
+ }
+ else if (version_ptr->major == 2 &&
+ version_ptr->minor == 40) {
+ dev->version = WC_PCKS11VERSION_2_40;
+ }
+ else {
+ WOLFSSL_MSG_EX("Unsupported PKCS#11 version: %d.%d",
+ version_ptr->major,
+ version_ptr->minor);
+ ret = WC_HW_E;
+ }
+ }
+ else {
+ PKCS11_RV("CK_C_GetFunctionList", rv);
+ ret = WC_HW_E;
+ }
+#else
+ /* Load dynamic library */
dev->dlHandle = dlopen(library, RTLD_NOW | RTLD_LOCAL);
if (dev->dlHandle == NULL) {
WOLFSSL_MSG(dlerror());
ret = BAD_PATH_ERROR;
}
+
+ if (ret == 0) {
+ /* Check if the library supports PKCS#11 version 3.0 (or above) by
+ * looking for the C_GetInterface method (only present for >= V3.0).
+ */
+ func = dlsym(dev->dlHandle, "C_GetInterface");
+ if (func != NULL) {
+ /* Function is present, use it */
+ CK_INTERFACE_PTR interface = NULL;
+ CK_VERSION pkcs11_version = {0, 0};
+ if (version != NULL) {
+ if (*version == WC_PCKS11VERSION_2_20) {
+ pkcs11_version.major = 2;
+ pkcs11_version.minor = 20;
+ }
+ else if (*version == WC_PCKS11VERSION_2_40) {
+ pkcs11_version.major = 2;
+ pkcs11_version.minor = 40;
+ }
+ else if (*version == WC_PCKS11VERSION_3_0) {
+ pkcs11_version.major = 3;
+ pkcs11_version.minor = 0;
+ }
+ else if (*version == WC_PCKS11VERSION_3_1) {
+ pkcs11_version.major = 3;
+ pkcs11_version.minor = 1;
+ }
+ else if (*version == WC_PCKS11VERSION_3_2) {
+ pkcs11_version.major = 3;
+ pkcs11_version.minor = 2;
+ }
+ version_ptr = &pkcs11_version;
+ }
+ else {
+ version_ptr = NULL;
+ }
+
+ rv = ((CK_C_GetInterface)func)((CK_UTF8CHAR_PTR) interfaceName,
+ version_ptr, &interface, 0);
+ if (rv == CKR_OK) {
+ dev->func = interface->pFunctionList;
+ version_ptr = (CK_VERSION_PTR) interface->pFunctionList;
+ if (version_ptr->major == 2 && version_ptr->minor == 20) {
+ dev->version = WC_PCKS11VERSION_2_20;
+ }
+ else if (version_ptr->major == 2 &&
+ version_ptr->minor == 40) {
+ dev->version = WC_PCKS11VERSION_2_40;
+ }
+ else if (version_ptr->major == 3 &&
+ version_ptr->minor == 0) {
+ dev->version = WC_PCKS11VERSION_3_0;
+ }
+ else if (version_ptr->major == 3 &&
+ version_ptr->minor == 1) {
+ dev->version = WC_PCKS11VERSION_3_1;
+ }
+ else if (version_ptr->major == 3 &&
+ version_ptr->minor == 2) {
+ dev->version = WC_PCKS11VERSION_3_2;
+ }
+ else {
+ WOLFSSL_MSG_EX("Unsupported PKCS#11 version: %d.%d",
+ version_ptr->major, version_ptr->minor);
+ ret = WC_HW_E;
+ }
+ }
+ else {
+ PKCS11_RV("CK_C_GetInterface", rv);
+ ret = WC_HW_E;
+ }
+ }
+ else {
+ /* Function not present, try a 2.x library by looking for
+ * C_GetFunctionList. */
+ func = dlsym(dev->dlHandle, "C_GetFunctionList");
+ if (func == NULL) {
+ #if defined(_WIN32)
+ WOLFSSL_MSG_EX("GetProcAddress(): %d", GetLastError());
+ #else
+ WOLFSSL_MSG(dlerror());
+ #endif
+ ret = WC_HW_E;
+ }
+ if (ret == 0) {
+ rv = ((CK_C_GetFunctionList)func)(&dev->func);
+ if (rv == CKR_OK) {
+ version_ptr = (CK_VERSION_PTR) dev->func;
+ if (version_ptr->major == 2 &&
+ version_ptr->minor == 20) {
+ dev->version = WC_PCKS11VERSION_2_20;
+ }
+ else if (version_ptr->major == 2 &&
+ version_ptr->minor == 40) {
+ dev->version = WC_PCKS11VERSION_2_40;
+ }
+ else {
+ WOLFSSL_MSG_EX("Unsupported PKCS#11 version: %d.%d",
+ version_ptr->major,
+ version_ptr->minor);
+ ret = WC_HW_E;
+ }
+ }
+ else {
+ PKCS11_RV("CK_C_GetFunctionList", rv);
+ ret = WC_HW_E;
+ }
+ }
+ }
+ }
+#endif
}
- if (ret == 0) {
- dev->func = NULL;
- func = dlsym(dev->dlHandle, "C_GetFunctionList");
- if (func == NULL) {
- WOLFSSL_MSG(dlerror());
- ret = WC_HW_E;
- }
- }
- if (ret == 0) {
- rv = ((CK_C_GetFunctionList)func)(&dev->func);
-#else
- rv = C_GetFunctionList(&dev->func);
-#endif
- if (rv != CKR_OK) {
- PKCS11_RV("CK_C_GetFunctionList", ret);
- ret = WC_HW_E;
- }
- }
+ if (ret == 0 && version != NULL)
+ *version = dev->version;
if (ret == 0) {
XMEMSET(&args, 0x00, sizeof(args));
args.flags = CKF_OS_LOCKING_OK;
rv = dev->func->C_Initialize(&args);
- if (rv != CKR_OK) {
- PKCS11_RV("C_Initialize", ret);
+ if (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED) {
+ WOLFSSL_MSG("PKCS#11 already initialized");
+ rv = CKR_OK;
+ }
+ else if (rv != CKR_OK) {
+ PKCS11_RV("C_Initialize", rv);
ret = WC_INIT_E;
}
}
@@ -520,7 +804,7 @@ int wc_Pkcs11_Initialize_ex(Pkcs11Dev* dev, const char* library, void* heap,
void wc_Pkcs11_Finalize(Pkcs11Dev* dev)
{
if (dev != NULL
-#ifndef HAVE_PKCS11_STATIC
+#if !defined(HAVE_PKCS11_STATIC) && !defined(HAVE_PKCS11_V3_STATIC)
&& dev->dlHandle != NULL
#endif
) {
@@ -528,7 +812,7 @@ void wc_Pkcs11_Finalize(Pkcs11Dev* dev)
dev->func->C_Finalize(NULL);
dev->func = NULL;
}
-#ifndef HAVE_PKCS11_STATIC
+#if !defined(HAVE_PKCS11_STATIC) && !defined(HAVE_PKCS11_V3_STATIC)
dlclose(dev->dlHandle);
dev->dlHandle = NULL;
#endif
@@ -633,6 +917,7 @@ static int Pkcs11Token_Init(Pkcs11Token* token, Pkcs11Dev* dev, int slotId,
token->userPin = NULL_PTR;
token->userPinSz = 0;
token->userPinLogin = 0;
+ token->version = dev->version;
}
XFREE(slot, dev->heap, DYNAMIC_TYPE_TMP_BUFFER);
@@ -809,6 +1094,7 @@ static int Pkcs11OpenSession(Pkcs11Token* token, Pkcs11Session* session,
if (ret == 0) {
session->func = token->func;
session->slotId = token->slotId;
+ session->version = token->version;
}
return ret;
@@ -1060,13 +1346,24 @@ static int Pkcs11EccSetParams(ecc_key* key, CK_ATTRIBUTE* tmpl, int idx)
{
int ret = 0;
- if (key->dp != NULL && key->dp->oid != NULL) {
+ if (key != NULL && key->dp != NULL && key->dp->oid != NULL) {
unsigned char* derParams = tmpl[idx].pValue;
+ #if defined(HAVE_OID_ENCODING)
+ word32 oidSz = ECC_MAX_OID_LEN - 2;
+ ret = wc_EncodeObjectId(key->dp->oid, key->dp->oidSz, derParams+2, &oidSz);
+ if (ret != 0) {
+ return ret;
+ }
+ tmpl[idx].ulValueLen = oidSz + 2;
+ derParams[0] = ASN_OBJECT_ID;
+ derParams[1] = oidSz;
+ #else
/* ASN.1 encoding: OBJ + ecc parameters OID */
tmpl[idx].ulValueLen = key->dp->oidSz + 2;
derParams[0] = ASN_OBJECT_ID;
derParams[1] = key->dp->oidSz;
XMEMCPY(derParams + 2, key->dp->oid, key->dp->oidSz);
+ #endif
}
else
ret = NOT_COMPILED_IN;
@@ -1096,7 +1393,7 @@ static int Pkcs11CreateEccPublicKey(CK_OBJECT_HANDLE* publicKey,
unsigned char* ecPoint = NULL;
word32 len;
CK_RV rv;
- CK_UTF8CHAR params[MAX_EC_PARAM_LEN];
+ CK_UTF8CHAR params[ECC_MAX_OID_LEN];
/* Empty entries for optional label/ID. */
CK_ATTRIBUTE keyTemplate[] = {
{ CKA_CLASS, &pubKeyClass, sizeof(pubKeyClass) },
@@ -1180,7 +1477,7 @@ static int Pkcs11CreateEccPrivateKey(CK_OBJECT_HANDLE* privateKey,
{
int ret = 0;
CK_RV rv;
- CK_UTF8CHAR params[MAX_EC_PARAM_LEN];
+ CK_UTF8CHAR params[ECC_MAX_OID_LEN];
/* Empty entries for optional label/ID. */
CK_ATTRIBUTE keyTemplate[] = {
{ CKA_CLASS, &privKeyClass, sizeof(privKeyClass) },
@@ -1209,16 +1506,30 @@ static int Pkcs11CreateEccPrivateKey(CK_OBJECT_HANDLE* privateKey,
ret = Pkcs11EccSetParams(private_key, keyTemplate, 3);
if (ret == 0) {
- keyTemplate[4].pValue = wc_ecc_key_get_priv(private_key)->raw.buf;
- keyTemplate[4].ulValueLen = wc_ecc_key_get_priv(private_key)->raw.len;
-
- PKCS11_DUMP_TEMPLATE("Ec Private Key", keyTemplate, keyTmplCnt);
- rv = session->func->C_CreateObject(session->handle, keyTemplate,
- keyTmplCnt, privateKey);
- PKCS11_RV("C_CreateObject", rv);
- if (rv != CKR_OK) {
- ret = WC_HW_E;
+ word32 privLen = private_key->dp->size;
+ byte* priv = (byte*)XMALLOC(privLen, private_key->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (priv == NULL) {
+ ret = MEMORY_E;
}
+ if (ret == 0) {
+ PRIVATE_KEY_LOCK();
+ ret = wc_ecc_export_private_only(private_key, priv, &privLen);
+ PRIVATE_KEY_UNLOCK();
+ }
+ if (ret == 0) {
+ keyTemplate[4].pValue = priv;
+ keyTemplate[4].ulValueLen = privLen;
+
+ PKCS11_DUMP_TEMPLATE("Ec Private Key", keyTemplate, keyTmplCnt);
+ rv = session->func->C_CreateObject(session->handle, keyTemplate,
+ keyTmplCnt, privateKey);
+ PKCS11_RV("C_CreateObject", rv);
+ if (rv != CKR_OK) {
+ ret = WC_HW_E;
+ }
+ }
+ XFREE(priv, private_key->heap, DYNAMIC_TYPE_TMP_BUFFER);
}
return ret;
@@ -1230,22 +1541,28 @@ static int Pkcs11CreateEccPrivateKey(CK_OBJECT_HANDLE* privateKey,
/**
* Check if mechanism is available in session on token.
*
- * @param [in] session Session object.
- * @param [in] mech Mechanism to look for.
+ * @param [in] session Session object.
+ * @param [in] mech Mechanism to look for.
+ * @param [out] mechInfoPtr Mechanism info return data (optional).
* @return NOT_COMPILED_IN when mechanism not available.
* @return 0 when mechanism is available.
*/
-static int Pkcs11MechAvail(Pkcs11Session* session, CK_MECHANISM_TYPE mech)
+static int Pkcs11MechAvail(Pkcs11Session* session, CK_MECHANISM_TYPE mech,
+ CK_MECHANISM_INFO_PTR mechInfoPtr)
{
int ret = 0;
CK_RV rv;
CK_MECHANISM_INFO mechInfo;
+ PKCS11_DUMP_MECHANSIM("PKCS#11: Check if mechanism is available", mech);
rv = session->func->C_GetMechanismInfo(session->slotId, mech, &mechInfo);
PKCS11_RV("C_GetMechanismInfo", rv);
if (rv != CKR_OK) {
ret = NOT_COMPILED_IN;
}
+ if (mechInfoPtr != NULL) {
+ *mechInfoPtr = mechInfo;
+ }
return ret;
}
@@ -1335,7 +1652,7 @@ int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, void* key)
case PKCS11_KEY_TYPE_AES_GCM: {
Aes* aes = (Aes*)key;
- ret = Pkcs11MechAvail(&session, CKM_AES_GCM);
+ ret = Pkcs11MechAvail(&session, CKM_AES_GCM, NULL);
if (ret == 0) {
ret = Pkcs11CreateSecretKey(&privKey, &session, CKK_AES,
(unsigned char*)aes->devKey,
@@ -1353,7 +1670,7 @@ int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, void* key)
case PKCS11_KEY_TYPE_AES_CBC: {
Aes* aes = (Aes*)key;
- ret = Pkcs11MechAvail(&session, CKM_AES_CBC);
+ ret = Pkcs11MechAvail(&session, CKM_AES_CBC, NULL);
if (ret == 0) {
ret = Pkcs11CreateSecretKey(&privKey, &session, CKK_AES,
(unsigned char*)aes->devKey,
@@ -1378,7 +1695,7 @@ int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, void* key)
break;
if (ret == 0)
- ret = Pkcs11MechAvail(&session, mechType);
+ ret = Pkcs11MechAvail(&session, mechType, NULL);
if (ret == 0) {
ret = Pkcs11CreateSecretKey(&privKey, &session, keyType,
(unsigned char*)hmac->keyRaw,
@@ -1403,7 +1720,7 @@ int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, void* key)
case PKCS11_KEY_TYPE_RSA: {
RsaKey* rsaKey = (RsaKey*)key;
- ret = Pkcs11MechAvail(&session, CKM_RSA_X_509);
+ ret = Pkcs11MechAvail(&session, CKM_RSA_X_509, NULL);
if (ret == 0)
ret = Pkcs11CreateRsaPrivateKey(&privKey, &session, rsaKey,
1);
@@ -1426,7 +1743,7 @@ int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, void* key)
#ifndef NO_PKCS11_ECDH
if ((eccKey->flags & WC_ECC_FLAG_DEC_SIGN) == 0) {
/* Try ECDH mechanism first. */
- ret = Pkcs11MechAvail(&session, CKM_ECDH1_DERIVE);
+ ret = Pkcs11MechAvail(&session, CKM_ECDH1_DERIVE, NULL);
if (ret == 0) {
ret = Pkcs11CreateEccPrivateKey(&privKey, &session,
eccKey, CKA_DERIVE);
@@ -1435,7 +1752,7 @@ int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, void* key)
#endif
if (ret == 0 || ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) {
/* Try ECDSA mechanism next. */
- ret2 = Pkcs11MechAvail(&session, CKM_ECDSA);
+ ret2 = Pkcs11MechAvail(&session, CKM_ECDSA, NULL);
if (ret2 == 0) {
ret2 = Pkcs11CreateEccPrivateKey(&privKey, &session,
eccKey, CKA_SIGN);
@@ -2188,7 +2505,6 @@ static int Pkcs11RsaSign(Pkcs11Session* session, wc_CryptoInfo* info,
static int Pkcs11Rsa(Pkcs11Session* session, wc_CryptoInfo* info)
{
int ret = 0;
- CK_RV rv;
CK_MECHANISM_INFO mechInfo;
CK_MECHANISM_TYPE mechanism = 0x0UL;
int sessionKey = 0;
@@ -2214,12 +2530,7 @@ static int Pkcs11Rsa(Pkcs11Session* session, wc_CryptoInfo* info)
}
/* Check operation is supported. */
- rv = session->func->C_GetMechanismInfo(session->slotId, mechanism,
- &mechInfo);
- PKCS11_RV("C_GetMechanismInfo", rv);
- if (rv != CKR_OK) {
- ret = NOT_COMPILED_IN;
- }
+ ret = Pkcs11MechAvail(session, mechanism, &mechInfo);
if (ret == 0) {
if ((type == RSA_PUBLIC_ENCRYPT) || (type == RSA_PUBLIC_DECRYPT)) {
@@ -2318,7 +2629,7 @@ static int Pkcs11RsaKeyGen(Pkcs11Session* session, wc_CryptoInfo* info)
int privTmplCnt = 2;
int i;
- ret = Pkcs11MechAvail(session, CKM_RSA_PKCS_KEY_PAIR_GEN);
+ ret = Pkcs11MechAvail(session, CKM_RSA_PKCS_KEY_PAIR_GEN, NULL);
if (ret == 0) {
WOLFSSL_MSG("PKCS#11: RSA Key Generation Operation");
@@ -2394,9 +2705,8 @@ static int Pkcs11FindEccKey(CK_OBJECT_HANDLE* key, CK_OBJECT_CLASS keyClass,
int i;
unsigned char* ecPoint = NULL;
word32 len = 0;
- CK_RV rv;
CK_ULONG count;
- CK_UTF8CHAR params[MAX_EC_PARAM_LEN];
+ CK_UTF8CHAR params[ECC_MAX_OID_LEN];
CK_ATTRIBUTE keyTemplate[] = {
{ CKA_CLASS, &keyClass, sizeof(keyClass) },
{ CKA_KEY_TYPE, &ecKeyType, sizeof(ecKeyType) },
@@ -2433,26 +2743,7 @@ static int Pkcs11FindEccKey(CK_OBJECT_HANDLE* key, CK_OBJECT_CLASS keyClass,
attrCnt++;
}
if (ret == 0) {
- PKCS11_DUMP_TEMPLATE("Find Ec Key", keyTemplate, attrCnt);
- rv = session->func->C_FindObjectsInit(session->handle, keyTemplate,
- attrCnt);
- PKCS11_RV("C_FindObjectsInit", rv);
- if (rv != CKR_OK) {
- ret = WC_HW_E;
- }
- }
- if (ret == 0) {
- rv = session->func->C_FindObjects(session->handle, key, 1, &count);
- PKCS11_RV("C_FindObjects", rv);
- PKCS11_VAL("C_FindObjects Count", count);
- if (rv != CKR_OK) {
- ret = WC_HW_E;
- }
- rv = session->func->C_FindObjectsFinal(session->handle);
- PKCS11_RV("C_FindObjectsFinal", rv);
- if (rv != CKR_OK) {
- ret = WC_HW_E;
- }
+ ret = Pkcs11FindKeyByTemplate(key, session, keyTemplate, attrCnt, &count);
}
XFREE(ecPoint, eccKey->heap, DYNAMIC_TYPE_ECC);
@@ -2560,7 +2851,7 @@ static int Pkcs11EcKeyGen(Pkcs11Session* session, wc_CryptoInfo* info)
CK_RV rv;
CK_OBJECT_HANDLE pubKey = NULL_PTR, privKey = NULL_PTR;
CK_MECHANISM mech;
- CK_UTF8CHAR params[MAX_EC_PARAM_LEN];
+ CK_UTF8CHAR params[ECC_MAX_OID_LEN];
CK_ATTRIBUTE pubKeyTmpl[] = {
{ CKA_EC_PARAMS, params, 0 },
{ CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
@@ -2584,7 +2875,7 @@ static int Pkcs11EcKeyGen(Pkcs11Session* session, wc_CryptoInfo* info)
/* Mandatory entries + 2 optional. */
int privTmplCnt = 1;
- ret = Pkcs11MechAvail(session, CKM_EC_KEY_PAIR_GEN);
+ ret = Pkcs11MechAvail(session, CKM_EC_KEY_PAIR_GEN, NULL);
if (ret == 0) {
WOLFSSL_MSG("PKCS#11: EC Key Generation Operation");
@@ -2670,7 +2961,9 @@ static int Pkcs11ExtractSecret(Pkcs11Session* session, CK_OBJECT_HANDLE secret,
}
PKCS11_DUMP_TEMPLATE("Secret Length", tmpl, tmplCnt);
if (ret == 0) {
- if (tmpl[0].ulValueLen > *outLen)
+ if (tmpl[0].ulValueLen == CK_UNAVAILABLE_INFORMATION)
+ ret = WC_HW_E;
+ else if (tmpl[0].ulValueLen > *outLen)
ret = BUFFER_E;
}
if (ret == 0) {
@@ -2720,7 +3013,7 @@ static int Pkcs11ECDH(Pkcs11Session* session, wc_CryptoInfo* info)
};
CK_ULONG tmplCnt = sizeof(tmpl) / sizeof(*tmpl);
- ret = Pkcs11MechAvail(session, CKM_ECDH1_DERIVE);
+ ret = Pkcs11MechAvail(session, CKM_ECDH1_DERIVE, NULL);
if (ret == 0 && info->pk.ecdh.outlen == NULL) {
ret = BAD_FUNC_ARG;
}
@@ -3008,12 +3301,10 @@ static int Pkcs11ECDSA_Sign(Pkcs11Session* session, wc_CryptoInfo* info)
CK_OBJECT_HANDLE privateKey = NULL_PTR;
/* Check operation is supported. */
- rv = session->func->C_GetMechanismInfo(session->slotId, CKM_ECDSA,
- &mechInfo);
- PKCS11_RV("C_GetMechanismInfo", rv);
- if (rv != CKR_OK || (mechInfo.flags & CKF_SIGN) == 0)
+ ret = Pkcs11MechAvail(session, CKM_ECDSA, &mechInfo);
+ if (ret == 0 && (mechInfo.flags & CKF_SIGN) == 0) {
ret = NOT_COMPILED_IN;
-
+ }
if (ret == 0 && info->pk.eccsign.outlen == NULL) {
ret = BAD_FUNC_ARG;
}
@@ -3105,20 +3396,20 @@ static int Pkcs11ECDSA_Sign(Pkcs11Session* session, wc_CryptoInfo* info)
static int Pkcs11ECDSA_Verify(Pkcs11Session* session, wc_CryptoInfo* info)
{
int ret = 0;
+ int sessionKey = 0;
CK_RV rv;
CK_MECHANISM mech;
CK_MECHANISM_INFO mechInfo;
CK_OBJECT_HANDLE publicKey = NULL_PTR;
unsigned char* sig = NULL;
- word32 sz = info->pk.eccverify.key->dp->size;
+ ecc_key* key = info->pk.eccverify.key;
+ word32 sz = key->dp->size;
/* Check operation is supported. */
- rv = session->func->C_GetMechanismInfo(session->slotId, CKM_ECDSA,
- &mechInfo);
- PKCS11_RV("C_GetMechanismInfo", rv);
- if (rv != CKR_OK || (mechInfo.flags & CKF_VERIFY) == 0)
+ ret = Pkcs11MechAvail(session, CKM_ECDSA, &mechInfo);
+ if (ret == 0 && (mechInfo.flags & CKF_VERIFY) == 0) {
ret = NOT_COMPILED_IN;
-
+ }
if (ret == 0 && info->pk.eccverify.res == NULL) {
ret = BAD_FUNC_ARG;
}
@@ -3126,12 +3417,32 @@ static int Pkcs11ECDSA_Verify(Pkcs11Session* session, wc_CryptoInfo* info)
if (ret == 0) {
WOLFSSL_MSG("PKCS#11: EC Verification Operation");
- ret = Pkcs11CreateEccPublicKey(&publicKey, session,
- info->pk.eccverify.key, CKA_VERIFY);
+ if (key->labelLen > 0) {
+ ret = Pkcs11FindKeyByLabel(&publicKey, CKO_PUBLIC_KEY, CKK_EC,
+ session, key->label, key->labelLen);
+ if (ret == 0 && key->dp == NULL) {
+ ret = Pkcs11GetEccParams(session, publicKey, key);
+ }
+ }
+ else if (key->idLen > 0) {
+ ret = Pkcs11FindKeyById(&publicKey, CKO_PUBLIC_KEY, CKK_EC,
+ session, key->id, key->idLen);
+ if (ret == 0 && key->dp == NULL) {
+ ret = Pkcs11GetEccParams(session, publicKey, key);
+ }
+ }
+ else if (!mp_iszero(key->pubkey.x)) {
+ ret = Pkcs11CreateEccPublicKey(&publicKey, session, key,
+ CKA_VERIFY);
+ sessionKey = 1;
+ }
+ else
+ ret = Pkcs11FindEccKey(&publicKey, CKO_PUBLIC_KEY, session,
+ info->pk.eccsign.key, CKA_VERIFY);
}
if (ret == 0) {
- sig = (unsigned char *)XMALLOC(sz * 2, info->pk.eccverify.key->heap,
+ sig = (unsigned char *)XMALLOC(sz * 2, key->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (sig == NULL)
ret = MEMORY_E;
@@ -3168,7 +3479,7 @@ static int Pkcs11ECDSA_Verify(Pkcs11Session* session, wc_CryptoInfo* info)
*info->pk.eccverify.res = 1;
}
- if (publicKey != NULL_PTR)
+ if (sessionKey && publicKey != NULL_PTR)
session->func->C_DestroyObject(session->handle, publicKey);
if (sig != NULL)
@@ -3429,12 +3740,10 @@ static int Pkcs11AesGcmEncrypt(Pkcs11Session* session, wc_CryptoInfo* info)
CK_ULONG outLen;
/* Check operation is supported. */
- rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_GCM,
- &mechInfo);
- PKCS11_RV("C_GetMechanismInfo", rv);
- if (rv != CKR_OK || (mechInfo.flags & CKF_ENCRYPT) == 0)
+ ret = Pkcs11MechAvail(session, CKM_AES_GCM, &mechInfo);
+ if (ret == 0 && (mechInfo.flags & CKF_ENCRYPT) == 0) {
ret = NOT_COMPILED_IN;
-
+ }
if (ret == 0) {
WOLFSSL_MSG("PKCS#11: AES-GCM Encryption Operation");
@@ -3524,12 +3833,10 @@ static int Pkcs11AesGcmDecrypt(Pkcs11Session* session, wc_CryptoInfo* info)
word32 len;
/* Check operation is supported. */
- rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_GCM,
- &mechInfo);
- PKCS11_RV("C_GetMechanismInfo", rv);
- if (rv != CKR_OK || (mechInfo.flags & CKF_DECRYPT) == 0)
+ ret = Pkcs11MechAvail(session, CKM_AES_GCM, &mechInfo);
+ if (ret == 0 && (mechInfo.flags & CKF_DECRYPT) == 0) {
ret = NOT_COMPILED_IN;
-
+ }
if (ret == 0) {
WOLFSSL_MSG("PKCS#11: AES-GCM Decryption Operation");
@@ -3633,12 +3940,10 @@ static int Pkcs11AesCbcEncrypt(Pkcs11Session* session, wc_CryptoInfo* info)
CK_ULONG outLen;
/* Check operation is supported. */
- rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_CBC,
- &mechInfo);
- PKCS11_RV("C_GetMechanismInfo", rv);
- if (rv != CKR_OK || (mechInfo.flags & CKF_ENCRYPT) == 0)
+ ret = Pkcs11MechAvail(session, CKM_AES_CBC, &mechInfo);
+ if (ret == 0 && (mechInfo.flags & CKF_ENCRYPT) == 0) {
ret = NOT_COMPILED_IN;
-
+ }
if (ret == 0) {
WOLFSSL_MSG("PKCS#11: AES-CBC Encryption Operation");
@@ -3709,12 +4014,10 @@ static int Pkcs11AesCbcDecrypt(Pkcs11Session* session, wc_CryptoInfo* info)
CK_ULONG outLen;
/* Check operation is supported. */
- rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_CBC,
- &mechInfo);
- PKCS11_RV("C_GetMechanismInfo", rv);
- if (rv != CKR_OK || (mechInfo.flags & CKF_DECRYPT) == 0)
+ ret = Pkcs11MechAvail(session, CKM_AES_CBC, &mechInfo);
+ if (ret == 0 && (mechInfo.flags & CKF_DECRYPT) == 0) {
ret = NOT_COMPILED_IN;
-
+ }
if (ret == 0) {
WOLFSSL_MSG("PKCS#11: AES-CBC Decryption Operation");
@@ -3789,12 +4092,10 @@ static int Pkcs11AesCtrEncrypt(Pkcs11Session* session, wc_CryptoInfo* info)
CK_ULONG outLen;
/* Check operation is supported. */
- rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_CTR,
- &mechInfo);
- PKCS11_RV("C_GetMechanismInfo", rv);
- if (rv != CKR_OK || (mechInfo.flags & CKF_ENCRYPT) == 0)
+ ret = Pkcs11MechAvail(session, CKM_AES_CTR, &mechInfo);
+ if (ret == 0 && (mechInfo.flags & CKF_ENCRYPT) == 0) {
ret = NOT_COMPILED_IN;
-
+ }
if (ret == 0) {
WOLFSSL_MSG("PKCS#11: AES-CTR Encryption Operation");
@@ -3870,12 +4171,10 @@ static int Pkcs11AesCtrDecrypt(Pkcs11Session* session, wc_CryptoInfo* info)
CK_ULONG outLen;
/* Check operation is supported. */
- rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_CTR,
- &mechInfo);
- PKCS11_RV("C_GetMechanismInfo", rv);
- if (rv != CKR_OK || (mechInfo.flags & CKF_DECRYPT) == 0)
+ ret = Pkcs11MechAvail(session, CKM_AES_CTR, &mechInfo);
+ if (ret == 0 && (mechInfo.flags & CKF_DECRYPT) == 0) {
ret = NOT_COMPILED_IN;
-
+ }
if (ret == 0) {
WOLFSSL_MSG("PKCS#11: AES-CTR Decryption Operation");
@@ -3960,11 +4259,10 @@ static int Pkcs11Hmac(Pkcs11Session* session, wc_CryptoInfo* info)
ret = Pkcs11HmacTypes(info->hmac.macType, &mechType, &keyType);
if (ret == 0) {
/* Check operation is supported. */
- rv = session->func->C_GetMechanismInfo(session->slotId, mechType,
- &mechInfo);
- PKCS11_RV("C_GetMechanismInfo", rv);
- if (rv != CKR_OK || (mechInfo.flags & CKF_SIGN) == 0)
+ ret = Pkcs11MechAvail(session, mechType, &mechInfo);
+ if (ret == 0 && (mechInfo.flags & CKF_SIGN) == 0) {
ret = NOT_COMPILED_IN;
+ }
}
/* Check whether key been used to initialized. */
diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c
index a14991294d..b9a28d4b18 100644
--- a/wolfcrypt/test/test.c
+++ b/wolfcrypt/test/test.c
@@ -31783,6 +31783,8 @@ typedef struct Srtp_Kdf_Tv {
word32 ksSz;
} Srtp_Kdf_Tv;
+#define SRTP_KDF_LONG_KEY 5000
+
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t srtpkdf_test(void)
{
wc_test_ret_t ret = 0;
@@ -32034,6 +32036,18 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t srtpkdf_test(void)
unsigned char keyE[32];
unsigned char keyA[20];
unsigned char keyS[14];
+#ifndef BENCH_EMBEDDED
+ WC_DECLARE_VAR(keyELong, byte, SRTP_KDF_LONG_KEY, HEAP_HINT);
+ WC_DECLARE_VAR(keyALong, byte, SRTP_KDF_LONG_KEY, HEAP_HINT);
+ WC_DECLARE_VAR(keySLong, byte, SRTP_KDF_LONG_KEY, HEAP_HINT);
+#endif
+
+#ifndef BENCH_EMBEDDED
+ WC_ALLOC_VAR(keyELong, byte, SRTP_KDF_LONG_KEY, HEAP_HINT);
+ WC_ALLOC_VAR(keyALong, byte, SRTP_KDF_LONG_KEY, HEAP_HINT);
+ WC_ALLOC_VAR(keySLong, byte, SRTP_KDF_LONG_KEY, HEAP_HINT);
+#endif
+
WOLFSSL_ENTER("srtpkdf_test");
for (i = 0; (ret == 0) && (i < SRTP_TV_CNT); i++) {
@@ -32284,6 +32298,30 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t srtpkdf_test(void)
return WC_TEST_RET_ENC_NC;
}
+#ifndef BENCH_EMBEDDED
+ /* Check that long messages can be created. */
+ ret = wc_SRTP_KDF(tv[0].key, tv[0].keySz, tv[0].salt, tv[0].saltSz,
+ tv[0].kdfIdx, tv[0].index_c, keyELong, SRTP_KDF_LONG_KEY, keyALong,
+ SRTP_KDF_LONG_KEY, keySLong, SRTP_KDF_LONG_KEY);
+ if (ret != 0)
+ return WC_TEST_RET_ENC_EC(ret);
+
+ /* Check that two bytes of counter are being used. */
+ if (XMEMCMP(keyELong, keyELong + 4096, SRTP_KDF_LONG_KEY - 4096) == 0) {
+ return WC_TEST_RET_ENC_NC;
+ }
+ if (XMEMCMP(keyELong, keyALong + 4096, SRTP_KDF_LONG_KEY - 4096) == 0) {
+ return WC_TEST_RET_ENC_NC;
+ }
+ if (XMEMCMP(keyELong, keySLong + 4096, SRTP_KDF_LONG_KEY - 4096) == 0) {
+ return WC_TEST_RET_ENC_NC;
+ }
+
+ WC_FREE_VAR(keyELong, HEAP_HINT);
+ WC_FREE_VAR(keyALong, HEAP_HINT);
+ WC_FREE_VAR(keySLong, HEAP_HINT);
+#endif
+
return 0;
}
#endif
diff --git a/wolfssl/internal.h b/wolfssl/internal.h
index 59fb268aef..5eca832149 100644
--- a/wolfssl/internal.h
+++ b/wolfssl/internal.h
@@ -5335,6 +5335,19 @@ struct WOLFSSL_X509_NAME {
#endif
#endif
+#ifndef WOLFSSL_AIA_ENTRY_DEFINED
+#ifndef WOLFSSL_MAX_AIA_ENTRIES
+ #define WOLFSSL_MAX_AIA_ENTRIES 8
+#endif
+
+#define WOLFSSL_AIA_ENTRY_DEFINED
+typedef struct WOLFSSL_AIA_ENTRY {
+ word32 method; /* AIA method OID sum (e.g., AIA_OCSP_OID). */
+ const byte* uri; /* Pointer into cert DER for the URI. */
+ word32 uriSz; /* Length of URI data. */
+} WOLFSSL_AIA_ENTRY;
+#endif /* WOLFSSL_AIA_ENTRY_DEFINED */
+
struct WOLFSSL_X509 {
int version;
int serialSz;
@@ -5405,6 +5418,9 @@ struct WOLFSSL_X509 {
byte* authInfoCaIssuer;
int authInfoCaIssuerSz;
#endif
+ WOLFSSL_AIA_ENTRY authInfoList[WOLFSSL_MAX_AIA_ENTRIES];
+ byte authInfoListSz:7;
+ byte authInfoListOverflow:1;
word32 pathLength;
word16 keyUsage;
int rawCRLInfoSz;
diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h
index 08989907c3..ed88c09002 100644
--- a/wolfssl/ssl.h
+++ b/wolfssl/ssl.h
@@ -1917,6 +1917,8 @@ WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* sk, int idx);
#endif
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
WOLFSSL_API int wolfSSL_sk_push_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* in);
+WOLFSSL_API int wolfSSL_sk_push_back_node(WOLFSSL_STACK** stack,
+ WOLFSSL_STACK* in);
WOLFSSL_API void wolfSSL_sk_free(WOLFSSL_STACK* sk);
WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* sk);
@@ -5796,6 +5798,11 @@ WOLFSSL_API int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer,
WOLFSSL_API void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk);
WOLFSSL_API WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x);
+WOLFSSL_API int wolfSSL_X509_get_aia_overflow(WOLFSSL_X509 *x);
+#ifdef WOLFSSL_ASN_CA_ISSUER
+WOLFSSL_API WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ca_issuers(
+ WOLFSSL_X509 *x);
+#endif /* WOLFSSL_ASN_CA_ISSUER */
WOLFSSL_API int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer,
WOLFSSL_X509 *subject);
diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h
index fa077bfe8e..85d5b71fa0 100644
--- a/wolfssl/wolfcrypt/aes.h
+++ b/wolfssl/wolfcrypt/aes.h
@@ -334,7 +334,7 @@ struct Aes {
#endif /* __aarch64__ && WOLFSSL_ARMASM && !WOLFSSL_ARMASM_NO_HW_CRYPTO */
#if defined(WOLF_CRYPTO_CB) || defined(WOLFSSL_STM32U5_DHUK)
int devId;
- void* devCtx;
+ void* devCtx; /* Opaque handle for CryptoCB device */
#endif
#ifdef WOLF_PRIVATE_KEY_ID
byte id[AES_MAX_ID_LEN];
diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h
index 992c715e7c..e1448c145a 100644
--- a/wolfssl/wolfcrypt/asn.h
+++ b/wolfssl/wolfcrypt/asn.h
@@ -1702,6 +1702,19 @@ typedef struct TrustedPeerCert TrustedPeerCert;
#endif /* WOLFSSL_TRUST_PEER_CERT */
typedef struct SignatureCtx SignatureCtx;
+#ifndef WOLFSSL_AIA_ENTRY_DEFINED
+#ifndef WOLFSSL_MAX_AIA_ENTRIES
+ #define WOLFSSL_MAX_AIA_ENTRIES 8
+#endif
+
+#define WOLFSSL_AIA_ENTRY_DEFINED
+typedef struct WOLFSSL_AIA_ENTRY {
+ word32 method; /* AIA method OID sum (e.g., AIA_OCSP_OID). */
+ const byte* uri; /* Pointer into cert DER for the URI. */
+ word32 uriSz; /* Length of URI data. */
+} WOLFSSL_AIA_ENTRY;
+#endif /* WOLFSSL_AIA_ENTRY_DEFINED */
+
#ifdef WC_ASN_UNKNOWN_EXT_CB
typedef int (*wc_UnknownExtCallback)(const word16* oid, word32 oidSz, int crit,
const unsigned char* der, word32 derSz);
@@ -2060,6 +2073,10 @@ struct DecodedCert {
WC_BITFIELD extAltSigAlgCrit:1;
WC_BITFIELD extAltSigValCrit:1;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
+
+ WOLFSSL_AIA_ENTRY extAuthInfoList[WOLFSSL_MAX_AIA_ENTRIES];
+ WC_BITFIELD extAuthInfoListSz:7;
+ WC_BITFIELD extAuthInfoListOverflow:1;
};
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
@@ -2209,6 +2226,8 @@ typedef enum MimeStatus
#define GetShortInt wc_GetShortInt
#define SetShortInt wc_SetShortInt
#define GetLength wc_GetLength
+ #define SetLength wc_SetLength
+ #define SetSequence wc_SetSequence
#define GetASNInt wc_GetASNInt
#define GetASNTag wc_GetASNTag
#define SetAlgoID wc_SetAlgoID
@@ -2468,11 +2487,11 @@ WOLFSSL_LOCAL word32 SetASNImplicit(byte tag,byte number, word32 len,
WOLFSSL_LOCAL word32 SetASNExplicit(byte number, word32 len, byte* output);
WOLFSSL_LOCAL word32 SetASNSet(word32 len, byte* output);
-WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output);
+WOLFSSL_ASN_API word32 SetLength(word32 length, byte* output);
WOLFSSL_LOCAL word32 SetLengthEx(word32 length, byte* output, byte isIndef);
WOLFSSL_LOCAL word32 SetHeader(byte tag, word32 len, byte* output,
byte isIndef);
-WOLFSSL_LOCAL word32 SetSequence(word32 len, byte* output);
+WOLFSSL_ASN_API word32 SetSequence(word32 len, byte* output);
WOLFSSL_LOCAL word32 SetSequenceEx(word32 len, byte* output, byte isIndef);
WOLFSSL_LOCAL word32 SetIndefEnd(byte* output);
WOLFSSL_LOCAL word32 SetOctetString(word32 len, byte* output);
diff --git a/wolfssl/wolfcrypt/cpuid.h b/wolfssl/wolfcrypt/cpuid.h
index 176f99f292..38b64e8fa7 100644
--- a/wolfssl/wolfcrypt/cpuid.h
+++ b/wolfssl/wolfcrypt/cpuid.h
@@ -122,7 +122,11 @@ typedef word32 cpuid_flags_t;
* accurate.
*/
static WC_INLINE int cpuid_get_flags_atomic(cpuid_flags_atomic_t *flags) {
+ #ifdef WOLFSSL_BSDKM
+ if (WOLFSSL_ATOMIC_LOAD_UINT(*flags) == WC_CPUID_INITIALIZER) {
+ #else
if (WOLFSSL_ATOMIC_LOAD(*flags) == WC_CPUID_INITIALIZER) {
+ #endif /* WOLFSSL_BSDKM */
cpuid_flags_t old_cpuid_flags = WC_CPUID_INITIALIZER;
return wolfSSL_Atomic_Uint_CompareExchange
(flags, &old_cpuid_flags, cpuid_get_flags());
diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h
index 455da94ddd..7e4924bc78 100644
--- a/wolfssl/wolfcrypt/cryptocb.h
+++ b/wolfssl/wolfcrypt/cryptocb.h
@@ -376,6 +376,13 @@ typedef struct wc_CryptoInfo {
const byte* in;
word32 sz;
} des3;
+ #endif
+ #if !defined(NO_AES) && defined(WOLF_CRYPTO_CB_AES_SETKEY)
+ struct {
+ Aes* aes;
+ const byte* key;
+ word32 keySz;
+ } aessetkey;
#endif
void* ctx;
#ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES
@@ -678,6 +685,9 @@ WOLFSSL_LOCAL int wc_CryptoCb_AesEcbEncrypt(Aes* aes, byte* out,
WOLFSSL_LOCAL int wc_CryptoCb_AesEcbDecrypt(Aes* aes, byte* out,
const byte* in, word32 sz);
#endif /* HAVE_AES_ECB */
+#ifdef WOLF_CRYPTO_CB_AES_SETKEY
+WOLFSSL_API int wc_CryptoCb_AesSetKey(Aes* aes, const byte* key, word32 keySz);
+#endif /* WOLF_CRYPTO_CB_AES_SETKEY */
#endif /* !NO_AES */
#ifndef NO_DES3
diff --git a/wolfssl/wolfcrypt/pkcs11.h b/wolfssl/wolfcrypt/pkcs11.h
index 2413e724e0..4cf7ae7011 100644
--- a/wolfssl/wolfcrypt/pkcs11.h
+++ b/wolfssl/wolfcrypt/pkcs11.h
@@ -34,6 +34,7 @@ extern "C" {
#define CK_INVALID_HANDLE 0UL
+#define CK_UNAVAILABLE_INFORMATION (~0UL)
#define CKN_SURRENDER 0UL
@@ -184,6 +185,7 @@ extern "C" {
#define CKR_OK 0x00000000UL
#define CKR_MECHANISM_INVALID 0x00000070UL
#define CKR_SIGNATURE_INVALID 0x000000C0UL
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191UL
#define CKD_NULL 0x00000001UL
#define CKZ_DATA_SPECIFIED 0x00000001UL
@@ -384,15 +386,47 @@ typedef struct CK_RSA_PKCS_OAEP_PARAMS {
} CK_RSA_PKCS_OAEP_PARAMS;
typedef CK_RSA_PKCS_OAEP_PARAMS *CK_RSA_PKCS_OAEP_PARAMS_PTR;
+typedef struct CK_ASYNC_DATA {
+ CK_ULONG ulVersion;
+ CK_BYTE_PTR pValue;
+ CK_ULONG ulValueLen;
+ CK_OBJECT_HANDLE hObject;
+ CK_OBJECT_HANDLE hAdditionalObject;
+} CK_ASYNC_DATA;
+typedef CK_ASYNC_DATA* CK_ASYNC_DATA_PTR;
+
/* Function list types. */
typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
+typedef struct CK_FUNCTION_LIST_3_0 CK_FUNCTION_LIST_3_0;
+typedef struct CK_FUNCTION_LIST_3_2 CK_FUNCTION_LIST_3_2;
+
typedef CK_FUNCTION_LIST* CK_FUNCTION_LIST_PTR;
+typedef CK_FUNCTION_LIST_3_0* CK_FUNCTION_LIST_3_0_PTR;
+typedef CK_FUNCTION_LIST_3_2* CK_FUNCTION_LIST_3_2_PTR;
+
typedef CK_FUNCTION_LIST_PTR* CK_FUNCTION_LIST_PTR_PTR;
+typedef CK_FUNCTION_LIST_3_0_PTR* CK_FUNCTION_LIST_3_0_PTR_PTR;
+typedef CK_FUNCTION_LIST_3_2_PTR* CK_FUNCTION_LIST_3_2_PTR_PTR;
typedef CK_RV (*CK_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR ppFunctionList);
-#ifdef HAVE_PKCS11_STATIC
+typedef struct CK_INTERFACE {
+ CK_UTF8CHAR_PTR pInterfaceName;
+ CK_VOID_PTR pFunctionList;
+ CK_FLAGS flags;
+} CK_INTERFACE;
+
+typedef CK_INTERFACE* CK_INTERFACE_PTR;
+typedef CK_INTERFACE_PTR* CK_INTERFACE_PTR_PTR;
+
+typedef CK_RV (*CK_C_GetInterface)(CK_UTF8CHAR_PTR pInterfaceName,
+ CK_VERSION_PTR pVersion, CK_INTERFACE_PTR_PTR ppInterface, CK_FLAGS flags);
+
+#if defined(HAVE_PKCS11_STATIC)
CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList);
+#elif defined(HAVE_PKCS11_V3_STATIC)
+CK_RV C_GetInterface(CK_UTF8CHAR_PTR pInterfaceName, CK_VERSION_PTR pVersion,
+ CK_INTERFACE_PTR_PTR ppInterface, CK_FLAGS flags);
#endif
struct CK_FUNCTION_LIST {
@@ -578,6 +612,533 @@ struct CK_FUNCTION_LIST {
};
+struct CK_FUNCTION_LIST_3_0 {
+ CK_VERSION version;
+
+ CK_RV (*C_Initialize)(CK_VOID_PTR pInitArgs);
+ CK_RV (*C_Finalize)(CK_VOID_PTR pReserved);
+ CK_RV (*C_GetInfo)(CK_INFO_PTR pInfo);
+ CK_RV (*C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR ppFunctionList);
+ CK_RV (*C_GetSlotList)(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
+ CK_ULONG_PTR pulCount);
+ CK_RV (*C_GetSlotInfo)(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo);
+ CK_RV (*C_GetTokenInfo)(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo);
+ CK_RV (*C_GetMechanismList)(CK_SLOT_ID slotID,
+ CK_MECHANISM_TYPE_PTR pMechanismList,
+ CK_ULONG_PTR pulCount);
+ CK_RV (*C_GetMechanismInfo)(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR pInfo);
+ CK_RV (*C_InitToken)(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin,
+ CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel);
+ CK_RV (*C_InitPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin,
+ CK_ULONG ulPinLen);
+ CK_RV (*C_SetPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin,
+ CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin,
+ CK_ULONG ulNewLen);
+ CK_RV (*C_OpenSession)(CK_SLOT_ID slotID, CK_FLAGS flags,
+ CK_VOID_PTR pApplication, CK_NOTIFY Notify,
+ CK_SESSION_HANDLE_PTR phSession);
+ CK_RV (*C_CloseSession)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_CloseAllSessions)(CK_SLOT_ID slotID);
+ CK_RV (*C_GetSessionInfo)(CK_SESSION_HANDLE hSession,
+ CK_SESSION_INFO_PTR pInfo);
+ CK_RV (*C_GetOperationState)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pOperationState,
+ CK_ULONG_PTR pulOperationStateLen);
+ CK_RV (*C_SetOperationState)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pOperationState,
+ CK_ULONG ulOperationStateLen,
+ CK_OBJECT_HANDLE hEncryptionKey,
+ CK_OBJECT_HANDLE hAuthenticationKey);
+ CK_RV (*C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
+ CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen);
+ CK_RV (*C_Logout)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_CreateObject)(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phObject);
+ CK_RV (*C_CopyObject)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phNewObject);
+ CK_RV (*C_DestroyObject)(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hObject);
+ CK_RV (*C_GetObjectSize)(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize);
+ CK_RV (*C_GetAttributeValue)(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount);
+ CK_RV (*C_SetAttributeValue)(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount);
+ CK_RV (*C_FindObjectsInit)(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount);
+ CK_RV (*C_FindObjects)(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE_PTR phObject,
+ CK_ULONG ulMaxObjectCount,
+ CK_ULONG_PTR pulObjectCount);
+ CK_RV (*C_FindObjectsFinal)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_EncryptInit)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_Encrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
+ CK_ULONG_PTR pulEncryptedDataLen);
+ CK_RV (*C_EncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG_PTR pulEncryptedPartLen);
+ CK_RV (*C_EncryptFinal)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pLastEncryptedPart,
+ CK_ULONG_PTR pulLastEncryptedPartLen);
+ CK_RV (*C_DecryptInit)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_Decrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData,
+ CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
+ CK_ULONG_PTR pulDataLen);
+ CK_RV (*C_DecryptUpdate)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
+ CK_ULONG_PTR pulPartLen);
+ CK_RV (*C_DecryptFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart,
+ CK_ULONG_PTR pulLastPartLen);
+ CK_RV (*C_DigestInit)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism);
+ CK_RV (*C_Digest)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pDigest,
+ CK_ULONG_PTR pulDigestLen);
+ CK_RV (*C_DigestUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen);
+ CK_RV (*C_DigestKey)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_DigestFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
+ CK_ULONG_PTR pulDigestLen);
+ CK_RV (*C_SignInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_Sign)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen);
+ CK_RV (*C_SignUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen);
+ CK_RV (*C_SignFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen);
+ CK_RV (*C_SignRecoverInit)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_SignRecover)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen);
+ CK_RV (*C_VerifyInit)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_Verify)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG ulSignatureLen);
+ CK_RV (*C_VerifyUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen);
+ CK_RV (*C_VerifyFinal)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen);
+ CK_RV (*C_VerifyRecoverInit)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_VerifyRecover)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen,
+ CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen);
+ CK_RV (*C_DigestEncryptUpdate)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pPart, CK_ULONG ulPartLen,
+ CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG_PTR pulEncryptedPartLen);
+ CK_RV (*C_DecryptDigestUpdate)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG ulEncryptedPartLen,
+ CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen);
+ CK_RV (*C_SignEncryptUpdate)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pPart, CK_ULONG ulPartLen,
+ CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG_PTR pulEncryptedPartLen);
+ CK_RV (*C_DecryptVerifyUpdate)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG ulEncryptedPartLen,
+ CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen);
+ CK_RV (*C_GenerateKey)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey);
+ CK_RV (*C_GenerateKeyPair)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey);
+ CK_RV (*C_WrapKey)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey,
+ CK_BYTE_PTR pWrappedKey,
+ CK_ULONG_PTR pulWrappedKeyLen);
+ CK_RV (*C_UnwrapKey)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hUnwrappingKey,
+ CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulAttributeCount,
+ CK_OBJECT_HANDLE_PTR phKey);
+ CK_RV (*C_DeriveKey)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hBaseKey,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulAttributeCount,
+ CK_OBJECT_HANDLE_PTR phKey);
+ CK_RV (*C_SeedRandom)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
+ CK_ULONG ulSeedLen);
+ CK_RV (*C_GenerateRandom)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen);
+ CK_RV (*C_GetFunctionStatus)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_CancelFunction)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_WaitForSlotEvent)(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot,
+ CK_VOID_PTR pReserved);
+ /* PKCS#11 V 3.0 functions */
+ CK_RV (*C_GetInterfaceList)(CK_INTERFACE_PTR pInterfacesList,
+ CK_ULONG_PTR pulCount);
+ CK_RV (*C_GetInterface)(CK_UTF8CHAR_PTR pInterfaceName,
+ CK_VERSION_PTR pVersion,
+ CK_INTERFACE_PTR_PTR ppInterface,
+ CK_FLAGS flags);
+ CK_RV (*C_LoginUser)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
+ CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen,
+ CK_UTF8CHAR_PTR pUsername, CK_ULONG ulUsernameLen);
+ CK_RV (*C_SessionCancel)(CK_SESSION_HANDLE hSession, CK_FLAGS flags);
+ CK_RV (*C_MessageEncryptInit)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_EncryptMessage)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pPlaintext,
+ CK_ULONG ulPlaintextLen, CK_BYTE_PTR pCiphertext,
+ CK_ULONG_PTR pulCiphertextLen);
+ CK_RV (*C_EncryptMessageBegin)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen);
+ CK_RV (*C_EncryptMessageNext)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pPlaintextPart,
+ CK_ULONG ulPlaintextPartLen, CK_BYTE_PTR pCiphertextPart,
+ CK_ULONG_PTR pulCiphertextPartLen, CK_FLAGS flags);
+ CK_RV (*C_MessageEncryptFinal)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_MessageDecryptInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_DecryptMessage)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pCiphertext,
+ CK_ULONG ulCiphertextLen, CK_BYTE_PTR pPlaintext,
+ CK_ULONG_PTR pulPlaintextLen);
+ CK_RV (*C_DecryptMessageBegin)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen);
+ CK_RV (*C_DecryptMessageNext)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pCiphertextPart,
+ CK_ULONG ulCiphertextPartLen, CK_BYTE_PTR pPlaintextPart,
+ CK_ULONG_PTR pulPlaintextPartLen, CK_FLAGS flags);
+ CK_RV (*C_MessageDecryptFinal)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_MessageSignInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_SignMessage)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen);
+ CK_RV (*C_SignMessageBegin)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen);
+ CK_RV (*C_SignMessageNext)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen);
+ CK_RV (*C_MessageSignFinal)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_MessageVerifyInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_VerifyMessage)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG ulSignatureLen);
+ CK_RV (*C_VerifyMessageBegin)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen);
+ CK_RV (*C_VerifyMessageNext)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG ulSignatureLen);
+ CK_RV (*C_MessageVerifyFinal)(CK_SESSION_HANDLE hSession);
+};
+
+struct CK_FUNCTION_LIST_3_2 {
+ CK_VERSION version;
+
+ CK_RV (*C_Initialize)(CK_VOID_PTR pInitArgs);
+ CK_RV (*C_Finalize)(CK_VOID_PTR pReserved);
+ CK_RV (*C_GetInfo)(CK_INFO_PTR pInfo);
+ CK_RV (*C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR ppFunctionList);
+ CK_RV (*C_GetSlotList)(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
+ CK_ULONG_PTR pulCount);
+ CK_RV (*C_GetSlotInfo)(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo);
+ CK_RV (*C_GetTokenInfo)(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo);
+ CK_RV (*C_GetMechanismList)(CK_SLOT_ID slotID,
+ CK_MECHANISM_TYPE_PTR pMechanismList,
+ CK_ULONG_PTR pulCount);
+ CK_RV (*C_GetMechanismInfo)(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR pInfo);
+ CK_RV (*C_InitToken)(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin,
+ CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel);
+ CK_RV (*C_InitPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin,
+ CK_ULONG ulPinLen);
+ CK_RV (*C_SetPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin,
+ CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin,
+ CK_ULONG ulNewLen);
+ CK_RV (*C_OpenSession)(CK_SLOT_ID slotID, CK_FLAGS flags,
+ CK_VOID_PTR pApplication, CK_NOTIFY Notify,
+ CK_SESSION_HANDLE_PTR phSession);
+ CK_RV (*C_CloseSession)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_CloseAllSessions)(CK_SLOT_ID slotID);
+ CK_RV (*C_GetSessionInfo)(CK_SESSION_HANDLE hSession,
+ CK_SESSION_INFO_PTR pInfo);
+ CK_RV (*C_GetOperationState)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pOperationState,
+ CK_ULONG_PTR pulOperationStateLen);
+ CK_RV (*C_SetOperationState)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pOperationState,
+ CK_ULONG ulOperationStateLen,
+ CK_OBJECT_HANDLE hEncryptionKey,
+ CK_OBJECT_HANDLE hAuthenticationKey);
+ CK_RV (*C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
+ CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen);
+ CK_RV (*C_Logout)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_CreateObject)(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phObject);
+ CK_RV (*C_CopyObject)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phNewObject);
+ CK_RV (*C_DestroyObject)(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hObject);
+ CK_RV (*C_GetObjectSize)(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize);
+ CK_RV (*C_GetAttributeValue)(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount);
+ CK_RV (*C_SetAttributeValue)(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount);
+ CK_RV (*C_FindObjectsInit)(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount);
+ CK_RV (*C_FindObjects)(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE_PTR phObject,
+ CK_ULONG ulMaxObjectCount,
+ CK_ULONG_PTR pulObjectCount);
+ CK_RV (*C_FindObjectsFinal)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_EncryptInit)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_Encrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
+ CK_ULONG_PTR pulEncryptedDataLen);
+ CK_RV (*C_EncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG_PTR pulEncryptedPartLen);
+ CK_RV (*C_EncryptFinal)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pLastEncryptedPart,
+ CK_ULONG_PTR pulLastEncryptedPartLen);
+ CK_RV (*C_DecryptInit)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_Decrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData,
+ CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
+ CK_ULONG_PTR pulDataLen);
+ CK_RV (*C_DecryptUpdate)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
+ CK_ULONG_PTR pulPartLen);
+ CK_RV (*C_DecryptFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart,
+ CK_ULONG_PTR pulLastPartLen);
+ CK_RV (*C_DigestInit)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism);
+ CK_RV (*C_Digest)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pDigest,
+ CK_ULONG_PTR pulDigestLen);
+ CK_RV (*C_DigestUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen);
+ CK_RV (*C_DigestKey)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_DigestFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
+ CK_ULONG_PTR pulDigestLen);
+ CK_RV (*C_SignInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_Sign)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen);
+ CK_RV (*C_SignUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen);
+ CK_RV (*C_SignFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen);
+ CK_RV (*C_SignRecoverInit)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_SignRecover)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen);
+ CK_RV (*C_VerifyInit)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_Verify)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG ulSignatureLen);
+ CK_RV (*C_VerifyUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen);
+ CK_RV (*C_VerifyFinal)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen);
+ CK_RV (*C_VerifyRecoverInit)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_VerifyRecover)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen,
+ CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen);
+ CK_RV (*C_DigestEncryptUpdate)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pPart, CK_ULONG ulPartLen,
+ CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG_PTR pulEncryptedPartLen);
+ CK_RV (*C_DecryptDigestUpdate)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG ulEncryptedPartLen,
+ CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen);
+ CK_RV (*C_SignEncryptUpdate)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pPart, CK_ULONG ulPartLen,
+ CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG_PTR pulEncryptedPartLen);
+ CK_RV (*C_DecryptVerifyUpdate)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG ulEncryptedPartLen,
+ CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen);
+ CK_RV (*C_GenerateKey)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey);
+ CK_RV (*C_GenerateKeyPair)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey);
+ CK_RV (*C_WrapKey)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey,
+ CK_BYTE_PTR pWrappedKey,
+ CK_ULONG_PTR pulWrappedKeyLen);
+ CK_RV (*C_UnwrapKey)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hUnwrappingKey,
+ CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulAttributeCount,
+ CK_OBJECT_HANDLE_PTR phKey);
+ CK_RV (*C_DeriveKey)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hBaseKey,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulAttributeCount,
+ CK_OBJECT_HANDLE_PTR phKey);
+ CK_RV (*C_SeedRandom)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
+ CK_ULONG ulSeedLen);
+ CK_RV (*C_GenerateRandom)(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen);
+ CK_RV (*C_GetFunctionStatus)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_CancelFunction)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_WaitForSlotEvent)(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot,
+ CK_VOID_PTR pReserved);
+
+ /* PKCS#11 V 3.0 functions */
+ CK_RV (*C_GetInterfaceList)(CK_INTERFACE_PTR pInterfacesList,
+ CK_ULONG_PTR pulCount);
+ CK_RV (*C_GetInterface)(CK_UTF8CHAR_PTR pInterfaceName,
+ CK_VERSION_PTR pVersion,
+ CK_INTERFACE_PTR_PTR ppInterface,
+ CK_FLAGS flags);
+ CK_RV (*C_LoginUser)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
+ CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen,
+ CK_UTF8CHAR_PTR pUsername, CK_ULONG ulUsernameLen);
+ CK_RV (*C_SessionCancel)(CK_SESSION_HANDLE hSession, CK_FLAGS flags);
+ CK_RV (*C_MessageEncryptInit)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_EncryptMessage)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pPlaintext,
+ CK_ULONG ulPlaintextLen, CK_BYTE_PTR pCiphertext,
+ CK_ULONG_PTR pulCiphertextLen);
+ CK_RV (*C_EncryptMessageBegin)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen);
+ CK_RV (*C_EncryptMessageNext)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pPlaintextPart,
+ CK_ULONG ulPlaintextPartLen, CK_BYTE_PTR pCiphertextPart,
+ CK_ULONG_PTR pulCiphertextPartLen, CK_FLAGS flags);
+ CK_RV (*C_MessageEncryptFinal)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_MessageDecryptInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_DecryptMessage)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pCiphertext,
+ CK_ULONG ulCiphertextLen, CK_BYTE_PTR pPlaintext,
+ CK_ULONG_PTR pulPlaintextLen);
+ CK_RV (*C_DecryptMessageBegin)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen);
+ CK_RV (*C_DecryptMessageNext)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pCiphertextPart,
+ CK_ULONG ulCiphertextPartLen, CK_BYTE_PTR pPlaintextPart,
+ CK_ULONG_PTR pulPlaintextPartLen, CK_FLAGS flags);
+ CK_RV (*C_MessageDecryptFinal)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_MessageSignInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_SignMessage)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen);
+ CK_RV (*C_SignMessageBegin)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen);
+ CK_RV (*C_SignMessageNext)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen);
+ CK_RV (*C_MessageSignFinal)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_MessageVerifyInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+ CK_RV (*C_VerifyMessage)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG ulSignatureLen);
+ CK_RV (*C_VerifyMessageBegin)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen);
+ CK_RV (*C_VerifyMessageNext)(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG ulSignatureLen);
+ CK_RV (*C_MessageVerifyFinal)(CK_SESSION_HANDLE hSession);
+
+ /* PKCS#11 V 3.2 functions */
+ CK_RV (*C_EncapsulateKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hPublicKey, CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey,
+ CK_BYTE_PTR pCiphertext, CK_ULONG_PTR pulCiphertextLen);
+ CK_RV (*C_DecapsulateKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hPrivateKey, CK_BYTE_PTR pCiphertext,
+ CK_ULONG ulCiphertextLen, CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey);
+ CK_RV (*C_VerifySignatureInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pSignature,
+ CK_ULONG ulSignatureLen);
+ CK_RV (*C_VerifySignature)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen);
+ CK_RV (*C_VerifySignatureUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen);
+ CK_RV (*C_VerifySignatureFinal)(CK_SESSION_HANDLE hSession);
+ CK_RV (*C_GetSessionValidationFlags)(CK_SESSION_HANDLE hSession, CK_ULONG type,
+ CK_FLAGS * pFlags);
+ CK_RV (*C_AsyncComplete)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pFunctionName,
+ CK_ASYNC_DATA_PTR pResult);
+ CK_RV (*C_AsyncGetID)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pFunctionName,
+ CK_ULONG_PTR pulID);
+ CK_RV (*C_AsyncJoin)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pFunctionName,
+ CK_ULONG ulID, CK_BYTE_PTR pData, CK_ULONG ulData);
+};
+
#ifdef __cplusplus
}
#endif
diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h
index 834d17fa5c..57bd83594d 100644
--- a/wolfssl/wolfcrypt/pkcs7.h
+++ b/wolfssl/wolfcrypt/pkcs7.h
@@ -229,6 +229,14 @@ typedef int (*CallbackRsaSignRawDigest)(wc_PKCS7* pkcs7, byte* digest,
int devId, int hashOID);
#endif
+#if defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && defined(HAVE_ECC)
+/* ECC sign raw digest callback, user signs hash directly */
+typedef int (*CallbackEccSignRawDigest)(wc_PKCS7* pkcs7, byte* digest,
+ word32 digestSz, byte* out, word32 outSz,
+ byte* privateKey, word32 privateKeySz,
+ int devId, int hashOID);
+#endif
+
/* Public Structure Warning:
* Existing members must not be changed to maintain backwards compatibility!
@@ -376,6 +384,10 @@ struct wc_PKCS7 {
CallbackAESKeyWrapUnwrap aesKeyWrapUnwrapCb;
+#if defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && defined(HAVE_ECC)
+ CallbackEccSignRawDigest eccSignRawDigestCb;
+#endif
+
/* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */
};
@@ -511,6 +523,11 @@ WOLFSSL_API int wc_PKCS7_SetRsaSignRawDigestCb(wc_PKCS7* pkcs7,
CallbackRsaSignRawDigest cb);
#endif
+#if defined(HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK) && defined(HAVE_ECC)
+WOLFSSL_API int wc_PKCS7_SetEccSignRawDigestCb(wc_PKCS7* pkcs7,
+ CallbackEccSignRawDigest cb);
+#endif
+
/* CMS/PKCS#7 EnvelopedData */
WOLFSSL_API int wc_PKCS7_EncodeEnvelopedData(wc_PKCS7* pkcs7,
byte* output, word32 outputSz);
diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h
index a499a95278..49301a4d3a 100644
--- a/wolfssl/wolfcrypt/settings.h
+++ b/wolfssl/wolfcrypt/settings.h
@@ -4990,6 +4990,10 @@ extern void uITRON4_free(void *p) ;
#error "If TLS is enabled please make sure either client or server is enabled."
#endif
+#if defined(WC_RNG_BANK_SUPPORT) && defined(NO_ASN_TIME)
+ #undef WC_RNG_BANK_SUPPORT
+#endif
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/wolfssl/wolfcrypt/wc_pkcs11.h b/wolfssl/wolfcrypt/wc_pkcs11.h
index 803a1a6c05..b4805690c7 100644
--- a/wolfssl/wolfcrypt/wc_pkcs11.h
+++ b/wolfssl/wolfcrypt/wc_pkcs11.h
@@ -37,13 +37,21 @@
extern "C" {
#endif
+enum Pkcs11InterfaceVersionType {
+ WC_PCKS11VERSION_2_20,
+ WC_PCKS11VERSION_2_40,
+ WC_PCKS11VERSION_3_0,
+ WC_PCKS11VERSION_3_1,
+ WC_PCKS11VERSION_3_2,
+};
typedef struct Pkcs11Dev {
-#ifndef HAVE_PKCS11_STATIC
+#if !defined(HAVE_PKCS11_STATIC) && !defined(HAVE_PKCS11_V3_STATIC)
void* dlHandle; /* Handle to library */
#endif
CK_FUNCTION_LIST* func; /* Array of functions */
void* heap;
+ int version; /* Pkcs11InterfaceVersionType */
} Pkcs11Dev;
typedef struct Pkcs11Token {
@@ -53,12 +61,14 @@ typedef struct Pkcs11Token {
CK_UTF8CHAR_PTR userPin; /* User's PIN to login with */
CK_ULONG userPinSz; /* Size of user's PIN in bytes */
byte userPinLogin:1; /* Login with User's PIN */
+ int version; /* Pkcs11InterfaceVersionType */
} Pkcs11Token;
typedef struct Pkcs11Session {
CK_FUNCTION_LIST* func; /* Table of PKCS#11 function from lib */
CK_SLOT_ID slotId; /* Id of slot to use */
CK_SESSION_HANDLE handle; /* Handle to active session */
+ int version; /* Pkcs11InterfaceVersionType */
} Pkcs11Session;
/* Types of keys that can be stored. */
@@ -74,6 +84,8 @@ WOLFSSL_API int wc_Pkcs11_Initialize(Pkcs11Dev* dev, const char* library,
void* heap);
WOLFSSL_API int wc_Pkcs11_Initialize_ex(Pkcs11Dev* dev, const char* library,
void* heap, CK_RV* rvp);
+WOLFSSL_API int wc_Pkcs11_Initialize_v3(Pkcs11Dev* dev, const char* library,
+ void* heap, int* version, const char* interfaceName, CK_RV* rvp);
WOLFSSL_API void wc_Pkcs11_Finalize(Pkcs11Dev* dev);
WOLFSSL_API int wc_Pkcs11Token_Init(Pkcs11Token* token, Pkcs11Dev* dev,
diff --git a/wrapper/rust/Makefile b/wrapper/rust/Makefile
index 73bd658e5a..dec76d4b05 100644
--- a/wrapper/rust/Makefile
+++ b/wrapper/rust/Makefile
@@ -6,6 +6,10 @@ all:
test:
+$(MAKE) -C wolfssl-wolfcrypt test
+.PHONY: testfips
+testfips:
+ +$(MAKE) -C wolfssl-wolfcrypt testfips
+
.PHONY: clean
clean:
+$(MAKE) -C wolfssl-wolfcrypt clean
diff --git a/wrapper/rust/wolfssl-wolfcrypt/Makefile b/wrapper/rust/wolfssl-wolfcrypt/Makefile
index 3944a1971b..7cda418962 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/Makefile
+++ b/wrapper/rust/wolfssl-wolfcrypt/Makefile
@@ -6,7 +6,11 @@ all:
.PHONY: test
test:
- cargo test
+ cargo test -- --test-threads=1
+
+.PHONY: testfips
+testfips:
+ cargo test --lib --bins --tests -- --test-threads=1
.PHONY: clean
clean:
diff --git a/wrapper/rust/wolfssl-wolfcrypt/build.rs b/wrapper/rust/wolfssl-wolfcrypt/build.rs
index 608c100e27..9580b1608b 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/build.rs
+++ b/wrapper/rust/wolfssl-wolfcrypt/build.rs
@@ -19,6 +19,7 @@ fn main() {
/// Returns `Ok(())` if successful, or an error if any step fails.
fn run_build() -> Result<()> {
generate_bindings()?;
+ generate_fips_aliases()?;
setup_wolfssl_link()?;
scan_cfg()?;
Ok(())
@@ -64,6 +65,79 @@ fn generate_bindings() -> Result<()> {
})
}
+/// Generate FIPS symbol aliases.
+///
+/// Since Rust can't use fips.h's #defines which map the "regular" wc function
+/// name to the _fips variant, and since bindgen has only seen the _fips
+/// variant, we will generate aliases that allow the non-_fips variant function
+/// name to be called without the _fips prefix by Rust sources in a manner
+/// similar to which C sources would be able to call the non-_fips variant
+/// function name.
+///
+/// Returns `Ok(())` if successful, or an error if generation fails.
+fn generate_fips_aliases() -> Result<()> {
+ let binding = read_file(bindings_path())?;
+ let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
+ let aliases_path = out_dir.join("fips_aliases.rs");
+
+ let mut aliases = String::new();
+
+ // Find all _fips symbol names
+ let fips_sym_re = Regex::new(r"pub fn (wc_\w+)_fips\s*\(").unwrap();
+
+ for cap in fips_sym_re.captures_iter(&binding) {
+ let mut base_name = &cap[1];
+ let fips_name = format!("{}_fips", base_name);
+
+ // Exception mappings: (standard_name, fips_name)
+ // For cases where FIPS name doesn't follow the simple _fips pattern
+ let exceptions: &[(&str, &str)] = &[
+ // _ex suffix changed to Ex before _fips
+ ("wc_InitRsaKey_ex", "wc_InitRsaKeyEx_fips"),
+ ("wc_RsaPublicEncrypt_ex", "wc_RsaPublicEncryptEx_fips"),
+ ("wc_RsaPrivateDecryptInline_ex", "wc_RsaPrivateDecryptInlineEx_fips"),
+ ("wc_RsaPrivateDecrypt_ex", "wc_RsaPrivateDecryptEx_fips"),
+ ("wc_RsaPSS_Sign_ex", "wc_RsaPSS_SignEx_fips"),
+ ("wc_RsaPSS_VerifyInline_ex", "wc_RsaPSS_VerifyInlineEx_fips"),
+ ("wc_RsaPSS_Verify_ex", "wc_RsaPSS_VerifyEx_fips"),
+ ("wc_RsaPSS_CheckPadding_ex", "wc_RsaPSS_CheckPaddingEx_fips"),
+ ("wc_DhSetKey_ex", "wc_DhSetKeyEx_fips"),
+ ("wc_DhCheckPubKey_ex", "wc_DhCheckPubKeyEx_fips"),
+ ("wc_DhCheckPrivKey_ex", "wc_DhCheckPrivKeyEx_fips"),
+
+ // Name change
+ ("wc_PRF_TLS", "wc_PRF_TLSv12_fips"),
+ ];
+
+ // Handle exceptions
+ for (exc_base_name, exc_fips_name) in exceptions {
+ if fips_name == *exc_fips_name {
+ base_name = exc_base_name;
+ break;
+ }
+ }
+
+ // Check if the non-_fips version exists in bindings
+ let non_fips_pattern = format!(r"pub fn {}\s*\(", regex::escape(base_name));
+ let non_fips_re = Regex::new(&non_fips_pattern).unwrap();
+
+ if non_fips_re.is_match(&binding) {
+ // Add any new known names defined with both a _fips suffix and not
+ // here. Warn if any new ones are discovered.
+ if base_name != "wc_AesGcmEncrypt" {
+ println!("cargo:warning=Skipping FIPS symbols alias for {}", base_name);
+ }
+ } else {
+ // Only alias if the base name doesn't already exist
+ aliases.push_str(&format!("pub use {} as {};\n", fips_name, base_name));
+ }
+ }
+
+ fs::write(&aliases_path, aliases)?;
+
+ Ok(())
+}
+
/// Instruct cargo to link against wolfssl C library
///
/// Returns `Ok(())` if successful, or an error if any step fails.
@@ -93,7 +167,7 @@ fn read_file(path: String) -> Result {
}
fn check_cfg(binding: &str, function_name: &str, cfg_name: &str) {
- let pattern = format!(r"\b{}\b", function_name);
+ let pattern = format!(r"\b{}(_fips)?\b", function_name);
let re = match Regex::new(&pattern) {
Ok(r) => r,
Err(e) => {
@@ -181,6 +255,9 @@ fn scan_cfg() -> Result<()> {
check_cfg(&binding, "wc_ed448_verify_msg_ex", "ed448_verify");
check_cfg(&binding, "wc_ed448_verify_msg_init", "ed448_streaming_verify");
+ /* fips */
+ check_cfg(&binding, "wc_SetSeed_Cb_fips", "fips");
+
/* hkdf */
check_cfg(&binding, "wc_HKDF_Extract_ex", "hkdf");
@@ -213,6 +290,8 @@ fn scan_cfg() -> Result<()> {
check_cfg(&binding, "wc_InitSha256", "sha256");
check_cfg(&binding, "wc_InitSha384", "sha384");
check_cfg(&binding, "wc_InitSha512", "sha512");
+ check_cfg(&binding, "wc_HashType_WC_HASH_TYPE_SHA512_224", "sha512_224");
+ check_cfg(&binding, "wc_HashType_WC_HASH_TYPE_SHA512_256", "sha512_256");
check_cfg(&binding, "wc_InitSha3_224", "sha3");
check_cfg(&binding, "wc_InitShake128", "shake128");
check_cfg(&binding, "wc_InitShake256", "shake256");
diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/ecc.rs b/wrapper/rust/wolfssl-wolfcrypt/src/ecc.rs
index a6c35c493a..2965cca3ae 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/src/ecc.rs
+++ b/wrapper/rust/wolfssl-wolfcrypt/src/ecc.rs
@@ -711,7 +711,7 @@ impl ECC {
}
let mut wc_ecc_key = unsafe { wc_ecc_key.assume_init() };
let priv_size = priv_buf.len() as u32;
- let pub_ptr = if pub_buf.len() == 0 {core::ptr::null()} else {pub_buf.as_ptr()};
+ let pub_ptr = if pub_buf.is_empty() {core::ptr::null()} else {pub_buf.as_ptr()};
let pub_size = pub_buf.len() as u32;
let rc = unsafe {
sys::wc_ecc_import_private_key(priv_buf.as_ptr(), priv_size,
@@ -785,7 +785,7 @@ impl ECC {
}
let mut wc_ecc_key = unsafe { wc_ecc_key.assume_init() };
let priv_size = priv_buf.len() as u32;
- let pub_ptr = if pub_buf.len() == 0 {core::ptr::null()} else {pub_buf.as_ptr()};
+ let pub_ptr = if pub_buf.is_empty() {core::ptr::null()} else {pub_buf.as_ptr()};
let pub_size = pub_buf.len() as u32;
let rc = unsafe {
sys::wc_ecc_import_private_key_ex(priv_buf.as_ptr(), priv_size,
diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/fips.rs b/wrapper/rust/wolfssl-wolfcrypt/src/fips.rs
new file mode 100644
index 0000000000..b77b93f5c3
--- /dev/null
+++ b/wrapper/rust/wolfssl-wolfcrypt/src/fips.rs
@@ -0,0 +1,34 @@
+#![cfg(fips)]
+
+use crate::sys;
+
+/// Enables or disables the ability to read private key data in FIPS mode.
+///
+/// In FIPS mode, private keys are protected and cannot be read by default.
+/// This function allows temporarily enabling private key reads for operations
+/// that require access to the raw key material, such as key export or backup.
+///
+/// # Arguments
+///
+/// * `enabled` - Set to `1` to enable private key reads, or `0` to disable.
+///
+/// # Returns
+///
+/// * `Ok(())` - The operation succeeded.
+/// * `Err(i32)` - The operation failed, returning the wolfSSL error code.
+///
+/// # Note
+///
+/// This function applies to all key types (`WC_KEYTYPE_ALL`). Private key
+/// reading should be disabled again after the required operation is complete
+/// to maintain FIPS compliance.
+pub fn set_private_key_read_enable(enabled: i32) -> Result<(), i32> {
+ let rc = unsafe {
+ sys::wolfCrypt_SetPrivateKeyReadEnable_fips(enabled, sys::wc_KeyType_WC_KEYTYPE_ALL)
+ };
+ if rc != 0 {
+ Err(rc)
+ } else {
+ Ok(())
+ }
+}
diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/hmac.rs b/wrapper/rust/wolfssl-wolfcrypt/src/hmac.rs
index 5c93c200c2..31505aa647 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/src/hmac.rs
+++ b/wrapper/rust/wolfssl-wolfcrypt/src/hmac.rs
@@ -38,7 +38,9 @@ impl HMAC {
pub const TYPE_SHA: i32 = sys::wc_HashType_WC_HASH_TYPE_SHA as i32;
pub const TYPE_SHA256: i32 = sys::wc_HashType_WC_HASH_TYPE_SHA256 as i32;
pub const TYPE_SHA512: i32 = sys::wc_HashType_WC_HASH_TYPE_SHA512 as i32;
+ #[cfg(sha512_224)]
pub const TYPE_SHA512_224: i32 = sys::wc_HashType_WC_HASH_TYPE_SHA512_224 as i32;
+ #[cfg(sha512_256)]
pub const TYPE_SHA512_256: i32 = sys::wc_HashType_WC_HASH_TYPE_SHA512_256 as i32;
pub const TYPE_SHA384: i32 = sys::wc_HashType_WC_HASH_TYPE_SHA384 as i32;
pub const TYPE_SHA224: i32 = sys::wc_HashType_WC_HASH_TYPE_SHA224 as i32;
diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/lib.rs b/wrapper/rust/wolfssl-wolfcrypt/src/lib.rs
index dfeef39b7f..b3f35822fd 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/src/lib.rs
+++ b/wrapper/rust/wolfssl-wolfcrypt/src/lib.rs
@@ -30,6 +30,7 @@ pub mod dh;
pub mod ecc;
pub mod ed25519;
pub mod ed448;
+pub mod fips;
pub mod hkdf;
pub mod hmac;
pub mod kdf;
diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/random.rs b/wrapper/rust/wolfssl-wolfcrypt/src/random.rs
index 9e12a5f376..d577cb7ffb 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/src/random.rs
+++ b/wrapper/rust/wolfssl-wolfcrypt/src/random.rs
@@ -87,6 +87,15 @@ impl RNG {
/// A Result which is Ok(RNG) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new_ex(heap: Option<*mut std::os::raw::c_void>, dev_id: Option) -> Result {
+ #[cfg(fips)]
+ {
+ let rc = unsafe {
+ sys::wc_SetSeed_Cb_fips(Some(sys::wc_GenerateSeed))
+ };
+ if rc != 0 {
+ return Err(rc);
+ }
+ }
let mut rng: MaybeUninit = MaybeUninit::uninit();
let heap = match heap {
Some(heap) => heap,
@@ -137,6 +146,15 @@ impl RNG {
/// A Result which is Ok(RNG) on success or an Err containing the wolfSSL
/// library return code on failure.
pub fn new_with_nonce_ex(nonce: &mut [T], heap: Option<*mut std::os::raw::c_void>, dev_id: Option) -> Result {
+ #[cfg(fips)]
+ {
+ let rc = unsafe {
+ sys::wc_SetSeed_Cb_fips(Some(sys::wc_GenerateSeed))
+ };
+ if rc != 0 {
+ return Err(rc);
+ }
+ }
let ptr = nonce.as_mut_ptr() as *mut u8;
let size: u32 = size_of_val(nonce) as u32;
let mut rng: MaybeUninit = MaybeUninit::uninit();
diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/rsa.rs b/wrapper/rust/wolfssl-wolfcrypt/src/rsa.rs
index 8b8d44f3f6..d1a2c17d37 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/src/rsa.rs
+++ b/wrapper/rust/wolfssl-wolfcrypt/src/rsa.rs
@@ -100,7 +100,9 @@ impl RSA {
pub const HASH_TYPE_SHA3_512 : u32 = sys::wc_HashType_WC_HASH_TYPE_SHA3_512;
pub const HASH_TYPE_BLAKE2B : u32 = sys::wc_HashType_WC_HASH_TYPE_BLAKE2B;
pub const HASH_TYPE_BLAKE2S : u32 = sys::wc_HashType_WC_HASH_TYPE_BLAKE2S;
+ #[cfg(sha512_224)]
pub const HASH_TYPE_SHA512_224 : u32 = sys::wc_HashType_WC_HASH_TYPE_SHA512_224;
+ #[cfg(sha512_256)]
pub const HASH_TYPE_SHA512_256 : u32 = sys::wc_HashType_WC_HASH_TYPE_SHA512_256;
#[cfg(shake128)]
pub const HASH_TYPE_SHAKE128 : u32 = sys::wc_HashType_WC_HASH_TYPE_SHAKE128;
diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/sys.rs b/wrapper/rust/wolfssl-wolfcrypt/src/sys.rs
index 3ab98816b7..5b90a342f9 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/src/sys.rs
+++ b/wrapper/rust/wolfssl-wolfcrypt/src/sys.rs
@@ -14,3 +14,6 @@
#![allow(unnecessary_transmutes)]
#![allow(unsafe_op_in_unsafe_fn)]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
+
+/* Include generated FIPS symbol aliases. */
+include!(concat!(env!("OUT_DIR"), "/fips_aliases.rs"));
diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/common/mod.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/common/mod.rs
new file mode 100644
index 0000000000..8d191ed97b
--- /dev/null
+++ b/wrapper/rust/wolfssl-wolfcrypt/tests/common/mod.rs
@@ -0,0 +1,12 @@
+#[cfg(fips)]
+fn setup_fips()
+{
+ use wolfssl_wolfcrypt::fips;
+ fips::set_private_key_read_enable(1).expect("Error with set_private_key_read_enable()");
+}
+
+pub fn setup()
+{
+ #[cfg(fips)]
+ setup_fips();
+}
diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_aes.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_aes.rs
index 7cd15f3670..522a875cc2 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_aes.rs
+++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_aes.rs
@@ -780,41 +780,39 @@ fn test_xts_consecutive_sectors() {
#[cfg(aes_xts_stream)]
fn test_xtsstream() {
let keys: [u8; 32] = [
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x39, 0x25, 0x79, 0x05, 0xdf, 0xcc, 0x77, 0x76,
+ 0x6c, 0x87, 0x0a, 0x80, 0x6a, 0x60, 0xe3, 0xc0,
+ 0x93, 0xd1, 0x2a, 0xcf, 0xcb, 0x51, 0x42, 0xfa,
+ 0x09, 0x69, 0x89, 0x62, 0x5b, 0x60, 0xdb, 0x16
];
let tweak: [u8; 16] = [
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x5c, 0xf7, 0x9d, 0xb6, 0xc5, 0xcd, 0x99, 0x1a,
+ 0x1c, 0x78, 0x81, 0x42, 0x24, 0x95, 0x1e, 0x84
];
- let plain: [u8; 40] = [
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0xff, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+ let plain: [u8; 32] = [
+ 0xbd, 0xc5, 0x46, 0x8f, 0xbc, 0x8d, 0x50, 0xa1,
+ 0x0d, 0x1c, 0x85, 0x7f, 0x79, 0x1c, 0x5c, 0xba,
+ 0xb3, 0x81, 0x0d, 0x0d, 0x73, 0xcf, 0x8f, 0x20,
+ 0x46, 0xb1, 0xd1, 0x9e, 0x7d, 0x5d, 0x8a, 0x56
];
- let expected_cipher: [u8; 40] = [
- 0xA2, 0x07, 0x47, 0x76, 0x3F, 0xEC, 0x0C, 0x23,
- 0x1B, 0xD0, 0xBD, 0x46, 0x9A, 0x27, 0x38, 0x12,
- 0x95, 0x02, 0x3D, 0x5D, 0xC6, 0x94, 0x51, 0x36,
- 0xA0, 0x85, 0xD2, 0x69, 0x6E, 0x87, 0x0A, 0xBF,
- 0xB5, 0x5A, 0xDD, 0xCB, 0x80, 0xE0, 0xFC, 0xCD
+ let expected_cipher: [u8; 32] = [
+ 0xd6, 0xbe, 0x04, 0x6d, 0x41, 0xf2, 0x3b, 0x5e,
+ 0xd7, 0x0b, 0x6b, 0x3d, 0x5c, 0x8e, 0x66, 0x23,
+ 0x2b, 0xe6, 0xb8, 0x07, 0xd4, 0xdc, 0xc6, 0x0e,
+ 0xff, 0x8d, 0xbc, 0x1d, 0x9f, 0x7f, 0xc8, 0x22
];
let mut xtsstream = XTSStream::new().expect("Failed to create XTSStream");
xtsstream.init_encrypt(&keys, &tweak).expect("Error with init_encrypt()");
- let mut cipher: [u8; 40] = [0; 40];
+ let mut cipher: [u8; 32] = [0; 32];
xtsstream.encrypt_update(&plain[0..16], &mut cipher[0..16]).expect("Error with encrypt_update()");
- xtsstream.encrypt_final(&plain[16..40], &mut cipher[16..40]).expect("Error with encrypt_final()");
+ xtsstream.encrypt_final(&plain[16..32], &mut cipher[16..32]).expect("Error with encrypt_final()");
assert_eq!(cipher, expected_cipher);
xtsstream.init_decrypt(&keys, &tweak).expect("Error with init_decrypt()");
- let mut plain_out: [u8; 40] = [0; 40];
+ let mut plain_out: [u8; 32] = [0; 32];
xtsstream.decrypt_update(&cipher[0..16], &mut plain_out[0..16]).expect("Error with decrypt_update()");
- xtsstream.decrypt_final(&cipher[16..40], &mut plain_out[16..40]).expect("Error with decrypt_final()");
+ xtsstream.decrypt_final(&cipher[16..32], &mut plain_out[16..32]).expect("Error with decrypt_final()");
assert_eq!(plain_out, plain);
}
diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_dh.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_dh.rs
index 99094e658b..1135954e32 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_dh.rs
+++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_dh.rs
@@ -1,5 +1,7 @@
#![cfg(dh)]
+mod common;
+
#[cfg(any(all(dh_keygen, dh_ffdhe_2048), random))]
use wolfssl_wolfcrypt::dh::DH;
#[cfg(random)]
@@ -31,6 +33,7 @@ fn test_dh_named_parameters() {
#[test]
#[cfg(all(dh_keygen, random))]
fn test_generate_params() {
+ common::setup();
let mut rng = RNG::new().expect("Error with RNG::new()");
let mut dh = DH::generate(&mut rng, 2048).expect("Error with generate()");
@@ -75,6 +78,7 @@ fn test_generate_key_pair() {
#[test]
#[cfg(random)]
fn test_dh_checks() {
+ common::setup();
let p = [
0xc5u8, 0x7c, 0xa2, 0x4f, 0x4b, 0xd6, 0x8c, 0x3c,
0xda, 0xc7, 0xba, 0xaa, 0xea, 0x2e, 0x5c, 0x1e,
diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_ecc.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_ecc.rs
index c828ab0540..82f5369fbe 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_ecc.rs
+++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_ecc.rs
@@ -1,5 +1,7 @@
#![cfg(ecc)]
+mod common;
+
#[cfg(any(all(ecc_import, ecc_export, ecc_sign, ecc_verify, random), random))]
use std::fs;
use wolfssl_wolfcrypt::ecc::*;
@@ -128,6 +130,8 @@ fn test_ecc_import_export_sign_verify() {
#[test]
#[cfg(all(ecc_dh, random))]
fn test_ecc_shared_secret() {
+ common::setup();
+
let mut rng = RNG::new().expect("Failed to create RNG");
let mut ecc0 = ECC::generate(32, &mut rng, None, None).expect("Error with generate()");
let mut ecc1 = ECC::generate(32, &mut rng, None, None).expect("Error with generate()");
@@ -152,6 +156,8 @@ fn test_ecc_shared_secret() {
#[test]
#[cfg(all(ecc_export, random))]
fn test_ecc_export() {
+ common::setup();
+
let mut rng = RNG::new().expect("Failed to create RNG");
let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()");
let mut qx = [0u8; 32];
@@ -166,6 +172,8 @@ fn test_ecc_export() {
#[test]
#[cfg(all(ecc_export, random))]
fn test_ecc_export_ex() {
+ common::setup();
+
let mut rng = RNG::new().expect("Failed to create RNG");
let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()");
let mut qx = [0u8; 32];
@@ -180,6 +188,8 @@ fn test_ecc_export_ex() {
#[test]
#[cfg(all(ecc_import, ecc_export, ecc_sign, ecc_verify, random))]
fn test_ecc_import_export_private() {
+ common::setup();
+
let mut rng = RNG::new().expect("Failed to create RNG");
let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()");
let hash = [0x42u8; 32];
@@ -204,6 +214,8 @@ fn test_ecc_import_export_private() {
#[test]
#[cfg(all(ecc_import, ecc_export, ecc_sign, ecc_verify, random))]
fn test_ecc_import_export_private_ex() {
+ common::setup();
+
let mut rng = RNG::new().expect("Failed to create RNG");
let curve_id = ECC::SECP256R1;
let curve_size = ECC::get_curve_size_from_id(curve_id).expect("Error with get_curve_size_from_id()");
@@ -242,6 +254,8 @@ fn test_ecc_export_public() {
#[test]
#[cfg(all(ecc_import, ecc_export, ecc_sign, ecc_verify, random))]
fn test_ecc_import_unsigned() {
+ common::setup();
+
let mut rng = RNG::new().expect("Failed to create RNG");
let curve_id = ECC::SECP256R1;
let curve_size = ECC::get_curve_size_from_id(curve_id).expect("Error with get_curve_size_from_id()");
diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_ed25519.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_ed25519.rs
index a61f132e0f..8c7e225c28 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_ed25519.rs
+++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_ed25519.rs
@@ -1,11 +1,15 @@
#![cfg(ed25519)]
+mod common;
+
use wolfssl_wolfcrypt::random::RNG;
use wolfssl_wolfcrypt::ed25519::*;
#[test]
#[cfg(all(ed25519_import, ed25519_export))]
fn test_make_public() {
+ common::setup();
+
let mut rng = RNG::new().expect("Error creating RNG");
let ed = Ed25519::generate(&mut rng).expect("Error with generate()");
let mut private = [0u8; Ed25519::KEY_SIZE];
@@ -210,6 +214,8 @@ fn test_ph_sign_verify() {
#[test]
#[cfg(all(ed25519_import, ed25519_export))]
fn test_import_export() {
+ common::setup();
+
let mut rng = RNG::new().expect("Error creating RNG");
let ed = Ed25519::generate(&mut rng).expect("Error with generate()");
diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_ed448.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_ed448.rs
index 2bd5582fc5..d0f7186f12 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_ed448.rs
+++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_ed448.rs
@@ -1,11 +1,15 @@
#![cfg(ed448)]
+mod common;
+
use wolfssl_wolfcrypt::random::RNG;
use wolfssl_wolfcrypt::ed448::*;
#[test]
#[cfg(all(ed448_import, ed448_export))]
fn test_make_public() {
+ common::setup();
+
let mut rng = RNG::new().expect("Error creating RNG");
let ed = Ed448::generate(&mut rng).expect("Error with generate()");
let mut private = [0u8; Ed448::KEY_SIZE];
@@ -214,6 +218,8 @@ fn test_ph_sign_verify() {
#[test]
#[cfg(all(ed448_import, ed448_export))]
fn test_import_export() {
+ common::setup();
+
let mut rng = RNG::new().expect("Error creating RNG");
let ed = Ed448::generate(&mut rng).expect("Error with generate()");
diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_hkdf.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_hkdf.rs
index 44b25580d0..e2b1e340c4 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_hkdf.rs
+++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_hkdf.rs
@@ -1,11 +1,15 @@
#![cfg(hkdf)]
+mod common;
+
use wolfssl_wolfcrypt::hkdf::*;
use wolfssl_wolfcrypt::hmac::HMAC;
use wolfssl_wolfcrypt::sha::SHA256;
#[test]
fn test_hkdf_extract_expand() {
+ common::setup();
+
let ikm = b"MyPassword0";
let salt = b"12345678ABCDEFGH";
let mut extract_out = [0u8; SHA256::DIGEST_SIZE];
@@ -26,6 +30,8 @@ fn test_hkdf_extract_expand() {
#[test]
fn test_hkdf_one_shot() {
+ common::setup();
+
let ikm = b"MyPassword0";
let salt = b"12345678ABCDEFGH";
let info = b"0";
diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_kdf.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_kdf.rs
index e540a5244a..a91edc1eee 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_kdf.rs
+++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_kdf.rs
@@ -1,5 +1,7 @@
#![cfg(any(kdf_srtp, all(hmac, any(kdf_pbkdf2, kdf_ssh, kdf_tls13))))]
+mod common;
+
#[cfg(all(hmac, any(kdf_pbkdf2, kdf_tls13)))]
use wolfssl_wolfcrypt::hmac::HMAC;
use wolfssl_wolfcrypt::kdf::*;
@@ -9,6 +11,8 @@ use wolfssl_wolfcrypt::sha::SHA256;
#[test]
#[cfg(all(hmac, kdf_pbkdf2))]
fn test_pbkdf2() {
+ common::setup();
+
let password = b"passwordpassword";
let salt = [0x78u8, 0x57, 0x8E, 0x5a, 0x5d, 0x63, 0xcb, 0x06];
let iterations = 2048;
@@ -50,6 +54,8 @@ fn test_pkcs12_pbkdf() {
#[test]
#[cfg(all(hmac, kdf_tls13))]
fn test_tls13_hkdf_extract_expand() {
+ common::setup();
+
let hash_hello1 = [
0x63u8, 0x83, 0x58, 0xab, 0x36, 0xcd, 0x0c, 0xf3,
0x26, 0x07, 0xb5, 0x5f, 0x0b, 0x8b, 0x45, 0xd6,
@@ -84,6 +90,8 @@ fn test_tls13_hkdf_extract_expand() {
#[test]
#[cfg(all(hmac, kdf_ssh))]
fn test_ssh_kdf() {
+ common::setup();
+
let ssh_kdf_set3_k = [
0x6Au8, 0xC3, 0x82, 0xEA, 0xAC, 0xA0, 0x93, 0xE1,
0x25, 0xE2, 0x5C, 0x24, 0xBE, 0xBC, 0x84, 0x64,
@@ -146,6 +154,8 @@ fn test_ssh_kdf() {
#[test]
#[cfg(kdf_srtp)]
fn test_srtp_kdf() {
+ common::setup();
+
let key = [
0xc4u8, 0x80, 0x9f, 0x6d, 0x36, 0x98, 0x88, 0x72,
0x8e, 0x26, 0xad, 0xb5, 0x32, 0x12, 0x98, 0x90
@@ -194,6 +204,8 @@ fn test_srtp_kdf() {
#[test]
#[cfg(kdf_srtp)]
fn test_srtcp_kdf() {
+ common::setup();
+
let key = [
0xc4u8, 0x80, 0x9f, 0x6d, 0x36, 0x98, 0x88, 0x72,
0x8e, 0x26, 0xad, 0xb5, 0x32, 0x12, 0x98, 0x90
diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_prf.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_prf.rs
index 511a8a07ef..9bbbc78d9e 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_prf.rs
+++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_prf.rs
@@ -1,9 +1,13 @@
#![cfg(all(prf, sha384))]
+mod common;
+
use wolfssl_wolfcrypt::prf::*;
#[test]
fn test_prf() {
+ common::setup();
+
let secret = [0x10u8, 0xbc, 0xb4, 0xa2, 0xe8, 0xdc, 0xf1, 0x9b, 0x4c,
0x51, 0x9c, 0xed, 0x31, 0x1b, 0x51, 0x57, 0x02, 0x3f,
0xa1, 0x7d, 0xfb, 0x0e, 0xf3, 0x4e, 0x8f, 0x6f, 0x71,
diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_rsa.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_rsa.rs
index 7ab9aaf9ab..b8d19cfaec 100644
--- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_rsa.rs
+++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_rsa.rs
@@ -1,5 +1,7 @@
#![cfg(rsa)]
+mod common;
+
#[cfg(any(all(sha256, random, rsa_pss), random, rsa_direct))]
use std::fs;
#[cfg(random)]
@@ -10,6 +12,8 @@ use wolfssl_wolfcrypt::rsa::*;
#[test]
#[cfg(rsa_keygen)]
fn test_rsa_generate() {
+ common::setup();
+
let mut rng = RNG::new().expect("Error creating RNG");
let mut rsa = RSA::generate(2048, 65537, &mut rng).expect("Error with generate()");
rsa.check().expect("Error with check()");