diff --git a/.github/workflows/cryptocb-only.yml b/.github/workflows/cryptocb-only.yml new file mode 100644 index 00000000000..b6ba4cc12bf --- /dev/null +++ b/.github/workflows/cryptocb-only.yml @@ -0,0 +1,95 @@ +name: cryptocb-only Tests + +# START OF COMMON SECTION +on: + push: + branches: [ 'master', 'main', 'release/**' ] + pull_request: + branches: [ '*' ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +# END OF COMMON SECTION + +jobs: + make_check: + strategy: + fail-fast: false + matrix: + include: + # WOLF_CRYPTO_CB_ONLY_ECC: strips software ECC; swdev provides the + # software path via cryptocb. FP_ECC / ECCSI / SAKKE / deterministic-k + # test / OPENSSL_EXTRA compat layer all reference stripped primitives + # directly, so they stay off. + - name: ECC + cppflags: -DWOLF_CRYPTO_CB_ONLY_ECC + # WOLF_CRYPTO_CB_ONLY_RSA: strips software RSA; swdev provides the + # software path via cryptocb. + - name: RSA + cppflags: -DWOLF_CRYPTO_CB_ONLY_RSA + # WOLF_CRYPTO_CB_ONLY_SHA256: strips software SHA-256; swdev provides + # the software path via cryptocb. SHA-224 piggybacks on the SHA-256 + # software core so it is incompatible with this strip and must be + # explicitly disabled (it is default-on on x86_64/aarch64). + - name: SHA256 + extra_config: --disable-sha224 + cppflags: -DWOLF_CRYPTO_CB_ONLY_SHA256 + # WOLF_CRYPTO_CB_ONLY_AES: strips software AES; swdev provides the + # software path via cryptocb. + - name: AES + cppflags: -DWOLF_CRYPTO_CB_ONLY_AES + # All four ONLY_* macros at once: every supported software primitive + # is stripped and dispatched through cryptocb. Catches any cross- + # algorithm call that a single-strip entry would still resolve via + # the remaining software paths. + - name: ALL + extra_config: --disable-sha224 + cppflags: >- + -DWOLF_CRYPTO_CB_ONLY_ECC -DWOLF_CRYPTO_CB_ONLY_RSA + -DWOLF_CRYPTO_CB_ONLY_SHA256 -DWOLF_CRYPTO_CB_ONLY_AES + name: make check (${{ matrix.name }}) + if: github.repository_owner == 'wolfssl' + runs-on: ubuntu-24.04 + timeout-minutes: 10 + env: + # Common feature set for every entry. SHA-224 is left at the platform + # default (on for x86_64/aarch64); entries that need it off pass + # --disable-sha224 in extra_config. + BASE_CONFIG: >- + --enable-swdev --enable-cryptocb --enable-ecc --enable-rsa --enable-dh + --enable-aesgcm --enable-aesccm --enable-aesctr --enable-aescfb + --enable-aeskeywrap --enable-aessiv --enable-aesofb --enable-aesxts + --enable-camellia --enable-chacha --enable-poly1305 + --enable-sha --enable-sha3 --enable-shake128 --enable-shake256 + --enable-blake2 --enable-blake2s + --enable-hkdf --enable-hashdrbg --enable-hashflags + --enable-curve25519 --enable-ed25519 --enable-curve448 --enable-ed448 + --enable-mlkem --enable-dilithium + --enable-scrypt --enable-pwdbased --enable-pkcs7 --enable-pkcs12 + --enable-certgen --enable-certreq --enable-certext + --enable-keygen --enable-asn=all + --enable-cmac --enable-xchacha + --enable-crl --enable-ocsp --enable-ocspstapling --enable-ocspstapling2 + --enable-dtls --enable-dtls13 --enable-tls13 + steps: + - uses: actions/checkout@v4 + name: Checkout wolfSSL + + - name: Test wolfSSL + run: | + ./autogen.sh + ./configure $BASE_CONFIG ${{ matrix.extra_config }} CPPFLAGS="${{ matrix.cppflags }}" + make -j 4 + make check + + - name: Print errors + if: ${{ failure() }} + run: | + for file in scripts/*.log + do + if [ -f "$file" ]; then + echo "${file}:" + cat "$file" + fi + done diff --git a/configure.ac b/configure.ac index 21ba1304a79..8caba288581 100644 --- a/configure.ac +++ b/configure.ac @@ -10666,6 +10666,25 @@ if test "$ENABLED_CRYPTOCB_UTILS" != "no"; then fi +# wc_swdev: software crypto-callback device for testing +AC_ARG_ENABLE([swdev], + [AS_HELP_STRING([--enable-swdev],[Build wc_swdev software crypto-callback for tests (default: disabled). Requires --enable-cryptocb, forces WOLF_CRYPTO_CB_FIND, and currently supports in-tree builds only.])], + [ ENABLED_SWDEV=$enableval ], + [ ENABLED_SWDEV=no ] +) + +if test "$ENABLED_SWDEV" = "yes" +then + if test "$ENABLED_CRYPTOCB" != "yes"; then + AC_MSG_ERROR([--enable-swdev requires --enable-cryptocb]) + fi + if test "x$srcdir" != "x."; then + AC_MSG_ERROR([--enable-swdev currently supports in-tree builds only]) + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SWDEV -DWOLF_CRYPTO_CB_FIND" +fi + + # Asynchronous Crypto AC_ARG_ENABLE([asynccrypt], [AS_HELP_STRING([--enable-asynccrypt],[Enable Asynchronous Crypto (default: disabled)])], @@ -12288,6 +12307,7 @@ AM_CONDITIONAL([BUILD_MCAPI],[test "x$ENABLED_MCAPI" = "xyes"]) AM_CONDITIONAL([BUILD_ASYNCCRYPT],[test "x$ENABLED_ASYNCCRYPT" = "xyes"]) AM_CONDITIONAL([BUILD_WOLFEVENT],[test "x$ENABLED_ASYNCCRYPT" = "xyes"]) AM_CONDITIONAL([BUILD_CRYPTOCB],[test "x$ENABLED_CRYPTOCB" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SWDEV],[test "x$ENABLED_SWDEV" = "xyes"]) AM_CONDITIONAL([BUILD_PSK],[test "x$ENABLED_PSK" = "xyes"]) AM_CONDITIONAL([BUILD_TRUST_PEER_CERT],[test "x$ENABLED_TRUSTED_PEER_CERT" = "xyes"]) AM_CONDITIONAL([BUILD_PKI],[test "x$ENABLED_PKI" = "xyes"]) diff --git a/examples/client/client.c b/examples/client/client.c index dfcfe5942ba..825c0f9d9a5 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -51,6 +51,10 @@ static const char *wolfsentry_config_path = NULL; #include #include +#ifdef WOLFSSL_SWDEV + #include "tests/swdev/swdev_loader.h" +#endif + #ifdef USE_FLAT_TEST_H #include "client.h" #else @@ -5054,6 +5058,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_Debugging_ON(); #endif wolfSSL_Init(); +#ifdef WOLFSSL_SWDEV + if (wc_SwDev_Init() != 0) { + fprintf(stderr, "wc_SwDev_Init failed\n"); + return EXIT_FAILURE; + } +#endif ChangeToWolfRoot(); #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS) @@ -5064,6 +5074,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif #else fprintf(stderr, "Client not compiled in!\n"); +#endif +#ifdef WOLFSSL_SWDEV + wc_SwDev_Cleanup(); #endif wolfSSL_Cleanup(); diff --git a/examples/client/include.am b/examples/client/include.am index 36e65f218c0..30d70e8c81c 100644 --- a/examples/client/include.am +++ b/examples/client/include.am @@ -7,6 +7,11 @@ noinst_HEADERS += examples/client/client.h examples_client_client_SOURCES = examples/client/client.c examples_client_client_LDADD = src/libwolfssl@LIBSUFFIX@.la $(LIB_STATIC_ADD) $(WOLFSENTRY_LIB) examples_client_client_DEPENDENCIES = src/libwolfssl@LIBSUFFIX@.la +if BUILD_SWDEV +examples_client_client_SOURCES += tests/swdev/swdev_loader.c +examples_client_client_LDADD += $(top_builddir)/tests/swdev/build/swdev.o $(LIBM) +examples_client_client_DEPENDENCIES += $(top_builddir)/tests/swdev/build/swdev.o +endif examples_client_client_CFLAGS = $(WOLFSENTRY_INCLUDE) $(AM_CFLAGS) endif EXTRA_DIST += examples/client/client.sln diff --git a/examples/server/include.am b/examples/server/include.am index cb591d9e34b..990bff650db 100644 --- a/examples/server/include.am +++ b/examples/server/include.am @@ -9,6 +9,11 @@ noinst_HEADERS += examples/server/server.h examples_server_server_SOURCES = examples/server/server.c examples_server_server_LDADD = src/libwolfssl@LIBSUFFIX@.la $(LIB_STATIC_ADD) $(WOLFSENTRY_LIB) examples_server_server_DEPENDENCIES = src/libwolfssl@LIBSUFFIX@.la +if BUILD_SWDEV +examples_server_server_SOURCES += tests/swdev/swdev_loader.c +examples_server_server_LDADD += $(top_builddir)/tests/swdev/build/swdev.o $(LIBM) +examples_server_server_DEPENDENCIES += $(top_builddir)/tests/swdev/build/swdev.o +endif examples_server_server_CFLAGS = $(WOLFSENTRY_INCLUDE) $(AM_CFLAGS) endif EXTRA_DIST += examples/server/server.sln diff --git a/examples/server/server.c b/examples/server/server.c index 25ae7851517..8604578d107 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -67,6 +67,10 @@ static const char *wolfsentry_config_path = NULL; #include #include +#ifdef WOLFSSL_SWDEV + #include "tests/swdev/swdev_loader.h" +#endif + #ifdef USE_FLAT_TEST_H #include "server.h" #else @@ -4258,6 +4262,12 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) wolfSSL_Init(); #ifdef WC_RNG_SEED_CB wc_SetSeed_Cb(WC_GENERATE_SEED_DEFAULT); +#endif +#ifdef WOLFSSL_SWDEV + if (wc_SwDev_Init() != 0) { + fprintf(stderr, "wc_SwDev_Init failed\n"); + return EXIT_FAILURE; + } #endif ChangeToWolfRoot(); @@ -4271,6 +4281,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) fprintf(stderr, "Server not compiled in!\n"); #endif +#ifdef WOLFSSL_SWDEV + wc_SwDev_Cleanup(); +#endif wolfSSL_Cleanup(); FreeTcpReady(&ready); diff --git a/tests/api.c b/tests/api.c index 05a7688d7ff..9016339722d 100644 --- a/tests/api.c +++ b/tests/api.c @@ -65,6 +65,10 @@ #include #include +#ifdef WOLFSSL_SWDEV +#include "swdev/swdev_loader.h" +#endif + /* for testing compatibility layer callbacks */ #include "examples/server/server.h" @@ -28467,7 +28471,9 @@ static int test_SSL_CIPHER_get_xxx(void) return EXPECT_RESULT(); } -#if defined(WOLF_CRYPTO_CB) && defined(HAVE_IO_TESTS_DEPENDENCIES) +#if defined(WOLF_CRYPTO_CB) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \ + !defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLF_CRYPTO_CB_ONLY_AES) && \ + !defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA) static int load_pem_key_file_as_der(const char* privKeyFile, DerBuffer** pDer, int* keyFormat) @@ -29469,7 +29475,9 @@ static int test_wc_CryptoCb_TLS(int tlsVer, static int test_wc_CryptoCb(void) { EXPECT_DECLS; -#ifdef WOLF_CRYPTO_CB +#if defined(WOLF_CRYPTO_CB) && \ + !defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLF_CRYPTO_CB_ONLY_AES) && \ + !defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA) /* TODO: Add crypto callback API tests */ #ifdef HAVE_IO_TESTS_DEPENDENCIES @@ -36801,7 +36809,7 @@ static int test_pkcs7_padding(void) /* Encode EncryptedData */ XMEMSET(&pkcs7, 0, sizeof(pkcs7)); - ExpectIntEQ(wc_PKCS7_Init(&pkcs7, NULL, 0), 0); + ExpectIntEQ(wc_PKCS7_Init(&pkcs7, NULL, INVALID_DEVID), 0); pkcs7.content = plaintext; pkcs7.contentSz = sizeof(plaintext); pkcs7.contentOID = DATA; @@ -36830,7 +36838,7 @@ static int test_pkcs7_padding(void) /* Decrypt modified ciphertext - must fail, not succeed */ XMEMSET(&pkcs7, 0, sizeof(pkcs7)); - ExpectIntEQ(wc_PKCS7_Init(&pkcs7, NULL, 0), 0); + ExpectIntEQ(wc_PKCS7_Init(&pkcs7, NULL, INVALID_DEVID), 0); pkcs7.encryptionKey = key; pkcs7.encryptionKeySz = sizeof(key); @@ -37707,7 +37715,9 @@ TEST_CASE testCases[] = { static void TestSetup(void) { -/* Stub, for now. Add common test setup code here. */ +#ifdef WOLFSSL_SWDEV + (void)wc_SwDev_Init(); +#endif } static void TestCleanup(void) @@ -37929,20 +37939,24 @@ int ApiTest(void) printf(" Begin API Tests\n"); fflush(stdout); - /* we must perform init and cleanup if not all tests are running */ - if (!testAll) { - #ifdef WOLFCRYPT_ONLY - if (wolfCrypt_Init() != 0) { - printf("wolfCrypt Initialization failed\n"); - res = 1; - } - #else - if (wolfSSL_Init() != WOLFSSL_SUCCESS) { - printf("wolfSSL Initialization failed\n"); - res = 1; - } - #endif +#ifdef WOLFCRYPT_ONLY + if (wolfCrypt_Init() != 0) { + printf("wolfCrypt Initialization failed\n"); + res = 1; + } +#else + if (wolfSSL_Init() != WOLFSSL_SUCCESS) { + printf("wolfSSL Initialization failed\n"); + res = 1; } +#endif + +#ifdef WOLFSSL_SWDEV + if (res == 0 && wc_SwDev_Init() != 0) { + printf("wc_SwDev_Init failed\n"); + res = 1; + } +#endif #ifdef WOLFSSL_DUMP_MEMIO_STREAM if (res == 0) { @@ -38034,13 +38048,15 @@ int ApiTest(void) wc_ecc_fp_free(); /* free per thread cache */ #endif - if (!testAll) { - #ifdef WOLFCRYPT_ONLY - wolfCrypt_Cleanup(); - #else - wolfSSL_Cleanup(); - #endif - } +#ifdef WOLFSSL_SWDEV + wc_SwDev_Cleanup(); +#endif + +#ifdef WOLFCRYPT_ONLY + wolfCrypt_Cleanup(); +#else + wolfSSL_Cleanup(); +#endif (void)testDevId; diff --git a/tests/api/test_ecc.c b/tests/api/test_ecc.c index f70882a76a7..ae080eae69b 100644 --- a/tests/api/test_ecc.c +++ b/tests/api/test_ecc.c @@ -785,9 +785,12 @@ int test_wc_ecc_import_x963(void) int test_wc_ecc_import_x963_off_curve(void) { EXPECT_DECLS; +/* point-on-curve validation inside wc_ecc_import_x963 is raw math stripped + * by WOLF_CRYPTO_CB_ONLY_ECC; swdev cannot reach below the dispatch layer. */ #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_IMPORT) && \ !defined(NO_ECC256) && !defined(NO_ECC_SECP) && \ - (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0)) && !defined(HAVE_SELFTEST) + (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0)) && !defined(HAVE_SELFTEST) && \ + !defined(WOLF_CRYPTO_CB_ONLY_ECC) ecc_key pubKey; /* Uncompressed X9.63 P-256 point: 0x04 || Gx || Gy with the last byte * of Gy flipped by 1. Gx/Gy are the NIST P-256 generator coordinates; diff --git a/tests/api/test_pkcs7.c b/tests/api/test_pkcs7.c index 6d033b15d04..504caeebb3a 100644 --- a/tests/api/test_pkcs7.c +++ b/tests/api/test_pkcs7.c @@ -2203,7 +2203,7 @@ int test_wc_PKCS7_VerifySignedData_RSA(void) /* verify using pre-computed content digest only (no content) */ { ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId)); - ExpectIntEQ(wc_PKCS7_Init(pkcs7, NULL, 0), 0); + ExpectIntEQ(wc_PKCS7_Init(pkcs7, NULL, testDevId), 0); ExpectIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, output, outputSz, NULL, 0), 0); wc_PKCS7_Free(pkcs7); @@ -2473,7 +2473,7 @@ int test_wc_PKCS7_VerifySignedData_ECC(void) ExpectIntEQ(wc_HashFree(&hash, hashType), 0); ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId)); - ExpectIntEQ(wc_PKCS7_Init(pkcs7, NULL, 0), 0); + ExpectIntEQ(wc_PKCS7_Init(pkcs7, NULL, testDevId), 0); ExpectIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, output, outputSz, NULL, 0), 0); wc_PKCS7_Free(pkcs7); @@ -4645,7 +4645,7 @@ int test_wc_PKCS7_signed_enveloped(void) ExpectIntGT(keySz = wolfSSL_KeyPemToDer(key, keySz, key, keySz, NULL), 0); /* sign cert for envelope */ - ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, testDevId)); ExpectIntEQ(wc_InitRng(&rng), 0); ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, (word32)certSz), 0); if (pkcs7 != NULL) { @@ -4665,7 +4665,7 @@ int test_wc_PKCS7_signed_enveloped(void) #if defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) /* create envelope */ - ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, testDevId)); ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, (word32)certSz), 0); if (pkcs7 != NULL) { pkcs7->content = sig; @@ -4683,7 +4683,7 @@ int test_wc_PKCS7_signed_enveloped(void) /* create bad signed enveloped data */ sigSz = FOURK_BUF * 2; - ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, testDevId)); ExpectIntEQ(wc_InitRng(&rng), 0); ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, (word32)certSz), 0); if (pkcs7 != NULL) { @@ -4708,7 +4708,7 @@ int test_wc_PKCS7_signed_enveloped(void) pkcs7 = NULL; /* check verify fails */ - ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, testDevId)); ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); ExpectIntEQ(wc_PKCS7_VerifySignedData(pkcs7, sig, (word32)sigSz), WC_NO_ERR_TRACE(PKCS7_SIGNEEDS_CHECK)); @@ -4735,7 +4735,7 @@ int test_wc_PKCS7_signed_enveloped(void) pkcs7 = NULL; /* initializing the PKCS7 struct with the signing certificate should pass */ - ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, testDevId)); ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, (word32)certSz), 0); ExpectIntEQ(wc_PKCS7_VerifySignedData(pkcs7, sig, (word32)sigSz), 0); @@ -4761,7 +4761,7 @@ int test_wc_PKCS7_signed_enveloped(void) /* create valid degenerate bundle */ sigSz = FOURK_BUF * 2; - ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, testDevId)); if (pkcs7 != NULL) { pkcs7->content = env; pkcs7->contentSz = (word32)envSz; @@ -4779,7 +4779,7 @@ int test_wc_PKCS7_signed_enveloped(void) wc_FreeRng(&rng); /* check verify */ - ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, testDevId)); ExpectIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, testDevId), 0); ExpectIntEQ(wc_PKCS7_VerifySignedData(pkcs7, sig, (word32)sigSz), 0); ExpectNotNull(pkcs7->content); @@ -4790,7 +4790,7 @@ int test_wc_PKCS7_signed_enveloped(void) /* create valid degenerate bundle */ sigSz = FOURK_BUF * 2; - ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, testDevId)); if (pkcs7 != NULL) { pkcs7->content = env; pkcs7->contentSz = (word32)envSz; @@ -4808,7 +4808,7 @@ int test_wc_PKCS7_signed_enveloped(void) wc_FreeRng(&rng); /* check verify */ - ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, testDevId)); ExpectIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, testDevId), 0); /* test for streaming */ ret = -1; @@ -4823,7 +4823,7 @@ int test_wc_PKCS7_signed_enveloped(void) #ifdef HAVE_AES_CBC /* check decode */ - ExpectNotNull(inner = wc_PKCS7_New(NULL, 0)); + ExpectNotNull(inner = wc_PKCS7_New(NULL, testDevId)); ExpectIntEQ(wc_PKCS7_InitWithCert(inner, cert, (word32)certSz), 0); if (inner != NULL) { inner->privateKey = key; @@ -4839,7 +4839,7 @@ int test_wc_PKCS7_signed_enveloped(void) #ifdef HAVE_AES_CBC /* check cert set */ - ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, testDevId)); ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); ExpectIntEQ(wc_PKCS7_VerifySignedData(pkcs7, decoded, (word32)decodedSz), 0); ExpectNotNull(pkcs7->singleCert); @@ -4848,7 +4848,7 @@ int test_wc_PKCS7_signed_enveloped(void) pkcs7 = NULL; #ifndef NO_PKCS7_STREAM - ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + ExpectNotNull(pkcs7 = wc_PKCS7_New(NULL, testDevId)); ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); /* test for streaming */ ret = -1; diff --git a/tests/include.am b/tests/include.am index fc1359d3d52..914bcb29f87 100644 --- a/tests/include.am +++ b/tests/include.am @@ -24,6 +24,11 @@ endif tests_unit_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) $(WOLFSENTRY_INCLUDE) tests_unit_test_LDADD = src/libwolfssl@LIBSUFFIX@.la $(LIB_STATIC_ADD) $(WOLFSENTRY_LIB) tests_unit_test_DEPENDENCIES = src/libwolfssl@LIBSUFFIX@.la +if BUILD_SWDEV +tests_unit_test_SOURCES += tests/swdev/swdev_loader.c +tests_unit_test_LDADD += $(top_builddir)/tests/swdev/build/swdev.o $(LIBM) +tests_unit_test_DEPENDENCIES += $(top_builddir)/tests/swdev/build/swdev.o +endif include tests/api/include.am endif EXTRA_DIST += tests/unit.h \ diff --git a/tests/suites.c b/tests/suites.c index dabc1f2756a..52c6bcd3ad7 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -1008,7 +1008,8 @@ int SuiteTest(int argc, char** argv) { #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) && \ !defined(NO_TLS) && !defined(SINGLE_THREADED) && \ - !defined(WOLF_CRYPTO_CB_ONLY_RSA) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) + (defined(WOLFSSL_SWDEV) || \ + (!defined(WOLF_CRYPTO_CB_ONLY_RSA) && !defined(WOLF_CRYPTO_CB_ONLY_ECC))) func_args args; char argv0[3][80]; char* myArgv[3]; diff --git a/tests/swdev/.gitignore b/tests/swdev/.gitignore new file mode 100644 index 00000000000..b021c8ed3ee --- /dev/null +++ b/tests/swdev/.gitignore @@ -0,0 +1,4 @@ +build/ +*.o +.deps/ +.dirstamp diff --git a/tests/swdev/Makefile b/tests/swdev/Makefile new file mode 100644 index 00000000000..1c0ce6a5738 --- /dev/null +++ b/tests/swdev/Makefile @@ -0,0 +1,104 @@ +# tests/swdev/Makefile -- builds swdev.o. +# +# Standalone: cd tests/swdev && make +# Invoked from wolfcrypt/test/include.am in the main build. + +SRCDIR ?= $(CURDIR) +WOLFROOT ?= $(abspath $(SRCDIR)/../..) +BUILDDIR ?= $(SRCDIR)/build + +CC ?= cc +CCAS ?= $(CC) +LD ?= ld +OBJCOPY ?= objcopy +NM ?= nm + +SWDEV_LOCAL_SRCS = swdev.c + +# PARENT_SRCS / PARENT_ASM_SRCS mirror the exact source set that the +# parent build compiled into libwolfssl (passed down by wolfcrypt/test/include.am). +# The configure.ac gate already requires in-tree builds, so PARENT_SRCS +# is always populated when swdev is built in-tree; fail loudly otherwise. +ifeq ($(strip $(PARENT_SRCS)),) +$(error PARENT_SRCS is empty -- swdev must be built from the top-level \ + Makefile so its source set matches the main library) +endif + +SWDEV_CRYPT_SRCS = $(filter wolfcrypt/src/%,$(PARENT_SRCS)) +SWDEV_SSL_SRCS = $(filter src/%,$(PARENT_SRCS)) +SWDEV_ASM_SRCS = $(PARENT_ASM_SRCS) + +# -I$(SRCDIR) routes settings.h to the swdev's user_settings.h. +# No BUILDING_WOLFSSL so WOLFSSL_API/LOCAL stay empty; then -fvisibility=hidden +# hides every emitted symbol. +CPPFLAGS_SWDEV = \ + $(PARENT_CPPFLAGS) \ + -DWOLFSSL_USER_SETTINGS \ + -I$(SRCDIR) \ + -I$(WOLFROOT) \ + -I$(WOLFROOT)/wolfssl + +# -fvisibility=hidden + -fno-common mark every symbol hidden at the ELF +# level (ABI-safe: attribute only, no struct layout impact). Optimization +# level and other flags are inherited from the parent build (PARENT_*_CFLAGS) +# so codegen stays in lockstep with libwolfssl. Use EXTRA_SWDEV_CFLAGS to +# append debug flags (e.g. -O0 -ggdb) on demand. +CFLAGS_SWDEV = \ + $(PARENT_BUILD_CFLAGS) \ + $(PARENT_CFLAGS) \ + -fvisibility=hidden \ + -fno-common \ + -Wno-pragmas \ + $(EXTRA_SWDEV_CFLAGS) + +CCASFLAGS_SWDEV = \ + $(PARENT_BUILD_CCASFLAGS) \ + $(PARENT_CCASFLAGS) + +CRYPT_OBJS = $(patsubst wolfcrypt/src/%.c,$(BUILDDIR)/wc/%.o,$(SWDEV_CRYPT_SRCS)) +SSL_OBJS = $(patsubst src/%.c,$(BUILDDIR)/ssl/%.o,$(SWDEV_SSL_SRCS)) +ASM_OBJS = $(patsubst wolfcrypt/src/%.S,$(BUILDDIR)/wc/%.o,$(SWDEV_ASM_SRCS)) +LOCAL_OBJS = $(patsubst %.c,$(BUILDDIR)/local/%.o,$(SWDEV_LOCAL_SRCS)) +ALL_OBJS = $(CRYPT_OBJS) $(SSL_OBJS) $(ASM_OBJS) $(LOCAL_OBJS) + +.PHONY: all clean +all: $(BUILDDIR)/swdev.o + +$(BUILDDIR)/wc/%.o: $(WOLFROOT)/wolfcrypt/src/%.c $(SRCDIR)/user_settings.h $(WOLFROOT)/wolfssl/options.h | $(BUILDDIR)/wc + $(CC) $(CPPFLAGS_SWDEV) $(CFLAGS_SWDEV) -c $< -o $@ + +$(BUILDDIR)/wc/%.o: $(WOLFROOT)/wolfcrypt/src/%.S $(SRCDIR)/user_settings.h $(WOLFROOT)/wolfssl/options.h | $(BUILDDIR)/wc + $(CCAS) $(CPPFLAGS_SWDEV) $(CCASFLAGS_SWDEV) -c $< -o $@ + +$(BUILDDIR)/ssl/%.o: $(WOLFROOT)/src/%.c $(SRCDIR)/user_settings.h $(WOLFROOT)/wolfssl/options.h | $(BUILDDIR)/ssl + $(CC) $(CPPFLAGS_SWDEV) $(CFLAGS_SWDEV) -c $< -o $@ + +$(BUILDDIR)/local/%.o: $(SRCDIR)/%.c $(SRCDIR)/swdev.h $(SRCDIR)/user_settings.h $(WOLFROOT)/wolfssl/options.h | $(BUILDDIR)/local + $(CC) $(CPPFLAGS_SWDEV) $(CFLAGS_SWDEV) -c $< -o $@ + +$(BUILDDIR)/swdev.partial.o: $(ALL_OBJS) + $(LD) -r -o $@ $(ALL_OBJS) + +$(BUILDDIR)/swdev.o: $(BUILDDIR)/swdev.partial.o + @# --keep-global-symbol localizes every global symbol *except* the + @# named one. We can't rely on --localize-hidden here because + @# wolfssl/wolfcrypt/libwolfssl_sources.h auto-defines BUILDING_WOLFSSL + @# at the top of every compiled source, which expands WOLFSSL_API to + @# visibility("default") and overrides the command-line + @# -fvisibility=hidden. --keep-global-symbol sidesteps that by matching + @# on symbol name directly. + $(OBJCOPY) --keep-global-symbol=wc_SwDev_Callback $< $@ + @# Sanity-check: only wc_SwDev_Callback may be externally visible. + @visible=$$( $(NM) --extern-only --defined-only $@ | awk '{print $$3}' \ + | grep -v '^wc_SwDev_Callback$$' || true); \ + if [ -n "$$visible" ]; then \ + echo "error: unexpected externally-visible symbols in $@:"; \ + echo "$$visible"; \ + exit 1; \ + fi + +$(BUILDDIR) $(BUILDDIR)/wc $(BUILDDIR)/ssl $(BUILDDIR)/local: + mkdir -p $@ + +clean: + rm -rf $(BUILDDIR) diff --git a/tests/swdev/swdev.c b/tests/swdev/swdev.c new file mode 100644 index 00000000000..d402207b54d --- /dev/null +++ b/tests/swdev/swdev.c @@ -0,0 +1,516 @@ +/* tests/swdev/swdev.c -- wc_swdev callback. */ + +#include "swdev.h" + +#include +#include +#include +#include + +#ifndef NO_RSA +#include +#endif +#ifdef HAVE_ECC +#include +#endif +#ifndef NO_SHA256 +#include +#endif +#ifndef NO_AES +#include +#endif + +static int swdev_initialized = 0; + +static int swdev_ensure_init(void) +{ + if (!swdev_initialized) { + int ret = wolfCrypt_Init(); + if (ret != 0) + return ret; + swdev_initialized = 1; + } + return 0; +} + +#ifndef NO_RSA +static int swdev_rsa(wc_CryptoInfo* info) +{ + switch (info->pk.rsa.type) { + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + case RSA_PRIVATE_DECRYPT: + return wc_RsaFunction(info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, info->pk.rsa.outLen, info->pk.rsa.type, + info->pk.rsa.key, info->pk.rsa.rng); + default: + return CRYPTOCB_UNAVAILABLE; + } +} + +#ifdef WOLFSSL_KEY_GEN +static int swdev_rsa_keygen(wc_CryptoInfo* info) +{ + return wc_MakeRsaKey(info->pk.rsakg.key, info->pk.rsakg.size, + info->pk.rsakg.e, info->pk.rsakg.rng); +} +#endif +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +static int swdev_ecc_keygen(wc_CryptoInfo* info) +{ +#ifdef HAVE_ECC_DHE + return wc_ecc_make_key_ex(info->pk.eckg.rng, info->pk.eckg.size, + info->pk.eckg.key, info->pk.eckg.curveId); +#else + (void)info; + return CRYPTOCB_UNAVAILABLE; +#endif +} + +static int swdev_ecdh(wc_CryptoInfo* info) +{ +#ifdef HAVE_ECC_DHE + return wc_ecc_shared_secret(info->pk.ecdh.private_key, + info->pk.ecdh.public_key, info->pk.ecdh.out, + info->pk.ecdh.outlen); +#else + (void)info; + return CRYPTOCB_UNAVAILABLE; +#endif +} + +static int swdev_ecc_sign(wc_CryptoInfo* info) +{ +#ifdef HAVE_ECC_SIGN + return wc_ecc_sign_hash(info->pk.eccsign.in, info->pk.eccsign.inlen, + info->pk.eccsign.out, info->pk.eccsign.outlen, + info->pk.eccsign.rng, info->pk.eccsign.key); +#else + (void)info; + return CRYPTOCB_UNAVAILABLE; +#endif +} + +static int swdev_ecc_verify(wc_CryptoInfo* info) +{ +#ifdef HAVE_ECC_VERIFY + return wc_ecc_verify_hash(info->pk.eccverify.sig, + info->pk.eccverify.siglen, info->pk.eccverify.hash, + info->pk.eccverify.hashlen, info->pk.eccverify.res, + info->pk.eccverify.key); +#else + (void)info; + return CRYPTOCB_UNAVAILABLE; +#endif +} + +static int swdev_ecc_get_size(wc_CryptoInfo* info) +{ + int sz = wc_ecc_size((ecc_key*)info->pk.ecc_get_size.key); + if (sz <= 0) + return sz; /* propagate negative error */ + *info->pk.ecc_get_size.keySize = sz; + return 0; +} + +static int swdev_ecc_get_sig_size(wc_CryptoInfo* info) +{ + int sz = wc_ecc_sig_size(info->pk.ecc_get_sig_size.key); + if (sz <= 0) + return sz; + *info->pk.ecc_get_sig_size.sigSize = sz; + return 0; +} +#endif /* HAVE_ECC */ + +#ifndef NO_SHA256 +/* Copy hash state between caller's wc_Sha256 and swdev's shadow, leaving + * admin fields (heap, devId, devCtx, W, async, HW ctx) per-side. */ +static void swdev_sha256_copy_state(wc_Sha256* dst, const wc_Sha256* src) +{ + XMEMCPY(dst->digest, src->digest, sizeof(dst->digest)); + XMEMCPY(dst->buffer, src->buffer, sizeof(dst->buffer)); + dst->buffLen = src->buffLen; + dst->loLen = src->loLen; + dst->hiLen = src->hiLen; +#ifdef WC_C_DYNAMIC_FALLBACK + dst->sha_method = src->sha_method; +#endif +#ifdef WOLFSSL_HASH_FLAGS + dst->flags = src->flags; +#endif +} + +/* Run the op on a per-call shadow wc_Sha256 owned by swdev, copying state + * in and out around it. The caller's struct, allocated by libwolfssl with + * the software init stripped, can't be used directly. */ +static int swdev_sha256(wc_CryptoInfo* info) +{ + wc_Sha256* sha256 = info->hash.sha256; + wc_Sha256 shadow; + int ret; + + if (sha256 == NULL) + return BAD_FUNC_ARG; + + ret = wc_InitSha256(&shadow); + if (ret != 0) + return ret; + + swdev_sha256_copy_state(&shadow, sha256); + + if (info->hash.in != NULL) { + ret = wc_Sha256Update(&shadow, info->hash.in, info->hash.inSz); + if (ret != 0) + goto out; + } + + if (info->hash.digest != NULL) { + ret = wc_Sha256Final(&shadow, info->hash.digest); + if (ret != 0) + goto out; + } + + swdev_sha256_copy_state(sha256, &shadow); + +out: + wc_Sha256Free(&shadow); + return ret; +} +#endif /* !NO_SHA256 */ + +#ifndef NO_AES +/* Rebuild a software AES shadow from the caller's raw devKey, since the + * caller's Aes has no software round-key schedule under CB_ONLY_AES. */ +static int swdev_aes_shadow_init(Aes* shadow, const Aes* aes, int dir) +{ + int ret; + + if (shadow == NULL || aes == NULL) + return BAD_FUNC_ARG; + if (aes->keylen <= 0 || aes->keylen > (int)sizeof(aes->devKey)) + return BAD_FUNC_ARG; + + ret = wc_AesInit(shadow, aes->heap, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_AesSetKey(shadow, (const byte*)aes->devKey, + (word32)aes->keylen, (const byte*)aes->reg, dir); + if (ret != 0) { + wc_AesFree(shadow); + return ret; + } + + XMEMCPY(shadow->tmp, aes->tmp, sizeof(shadow->tmp)); +#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \ + defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \ + defined(WOLFSSL_AES_CTS) + shadow->left = aes->left; +#endif + + return 0; +} + +static void swdev_aes_shadow_sync(Aes* dst, const Aes* src) +{ + XMEMCPY(dst->reg, src->reg, sizeof(dst->reg)); + XMEMCPY(dst->tmp, src->tmp, sizeof(dst->tmp)); +#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \ + defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \ + defined(WOLFSSL_AES_CTS) + dst->left = src->left; +#endif +} + +#ifdef HAVE_AES_CBC +static int swdev_aes_cbc(wc_CryptoInfo* info) +{ + Aes* aes = info->cipher.aescbc.aes; + byte* out = info->cipher.aescbc.out; + const byte* in = info->cipher.aescbc.in; + word32 sz = info->cipher.aescbc.sz; + Aes shadow; + int ret; + + ret = swdev_aes_shadow_init(&shadow, aes, + info->cipher.enc ? AES_ENCRYPTION : AES_DECRYPTION); + if (ret != 0) + return ret; + + if (info->cipher.enc) + ret = wc_AesCbcEncrypt(&shadow, out, in, sz); +#ifdef HAVE_AES_DECRYPT + else + ret = wc_AesCbcDecrypt(&shadow, out, in, sz); +#else + else + ret = CRYPTOCB_UNAVAILABLE; +#endif + swdev_aes_shadow_sync(aes, &shadow); + wc_AesFree(&shadow); + return ret; +} +#endif /* HAVE_AES_CBC */ + +#ifdef WOLFSSL_AES_COUNTER +static int swdev_aes_ctr(wc_CryptoInfo* info) +{ + Aes* aes = info->cipher.aesctr.aes; + Aes shadow; + int ret; + + ret = swdev_aes_shadow_init(&shadow, aes, AES_ENCRYPTION); + if (ret != 0) + return ret; + + ret = wc_AesCtrEncrypt(&shadow, info->cipher.aesctr.out, + info->cipher.aesctr.in, info->cipher.aesctr.sz); + swdev_aes_shadow_sync(aes, &shadow); + wc_AesFree(&shadow); + return ret; +} +#endif + +#if defined(HAVE_AES_ECB) || defined(WOLFSSL_AES_DIRECT) +static int swdev_aes_ecb(wc_CryptoInfo* info) +{ + Aes* aes = info->cipher.aesecb.aes; + byte* out = info->cipher.aesecb.out; + const byte* in = info->cipher.aesecb.in; + word32 sz = info->cipher.aesecb.sz; + Aes shadow; + int ret; + + ret = swdev_aes_shadow_init(&shadow, aes, + info->cipher.enc ? AES_ENCRYPTION : AES_DECRYPTION); + if (ret != 0) + return ret; + +#ifdef HAVE_AES_ECB + if (info->cipher.enc) + ret = wc_AesEcbEncrypt(&shadow, out, in, sz); +#ifdef HAVE_AES_DECRYPT + else + ret = wc_AesEcbDecrypt(&shadow, out, in, sz); +#else + else + ret = CRYPTOCB_UNAVAILABLE; +#endif +#elif defined(WOLFSSL_AES_DIRECT) + if (sz != WC_AES_BLOCK_SIZE) { + ret = CRYPTOCB_UNAVAILABLE; + } + else if (info->cipher.enc) { + ret = wc_AesEncryptDirect(&shadow, out, in); + } +#ifdef HAVE_AES_DECRYPT + else { + ret = wc_AesDecryptDirect(&shadow, out, in); + } +#else + else { + ret = CRYPTOCB_UNAVAILABLE; + } +#endif +#else + (void)out; + (void)in; + (void)sz; + ret = CRYPTOCB_UNAVAILABLE; +#endif + + wc_AesFree(&shadow); + return ret; +} +#endif /* HAVE_AES_ECB || WOLFSSL_AES_DIRECT */ + +#ifdef HAVE_AESGCM +static int swdev_aes_gcm(wc_CryptoInfo* info) +{ + Aes* aes = info->cipher.enc ? info->cipher.aesgcm_enc.aes : + info->cipher.aesgcm_dec.aes; + Aes shadow; + int ret; + + if (aes == NULL || aes->keylen <= 0 || aes->keylen > (int)sizeof(aes->devKey)) + return BAD_FUNC_ARG; + + ret = wc_AesInit(&shadow, aes->heap, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_AesGcmSetKey(&shadow, (const byte*)aes->devKey, (word32)aes->keylen); + if (ret != 0) { + wc_AesFree(&shadow); + return ret; + } + + if (info->cipher.enc) { + ret = wc_AesGcmEncrypt(&shadow, + 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); + } + else { + ret = wc_AesGcmDecrypt(&shadow, 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(&shadow); + return ret; +} +#endif /* HAVE_AESGCM */ + +#ifdef HAVE_AESCCM +static int swdev_aes_ccm(wc_CryptoInfo* info) +{ + Aes* aes = info->cipher.enc ? info->cipher.aesccm_enc.aes : + info->cipher.aesccm_dec.aes; + Aes shadow; + int ret; + + if (aes == NULL || aes->keylen <= 0 || aes->keylen > (int)sizeof(aes->devKey)) + return BAD_FUNC_ARG; + + ret = wc_AesInit(&shadow, aes->heap, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_AesCcmSetKey(&shadow, (const byte*)aes->devKey, (word32)aes->keylen); + if (ret != 0) { + wc_AesFree(&shadow); + return ret; + } + + if (info->cipher.enc) { + ret = wc_AesCcmEncrypt(&shadow, + info->cipher.aesccm_enc.out, info->cipher.aesccm_enc.in, + info->cipher.aesccm_enc.sz, + info->cipher.aesccm_enc.nonce, + info->cipher.aesccm_enc.nonceSz, + info->cipher.aesccm_enc.authTag, + info->cipher.aesccm_enc.authTagSz, + info->cipher.aesccm_enc.authIn, + info->cipher.aesccm_enc.authInSz); + } +#ifdef HAVE_AES_DECRYPT + else { + ret = wc_AesCcmDecrypt(&shadow, info->cipher.aesccm_dec.out, + info->cipher.aesccm_dec.in, info->cipher.aesccm_dec.sz, + info->cipher.aesccm_dec.nonce, + info->cipher.aesccm_dec.nonceSz, + info->cipher.aesccm_dec.authTag, + info->cipher.aesccm_dec.authTagSz, + info->cipher.aesccm_dec.authIn, + info->cipher.aesccm_dec.authInSz); + } +#else + else { + ret = CRYPTOCB_UNAVAILABLE; + } +#endif + + wc_AesFree(&shadow); + return ret; +} +#endif /* HAVE_AESCCM */ +#endif /* !NO_AES */ + +WC_SWDEV_EXPORT int wc_SwDev_Callback(int devId, wc_CryptoInfo* info, + void* ctx) +{ + int ret; + + (void)devId; + (void)ctx; + + if (info == NULL) + return BAD_FUNC_ARG; + + ret = swdev_ensure_init(); + if (ret != 0) + return ret; + + switch (info->algo_type) { +#if !defined(NO_RSA) || defined(HAVE_ECC) + case WC_ALGO_TYPE_PK: + switch (info->pk.type) { + #ifndef NO_RSA + case WC_PK_TYPE_RSA: + return swdev_rsa(info); + #ifdef WOLFSSL_KEY_GEN + case WC_PK_TYPE_RSA_KEYGEN: + return swdev_rsa_keygen(info); + #endif + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case WC_PK_TYPE_EC_KEYGEN: + return swdev_ecc_keygen(info); + case WC_PK_TYPE_ECDH: + return swdev_ecdh(info); + case WC_PK_TYPE_ECDSA_SIGN: + return swdev_ecc_sign(info); + case WC_PK_TYPE_ECDSA_VERIFY: + return swdev_ecc_verify(info); + case WC_PK_TYPE_EC_GET_SIZE: + return swdev_ecc_get_size(info); + case WC_PK_TYPE_EC_GET_SIG_SIZE: + return swdev_ecc_get_sig_size(info); + #endif /* HAVE_ECC */ + default: + return CRYPTOCB_UNAVAILABLE; + } +#endif +#ifndef NO_SHA256 + case WC_ALGO_TYPE_HASH: + switch (info->hash.type) { + case WC_HASH_TYPE_SHA256: + return swdev_sha256(info); + default: + return CRYPTOCB_UNAVAILABLE; + } +#endif +#ifndef NO_AES + case WC_ALGO_TYPE_CIPHER: + switch (info->cipher.type) { + #ifdef HAVE_AES_CBC + case WC_CIPHER_AES_CBC: + return swdev_aes_cbc(info); + #endif + #ifdef WOLFSSL_AES_COUNTER + case WC_CIPHER_AES_CTR: + return swdev_aes_ctr(info); + #endif + #if defined(HAVE_AES_ECB) || defined(WOLFSSL_AES_DIRECT) + case WC_CIPHER_AES_ECB: + return swdev_aes_ecb(info); + #endif + #ifdef HAVE_AESGCM + case WC_CIPHER_AES_GCM: + return swdev_aes_gcm(info); + #endif + #ifdef HAVE_AESCCM + case WC_CIPHER_AES_CCM: + return swdev_aes_ccm(info); + #endif + default: + return CRYPTOCB_UNAVAILABLE; + } +#endif /* !NO_AES */ + default: + return CRYPTOCB_UNAVAILABLE; + } +} diff --git a/tests/swdev/swdev.h b/tests/swdev/swdev.h new file mode 100644 index 00000000000..7003fcacaf2 --- /dev/null +++ b/tests/swdev/swdev.h @@ -0,0 +1,27 @@ +/* tests/swdev/swdev.h -- sole exported interface. */ + +#ifndef WC_SWDEV_H +#define WC_SWDEV_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define WC_SWDEV_ID 0x77736465 /* 'w' 's' 'd' 'e' */ + +#if defined(__GNUC__) || defined(__clang__) +#define WC_SWDEV_EXPORT __attribute__((visibility("default"))) +#else +#define WC_SWDEV_EXPORT +#endif + +WC_SWDEV_EXPORT int wc_SwDev_Callback(int devId, wc_CryptoInfo* info, + void* ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* WC_SWDEV_H */ diff --git a/tests/swdev/swdev_loader.c b/tests/swdev/swdev_loader.c new file mode 100644 index 00000000000..a1af81db068 --- /dev/null +++ b/tests/swdev/swdev_loader.c @@ -0,0 +1,57 @@ +/* tests/swdev/swdev_loader.c -- main-side loader for wc_swdev. */ + +#include "swdev_loader.h" + +#include + +#ifndef WOLF_CRYPTO_CB +#error "wc_swdev loader requires WOLF_CRYPTO_CB" +#endif + +/* resolved at link time from swdev.o */ +extern int wc_SwDev_Callback(int devId, wc_CryptoInfo* info, void* ctx); + +static int swdev_registered = 0; + +int wc_SwDev_Init(void) +{ + int ret; + + /* always re-register: cryptocb table is wiped by wolfCrypt_Cleanup */ + ret = wc_CryptoCb_RegisterDevice(WC_SWDEV_ID, wc_SwDev_Callback, NULL); + if (ret != 0) + return ret; + +#ifdef WOLF_CRYPTO_CB_FIND + wc_CryptoCb_SetDeviceFindCb(wc_SwDev_FindCb); +#endif + + swdev_registered = 1; + return 0; +} + +void wc_SwDev_Cleanup(void) +{ + if (!swdev_registered) + return; + +#ifdef WOLF_CRYPTO_CB_FIND + wc_CryptoCb_SetDeviceFindCb(NULL); +#endif + + wc_CryptoCb_UnRegisterDevice(WC_SWDEV_ID); + swdev_registered = 0; +} + +#ifdef WOLF_CRYPTO_CB_FIND +int wc_SwDev_FindCb(int currentId, int algoType) +{ + (void)algoType; + + /* only redirect ops with no bound device; let others pass through */ + if (currentId == INVALID_DEVID) + return WC_SWDEV_ID; + + return currentId; +} +#endif diff --git a/tests/swdev/swdev_loader.h b/tests/swdev/swdev_loader.h new file mode 100644 index 00000000000..49c9c49e2fd --- /dev/null +++ b/tests/swdev/swdev_loader.h @@ -0,0 +1,29 @@ +/* tests/swdev/swdev_loader.h -- test harness interface to register wc_swdev. */ + +#ifndef WC_SWDEV_LOADER_H +#define WC_SWDEV_LOADER_H + +#if !defined(WOLFSSL_USER_SETTINGS) && !defined(WOLFSSL_NO_OPTIONS_H) + #include +#endif +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define WC_SWDEV_ID 0x77736465 /* 'w' 's' 'd' 'e' */ + +int wc_SwDev_Init(void); +void wc_SwDev_Cleanup(void); + +#ifdef WOLF_CRYPTO_CB_FIND +int wc_SwDev_FindCb(int currentId, int algoType); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* WC_SWDEV_LOADER_H */ diff --git a/tests/swdev/user_settings.h b/tests/swdev/user_settings.h new file mode 100644 index 00000000000..e6a55019ec5 --- /dev/null +++ b/tests/swdev/user_settings.h @@ -0,0 +1,25 @@ +/* tests/swdev/user_settings.h -- settings for wc_swdev. + * + * The swdev software backend must stay ABI-identical to the main library: + * every wolfCrypt struct that crosses the cryptocb boundary (wc_Sha256, + * Aes, RsaKey, ecc_key, ...) is allocated by one compilation and used by + * the other. The only macros that may differ between the two compilations + * are the WOLF_CRYPTO_CB_ONLY_* gates below -- those strip the software + * implementations from the main library so every operation routes through + * the crypto callback; swdev needs the software paths intact. Every other + * setting is inherited from wolfssl/options.h so layouts stay in sync. */ +#ifndef WC_SWDEV_USER_SETTINGS_H +#define WC_SWDEV_USER_SETTINGS_H + +#include + +#undef WOLF_CRYPTO_CB_ONLY_RSA +#undef WOLF_CRYPTO_CB_ONLY_ECC +#undef WOLF_CRYPTO_CB_ONLY_SHA256 +#undef WOLF_CRYPTO_CB_ONLY_AES + +#ifndef WOLF_CRYPTO_CB + #error "wc_swdev requires the main build to define WOLF_CRYPTO_CB" +#endif + +#endif /* WC_SWDEV_USER_SETTINGS_H */ diff --git a/tests/unit.c b/tests/unit.c index 058ba6cd70f..495d8debf6d 100644 --- a/tests/unit.c +++ b/tests/unit.c @@ -34,6 +34,10 @@ #include "wolfcrypt/test/test.h" #endif +#ifdef WOLFSSL_SWDEV +#include "swdev/swdev_loader.h" +#endif + int allTesting = 1; int apiTesting = 1; int myoptind = 0; @@ -260,6 +264,13 @@ int unit_test(int argc, char** argv) goto exit; } + #ifdef WOLFSSL_SWDEV + if ((ret = wc_SwDev_Init()) != 0) { + fprintf(stderr, "wc_SwDev_Init failed: %d\n", (int)ret); + goto exit; + } + #endif + XMEMSET(&wc_args, 0, sizeof(wc_args)); wolfcrypt_test(&wc_args); if (wc_args.return_code != 0) { @@ -267,6 +278,10 @@ int unit_test(int argc, char** argv) goto exit; } + #ifdef WOLFSSL_SWDEV + wc_SwDev_Cleanup(); + #endif + if ((ret = wolfCrypt_Cleanup()) != 0) { fprintf(stderr, "wolfCrypt_Cleanup failed: %d\n", (int)ret); goto exit; @@ -319,10 +334,26 @@ int unit_test(int argc, char** argv) !defined(NO_TLS) && \ !defined(SINGLE_THREADED) && \ defined(WOLFSSL_PEM_TO_DER) + #ifdef WOLFSSL_SWDEV + if (wolfCrypt_Init() != 0) { + fprintf(stderr, "wolfCrypt_Init before SuiteTest failed\n"); + ret = 1; + goto exit; + } + if (wc_SwDev_Init() != 0) { + fprintf(stderr, "wc_SwDev_Init before SuiteTest failed\n"); + ret = 1; + goto exit; + } + #endif if ((ret = SuiteTest(argc, argv)) != 0) { fprintf(stderr, "suite test failed with %d\n", ret); goto exit; } + #ifdef WOLFSSL_SWDEV + wc_SwDev_Cleanup(); + wolfCrypt_Cleanup(); + #endif #endif exit: diff --git a/testsuite/include.am b/testsuite/include.am index 5c750e6a3fa..97fe77ccdae 100644 --- a/testsuite/include.am +++ b/testsuite/include.am @@ -17,6 +17,11 @@ testsuite_testsuite_test_SOURCES = \ testsuite_testsuite_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) $(WOLFSENTRY_INCLUDE) testsuite_testsuite_test_LDADD = src/libwolfssl@LIBSUFFIX@.la $(LIB_STATIC_ADD) $(WOLFSENTRY_LIB) testsuite_testsuite_test_DEPENDENCIES = src/libwolfssl@LIBSUFFIX@.la +if BUILD_SWDEV +testsuite_testsuite_test_SOURCES += tests/swdev/swdev_loader.c +testsuite_testsuite_test_LDADD += $(top_builddir)/tests/swdev/build/swdev.o $(LIBM) +testsuite_testsuite_test_DEPENDENCIES += $(top_builddir)/tests/swdev/build/swdev.o +endif endif EXTRA_DIST += testsuite/testsuite.sln EXTRA_DIST += testsuite/testsuite.vcproj diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index 0b48adbd177..9dda0e51d4d 100644 --- a/testsuite/testsuite.c +++ b/testsuite/testsuite.c @@ -47,6 +47,10 @@ #include #include +#ifdef WOLFSSL_SWDEV + #include "../tests/swdev/swdev_loader.h" +#endif + #include #include #include @@ -125,7 +129,8 @@ int testsuite_test(int argc, char** argv) { #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) && \ !defined(NO_TLS) && \ - (!defined(WOLF_CRYPTO_CB_ONLY_RSA) && !defined(WOLF_CRYPTO_CB_ONLY_ECC)) + (defined(WOLFSSL_SWDEV) || \ + (!defined(WOLF_CRYPTO_CB_ONLY_RSA) && !defined(WOLF_CRYPTO_CB_ONLY_ECC))) func_args server_args; tcp_ready ready; @@ -191,6 +196,13 @@ int testsuite_test(int argc, char** argv) server_args.signal = &ready; InitTcpReady(&ready); +#ifdef WOLFSSL_SWDEV + if (wc_SwDev_Init() != 0) { + printf("wc_SwDev_Init failed\n"); + return EXIT_FAILURE; + } +#endif + #ifndef NO_CRYPT_TEST /* wc_ test */ #ifdef HAVE_STACK_SIZE @@ -275,6 +287,10 @@ int testsuite_test(int argc, char** argv) return EXIT_FAILURE; #endif +#ifdef WOLFSSL_SWDEV + wc_SwDev_Cleanup(); +#endif + wolfSSL_Cleanup(); FreeTcpReady(&ready); @@ -600,7 +616,8 @@ static int test_ocsp_responder(void) #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) && \ !defined(NO_TLS) && \ - (!defined(WOLF_CRYPTO_CB_ONLY_RSA) && !defined(WOLF_CRYPTO_CB_ONLY_ECC)) + (defined(WOLFSSL_SWDEV) || \ + (!defined(WOLF_CRYPTO_CB_ONLY_RSA) && !defined(WOLF_CRYPTO_CB_ONLY_ECC))) /* Perform a basic TLS handshake. * * First connection to echo a file. @@ -856,8 +873,17 @@ int main(int argc, char** argv) wolfSSL_Init(); ChangeToWolfRoot(); +#ifdef WOLFSSL_SWDEV + if (wc_SwDev_Init() != 0) { + printf("wc_SwDev_Init failed\n"); + return EXIT_FAILURE; + } +#endif /* No TLS - only doing cryptographic algorithm testing. */ wolfcrypt_test(&wolfcrypt_test_args); +#ifdef WOLFSSL_SWDEV + wc_SwDev_Cleanup(); +#endif if (wolfcrypt_test_args.return_code != 0) return wolfcrypt_test_args.return_code; diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index c2c982203fe..ff3e9d103cc 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -1257,6 +1257,9 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, } #endif +#elif defined(WOLF_CRYPTO_CB_ONLY_AES) + /* No software implementation AES T-tables, S-box, Rcon and the C key + * schedule are stripped. */ #else /* using wolfCrypt software implementation */ @@ -4108,6 +4111,51 @@ WC_ALL_ARGS_NOT_NULL static WARN_UNUSED_RESULT int wc_AesDecrypt( #endif /* NEED_AES_TABLES */ +#ifdef WOLF_CRYPTO_CB_ONLY_AES +/* Under WOLF_CRYPTO_CB_ONLY_AES the per-block primitive is a thin shim over + * the cryptocb ECB callback. When the callback returns CRYPTOCB_UNAVAILABLE + * there is no software fallback, so the operation fails with NO_VALID_DEVID. */ +static WARN_UNUSED_RESULT int wc_AesEncrypt(Aes* aes, const byte* inBlock, + byte* outBlock) +{ + int ret; + + if (aes == NULL || inBlock == NULL || outBlock == NULL) + return BAD_FUNC_ARG; +#ifdef WC_DEBUG_CIPHER_LIFECYCLE + ret = wc_debug_CipherLifecycleCheck(aes->CipherLifecycleTag, 0); + if (ret < 0) + return ret; +#endif + + ret = wc_CryptoCb_AesEcbEncrypt(aes, outBlock, inBlock, WC_AES_BLOCK_SIZE); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + return NO_VALID_DEVID; +} + +#ifdef HAVE_AES_DECRYPT +static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, + byte* outBlock) +{ + int ret; + + if (aes == NULL || inBlock == NULL || outBlock == NULL) + return BAD_FUNC_ARG; +#ifdef WC_DEBUG_CIPHER_LIFECYCLE + ret = wc_debug_CipherLifecycleCheck(aes->CipherLifecycleTag, 0); + if (ret < 0) + return ret; +#endif + + ret = wc_CryptoCb_AesEcbDecrypt(aes, outBlock, inBlock, WC_AES_BLOCK_SIZE); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + return NO_VALID_DEVID; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* WOLF_CRYPTO_CB_ONLY_AES */ + #ifndef WC_AES_HAVE_PREFETCH_ARG #ifndef AesEncrypt_preFetchOpt #define AesEncrypt_preFetchOpt(aes, inBlock, outBlock, do_preFetch) \ @@ -5002,7 +5050,10 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) } #ifdef WOLF_CRYPTO_CB - if (aes->devId != INVALID_DEVID) { + #ifndef WOLF_CRYPTO_CB_FIND + if (aes->devId != INVALID_DEVID) + #endif + { #ifdef WOLF_CRYPTO_CB_AES_SETKEY ret = wc_CryptoCb_AesSetKey(aes, userKey, keylen); if (ret == 0) { @@ -5104,8 +5155,10 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))) || \ (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)) #ifdef WOLF_CRYPTO_CB + #ifndef WOLF_CRYPTO_CB_FIND if (aes->devId != INVALID_DEVID) #endif + #endif { if (keylen > sizeof(aes->devKey)) { return BAD_FUNC_ARG; @@ -5114,6 +5167,22 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) } #endif + #ifdef WOLF_CRYPTO_CB_ONLY_AES + /* No software AES schedule under CB_ONLY: aes->key[] (round keys) are + * unused because the static wc_AesEncrypt/wc_AesDecrypt are cryptocb- + * ECB shims. aes->rounds is still populated because wc_AesGetKeySize() + * reads it as the source of truth for the configured key size. */ + aes->keylen = (int)keylen; + aes->rounds = (keylen / 4) + 6; + #if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \ + defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \ + defined(WOLFSSL_AES_CTS) + aes->left = 0; + #endif + (void)dir; + return wc_AesSetIV(aes, iv); + #endif + #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE < 256 if (checkKeyLen) { /* Check key length only when AES_MAX_KEY_SIZE doesn't allow @@ -7693,6 +7762,11 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) #endif XMEMSET(iv, 0, WC_AES_BLOCK_SIZE); ret = wc_AesSetKey(aes, key, len, iv, AES_ENCRYPTION); +#ifdef WOLF_CRYPTO_CB_ONLY_AES + /* Device handles GCM end-to-end; GHASH H / M0 setup below is dead state + * under CB_ONLY (no host-side software path consumes aes->gcm.H or M0). */ + return ret; +#endif #ifdef WOLFSSL_AESGCM_STREAM aes->gcmKeySet = 1; #endif @@ -14047,6 +14121,11 @@ static WARN_UNUSED_RESULT int _AesEcbEncrypt( /* fall-through when unavailable */ } #endif +#ifdef WOLF_CRYPTO_CB_ONLY_AES + /* No software fallback: the per-block loop below would only re-invoke + * cryptocb ECB and propagate UNAVAILABLE; short-circuit instead. */ + return NO_VALID_DEVID; +#endif #ifdef WOLFSSL_IMXRT_DCP if (aes->keylen == 16) return DCPAesEcbEncrypt(aes, out, in, sz); @@ -14136,6 +14215,9 @@ static WARN_UNUSED_RESULT int _AesEcbDecrypt( /* fall-through when unavailable */ } #endif +#ifdef WOLF_CRYPTO_CB_ONLY_AES + return NO_VALID_DEVID; +#endif #ifdef WOLFSSL_IMXRT_DCP if (aes->keylen == 16) return DCPAesEcbDecrypt(aes, out, in, sz); diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index dcdb5bf7b01..e92b0278b75 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -52,6 +52,8 @@ Crypto Callback Build Options: * and SHA-512 operations. * WOLF_CRYPTO_CB_ONLY_ECC: Use only callbacks for ECC default: off * WOLF_CRYPTO_CB_ONLY_RSA: Use only callbacks for RSA default: off + * WOLF_CRYPTO_CB_ONLY_SHA256: Use only callbacks for SHA-256 default: off + * WOLF_CRYPTO_CB_ONLY_AES: Use only callbacks for AES default: off */ #include @@ -1575,7 +1577,8 @@ int wc_CryptoCb_AesCtrEncrypt(Aes* aes, byte* out, return wc_CryptoCb_TranslateErrorCode(ret); } #endif /* WOLFSSL_AES_COUNTER */ -#ifdef HAVE_AES_ECB +#if defined(HAVE_AES_ECB) || defined(WOLFSSL_AES_DIRECT) || \ + defined(WOLF_CRYPTO_CB_ONLY_AES) int wc_CryptoCb_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { @@ -1639,7 +1642,7 @@ int wc_CryptoCb_AesEcbDecrypt(Aes* aes, byte* out, return wc_CryptoCb_TranslateErrorCode(ret); } -#endif /* HAVE_AES_ECB */ +#endif /* HAVE_AES_ECB || WOLFSSL_AES_DIRECT || WOLF_CRYPTO_CB_ONLY_AES */ #ifdef WOLF_CRYPTO_CB_AES_SETKEY int wc_CryptoCb_AesSetKey(Aes* aes, const byte* key, word32 keySz) diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 78240b21cfb..ca1491a4113 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -60,6 +60,10 @@ on the specific device platform. #if !defined(NO_SHA256) && !defined(WOLFSSL_RISCV_ASM) +#if defined(WOLF_CRYPTO_CB_ONLY_SHA256) && defined(WOLFSSL_SHA224) + #error "WOLF_CRYPTO_CB_ONLY_SHA256 is incompatible with WOLFSSL_SHA224" +#endif + #if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ #define FIPS_NO_WRAPPERS @@ -290,7 +294,8 @@ static int InitSha256(wc_Sha256* sha256) /* Hardware Acceleration */ #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ - (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) + (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) && \ + !defined(WOLF_CRYPTO_CB_ONLY_SHA256) /* in case intel instructions aren't available, plus we need the K[] global */ #define NEED_SOFT_SHA256 @@ -1080,7 +1085,7 @@ static int InitSha256(wc_Sha256* sha256) #elif defined(WOLFSSL_RENESAS_RX64_HASH) /* implemented in wolfcrypt/src/port/Renesas/renesas_rx64_hw_sha.c */ -#elif defined(WOLFSSL_PPC32_ASM) +#elif defined(WOLFSSL_PPC32_ASM) && !defined(WOLF_CRYPTO_CB_ONLY_SHA256) extern void Transform_Sha256_Len(wc_Sha256* sha256, const byte* data, word32 len); @@ -1110,7 +1115,7 @@ static int Transform_Sha256(wc_Sha256* sha256, const byte* data) #define XTRANSFORM Transform_Sha256 #define XTRANSFORM_LEN Transform_Sha256_Len -#elif defined(WOLFSSL_ARMASM) +#elif defined(WOLFSSL_ARMASM) && !defined(WOLF_CRYPTO_CB_ONLY_SHA256) int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) { @@ -1165,6 +1170,21 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data, #define XTRANSFORM Transform_Sha256 #define XTRANSFORM_LEN Transform_Sha256_Len +#elif defined(WOLF_CRYPTO_CB_ONLY_SHA256) + /* Software SHA-256 stripped; every op dispatches via cryptocb. */ + int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) + { + int ret; + if (sha256 == NULL) + return BAD_FUNC_ARG; + ret = InitSha256(sha256); + if (ret != 0) + return ret; + sha256->heap = heap; + sha256->devId = devId; + sha256->devCtx = NULL; + return ret; + } #else #define NEED_SOFT_SHA256 @@ -1397,7 +1417,6 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data, #endif /* End wc_ software implementation */ - #ifdef XTRANSFORM static WC_INLINE void AddLength(wc_Sha256* sha256, word32 len) @@ -1774,6 +1793,7 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data, #if !defined(WOLFSSL_KCAPI_HASH) +#ifndef WOLFSSL_NO_HASH_RAW int wc_Sha256FinalRaw(wc_Sha256* sha256, byte* hash) { #ifdef LITTLE_ENDIAN_ORDER @@ -1797,6 +1817,7 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data, return 0; } +#endif /* !WOLFSSL_NO_HASH_RAW */ int wc_Sha256Final(wc_Sha256* sha256, byte* hash) { @@ -1960,6 +1981,55 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data, #endif /* XTRANSFORM */ +#ifdef WOLF_CRYPTO_CB_ONLY_SHA256 + + int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) + { + if (sha256 == NULL) { + return BAD_FUNC_ARG; + } + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } + if (data == NULL) { + return BAD_FUNC_ARG; + } + + #ifndef WOLF_CRYPTO_CB_FIND + if (sha256->devId != INVALID_DEVID) + #endif + { + int ret = wc_CryptoCb_Sha256Hash(sha256, data, len, NULL); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + } + + return NO_VALID_DEVID; + } + + int wc_Sha256Final(wc_Sha256* sha256, byte* hash) + { + int ret; + + if (sha256 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + #ifndef WOLF_CRYPTO_CB_FIND + if (sha256->devId != INVALID_DEVID) + #endif + { + ret = wc_CryptoCb_Sha256Hash(sha256, NULL, 0, hash); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + } + + return NO_VALID_DEVID; + } + +#endif /* WOLF_CRYPTO_CB_ONLY_SHA256 */ + #ifdef WOLFSSL_SHA224 diff --git a/wolfcrypt/test/include.am b/wolfcrypt/test/include.am index 8f13876a215..e647b979742 100644 --- a/wolfcrypt/test/include.am +++ b/wolfcrypt/test/include.am @@ -12,10 +12,57 @@ noinst_PROGRAMS+= wolfcrypt/test/testwolfcrypt wolfcrypt_test_testwolfcrypt_SOURCES = wolfcrypt/test/test.c wolfcrypt_test_testwolfcrypt_LDADD = src/libwolfssl@LIBSUFFIX@.la $(LIB_STATIC_ADD) wolfcrypt_test_testwolfcrypt_DEPENDENCIES = src/libwolfssl@LIBSUFFIX@.la +if BUILD_SWDEV +wolfcrypt_test_testwolfcrypt_SOURCES += tests/swdev/swdev_loader.c +wolfcrypt_test_testwolfcrypt_LDADD += $(top_builddir)/tests/swdev/build/swdev.o $(LIBM) +wolfcrypt_test_testwolfcrypt_DEPENDENCIES += $(top_builddir)/tests/swdev/build/swdev.o +endif noinst_HEADERS += wolfcrypt/test/test.h wolfcrypt/test/test_paths.h.in endif endif +if BUILD_SWDEV +# delegates to tests/swdev/Makefile +$(top_builddir)/tests/swdev/build/swdev.o: $(top_builddir)/wolfssl/options.h FORCE + @test "$(abs_top_srcdir)" = "$(abs_top_builddir)" || { \ + echo "error: --enable-swdev currently supports in-tree builds only"; \ + exit 1; \ + } + $(MAKE) -C $(top_srcdir)/tests/swdev \ + SRCDIR=$(abs_top_srcdir)/tests/swdev \ + WOLFROOT=$(abs_top_srcdir) \ + $(if $(CC),CC='$(CC)') \ + $(if $(CCAS),CCAS='$(CCAS)') \ + $(if $(LD),LD='$(LD)') \ + $(if $(OBJCOPY),OBJCOPY='$(OBJCOPY)') \ + PARENT_SRCS='$(filter wolfcrypt/src/%.c src/%.c,$(src_libwolfssl_la_SOURCES))' \ + PARENT_ASM_SRCS='$(filter %.S,$(src_libwolfssl_la_SOURCES))' \ + PARENT_CPPFLAGS='$(CPPFLAGS) $(filter-out -DBUILDING_WOLFSSL,$(DEFS))' \ + PARENT_BUILD_CFLAGS='$(filter-out -include ./.build_params -DBUILDING_WOLFSSL,$(AM_CFLAGS))' \ + PARENT_CFLAGS='$(CFLAGS)' \ + PARENT_BUILD_CCASFLAGS='$(filter-out -DBUILDING_WOLFSSL,$(AM_CCASFLAGS))' \ + PARENT_CCASFLAGS='$(CCASFLAGS)' \ + BUILDDIR=$(abs_top_builddir)/tests/swdev/build + +FORCE: + +EXTRA_DIST += tests/swdev/swdev.c \ + tests/swdev/swdev.h \ + tests/swdev/swdev_loader.c \ + tests/swdev/swdev_loader.h \ + tests/swdev/user_settings.h \ + tests/swdev/Makefile + +CLEANFILES += $(top_builddir)/tests/swdev/build/swdev.o \ + $(top_builddir)/tests/swdev/build/swdev.partial.o + +# Use mostlyclean-local rather than clean-local to avoid colliding with +# doc/include.am's clean-local (automake allows only one definition per +# Makefile). make clean triggers mostlyclean, so coverage is equivalent. +mostlyclean-local: + rm -rf $(top_builddir)/tests/swdev/build +endif + if BUILD_WOLFCRYPT_TESTS_LIBS lib_LTLIBRARIES += wolfcrypt/test/libwolfcrypttest.la wolfcrypt_test_libwolfcrypttest_la_SOURCES = wolfcrypt/test/test.c diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index b016204f7a4..57ae6c0bcd8 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -64,6 +64,10 @@ #undef err_sys #endif +#ifdef WOLFSSL_SWDEV + #include "../../tests/swdev/swdev_loader.h" +#endif + #if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_PUBLIC_MP) && \ defined(HAVE_ECC_SIGN) && defined(HAVE_ECC_VERIFY) && \ !defined(NO_STDINT_H) @@ -944,7 +948,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t scrypt_test(void); #if defined(USE_CERT_BUFFERS_256) && !defined(WOLFSSL_ATECC508A) && \ !defined(WOLFSSL_ATECC608A) && !defined(NO_ECC256) && \ defined(HAVE_ECC_VERIFY) && defined(HAVE_ECC_SIGN) && \ - !defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(NO_ECC_SECP) && \ + (!defined(WOLF_CRYPTO_CB_ONLY_ECC) || defined(WOLFSSL_SWDEV)) && !defined(NO_ECC_SECP) && \ !defined(WOLFSSL_SE050) /* skip for ATECC508/608A (cannot import private key buffers) and * SE050 (test vector uses a digest size SE050 does not accept) */ @@ -3046,7 +3050,8 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ else TEST_PASS("OPENSSL (PKEY1) passed!\n"); - #if !defined(WOLF_CRYPTO_CB_ONLY_RSA) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) + #if (!defined(WOLF_CRYPTO_CB_ONLY_RSA) || defined(WOLFSSL_SWDEV)) && \ + (!defined(WOLF_CRYPTO_CB_ONLY_ECC) || defined(WOLFSSL_SWDEV)) if ( (ret = openssl_evpSig_test()) != 0) TEST_FAIL("OPENSSL (EVP Sign/Verify) test failed!\n", ret); else @@ -3071,7 +3076,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #if defined(USE_CERT_BUFFERS_256) && !defined(WOLFSSL_ATECC508A) && \ !defined(WOLFSSL_ATECC608A) && !defined(NO_ECC256) && \ defined(HAVE_ECC_VERIFY) && defined(HAVE_ECC_SIGN) && \ - !defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(NO_ECC_SECP) && \ + (!defined(WOLF_CRYPTO_CB_ONLY_ECC) || defined(WOLFSSL_SWDEV)) && !defined(NO_ECC_SECP) && \ !defined(WOLFSSL_SE050) /* skip for ATECC508/608A (cannot import private key buffers) and * SE050 (test vector uses a digest size SE050 does not accept) */ @@ -3512,6 +3517,14 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ err_sys("Error with wolfCrypt_Init!\n", args.return_code); } +#ifdef WOLFSSL_SWDEV + if ((ret = wc_SwDev_Init()) != 0) { + printf("wc_SwDev_Init failed %d\n", (int)ret); + args.return_code = WC_TEST_RET_ENC_EC(ret); + err_sys("Error with wc_SwDev_Init!\n", args.return_code); + } +#endif + #ifdef HAVE_WC_INTROSPECTION printf("Math: %s\n", wc_GetMathInfo()); #endif @@ -3524,6 +3537,10 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #endif } +#ifdef WOLFSSL_SWDEV + wc_SwDev_Cleanup(); +#endif + if ((ret = wolfCrypt_Cleanup()) != 0) { printf("wolfCrypt_Cleanup failed %d\n", (int)ret); args.return_code = WC_TEST_RET_ENC_EC(ret); @@ -5648,7 +5665,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t sha256_test(void) #undef LARGE_HASH_TEST_INPUT_SZ #endif /* NO_LARGE_HASH_TEST */ -#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_FULL_HASH) +#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_FULL_HASH) && \ + !defined(WOLF_CRYPTO_CB_ONLY_SHA256) { WOLFSSL_SMALL_STACK_STATIC const unsigned char data_hb[WC_SHA256_BLOCK_SIZE] = { @@ -22965,12 +22983,13 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t memory_test(void) #endif #endif #if defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) && \ - !defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(NO_ASN_CRYPT) + (!defined(WOLF_CRYPTO_CB_ONLY_ECC) || defined(WOLFSSL_SWDEV)) && \ + !defined(NO_ASN_CRYPT) static const char* eccCaKeyPemFile = CERT_WRITE_TEMP_DIR "ecc-key.pem"; static const char* eccPubKeyDerFile = CERT_WRITE_TEMP_DIR "ecc-public-key.der"; static const char* eccCaKeyTempFile = CERT_WRITE_TEMP_DIR "ecc-key.der"; #if defined(HAVE_PKCS8) && !defined(WC_NO_RNG) && \ - !defined(WOLF_CRYPTO_CB_ONLY_ECC) + (!defined(WOLF_CRYPTO_CB_ONLY_ECC) || defined(WOLFSSL_SWDEV)) static const char* eccPkcs8KeyDerFile = CERT_WRITE_TEMP_DIR "ecc-key-pkcs8.der"; #endif #endif /* HAVE_ECC_KEY_EXPORT */ @@ -24047,7 +24066,7 @@ static wc_test_ret_t rsa_sig_test(RsaKey* key, word32 keyLen, int modLen, WC_RNG if (ret != 0) #elif defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) /* async may not require RNG */ - #if defined(WOLF_CRYPTO_CB_ONLY_RSA) + #if defined(WOLF_CRYPTO_CB_ONLY_RSA) && !defined(WOLFSSL_SWDEV) if (ret != WC_NO_ERR_TRACE(NO_VALID_DEVID)) #else if (ret != 0 && ret != WC_NO_ERR_TRACE(MISSING_RNG_E)) @@ -24100,7 +24119,7 @@ static wc_test_ret_t rsa_sig_test(RsaKey* key, word32 keyLen, int modLen, WC_RNG if (ret != WC_NO_ERR_TRACE(SIG_TYPE_E)) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_rsa_sig); #endif -#if defined(WOLF_CRYPTO_CB_ONLY_RSA) +#if defined(WOLF_CRYPTO_CB_ONLY_RSA) && !defined(WOLFSSL_SWDEV) ret = 0; goto exit_rsa_sig; #endif @@ -24583,7 +24602,7 @@ static wc_test_ret_t rsa_decode_test(RsaKey* keyPub) !defined(WC_NO_RNG) /* Need to create known good signatures to test with this. */ #if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \ -!defined(WOLF_CRYPTO_CB_ONLY_RSA) +(!defined(WOLF_CRYPTO_CB_ONLY_RSA) || defined(WOLFSSL_SWDEV)) static wc_test_ret_t rsa_pss_test(WC_RNG* rng, RsaKey* key) { byte digest[WC_MAX_DIGEST_SIZE]; @@ -25965,7 +25984,7 @@ static wc_test_ret_t rsa_keygen_test(WC_RNG* rng) int keySz = 2048; #endif -#ifdef WOLF_CRYPTO_CB_ONLY_RSA +#if defined(WOLF_CRYPTO_CB_ONLY_RSA) && !defined(WOLFSSL_SWDEV) if (devId == INVALID_DEVID) { /* must call keygen with devId */ return 0; @@ -26068,7 +26087,7 @@ static wc_test_ret_t rsa_keygen_test(WC_RNG* rng) #if !defined(WC_NO_RSA_OAEP) && !defined(WC_NO_RNG) && \ (!defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) \ - && !defined(WOLF_CRYPTO_CB_ONLY_RSA) + && (!defined(WOLF_CRYPTO_CB_ONLY_RSA) || defined(WOLFSSL_SWDEV)) static wc_test_ret_t rsa_oaep_padding_test(RsaKey* key, WC_RNG* rng) { wc_test_ret_t ret = 0; @@ -26605,7 +26624,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rsa_test(void) #endif #if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \ - !defined(WC_NO_RNG) && !defined(WOLF_CRYPTO_CB_ONLY_RSA) + !defined(WC_NO_RNG) && (!defined(WOLF_CRYPTO_CB_ONLY_RSA) || defined(WOLFSSL_SWDEV)) /* Reload the key so the public-encrypt below is the first operation * against it. Exercises backends that distinguish public-only material * from full-keypair bindings: a public-encrypt on a freshly-loaded key @@ -26733,7 +26752,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rsa_test(void) #if !defined(WC_NO_RNG) && !defined(WC_NO_RSA_OAEP) && \ !defined(WOLFSSL_RSA_VERIFY_ONLY) && defined(WOLFSSL_PUBLIC_MP) && \ - !defined(WOLF_CRYPTO_CB_ONLY_RSA) + (!defined(WOLF_CRYPTO_CB_ONLY_RSA) || defined(WOLFSSL_SWDEV)) idx = (word32)ret; XMEMSET(plain, 0, plainSz); do { @@ -26780,7 +26799,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rsa_test(void) #if !defined(WC_NO_RSA_OAEP) && !defined(WC_NO_RNG) #if (!defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) \ - && !defined(WOLF_CRYPTO_CB_ONLY_RSA) + && (!defined(WOLF_CRYPTO_CB_ONLY_RSA) || defined(WOLFSSL_SWDEV)) ret = rsa_oaep_padding_test(key, &rng); if (ret != 0) goto exit_rsa; @@ -27046,7 +27065,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rsa_test(void) !defined(WC_NO_RNG) /* Need to create known good signatures to test with this. */ #if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \ - !defined(WOLF_CRYPTO_CB_ONLY_RSA) + (!defined(WOLF_CRYPTO_CB_ONLY_RSA) || defined(WOLFSSL_SWDEV)) ret = rsa_pss_test(&rng, key); if (ret != 0) goto exit_rsa; @@ -34763,7 +34782,7 @@ typedef struct eccVector { word32 sSz; } eccVector; -#if !defined(WOLF_CRYPTO_CB_ONLY_ECC) +#if !defined(WOLF_CRYPTO_CB_ONLY_ECC) || defined(WOLFSSL_SWDEV) static wc_test_ret_t ecc_test_vector_item(const eccVector* vector) { wc_test_ret_t ret = 0; @@ -36241,7 +36260,7 @@ static wc_test_ret_t ecc_test_make_pub(WC_RNG* rng) } #if defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT) && \ - !defined(WC_NO_RNG) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) + !defined(WC_NO_RNG) && (!defined(WOLF_CRYPTO_CB_ONLY_ECC) || defined(WOLFSSL_SWDEV)) static wc_test_ret_t ecc_test_key_decode(WC_RNG* rng, int keySize) { wc_test_ret_t ret; @@ -36322,7 +36341,7 @@ static wc_test_ret_t ecc_test_key_decode(WC_RNG* rng, int keySize) #endif /* HAVE_ECC_KEY_IMPORT */ #if defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT) && \ - !defined(WC_NO_RNG) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) + !defined(WC_NO_RNG) && (!defined(WOLF_CRYPTO_CB_ONLY_ECC) || defined(WOLFSSL_SWDEV)) static wc_test_ret_t ecc_test_key_gen(WC_RNG* rng, int keySize) { wc_test_ret_t ret = 0; @@ -36917,7 +36936,7 @@ static wc_test_ret_t ecc_test_curve(WC_RNG* rng, int keySize, int curve_id) return ret; } } -#ifndef WOLF_CRYPTO_CB_ONLY_ECC +#if !defined(WOLF_CRYPTO_CB_ONLY_ECC) || defined(WOLFSSL_SWDEV) #if FIPS_VERSION3_GE(6,0,0) skip_A: #endif @@ -37227,7 +37246,7 @@ static wc_test_ret_t ecc_point_test(void) } #endif /* !WOLFSSL_ATECC508A && HAVE_ECC_KEY_IMPORT && HAVE_ECC_KEY_EXPORT */ -#if !defined(NO_SIG_WRAPPER) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) && \ +#if !defined(NO_SIG_WRAPPER) && (!defined(WOLF_CRYPTO_CB_ONLY_ECC) || defined(WOLFSSL_SWDEV)) && \ !defined(NO_ECC_SIGN) static wc_test_ret_t ecc_sig_test(WC_RNG* rng, ecc_key* key) { @@ -37286,7 +37305,7 @@ static wc_test_ret_t ecc_sig_test(WC_RNG* rng, ecc_key* key) #endif #if defined(HAVE_ECC_KEY_IMPORT) && defined(HAVE_ECC_KEY_EXPORT) && \ - !defined(WOLF_CRYPTO_CB_ONLY_ECC) + (!defined(WOLF_CRYPTO_CB_ONLY_ECC) || defined(WOLFSSL_SWDEV)) static wc_test_ret_t ecc_exp_imp_test(ecc_key* key) { @@ -37398,6 +37417,8 @@ static wc_test_ret_t ecc_exp_imp_test(ecc_key* key) } #endif /* HAVE_ECC_KEY_IMPORT && HAVE_ECC_KEY_EXPORT */ +/* wc_ecc_mulmod is a raw math primitive stripped by WOLF_CRYPTO_CB_ONLY_ECC; + * swdev operates at the cryptocb dispatch layer and cannot rescue it. */ #if defined(HAVE_ECC_KEY_IMPORT) && !defined(WOLFSSL_VALIDATE_ECC_IMPORT) && \ !defined(WOLFSSL_CRYPTOCELL) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) static wc_test_ret_t ecc_mulmod_test(ecc_key* key1) @@ -37564,7 +37585,7 @@ static wc_test_ret_t ecc_def_curve_test(WC_RNG *rng) ret = wc_ecc_set_flags(key, 0); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); -#ifndef WOLF_CRYPTO_CB_ONLY_ECC +#if !defined(WOLF_CRYPTO_CB_ONLY_ECC) || defined(WOLFSSL_SWDEV) #ifndef WC_NO_RNG ret = wc_ecc_make_key(rng, ECC_KEYGEN_SIZE, key); #if defined(WOLFSSL_ASYNC_CRYPT) @@ -37633,7 +37654,7 @@ static wc_test_ret_t ecc_def_curve_test(WC_RNG *rng) goto done; #endif #if defined(HAVE_ECC_KEY_IMPORT) && !defined(WOLFSSL_VALIDATE_ECC_IMPORT) && \ - !defined(WOLFSSL_CRYPTOCELL) + !defined(WOLFSSL_CRYPTOCELL) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) ret = ecc_mulmod_test(key); if (ret < 0) goto done; @@ -38805,7 +38826,7 @@ static wc_test_ret_t ecc_test_cert_gen(WC_RNG* rng) #endif /* WOLFSSL_CERT_GEN */ #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ - !defined(WOLFSSL_NO_MALLOC) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) && \ + !defined(WOLFSSL_NO_MALLOC) && (!defined(WOLF_CRYPTO_CB_ONLY_ECC) || defined(WOLFSSL_SWDEV)) && \ (!defined(NO_ECC_SECP) || defined(WOLFSSL_CUSTOM_CURVES)) /* Test for the wc_ecc_key_new() and wc_ecc_key_free() functions. */ static wc_test_ret_t ecc_test_allocator(WC_RNG* rng) @@ -39616,7 +39637,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ecc_test(void) } #endif #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && !defined(WOLFSSL_NO_MALLOC) && \ - !defined(WOLF_CRYPTO_CB_ONLY_ECC) && (!defined(NO_ECC_SECP) || \ + (!defined(WOLF_CRYPTO_CB_ONLY_ECC) || defined(WOLFSSL_SWDEV)) && (!defined(NO_ECC_SECP) || \ defined(WOLFSSL_CUSTOM_CURVES)) ret = ecc_test_allocator(&rng); if (ret != 0) { @@ -40459,7 +40480,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ecc_encrypt_test(void) #if defined(USE_CERT_BUFFERS_256) && !defined(WOLFSSL_ATECC508A) && \ !defined(WOLFSSL_ATECC608A) && !defined(NO_ECC256) && \ defined(HAVE_ECC_VERIFY) && defined(HAVE_ECC_SIGN) && \ - !defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(NO_ECC_SECP) && \ + (!defined(WOLF_CRYPTO_CB_ONLY_ECC) || defined(WOLFSSL_SWDEV)) && !defined(NO_ECC_SECP) && \ !defined(WOLFSSL_SE050) WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ecc_test_buffers(void) { @@ -61736,7 +61757,7 @@ static wc_test_ret_t getFirmwareKey(wc_PKCS7* pkcs7, byte* key, word32 keySz) return MEMORY_E; } - wc_PKCS7_Init(envPkcs7, NULL, 0); + wc_PKCS7_Init(envPkcs7, NULL, INVALID_DEVID); ret = wc_PKCS7_SetWrapCEKCb(envPkcs7, myCEKwrapFunc); if (ret == 0) { /* expecting FIRMWARE_PKG_DATA content */ @@ -67786,7 +67807,8 @@ static wc_test_ret_t ecc_onlycb_test(myCryptoDevCtx *ctx) ecc_key* pub = (ecc_key *)XMALLOC(sizeof(*pub), HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); byte* out = (byte*)XMALLOC(256, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - #if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA) + #if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA) && \ + defined(USE_CERT_BUFFERS_256) byte* check = (byte*)XMALLOC(256, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #endif #else @@ -67797,17 +67819,17 @@ static wc_test_ret_t ecc_onlycb_test(myCryptoDevCtx *ctx) #if defined(HAVE_ECC_SIGN) && defined(HAVE_ECC_VERIFY) byte out[256]; #endif - #if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA) + #if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA) && \ + defined(USE_CERT_BUFFERS_256) byte check[256]; #endif #endif -#if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA) +#if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA) && \ + defined(USE_CERT_BUFFERS_256) WOLFSSL_EVP_PKEY* privKey = NULL; WOLFSSL_EVP_PKEY* pubKey = NULL; - #ifdef USE_CERT_BUFFERS_256 ecc_key* pkey; const unsigned char* cp; - #endif WOLFSSL_EVP_MD_CTX mdCtx; const char testData[] = "Hi There"; size_t checkSz = -1; @@ -67952,7 +67974,8 @@ static wc_test_ret_t ecc_onlycb_test(myCryptoDevCtx *ctx) #endif /* HAVE_ECC_DHE */ -#if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA) +#if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA) && \ + defined(USE_CERT_BUFFERS_256) (void)pkey; cp = ecc_clikey_der_256; privKey = d2i_PrivateKey(WC_EVP_PKEY_EC, NULL, &cp, @@ -68048,7 +68071,7 @@ static wc_test_ret_t ecc_onlycb_test(myCryptoDevCtx *ctx) ERROR_OUT(WC_TEST_RET_ENC_NC, exit_onlycb); } else ret = 0; -#endif /* !WOLFCRYPT_ONLY && OPENSSL_EXTRA */ +#endif /* !WOLFCRYPT_ONLY && OPENSSL_EXTRA && USE_CERT_BUFFERS_256 */ (void)keyFormat; (void)encInfo; @@ -68062,14 +68085,16 @@ static wc_test_ret_t ecc_onlycb_test(myCryptoDevCtx *ctx) } XFREE(pub, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - #if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA) + #if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA) && \ + defined(USE_CERT_BUFFERS_256) if (check) { FREE(check, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } #endif #else wc_ecc_free(key); - #if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA) + #if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA) && \ + defined(USE_CERT_BUFFERS_256) if (privKey) wolfSSL_EVP_PKEY_free(privKey); if (pubKey) @@ -68082,6 +68107,104 @@ static wc_test_ret_t ecc_onlycb_test(myCryptoDevCtx *ctx) } #endif +#ifdef WOLF_CRYPTO_CB_ONLY_SHA256 +/* Exercise SHA-256 dispatch under CB_ONLY_SHA256: cb-handled then cb-delegated. */ +static wc_test_ret_t sha256_onlycb_test(myCryptoDevCtx *ctx) +{ + wc_test_ret_t ret = 0; +#if !defined(NO_SHA256) + wc_Sha256 sha; + byte hash[WC_SHA256_DIGEST_SIZE]; + const byte in[] = "abc"; + + ret = wc_InitSha256_ex(&sha, HEAP_HINT, devId); + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); + + /* cb handles the op, expects 0(success) */ + ctx->exampleVar = 99; + ret = wc_Sha256Update(&sha, in, (word32)sizeof(in) - 1); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_onlycb); + ret = wc_Sha256Final(&sha, hash); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_onlycb); + + /* cb delegates to software, expects NO_VALID_DEVID(failure) */ + ctx->exampleVar = 1; + ret = wc_Sha256Update(&sha, in, (word32)sizeof(in) - 1); + if (ret != WC_NO_ERR_TRACE(NO_VALID_DEVID)) { + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_onlycb); + } else { + ret = 0; + } + ret = wc_Sha256Final(&sha, hash); + if (ret != WC_NO_ERR_TRACE(NO_VALID_DEVID)) { + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_onlycb); + } else { + ret = 0; + } + +exit_onlycb: + wc_Sha256Free(&sha); +#endif /* !NO_SHA256 */ + (void)ctx; + return ret; +} +#endif /* WOLF_CRYPTO_CB_ONLY_SHA256 */ + +#ifdef WOLF_CRYPTO_CB_ONLY_AES +/* Exercise AES dispatch under CB_ONLY_AES: cb-handled then cb-delegated. */ +static wc_test_ret_t aes_onlycb_test(myCryptoDevCtx *ctx) +{ + wc_test_ret_t ret = 0; +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128) + Aes aes; + const byte key[16] = { + 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6, + 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c + }; + const byte iv[WC_AES_BLOCK_SIZE] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f + }; + const byte plain[WC_AES_BLOCK_SIZE] = { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + byte out[WC_AES_BLOCK_SIZE]; + + ret = wc_AesInit(&aes, HEAP_HINT, devId); + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); + + ret = wc_AesSetKey(&aes, key, sizeof(key), iv, AES_ENCRYPTION); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_onlycb); + + /* cb handles the op, expects 0(success) */ + ctx->exampleVar = 99; + ret = wc_AesCbcEncrypt(&aes, out, plain, sizeof(plain)); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_onlycb); + + /* cb delegates to software, expects NO_VALID_DEVID(failure) */ + ctx->exampleVar = 1; + ret = wc_AesCbcEncrypt(&aes, out, plain, sizeof(plain)); + if (ret != WC_NO_ERR_TRACE(NO_VALID_DEVID)) { + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_onlycb); + } else { + ret = 0; + } + +exit_onlycb: + wc_AesFree(&aes); +#endif /* !NO_AES && HAVE_AES_CBC && WOLFSSL_AES_128 */ + (void)ctx; + return ret; +} +#endif /* WOLF_CRYPTO_CB_ONLY_AES */ + /* Example crypto dev callback function that calls software version */ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) { @@ -68520,6 +68643,10 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) #endif /* HAVE_AESGCM */ #ifdef HAVE_AES_CBC if (info->cipher.type == WC_CIPHER_AES_CBC) { + #if defined(WOLF_CRYPTO_CB_ONLY_AES) + if (myCtx->exampleVar == 99) + return 0; + #endif if (info->cipher.enc) { /* set devId to invalid, so software is used */ info->cipher.aescbc.aes->devId = INVALID_DEVID; @@ -68703,6 +68830,15 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) /* set devId to invalid, so software is used */ info->hash.sha256->devId = INVALID_DEVID; + #if defined(WOLF_CRYPTO_CB_ONLY_SHA256) + #ifdef DEBUG_WOLFSSL + printf("CryptoDevCb: exampleVar %d\n", myCtx->exampleVar); + #endif + if (myCtx->exampleVar == 99) { + info->hash.sha256->devId = devIdArg; + return 0; + } + #endif if (info->hash.in != NULL) { ret = wc_Sha256Update( @@ -69801,9 +69937,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) ret = wc_CryptoCb_RegisterDevice(devId, myCryptoDevCb, &myCtx); if (ret != 0) ret = WC_TEST_RET_ENC_EC(ret); -#ifdef WOLF_CRYPTO_CB_FIND + /* don't overwrite find cb when using WOLFSSL_SWDEV */ +#if defined(WOLF_CRYPTO_CB_FIND) && !defined(WOLFSSL_SWDEV) wc_CryptoCb_SetDeviceFindCb(myCryptoCbFind); -#endif /* WOLF_CRYPTO_CB_FIND */ +#endif #ifndef WC_NO_RNG if (ret == 0) ret = random_test(); @@ -69814,7 +69951,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) ret = rsa_test(); PRIVATE_KEY_LOCK(); #endif -#if defined(WOLF_CRYPTO_CB_ONLY_RSA) +#if defined(WOLF_CRYPTO_CB_ONLY_RSA) && !defined(WOLFSSL_SWDEV) PRIVATE_KEY_UNLOCK(); if (ret == 0) ret = rsa_onlycb_test(&myCtx); @@ -69826,12 +69963,24 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) ret = ecc_test(); PRIVATE_KEY_LOCK(); #endif -#if defined(WOLF_CRYPTO_CB_ONLY_ECC) +#if defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLFSSL_SWDEV) PRIVATE_KEY_UNLOCK(); if (ret == 0) ret = ecc_onlycb_test(&myCtx); PRIVATE_KEY_LOCK(); #endif +#if defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLFSSL_SWDEV) + PRIVATE_KEY_UNLOCK(); + if (ret == 0) + ret = sha256_onlycb_test(&myCtx); + PRIVATE_KEY_LOCK(); +#endif +#if defined(WOLF_CRYPTO_CB_ONLY_AES) && !defined(WOLFSSL_SWDEV) + PRIVATE_KEY_UNLOCK(); + if (ret == 0) + ret = aes_onlycb_test(&myCtx); + PRIVATE_KEY_LOCK(); +#endif #ifdef WOLFSSL_HAVE_MLKEM if (ret == 0) ret = mlkem_test(); @@ -69850,7 +69999,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) if (ret == 0) ret = curve25519_test(); #endif -#ifndef NO_AES +#if !defined(NO_AES) && !defined(WOLF_CRYPTO_CB_ONLY_AES) + /* CB_ONLY_AES skips these (aes_onlycb_test covers that path). */ #ifdef HAVE_AESGCM if (ret == 0) ret = aesgcm_test(); @@ -69867,7 +70017,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) if (ret == 0) ret = aesccm_test(); #endif -#endif /* !NO_AES */ +#endif /* !NO_AES && !WOLF_CRYPTO_CB_ONLY_AES */ #ifndef NO_DES3 if (ret == 0) ret = des3_test(); diff --git a/wolfcrypt/test/test.h b/wolfcrypt/test/test.h index 75ea16234a7..1fb33fb5580 100644 --- a/wolfcrypt/test/test.h +++ b/wolfcrypt/test/test.h @@ -281,7 +281,7 @@ extern WOLFSSL_TEST_SUBROUTINE wc_test_ret_t scrypt_test(void); #if defined(USE_CERT_BUFFERS_256) && !defined(WOLFSSL_ATECC508A) && \ !defined(WOLFSSL_ATECC608A) && !defined(NO_ECC256) && \ defined(HAVE_ECC_VERIFY) && defined(HAVE_ECC_SIGN) && \ - !defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(NO_ECC_SECP) + (!defined(WOLF_CRYPTO_CB_ONLY_ECC) || defined(WOLFSSL_SWDEV)) && !defined(NO_ECC_SECP) /* skip for ATECC508/608A, cannot import private key buffers */ extern WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ecc_test_buffers(void); #endif diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index 710b522b9e7..5130efaecb3 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -384,14 +384,15 @@ typedef struct wc_CryptoInfo { word32 sz; } aesctr; #endif /* WOLFSSL_AES_COUNTER */ - #if defined(HAVE_AES_ECB) + #if defined(HAVE_AES_ECB) || defined(WOLFSSL_AES_DIRECT) || \ + defined(WOLF_CRYPTO_CB_ONLY_AES) struct { Aes* aes; byte* out; const byte* in; word32 sz; } aesecb; - #endif /* HAVE_AES_ECB */ + #endif /* HAVE_AES_ECB || WOLFSSL_AES_DIRECT || WOLF_CRYPTO_CB_ONLY_AES */ #ifndef NO_DES3 struct { Des3* des; @@ -783,12 +784,13 @@ WOLFSSL_LOCAL int wc_CryptoCb_AesCbcDecrypt(Aes* aes, byte* out, WOLFSSL_LOCAL int wc_CryptoCb_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz); #endif /* WOLFSSL_AES_COUNTER */ -#ifdef HAVE_AES_ECB +#if defined(HAVE_AES_ECB) || defined(WOLFSSL_AES_DIRECT) || \ + defined(WOLF_CRYPTO_CB_ONLY_AES) WOLFSSL_LOCAL int wc_CryptoCb_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz); WOLFSSL_LOCAL int wc_CryptoCb_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz); -#endif /* HAVE_AES_ECB */ +#endif /* HAVE_AES_ECB || WOLFSSL_AES_DIRECT || WOLF_CRYPTO_CB_ONLY_AES */ #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 */ diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 1dfc05a909f..5e665850fb9 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -5061,6 +5061,10 @@ extern void uITRON4_free(void *p) ; #error "AES-GCM streaming (WOLFSSL_AESGCM_STREAM)" \ " requires AES-GCM (HAVE_AESGCM)" #endif +#if defined(WOLFSSL_AESGCM_STREAM) && defined(WOLF_CRYPTO_CB_ONLY_AES) + #error "AES-GCM streaming (WOLFSSL_AESGCM_STREAM)" \ + " is not supported with WOLF_CRYPTO_CB_ONLY_AES" +#endif #if defined(WOLFSSL_AESXTS_STREAM) && !defined(WOLFSSL_AES_XTS) #error "AES-XTS streaming (WOLFSSL_AESXTS_STREAM)" \ " requires AES-XTS (WOLFSSL_AES_XTS)" @@ -5109,6 +5113,22 @@ extern void uITRON4_free(void *p) ; " (WOLF_CRYPTO_CB_COPY/WOLF_CRYPTO_CB_FREE)" \ " require WOLF_CRYPTO_CB" #endif +/* + * WOLF_CRYPTO_CB_ONLY_* assumes no hardware crypto port is compiled in for + * the selected algorithm. Crypto Callback is expected to be the only provider. + */ +#if defined(WOLF_CRYPTO_CB_ONLY_RSA) && !defined(WOLF_CRYPTO_CB) + #error "WOLF_CRYPTO_CB_ONLY_RSA requires WOLF_CRYPTO_CB" +#endif +#if defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB) + #error "WOLF_CRYPTO_CB_ONLY_ECC requires WOLF_CRYPTO_CB" +#endif +#if defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLF_CRYPTO_CB) + #error "WOLF_CRYPTO_CB_ONLY_SHA256 requires WOLF_CRYPTO_CB" +#endif +#if defined(WOLF_CRYPTO_CB_ONLY_AES) && !defined(WOLF_CRYPTO_CB) + #error "WOLF_CRYPTO_CB_ONLY_AES requires WOLF_CRYPTO_CB" +#endif /* Early Data / Session Rules */ #if !defined(WOLFCRYPT_ONLY) && defined(WOLFSSL_EARLY_DATA) && \ diff --git a/wolfssl/wolfcrypt/sha256.h b/wolfssl/wolfcrypt/sha256.h index dd69f57603c..ea354695f98 100644 --- a/wolfssl/wolfcrypt/sha256.h +++ b/wolfssl/wolfcrypt/sha256.h @@ -102,6 +102,12 @@ #define WOLFSSL_NO_HASH_RAW #endif +/* no raw hash access when software transform is stripped */ +#if defined(WOLF_CRYPTO_CB_ONLY_SHA256) +#undef WOLFSSL_NO_HASH_RAW +#define WOLFSSL_NO_HASH_RAW +#endif + #define SHA256_NOINLINE WC_NO_INLINE #if !defined(NO_OLD_SHA_NAMES)