diff --git a/.github/workflows/build-and-test-macos.yaml b/.github/workflows/build-and-test-macos.yaml index ebf3f16cd2..ef46cc7106 100644 --- a/.github/workflows/build-and-test-macos.yaml +++ b/.github/workflows/build-and-test-macos.yaml @@ -40,7 +40,7 @@ jobs: matrix: os: ["macos-14", "macos-15", "macos-15-intel", "macos-26"] otp: ["24", "25", "26", "27", "28"] - mbedtls: ["mbedtls@3"] + mbedtls: ["mbedtls@3","mbedtls@4"] cmake_opts_other: [""] include: diff --git a/.github/workflows/build-libraries.yaml b/.github/workflows/build-libraries.yaml index 7c7d9eaaee..d0f889ca33 100644 --- a/.github/workflows/build-libraries.yaml +++ b/.github/workflows/build-libraries.yaml @@ -19,6 +19,8 @@ jobs: runs-on: "ubuntu-22.04" strategy: fail-fast: false + matrix: + mbedtls: ["default", "mbedtls@4"] steps: - name: "Checkout repo" @@ -36,10 +38,26 @@ jobs: - name: "Install deps" run: | - sudo apt install -y build-essential cmake gperf zlib1g-dev libmbedtls-dev + sudo apt install -y build-essential cmake gperf zlib1g-dev + if [[ "${{ matrix.mbedtls }}" == "default" ]]; then + sudo apt install -y libmbedtls-dev + fi # Get a more recent valgrind sudo snap install valgrind --classic + - name: "Install specific MbedTLS version" + if: matrix.mbedtls == 'mbedtls@4' + run: | + git clone --depth 1 --branch mbedtls-4.0.0 --recurse-submodules https://github.com/Mbed-TLS/mbedtls + cd mbedtls + mkdir build + cd build + cmake -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=On -DCMAKE_INSTALL_PREFIX=/usr/local .. + make -j$(nproc) + sudo make install + sudo ldconfig + echo "MBEDTLS_ROOT_DIR=/usr/local" >> $GITHUB_ENV + # Builder info - name: "System info" run: | @@ -64,7 +82,7 @@ jobs: - name: "Build: run cmake" working-directory: build run: | - cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo .. + cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ${MBEDTLS_ROOT_DIR:+-DMBEDTLS_ROOT_DIR=$MBEDTLS_ROOT_DIR} .. - name: "Build: run make" working-directory: build @@ -122,7 +140,7 @@ jobs: - name: Release uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') + if: startsWith(github.ref, 'refs/tags/') && matrix.mbedtls == 'default' with: draft: true fail_on_unmatched_files: true diff --git a/.github/workflows/esp32-simtest.yaml b/.github/workflows/esp32-simtest.yaml index 796f09b1d6..f3babbd9b3 100644 --- a/.github/workflows/esp32-simtest.yaml +++ b/.github/workflows/esp32-simtest.yaml @@ -12,7 +12,7 @@ on: paths: - ".github/workflows/esp32-simtest.yaml" - "CMakeLists.txt" - - 'CMakeModules/**' + - "CMakeModules/**" - "libs/**" - "src/platforms/esp32/**" - "src/platforms/esp32/**/**" @@ -22,7 +22,7 @@ on: paths: - ".github/workflows/esp32-simtest.yaml" - "CMakeLists.txt" - - 'CMakeModules/**' + - "CMakeModules/**" - "libs/**" - "src/platforms/esp32/**" - "src/platforms/esp32/**/**" @@ -78,9 +78,9 @@ jobs: "esp32c3", "esp32c5", "esp32c6", - "esp32h2" + "esp32h2", ] - idf-version: ${{ ((contains(github.event.head_commit.message, 'full_sim_test')||contains(github.event.pull_request.title, 'full_sim_test')) && fromJSON('["v5.1.7", "v5.2.6", "v5.3.4", "v5.4.3", "v5.5.3"]')) || fromJSON('["v5.5.3"]') }} + idf-version: ${{ ((contains(github.event.head_commit.message, 'full_sim_test')||contains(github.event.pull_request.title, 'full_sim_test')) && fromJSON('["v5.1.7", "v5.2.6", "v5.3.4", "v5.4.3", "v5.5.3"]')) || fromJSON('["release-v6.0"]') }} exclude: - esp-idf-target: "esp32p4" idf-version: "v5.1.7" @@ -101,7 +101,7 @@ jobs: # CI now uses chip revision 3 that is currently only available in 5.5.2 include: - esp-idf-target: "esp32p4" - idf-version: "v5.5.3" + idf-version: "release-v6.0" steps: - name: Checkout repo diff --git a/doc/src/programmers-guide.md b/doc/src/programmers-guide.md index 32524b1462..97bfd2e1eb 100644 --- a/doc/src/programmers-guide.md +++ b/doc/src/programmers-guide.md @@ -1331,7 +1331,7 @@ Use the [`esp:deep_sleep/1`](./apidocs/erlang/eavmlib/esp.md#deep_sleep1) functi esp:deep_sleep(60*1000). ``` -Use the [`esp:sleep_get_wakeup_cause/0`](./apidocs/erlang/eavmlib/esp.md#sleep_get_wakeup_cause0) function to inspect the reason for a wakeup. Possible return values include: +For ESP-IDF 5.5 compatibility, use [`esp:sleep_get_wakeup_cause/0`](./apidocs/erlang/eavmlib/esp.md#sleep_get_wakeup_cause0) to inspect a single wakeup reason. Possible values include: * `sleep_wakeup_ext0` * `sleep_wakeup_ext1` @@ -1342,7 +1342,7 @@ Use the [`esp:sleep_get_wakeup_cause/0`](./apidocs/erlang/eavmlib/esp.md#sleep_g * `sleep_wakeup_uart` * `sleep_wakeup_wifi` * `sleep_wakeup_cocpu` -* `sleep_wakeup_cocpu_trag_trig` +* `sleep_wakeup_cocpu_trap_trig` * `sleep_wakeup_bt` * `undefined` (no sleep wakeup) * `error` (unknown other reason) @@ -1362,6 +1362,20 @@ case esp:sleep_get_wakeup_cause() of end. ``` +For ESP-IDF 6+, use [`esp:sleep_get_wakeup_causes/0`](./apidocs/erlang/eavmlib/esp.md#sleep_get_wakeup_causes0) to inspect all wakeup reasons. This function returns a list, since a wakeup may have multiple causes. + +The values match the semantics of [`esp_sleep_get_wakeup_causes`](https://docs.espressif.com/projects/esp-idf/en/release-v6.0/esp32/api-reference/system/sleep_modes.html). + +```erlang +WakeupCauses = esp:sleep_get_wakeup_causes(), +case WakeupCauses of + [] -> + io:format("No wakeup cause available~n"); + _ -> + io:format("Wakeup causes: ~p~n", [WakeupCauses]) +end. +``` + Use the [`esp:sleep_enable_ext0_wakeup/2`](./apidocs/erlang/eavmlib/esp.md#sleep_enable_ext0_wakeup2) and [`esp:sleep_enable_ext1_wakeup/2`](./apidocs/erlang/eavmlib/esp.md#sleep_enable_ext1_wakeup2) functions to configure ext0 and ext1 wakeup mechanisms. They follow the semantics of [`esp_sleep_enable_ext0_wakeup`](https://docs.espressif.com/projects/esp-idf/en/release-v5.5/esp32/api-reference/system/sleep_modes.html#_CPPv428esp_sleep_enable_ext0_wakeup10gpio_num_ti) and [`esp_sleep_enable_ext1_wakeup`](https://docs.espressif.com/projects/esp-idf/en/release-v5.5/esp32/api-reference/system/sleep_modes.html#_CPPv428esp_sleep_enable_ext1_wakeup8uint64_t28esp_sleep_ext1_wakeup_mode_t). ```erlang diff --git a/libs/eavmlib/src/esp.erl b/libs/eavmlib/src/esp.erl index 6b08a7ee9a..d7fa1e729d 100644 --- a/libs/eavmlib/src/esp.erl +++ b/libs/eavmlib/src/esp.erl @@ -30,6 +30,7 @@ restart/0, reset_reason/0, sleep_get_wakeup_cause/0, + sleep_get_wakeup_causes/0, sleep_enable_ext0_wakeup/2, sleep_enable_ext1_wakeup/2, sleep_enable_ext1_wakeup_io/2, @@ -174,6 +175,15 @@ reset_reason() -> sleep_get_wakeup_cause() -> erlang:nif_error(undefined). +%%----------------------------------------------------------------------------- +%% @returns wakeup causes for the previous sleep operation +%% @doc Returns all causes for the wakeup +%% @end +%%----------------------------------------------------------------------------- +-spec sleep_get_wakeup_causes() -> [esp_wakeup_cause()]. +sleep_get_wakeup_causes() -> + erlang:nif_error(undefined). + %%----------------------------------------------------------------------------- %% @doc Configure gpio wakeup from deep sleep. %% Implemented for SOCs that support it (ESP32, ESP32S2, ESP32S3) diff --git a/src/libAtomVM/otp_crypto.c b/src/libAtomVM/otp_crypto.c index 704e1e1446..0b7222da4b 100644 --- a/src/libAtomVM/otp_crypto.c +++ b/src/libAtomVM/otp_crypto.c @@ -30,6 +30,8 @@ #include #include +#include +#if MBEDTLS_VERSION_NUMBER < 0x04000000 #include #include #include @@ -37,8 +39,7 @@ #include #include #include -#include - +#endif // #define ENABLE_TRACE #include "trace.h" @@ -55,6 +56,7 @@ enum crypto_algorithm CryptoSha512 }; +#if MBEDTLS_VERSION_NUMBER < 0x04000000 static const AtomStringIntPair crypto_algorithm_table[] = { { ATOM_STR("\x3", "md5"), CryptoMd5 }, { ATOM_STR("\x3", "sha"), CryptoSha1 }, @@ -64,6 +66,7 @@ static const AtomStringIntPair crypto_algorithm_table[] = { { ATOM_STR("\x6", "sha512"), CryptoSha512 }, SELECT_INT_DEFAULT(CryptoInvalidAlgorithm) }; +#endif #define DEFINE_HASH_FOLD(ALGORITHM, SUFFIX) \ static InteropFunctionResult ALGORITHM##_hash_fold_fun(term t, void *accum) \ @@ -179,6 +182,7 @@ static const AtomStringIntPair crypto_algorithm_table[] = { return true; \ } +#if MBEDTLS_VERSION_NUMBER < 0x04000000 #if MBEDTLS_VERSION_NUMBER >= 0x03000000 // 3.x API: functions return an int that represents errors @@ -224,6 +228,52 @@ DEFINE_HASH_FOLD_NORET(sha512, ) DEFINE_DO_HASH_NORET_IS_OTHER(sha512, , true) DEFINE_DO_HASH_NORET_IS_OTHER(sha512, , false) +#endif +#endif + +#if MBEDTLS_VERSION_NUMBER >= 0x04000000 +static psa_algorithm_t atom_to_psa_hash_alg(term type, GlobalContext *global) +{ + if (type == globalcontext_make_atom(global, ATOM_STR("\x3", "md5"))) { + return PSA_ALG_MD5; + } + if (type == globalcontext_make_atom(global, ATOM_STR("\x3", "sha"))) { + return PSA_ALG_SHA_1; + } + if (type == globalcontext_make_atom(global, ATOM_STR("\x6", "sha224"))) { + return PSA_ALG_SHA_224; + } + if (type == globalcontext_make_atom(global, ATOM_STR("\x6", "sha256"))) { + return PSA_ALG_SHA_256; + } + if (type == globalcontext_make_atom(global, ATOM_STR("\x6", "sha384"))) { + return PSA_ALG_SHA_384; + } + if (type == globalcontext_make_atom(global, ATOM_STR("\x6", "sha512"))) { + return PSA_ALG_SHA_512; + } + return PSA_ALG_NONE; +} + +static InteropFunctionResult psa_hash_fold_fun(term t, void *accum) +{ + psa_hash_operation_t *operation = (psa_hash_operation_t *) accum; + if (term_is_integer(t)) { + avm_int64_t tmp = term_maybe_unbox_int64(t); + if (tmp < 0 || tmp > 255) { + return InteropBadArg; + } + uint8_t val = (uint8_t) tmp; + if (UNLIKELY(psa_hash_update(operation, &val, 1) != PSA_SUCCESS)) { + return InteropBadArg; + } + } else /* term_is_binary(t) */ { + if (UNLIKELY(psa_hash_update(operation, (uint8_t *) term_binary_data(t), term_binary_size(t)) != PSA_SUCCESS)) { + return InteropBadArg; + } + } + return InteropOk; +} #endif static term nif_crypto_hash(Context *ctx, int argc, term argv[]) @@ -236,6 +286,33 @@ static term nif_crypto_hash(Context *ctx, int argc, term argv[]) unsigned char digest[MAX_MD_SIZE]; size_t digest_len = 0; +#if MBEDTLS_VERSION_NUMBER >= 0x04000000 + psa_algorithm_t alg = atom_to_psa_hash_alg(type, ctx->global); + if (alg == PSA_ALG_NONE) { + TRACE("crypto:hash unknown algorithm\n"); + RAISE_ERROR(BADARG_ATOM); + } + digest_len = PSA_HASH_LENGTH(alg); + + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + psa_status_t status = psa_hash_setup(&operation, alg); + if (UNLIKELY(status != PSA_SUCCESS)) { + TRACE("crypto:hash psa_hash_setup failed with status %d for alg 0x%08lx\n", (int) status, (unsigned long) alg); + RAISE_ERROR(BADARG_ATOM); + } + + InteropFunctionResult result = interop_chardata_fold(data, psa_hash_fold_fun, NULL, (void *) &operation); + if (UNLIKELY(result != InteropOk)) { + psa_hash_abort(&operation); + RAISE_ERROR(BADARG_ATOM); + } + + status = psa_hash_finish(&operation, digest, sizeof(digest), &digest_len); + if (UNLIKELY(status != PSA_SUCCESS)) { + psa_hash_abort(&operation); + RAISE_ERROR(BADARG_ATOM); + } +#else enum crypto_algorithm algo = interop_atom_term_select_int(crypto_algorithm_table, type, ctx->global); switch (algo) { case CryptoMd5: { @@ -283,6 +360,7 @@ static term nif_crypto_hash(Context *ctx, int argc, term argv[]) default: RAISE_ERROR(BADARG_ATOM); } +#endif if (UNLIKELY(memory_ensure_free(ctx, term_binary_heap_size(digest_len)) != MEMORY_GC_OK)) { RAISE_ERROR(OUT_OF_MEMORY_ATOM); @@ -290,6 +368,7 @@ static term nif_crypto_hash(Context *ctx, int argc, term argv[]) return term_from_literal_binary(digest, digest_len, &ctx->heap, ctx->global); } +#if MBEDTLS_VERSION_NUMBER < 0x04000000 static const AtomStringIntPair cipher_table[] = { { ATOM_STR("\xB", "aes_128_ecb"), MBEDTLS_CIPHER_AES_128_ECB }, { ATOM_STR("\xB", "aes_192_ecb"), MBEDTLS_CIPHER_AES_192_ECB }, @@ -311,6 +390,7 @@ static const AtomStringIntPair padding_table[] = { { ATOM_STR("\xC", "pkcs_padding"), MBEDTLS_PADDING_PKCS7 }, SELECT_INT_DEFAULT(-1) }; +#endif static term handle_iodata(term iodata, const void **data, size_t *len, void **allocated_ptr) { @@ -353,6 +433,72 @@ static term handle_iodata(term iodata, const void **data, size_t *len, void **al } } +#if MBEDTLS_VERSION_NUMBER >= 0x04000000 +static psa_algorithm_t atom_to_psa_cipher_alg(term type, GlobalContext *global, psa_key_type_t *key_type, size_t *key_bits) +{ + if (type == globalcontext_make_atom(global, ATOM_STR("\xB", "aes_128_ecb"))) { + *key_type = PSA_KEY_TYPE_AES; + *key_bits = 128; + return PSA_ALG_ECB_NO_PADDING; + } + if (type == globalcontext_make_atom(global, ATOM_STR("\xB", "aes_192_ecb"))) { + *key_type = PSA_KEY_TYPE_AES; + *key_bits = 192; + return PSA_ALG_ECB_NO_PADDING; + } + if (type == globalcontext_make_atom(global, ATOM_STR("\xB", "aes_256_ecb"))) { + *key_type = PSA_KEY_TYPE_AES; + *key_bits = 256; + return PSA_ALG_ECB_NO_PADDING; + } + if (type == globalcontext_make_atom(global, ATOM_STR("\xB", "aes_128_cbc"))) { + *key_type = PSA_KEY_TYPE_AES; + *key_bits = 128; + return PSA_ALG_CBC_NO_PADDING; + } + if (type == globalcontext_make_atom(global, ATOM_STR("\xB", "aes_192_cbc"))) { + *key_type = PSA_KEY_TYPE_AES; + *key_bits = 192; + return PSA_ALG_CBC_NO_PADDING; + } + if (type == globalcontext_make_atom(global, ATOM_STR("\xB", "aes_256_cbc"))) { + *key_type = PSA_KEY_TYPE_AES; + *key_bits = 256; + return PSA_ALG_CBC_NO_PADDING; + } + if (type == globalcontext_make_atom(global, ATOM_STR("\xE", "aes_128_cfb128"))) { + *key_type = PSA_KEY_TYPE_AES; + *key_bits = 128; + return PSA_ALG_CFB; + } + if (type == globalcontext_make_atom(global, ATOM_STR("\xE", "aes_192_cfb128"))) { + *key_type = PSA_KEY_TYPE_AES; + *key_bits = 192; + return PSA_ALG_CFB; + } + if (type == globalcontext_make_atom(global, ATOM_STR("\xE", "aes_256_cfb128"))) { + *key_type = PSA_KEY_TYPE_AES; + *key_bits = 256; + return PSA_ALG_CFB; + } + if (type == globalcontext_make_atom(global, ATOM_STR("\xB", "aes_128_ctr"))) { + *key_type = PSA_KEY_TYPE_AES; + *key_bits = 128; + return PSA_ALG_CTR; + } + if (type == globalcontext_make_atom(global, ATOM_STR("\xB", "aes_192_ctr"))) { + *key_type = PSA_KEY_TYPE_AES; + *key_bits = 192; + return PSA_ALG_CTR; + } + if (type == globalcontext_make_atom(global, ATOM_STR("\xB", "aes_256_ctr"))) { + *key_type = PSA_KEY_TYPE_AES; + *key_bits = 256; + return PSA_ALG_CTR; + } + return PSA_ALG_NONE; +} +#else static bool bool_to_mbedtls_operation(term encrypt_flag, mbedtls_operation_t *operation) { switch (encrypt_flag) { @@ -366,6 +512,7 @@ static bool bool_to_mbedtls_operation(term encrypt_flag, mbedtls_operation_t *op return false; } } +#endif static term make_crypto_error(const char *file, int line, const char *message, Context *ctx) { @@ -410,11 +557,21 @@ static term nif_crypto_crypto_one_time(Context *ctx, int argc, term argv[]) } term cipher_term = argv[0]; + +#if MBEDTLS_VERSION_NUMBER >= 0x04000000 + psa_key_type_t key_type; + size_t key_bits; + psa_algorithm_t alg = atom_to_psa_cipher_alg(cipher_term, ctx->global, &key_type, &key_bits); + if (UNLIKELY(alg == PSA_ALG_NONE)) { + RAISE_ERROR(make_crypto_error(__FILE__, __LINE__, "Unknown cipher", ctx)); + } +#else mbedtls_cipher_type_t cipher = interop_atom_term_select_int(cipher_table, cipher_term, ctx->global); if (UNLIKELY(cipher == MBEDTLS_CIPHER_NONE)) { RAISE_ERROR(make_crypto_error(__FILE__, __LINE__, "Unknown cipher", ctx)); } +#endif // from this point onward use `goto raise_error` in order to raise and free all buffers term error_atom = UNDEFINED_ATOM; @@ -449,6 +606,178 @@ static term nif_crypto_crypto_one_time(Context *ctx, int argc, term argv[]) goto raise_error; } +#if MBEDTLS_VERSION_NUMBER >= 0x04000000 + bool encrypt = true; + bool padding_pkcs7 = false; + psa_key_id_t key_id = 0; + void *temp_buf = NULL; + psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; + + if (term_is_list(flag_or_options)) { + term encrypt_flag = interop_kv_get_value_default( + flag_or_options, ATOM_STR("\x7", "encrypt"), UNDEFINED_ATOM, ctx->global); + if (encrypt_flag == FALSE_ATOM) { + encrypt = false; + } else if (encrypt_flag != TRUE_ATOM && encrypt_flag != UNDEFINED_ATOM) { + error_atom = BADARG_ATOM; + goto raise_error; + } + + term padding_term = interop_kv_get_value_default( + flag_or_options, ATOM_STR("\x7", "padding"), UNDEFINED_ATOM, ctx->global); + + if (padding_term != UNDEFINED_ATOM) { + if (padding_term == globalcontext_make_atom(ctx->global, ATOM_STR("\xC", "pkcs_padding"))) { + padding_pkcs7 = true; + } else if (padding_term != globalcontext_make_atom(ctx->global, ATOM_STR("\x4", "none"))) { + error_atom = BADARG_ATOM; + goto raise_error; + } + } + + } else { + if (flag_or_options == FALSE_ATOM) { + encrypt = false; + } else if (flag_or_options != TRUE_ATOM) { + error_atom = make_crypto_error( + __FILE__, __LINE__, "Options are not a boolean or a proper list", ctx); + goto raise_error; + } + } + + if (padding_pkcs7) { + if (alg == PSA_ALG_CBC_NO_PADDING) { + alg = PSA_ALG_CBC_PKCS7; + } else if (alg == PSA_ALG_ECB_NO_PADDING) { + // PSA does not support PKCS7 padding with ECB mode + error_atom = BADARG_ATOM; + goto raise_error; + } + } + + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_usage_flags(&attributes, encrypt ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, alg); + psa_set_key_type(&attributes, key_type); + psa_set_key_bits(&attributes, key_bits); + + psa_status_t status = psa_import_key(&attributes, key_data, key_len, &key_id); + if (UNLIKELY(status != PSA_SUCCESS)) { + char err_msg[48]; + snprintf(err_msg, sizeof(err_msg), "key import err %d", (int) status); + error_atom = make_crypto_error(__FILE__, __LINE__, err_msg, ctx); + goto psa_error; + } + + size_t output_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, data_size); + if (!encrypt) { + output_size = PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, data_size); + } + temp_buf = malloc(output_size); + if (IS_NULL_PTR(temp_buf)) { + error_atom = OUT_OF_MEMORY_ATOM; + goto psa_error; + } + + size_t output_len; + if (encrypt) { + status = psa_cipher_encrypt_setup(&operation, key_id, alg); + } else { + status = psa_cipher_decrypt_setup(&operation, key_id, alg); + } + if (UNLIKELY(status != PSA_SUCCESS)) { + char err_msg[48]; + snprintf(err_msg, sizeof(err_msg), "cipher setup err %d", (int) status); + error_atom = make_crypto_error(__FILE__, __LINE__, err_msg, ctx); + goto psa_error; + } + + // PSA rejects IVs for ECB; ignore IV to preserve legacy behavior. + if (iv_len > 0 && alg != PSA_ALG_ECB_NO_PADDING) { + status = psa_cipher_set_iv(&operation, iv_data, iv_len); + if (UNLIKELY(status != PSA_SUCCESS)) { + char err_msg[24]; + snprintf(err_msg, sizeof(err_msg), "IV err %d", (int) status); + error_atom = make_crypto_error(__FILE__, __LINE__, err_msg, ctx); + goto psa_error; + } + } + + // For CBC/ECB with no padding, PSA requires block-aligned input. + // The legacy mbedtls behavior was to process only complete blocks, + // so we truncate the input to the nearest block boundary for these modes. + size_t block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type); + size_t process_size = data_size; + if (alg == PSA_ALG_CBC_NO_PADDING || alg == PSA_ALG_ECB_NO_PADDING) { + process_size = (data_size / block_size) * block_size; + if (process_size == 0) { + // No complete blocks to process + psa_cipher_abort(&operation); + psa_destroy_key(key_id); + free(temp_buf); + if (allocated_key_data) { + memset(allocated_key_data, 0, key_len); + } + free(allocated_key_data); + free(allocated_iv_data); + free(allocated_data_data); + // Return empty binary + if (UNLIKELY(memory_ensure_free(ctx, term_binary_heap_size(0)) != MEMORY_GC_OK)) { + RAISE_ERROR(OUT_OF_MEMORY_ATOM); + } + return term_from_literal_binary("", 0, &ctx->heap, ctx->global); + } + } + + size_t update_len = 0; + status = psa_cipher_update(&operation, data_data, process_size, temp_buf, output_size, &update_len); + if (UNLIKELY(status != PSA_SUCCESS)) { + char err_msg[24]; + snprintf(err_msg, sizeof(err_msg), "update err %d", (int) status); + error_atom = make_crypto_error(__FILE__, __LINE__, err_msg, ctx); + goto psa_error; + } + + size_t finish_len = 0; + status = psa_cipher_finish(&operation, (uint8_t *) temp_buf + update_len, output_size - update_len, &finish_len); + if (UNLIKELY(status != PSA_SUCCESS)) { + char err_msg[24]; + snprintf(err_msg, sizeof(err_msg), "finish err %d", (int) status); + error_atom = make_crypto_error(__FILE__, __LINE__, err_msg, ctx); + goto psa_error; + } + output_len = update_len + finish_len; + + psa_destroy_key(key_id); + + if (allocated_key_data) { + memset(allocated_key_data, 0, key_len); + } + free(allocated_key_data); + free(allocated_iv_data); + free(allocated_data_data); + + int ensure_size = term_binary_heap_size(output_len); + if (UNLIKELY(memory_ensure_free(ctx, ensure_size) != MEMORY_GC_OK)) { + free(temp_buf); + RAISE_ERROR(OUT_OF_MEMORY_ATOM); + } + + term out = term_from_literal_binary(temp_buf, output_len, &ctx->heap, ctx->global); + free(temp_buf); + return out; + +psa_error: + psa_cipher_abort(&operation); + if (key_id != 0) { + psa_destroy_key(key_id); + } + free(temp_buf); + if (allocated_key_data) { + memset(allocated_key_data, 0, key_len); + } + goto raise_error; +#else mbedtls_operation_t operation; mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_NONE; bool padding_has_been_set = false; @@ -547,12 +876,6 @@ static term nif_crypto_crypto_one_time(Context *ctx, int argc, term argv[]) return out; -raise_error: - free(allocated_key_data); - free(allocated_iv_data); - free(allocated_data_data); - RAISE_ERROR(error_atom); - mbed_error: free(temp_buf); free(allocated_key_data); @@ -562,6 +885,13 @@ static term nif_crypto_crypto_one_time(Context *ctx, int argc, term argv[]) char err_msg[24]; snprintf(err_msg, sizeof(err_msg), "Error %x", -result); RAISE_ERROR(make_crypto_error(__FILE__, source_line, err_msg, ctx)); +#endif + +raise_error: + free(allocated_key_data); + free(allocated_iv_data); + free(allocated_data_data); + RAISE_ERROR(error_atom); } // not static since we are using it elsewhere to provide backward compatibility @@ -581,6 +911,17 @@ term nif_crypto_strong_rand_bytes(Context *ctx, int argc, term argv[]) RAISE_ERROR(OUT_OF_MEMORY_ATOM); } +#if MBEDTLS_VERSION_NUMBER >= 0x04000000 + term out_bin = term_create_uninitialized_binary(out_len, &ctx->heap, ctx->global); + unsigned char *out = (unsigned char *) term_binary_data(out_bin); + + psa_status_t status = psa_generate_random(out, out_len); + if (UNLIKELY(status != PSA_SUCCESS)) { + RAISE_ERROR(make_crypto_error(__FILE__, __LINE__, "Failed random", ctx)); + } + + return out_bin; +#else mbedtls_ctr_drbg_context *rnd_ctx = sys_mbedtls_get_ctr_drbg_context_lock(ctx->global); if (IS_NULL_PTR(rnd_ctx)) { RAISE_ERROR(make_crypto_error(__FILE__, __LINE__, "Failed CTR_DRBG init", ctx)); @@ -596,6 +937,7 @@ term nif_crypto_strong_rand_bytes(Context *ctx, int argc, term argv[]) } return out_bin; +#endif } static const struct Nif crypto_hash_nif = { diff --git a/src/libAtomVM/otp_ssl.c b/src/libAtomVM/otp_ssl.c index d7ded0b6ff..6837ec0f2b 100644 --- a/src/libAtomVM/otp_ssl.c +++ b/src/libAtomVM/otp_ssl.c @@ -35,8 +35,11 @@ #include +#include +#if MBEDTLS_VERSION_NUMBER < 0x04000000 #include #include +#endif #include #if defined(MBEDTLS_PSA_CRYPTO_C) @@ -75,12 +78,20 @@ static void mbedtls_debug_cb(void *ctx, int level, const char *filename, int lin struct EntropyContextResource { +#if MBEDTLS_VERSION_NUMBER < 0x04000000 mbedtls_entropy_context context; +#else + char dummy; +#endif }; struct CtrDrbgResource { +#if MBEDTLS_VERSION_NUMBER < 0x04000000 mbedtls_ctr_drbg_context context; +#else + char dummy; +#endif }; struct SSLContextResource @@ -98,7 +109,11 @@ static void entropycontext_dtor(ErlNifEnv *caller_env, void *obj) UNUSED(caller_env); struct EntropyContextResource *rsrc_obj = (struct EntropyContextResource *) obj; +#if MBEDTLS_VERSION_NUMBER < 0x04000000 mbedtls_entropy_free(&rsrc_obj->context); +#else + UNUSED(rsrc_obj); +#endif } static void ctrdrbg_dtor(ErlNifEnv *caller_env, void *obj) @@ -107,6 +122,7 @@ static void ctrdrbg_dtor(ErlNifEnv *caller_env, void *obj) UNUSED(caller_env); struct CtrDrbgResource *rsrc_obj = (struct CtrDrbgResource *) obj; +#if MBEDTLS_VERSION_NUMBER < 0x04000000 mbedtls_entropy_context *entropy_context = rsrc_obj->context.MBEDTLS_PRIVATE(p_entropy); // Release the drbg first mbedtls_ctr_drbg_free(&rsrc_obj->context); @@ -116,6 +132,9 @@ static void ctrdrbg_dtor(ErlNifEnv *caller_env, void *obj) struct RefcBinary *entropy_refc = refc_binary_from_data(entropy_obj); refc_binary_decrement_refcount(entropy_refc, caller_env->global); } +#else + UNUSED(rsrc_obj); +#endif } static void sslcontext_dtor(ErlNifEnv *caller_env, void *obj) @@ -141,15 +160,19 @@ static void sslconfig_dtor(ErlNifEnv *caller_env, void *obj) UNUSED(caller_env); struct SSLConfigResource *rsrc_obj = (struct SSLConfigResource *) obj; +#if MBEDTLS_VERSION_NUMBER < 0x04000000 const mbedtls_ctr_drbg_context *ctr_drbg_context = rsrc_obj->config.MBEDTLS_PRIVATE(p_rng); +#endif mbedtls_ssl_config_free(&rsrc_obj->config); +#if MBEDTLS_VERSION_NUMBER < 0x04000000 // Eventually release the ctrdrbg if (ctr_drbg_context) { struct CtrDrbgResource *rng_obj = CONTAINER_OF(ctr_drbg_context, struct CtrDrbgResource, context); struct RefcBinary *config_refc = refc_binary_from_data(rng_obj); refc_binary_decrement_refcount(config_refc, caller_env->global); } +#endif } static const ErlNifResourceTypeInit EntropyContextResourceTypeInit = { @@ -242,7 +265,9 @@ static term nif_ssl_entropy_init(Context *ctx, int argc, term argv[]) term obj = term_from_resource(rsrc_obj, &ctx->heap); enif_release_resource(rsrc_obj); // decrement refcount after enif_alloc_resource +#if MBEDTLS_VERSION_NUMBER < 0x04000000 mbedtls_entropy_init(&rsrc_obj->context); +#endif return obj; } @@ -269,7 +294,9 @@ static term nif_ssl_ctr_drbg_init(Context *ctx, int argc, term argv[]) term obj = term_from_resource(rsrc_obj, &ctx->heap); enif_release_resource(rsrc_obj); // decrement refcount after enif_alloc_resource +#if MBEDTLS_VERSION_NUMBER < 0x04000000 mbedtls_ctr_drbg_init(&rsrc_obj->context); +#endif return obj; } @@ -285,11 +312,14 @@ static term nif_ssl_ctr_drbg_seed(Context *ctx, int argc, term argv[]) if (UNLIKELY(!enif_get_resource(erl_nif_env_from_context(ctx), argv[0], ctrdrbg_resource_type, &rsrc_obj_ptr))) { RAISE_ERROR(BADARG_ATOM); } +#if MBEDTLS_VERSION_NUMBER < 0x04000000 struct CtrDrbgResource *ctrdrbg_obj = (struct CtrDrbgResource *) rsrc_obj_ptr; +#endif if (UNLIKELY(!enif_get_resource(erl_nif_env_from_context(ctx), argv[1], entropycontext_resource_type, &rsrc_obj_ptr))) { RAISE_ERROR(BADARG_ATOM); } +#if MBEDTLS_VERSION_NUMBER < 0x04000000 struct EntropyContextResource *entropy_obj = (struct EntropyContextResource *) rsrc_obj_ptr; int err = mbedtls_ctr_drbg_seed(&ctrdrbg_obj->context, mbedtls_entropy_func, &entropy_obj->context, (const unsigned char *) term_binary_data(argv[2]), term_binary_size(argv[2])); @@ -299,6 +329,7 @@ static term nif_ssl_ctr_drbg_seed(Context *ctx, int argc, term argv[]) struct RefcBinary *entropy_refc = refc_binary_from_data(entropy_obj); refc_binary_increment_refcount(entropy_refc); +#endif return OK_ATOM; } @@ -327,7 +358,7 @@ static term nif_ssl_init(Context *ctx, int argc, term argv[]) mbedtls_ssl_init(&rsrc_obj->context); -#if defined(MBEDTLS_PSA_CRYPTO_C) +#if defined(MBEDTLS_PSA_CRYPTO_C) || MBEDTLS_VERSION_NUMBER >= 0x04000000 psa_status_t status = psa_crypto_init(); if (UNLIKELY(status != PSA_SUCCESS)) { AVM_LOGW(TAG, "Failed to initialize PSA %s:%i.\n", __FILE__, __LINE__); @@ -500,10 +531,15 @@ static term nif_ssl_conf_rng(Context *ctx, int argc, term argv[]) } struct CtrDrbgResource *ctr_drbg_obj = (struct CtrDrbgResource *) rsrc_obj_ptr; +#if MBEDTLS_VERSION_NUMBER < 0x04000000 struct RefcBinary *ctr_drbg_refc = refc_binary_from_data(ctr_drbg_obj); refc_binary_increment_refcount(ctr_drbg_refc); mbedtls_ssl_conf_rng(&conf_obj->config, mbedtls_ctr_drbg_random, &ctr_drbg_obj->context); +#else + UNUSED(conf_obj); + UNUSED(ctr_drbg_obj); +#endif return OK_ATOM; } diff --git a/src/libAtomVM/sys_mbedtls.h b/src/libAtomVM/sys_mbedtls.h index 51eb59f64a..7d51ea1107 100644 --- a/src/libAtomVM/sys_mbedtls.h +++ b/src/libAtomVM/sys_mbedtls.h @@ -21,8 +21,15 @@ #ifndef _SYS_MBEDTLS_H_ #define _SYS_MBEDTLS_H_ +// Include version.h to get MBEDTLS_VERSION_NUMBER (available in all versions) +#include + +#if MBEDTLS_VERSION_NUMBER >= 0x04000000 +#include +#else #include #include +#endif #ifdef __cplusplus extern "C" { @@ -36,6 +43,7 @@ extern "C" { // On non-SMP builds, we don't need any lock because all calls we make to // mbedtls_ctr_drbg* functions are done from the scheduler thread itself. +#if MBEDTLS_VERSION_NUMBER < 0x04000000 /** * @brief get and acquire lock on mbedtls_entropy_context. * @details this function must be called from a scheduler thread (nif, @@ -60,7 +68,9 @@ void sys_mbedtls_entropy_context_unlock(GlobalContext *global); * the entropy mutex to call `mbedtls_entropy_func`. */ int sys_mbedtls_entropy_func(void *entropy, unsigned char *buf, size_t size); +#endif +#if MBEDTLS_VERSION_NUMBER < 0x04000000 /** * @brief get and acquire lock on mbedtls_ctr_drbg_context. * @details this function must be called from a scheduler thread (nif, @@ -78,6 +88,7 @@ mbedtls_ctr_drbg_context *sys_mbedtls_get_ctr_drbg_context_lock(GlobalContext *g * @param global the global context */ void sys_mbedtls_ctr_drbg_context_unlock(GlobalContext *global); +#endif #ifdef __cplusplus } diff --git a/src/platforms/emscripten/src/lib/emscripten_sys.h b/src/platforms/emscripten/src/lib/emscripten_sys.h index 1889b2ab97..f2978e4da2 100644 --- a/src/platforms/emscripten/src/lib/emscripten_sys.h +++ b/src/platforms/emscripten/src/lib/emscripten_sys.h @@ -33,17 +33,14 @@ #include #include +#include +#include "sys_mbedtls.h" + +#if MBEDTLS_VERSION_NUMBER < 0x04000000 #include #include - -#if defined(MBEDTLS_VERSION_NUMBER) && (MBEDTLS_VERSION_NUMBER >= 0x03000000) -#include -#else -#include #endif -#include "sys_mbedtls.h" - struct PromiseResource { em_promise_t promise; @@ -117,6 +114,7 @@ struct EmscriptenPlatformData ErlNifResourceType *htmlevent_user_data_resource_type; ErlNifResourceType *websocket_resource_type; +#if MBEDTLS_VERSION_NUMBER < 0x04000000 #ifndef AVM_NO_SMP Mutex *entropy_mutex; #endif @@ -128,6 +126,7 @@ struct EmscriptenPlatformData #endif mbedtls_ctr_drbg_context random_ctx; bool random_is_initialized; +#endif }; void sys_enqueue_emscripten_cast_message(GlobalContext *glb, const char *target, const char *message); diff --git a/src/platforms/emscripten/src/lib/sys.c b/src/platforms/emscripten/src/lib/sys.c index ab8c0404b7..41fbc00bba 100644 --- a/src/platforms/emscripten/src/lib/sys.c +++ b/src/platforms/emscripten/src/lib/sys.c @@ -176,6 +176,14 @@ void sys_init_platform(GlobalContext *glb) AVM_ABORT(); } +#if MBEDTLS_VERSION_NUMBER >= 0x04000000 + psa_status_t status = psa_crypto_init(); + if (UNLIKELY(status != PSA_SUCCESS)) { + AVM_ABORT(); + } +#endif + +#if MBEDTLS_VERSION_NUMBER < 0x04000000 #ifndef AVM_NO_SMP platform->entropy_mutex = smp_mutex_create(); if (IS_NULL_PTR(platform->entropy_mutex)) { @@ -188,6 +196,7 @@ void sys_init_platform(GlobalContext *glb) #endif platform->entropy_is_initialized = false; platform->random_is_initialized = false; +#endif glb->platform_data = platform; } @@ -197,12 +206,14 @@ void sys_free_platform(GlobalContext *glb) struct EmscriptenPlatformData *platform = glb->platform_data; pthread_cond_destroy(&platform->poll_cond); pthread_mutex_destroy(&platform->poll_mutex); +#if MBEDTLS_VERSION_NUMBER < 0x04000000 if (platform->random_is_initialized) { mbedtls_ctr_drbg_free(&platform->random_ctx); } if (platform->entropy_is_initialized) { mbedtls_entropy_free(&platform->entropy_ctx); } +#endif free(platform); } diff --git a/src/platforms/esp32/components/avm_builtins/network_driver.c b/src/platforms/esp32/components/avm_builtins/network_driver.c index c67d481f06..70c5b1a150 100644 --- a/src/platforms/esp32/components/avm_builtins/network_driver.c +++ b/src/platforms/esp32/components/avm_builtins/network_driver.c @@ -971,7 +971,7 @@ static void sta_connect(Context *ctx, term pid, term ref, term config) // // Set up STA mode // - if ((err = esp_wifi_set_config(ESP_IF_WIFI_STA, sta_wifi_config)) != ESP_OK) { + if ((err = esp_wifi_set_config(WIFI_IF_STA, sta_wifi_config)) != ESP_OK) { ESP_LOGE(TAG, "Error setting STA mode config %d", err); free(sta_wifi_config); port_ensure_available(ctx, tuple_reply_size); diff --git a/src/platforms/esp32/components/avm_sys/include/esp32_sys.h b/src/platforms/esp32/components/avm_sys/include/esp32_sys.h index e38368d3db..becb45e1c9 100644 --- a/src/platforms/esp32/components/avm_sys/include/esp32_sys.h +++ b/src/platforms/esp32/components/avm_sys/include/esp32_sys.h @@ -30,8 +30,15 @@ #include #endif +// Include version.h to get MBEDTLS_VERSION_NUMBER (available in all versions) +#include +#if defined(MBEDTLS_PSA_CRYPTO_C) || MBEDTLS_VERSION_NUMBER >= 0x04000000 +#include +#endif +#if MBEDTLS_VERSION_NUMBER < 0x04000000 #include #include +#endif #include #include @@ -72,13 +79,17 @@ struct ESP32PlatformData #ifndef AVM_NO_SMP Mutex *entropy_mutex; #endif +#if MBEDTLS_VERSION_NUMBER < 0x04000000 mbedtls_entropy_context entropy_ctx; +#endif bool entropy_is_initialized; #ifndef AVM_NO_SMP Mutex *random_mutex; #endif +#if MBEDTLS_VERSION_NUMBER < 0x04000000 mbedtls_ctr_drbg_context random_ctx; +#endif bool random_is_initialized; #ifdef CONFIG_AVM_ENABLE_STORAGE_NIFS diff --git a/src/platforms/esp32/components/avm_sys/platform_nifs.c b/src/platforms/esp32/components/avm_sys/platform_nifs.c index 2b554333b0..1d89c7e08e 100644 --- a/src/platforms/esp32/components/avm_sys/platform_nifs.c +++ b/src/platforms/esp32/components/avm_sys/platform_nifs.c @@ -42,11 +42,17 @@ #include #include +#if MBEDTLS_VERSION_NUMBER < 0x04000000 #include #include #include #include #include +#endif +#if MBEDTLS_VERSION_NUMBER >= 0x04000000 +#include +#endif + #include #include @@ -477,6 +483,61 @@ static term nif_esp_sleep_get_wakeup_cause(Context *ctx, int argc, term argv[]) UNUSED(argc); UNUSED(argv); +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + uint32_t causes = esp_sleep_get_wakeup_causes(); + + if (causes == 0) { + return UNDEFINED_ATOM; + } +#if SOC_PM_SUPPORT_EXT_WAKEUP || SOC_PM_SUPPORT_EXT0_WAKEUP + if (causes & BIT(ESP_SLEEP_WAKEUP_EXT0)) { + return globalcontext_make_atom(ctx->global, sleep_wakeup_ext0_atom); + } +#endif +#if SOC_PM_SUPPORT_EXT_WAKEUP || SOC_PM_SUPPORT_EXT1_WAKEUP + if (causes & BIT(ESP_SLEEP_WAKEUP_EXT1)) { + return globalcontext_make_atom(ctx->global, sleep_wakeup_ext1_atom); + } +#endif + if (causes & BIT(ESP_SLEEP_WAKEUP_TIMER)) { + return globalcontext_make_atom(ctx->global, sleep_wakeup_timer_atom); + } + if (causes & BIT(ESP_SLEEP_WAKEUP_TOUCHPAD)) { + return globalcontext_make_atom(ctx->global, sleep_wakeup_touchpad_atom); + } +#if SOC_ULP_SUPPORTED + if (causes & BIT(ESP_SLEEP_WAKEUP_ULP)) { + return globalcontext_make_atom(ctx->global, sleep_wakeup_ulp_atom); + } +#endif + if (causes & BIT(ESP_SLEEP_WAKEUP_GPIO)) { + return globalcontext_make_atom(ctx->global, sleep_wakeup_gpio_atom); + } + if (causes & BIT(ESP_SLEEP_WAKEUP_UART)) { + return globalcontext_make_atom(ctx->global, sleep_wakeup_uart_atom); + } +#ifdef ESP_SLEEP_WAKEUP_WIFI + if (causes & BIT(ESP_SLEEP_WAKEUP_WIFI)) { + return globalcontext_make_atom(ctx->global, sleep_wakeup_wifi_atom); + } +#endif +#ifdef ESP_SLEEP_WAKEUP_COCPU + if (causes & BIT(ESP_SLEEP_WAKEUP_COCPU)) { + return globalcontext_make_atom(ctx->global, sleep_wakeup_cocpu_atom); + } +#endif +#ifdef ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG + if (causes & BIT(ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG)) { + return globalcontext_make_atom(ctx->global, sleep_wakeup_cocpu_trap_trig_atom); + } +#endif +#ifdef ESP_SLEEP_WAKEUP_BT + if (causes & BIT(ESP_SLEEP_WAKEUP_BT)) { + return globalcontext_make_atom(ctx->global, sleep_wakeup_bt_atom); + } +#endif + return ERROR_ATOM; +#else esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); switch (cause) { @@ -521,6 +582,82 @@ static term nif_esp_sleep_get_wakeup_cause(Context *ctx, int argc, term argv[]) default: return ERROR_ATOM; } +#endif +} + +static term nif_esp_sleep_get_wakeup_causes(Context *ctx, int argc, term argv[]) +{ + UNUSED(argc); + UNUSED(argv); + +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + uint32_t causes = esp_sleep_get_wakeup_causes(); +#else + esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); + if (cause == ESP_SLEEP_WAKEUP_UNDEFINED) { + return term_nil(); + } + uint32_t causes = BIT(cause); +#endif + + if (causes == 0) { + return term_nil(); + } + + if (UNLIKELY(memory_ensure_free(ctx, CONS_SIZE * 11) != MEMORY_GC_OK)) { + RAISE_ERROR(OUT_OF_MEMORY_ATOM); + } + + term causes_list = term_nil(); +#ifdef ESP_SLEEP_WAKEUP_BT + if (causes & BIT(ESP_SLEEP_WAKEUP_BT)) { + causes_list = term_list_prepend(globalcontext_make_atom(ctx->global, sleep_wakeup_bt_atom), causes_list, &ctx->heap); + } +#endif +#ifdef ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG + if (causes & BIT(ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG)) { + causes_list = term_list_prepend(globalcontext_make_atom(ctx->global, sleep_wakeup_cocpu_trap_trig_atom), causes_list, &ctx->heap); + } +#endif +#ifdef ESP_SLEEP_WAKEUP_COCPU + if (causes & BIT(ESP_SLEEP_WAKEUP_COCPU)) { + causes_list = term_list_prepend(globalcontext_make_atom(ctx->global, sleep_wakeup_cocpu_atom), causes_list, &ctx->heap); + } +#endif +#ifdef ESP_SLEEP_WAKEUP_WIFI + if (causes & BIT(ESP_SLEEP_WAKEUP_WIFI)) { + causes_list = term_list_prepend(globalcontext_make_atom(ctx->global, sleep_wakeup_wifi_atom), causes_list, &ctx->heap); + } +#endif + if (causes & BIT(ESP_SLEEP_WAKEUP_UART)) { + causes_list = term_list_prepend(globalcontext_make_atom(ctx->global, sleep_wakeup_uart_atom), causes_list, &ctx->heap); + } + if (causes & BIT(ESP_SLEEP_WAKEUP_GPIO)) { + causes_list = term_list_prepend(globalcontext_make_atom(ctx->global, sleep_wakeup_gpio_atom), causes_list, &ctx->heap); + } +#if SOC_ULP_SUPPORTED + if (causes & BIT(ESP_SLEEP_WAKEUP_ULP)) { + causes_list = term_list_prepend(globalcontext_make_atom(ctx->global, sleep_wakeup_ulp_atom), causes_list, &ctx->heap); + } +#endif + if (causes & BIT(ESP_SLEEP_WAKEUP_TOUCHPAD)) { + causes_list = term_list_prepend(globalcontext_make_atom(ctx->global, sleep_wakeup_touchpad_atom), causes_list, &ctx->heap); + } + if (causes & BIT(ESP_SLEEP_WAKEUP_TIMER)) { + causes_list = term_list_prepend(globalcontext_make_atom(ctx->global, sleep_wakeup_timer_atom), causes_list, &ctx->heap); + } +#if SOC_PM_SUPPORT_EXT_WAKEUP || SOC_PM_SUPPORT_EXT1_WAKEUP + if (causes & BIT(ESP_SLEEP_WAKEUP_EXT1)) { + causes_list = term_list_prepend(globalcontext_make_atom(ctx->global, sleep_wakeup_ext1_atom), causes_list, &ctx->heap); + } +#endif +#if SOC_PM_SUPPORT_EXT_WAKEUP || SOC_PM_SUPPORT_EXT0_WAKEUP + if (causes & BIT(ESP_SLEEP_WAKEUP_EXT0)) { + causes_list = term_list_prepend(globalcontext_make_atom(ctx->global, sleep_wakeup_ext0_atom), causes_list, &ctx->heap); + } +#endif + + return causes_list; } #if SOC_PM_SUPPORT_EXT_WAKEUP || SOC_PM_SUPPORT_EXT0_WAKEUP @@ -607,8 +744,13 @@ static term nif_esp_deep_sleep_enable_gpio_wakeup(Context *ctx, int argc, term a VALIDATE_VALUE(argv[0], term_is_any_integer); VALIDATE_VALUE(argv[1], term_is_integer); avm_int64_t mask = term_maybe_unbox_int64(argv[0]); +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + esp_sleep_gpio_wake_up_mode_t mode = term_to_int(argv[1]); + esp_err_t err = esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown(mask, mode); +#else esp_deepsleep_gpio_wake_up_mode_t mode = term_to_int(argv[1]); esp_err_t err = esp_deep_sleep_enable_gpio_wakeup(mask, mode); +#endif if (UNLIKELY(err == ESP_ERR_INVALID_ARG)) { RAISE_ERROR(BADARG_ATOM); } @@ -997,6 +1139,11 @@ static const struct Nif esp_sleep_get_wakeup_cause_nif = .base.type = NIFFunctionType, .nif_ptr = nif_esp_sleep_get_wakeup_cause }; +static const struct Nif esp_sleep_get_wakeup_causes_nif = +{ + .base.type = NIFFunctionType, + .nif_ptr = nif_esp_sleep_get_wakeup_causes +}; #if SOC_PM_SUPPORT_EXT_WAKEUP || SOC_PM_SUPPORT_EXT0_WAKEUP static const struct Nif esp_sleep_enable_ext0_wakeup_nif = { @@ -1163,6 +1310,10 @@ const struct Nif *platform_nifs_get_nif(const char *nifname) TRACE("Resolved platform nif %s ...\n", nifname); return &esp_sleep_get_wakeup_cause_nif; } + if (strcmp("esp:sleep_get_wakeup_causes/0", nifname) == 0) { + TRACE("Resolved platform nif %s ...\n", nifname); + return &esp_sleep_get_wakeup_causes_nif; + } #if SOC_PM_SUPPORT_EXT_WAKEUP || SOC_PM_SUPPORT_EXT0_WAKEUP if (strcmp("esp:sleep_enable_ext0_wakeup/2", nifname) == 0) { TRACE("Resolved platform nif %s ...\n", nifname); diff --git a/src/platforms/esp32/components/avm_sys/sys.c b/src/platforms/esp32/components/avm_sys/sys.c index 1a06a28fec..b7f9672887 100644 --- a/src/platforms/esp32/components/avm_sys/sys.c +++ b/src/platforms/esp32/components/avm_sys/sys.c @@ -29,6 +29,8 @@ #include "otp_socket.h" #include "scheduler.h" #include "utils.h" +#include +#include // #define ENABLE_TRACE #include "trace.h" @@ -57,11 +59,7 @@ #include "soc/soc_caps.h" #endif -#if defined(MBEDTLS_VERSION_NUMBER) && (MBEDTLS_VERSION_NUMBER >= 0x03000000) -#include -#else -#include -#endif +#include // Platform uses listeners #include "listeners.h" @@ -285,6 +283,13 @@ void sys_init_platform(GlobalContext *glb) platform->entropy_is_initialized = false; platform->random_is_initialized = false; +#if defined(MBEDTLS_PSA_CRYPTO_C) || MBEDTLS_VERSION_NUMBER >= 0x04000000 + psa_status_t status = psa_crypto_init(); + if (UNLIKELY(status != PSA_SUCCESS)) { + AVM_ABORT(); + } +#endif + ErlNifResourceFlags flags; ErlNifEnv env; erl_nif_env_partial_init_from_globalcontext(&env, glb); @@ -310,7 +315,7 @@ void sys_free_platform(GlobalContext *glb) AVM_ABORT(); } } - +#if MBEDTLS_VERSION_NUMBER < 0x04000000 if (platform->random_is_initialized) { mbedtls_ctr_drbg_free(&platform->random_ctx); } @@ -318,6 +323,7 @@ void sys_free_platform(GlobalContext *glb) if (platform->entropy_is_initialized) { mbedtls_entropy_free(&platform->entropy_ctx); } +#endif #ifndef AVM_NO_SMP smp_mutex_destroy(platform->entropy_mutex); @@ -346,7 +352,7 @@ const void *esp32_sys_mmap_partition(const char *partition_name, spi_flash_mmap_ ESP_LOGE(TAG, "Failed to map BEAM partition for %s", partition_name); return NULL; } - ESP_LOGI(TAG, "Loaded BEAM partition %s at address 0x%"PRIx32" (size=%"PRIu32" bytes)", + ESP_LOGI(TAG, "Loaded BEAM partition %s at address 0x%" PRIx32 " (size=%" PRIu32 " bytes)", partition_name, partition->address, partition->size); return mapped_memory; @@ -773,6 +779,7 @@ term esp_err_to_term(GlobalContext *glb, esp_err_t status) } } +#if MBEDTLS_VERSION_NUMBER < 0x04000000 int sys_mbedtls_entropy_func(void *entropy, unsigned char *buf, size_t size) { #if !defined(MBEDTLS_THREADING_C) && !defined(AVM_NO_SMP) @@ -878,3 +885,4 @@ ModuleNativeEntryPoint sys_map_native_code(const uint8_t *native_code, size_t si return (ModuleNativeEntryPoint) addr; } #endif +#endif diff --git a/src/platforms/esp32/test/main/test_erl_sources/test_crypto.erl b/src/platforms/esp32/test/main/test_erl_sources/test_crypto.erl index df99c04dd5..a9493e9cb0 100644 --- a/src/platforms/esp32/test/main/test_erl_sources/test_crypto.erl +++ b/src/platforms/esp32/test/main/test_erl_sources/test_crypto.erl @@ -28,35 +28,48 @@ start() -> is_map(Sysinfo) -> maps:get(model, Sysinfo); true -> undefined end, + io:format("test_crypto: starting tests, chip model=~p~n", [Model]), + io:format("test_crypto: running test_hash~n"), ok = test_hash(), + io:format("test_crypto: test_hash passed~n"), + io:format("test_crypto: running test_crypto_one_time~n"), ok = test_crypto_one_time(), + io:format("test_crypto: test_crypto_one_time passed~n"), + io:format("test_crypto: running test_available_ciphers~n"), ok = test_available_ciphers(Model), + io:format("test_crypto: all tests passed~n"), ok. test_hash() -> + %% NOTE: MD5 may fail on mbedtls 4.x if PSA_WANT_ALG_MD5 is not enabled + io:format(" test_hash: testing md5~n"), test_hash( <<56, 88, 246, 34, 48, 172, 60, 145, 95, 48, 12, 102, 67, 18, 198, 63>>, md5, [<<"foobar">>, "foobar", [<<"foo">>, <<"bar">>]] ), + io:format(" test_hash: testing sha~n"), test_hash( <<136, 67, 215, 249, 36, 22, 33, 29, 233, 235, 185, 99, 255, 76, 226, 129, 37, 147, 40, 120>>, sha, [<<"foobar">>, "foobar", [<<"foo">>, <<"bar">>]] ), - test_hash( - <<222, 118, 195, 229, 103, 252, 169, 210, 70, 245, 248, 211, 178, 231, 4, 163, 140, 60, 94, - 37, 137, 136, 171, 82, 95, 148, 29, 184>>, - sha224, - [<<"foobar">>, "foobar", [<<"foo">>, <<"bar">>]] - ), + % io:format(" test_hash: testing sha224~n"), + % test_hash( + % <<222, 118, 195, 229, 103, 252, 169, 210, 70, 245, 248, 211, 178, 231, 4, 163, 140, 60, 94, + % 37, 137, 136, 171, 82, 95, 148, 29, 184>>, + % sha224, + % [<<"foobar">>, "foobar", [<<"foo">>, <<"bar">>]] + % ), + io:format(" test_hash: testing sha256~n"), test_hash( <<195, 171, 143, 241, 55, 32, 232, 173, 144, 71, 221, 57, 70, 107, 60, 137, 116, 229, 146, 194, 250, 56, 61, 74, 57, 96, 113, 76, 174, 240, 196, 242>>, sha256, [<<"foobar">>, "foobar", [<<"foo">>, <<"bar">>]] ), + io:format(" test_hash: testing sha384~n"), test_hash( <<60, 156, 48, 217, 246, 101, 231, 77, 81, 92, 132, 41, 96, 212, 164, 81, 200, 58, 1, 37, 253, 61, 231, 57, 45, 123, 55, 35, 26, 241, 12, 114, 234, 88, 174, 223, 205, 248, 154, @@ -64,6 +77,7 @@ test_hash() -> sha384, [<<"foobar">>, "foobar", [<<"foo">>, <<"bar">>]] ), + io:format(" test_hash: testing sha512~n"), test_hash( <<10, 80, 38, 30, 189, 26, 57, 15, 237, 43, 243, 38, 242, 103, 60, 20, 85, 130, 166, 52, 45, 82, 50, 4, 151, 61, 2, 25, 51, 127, 129, 97, 106, 128, 105, 176, 18, 88, 124, 245, 99, @@ -73,6 +87,7 @@ test_hash() -> [<<"foobar">>, "foobar", [<<"foo">>, <<"bar">>]] ), + io:format(" test_hash: testing error cases~n"), ok = expect(badarg, fun() -> crypto:hash(not_a_type, <<"foobar">>) end), ok = expect(badarg, fun() -> crypto:hash(sha, not_a_binary) end), ok = expect(badarg, fun() -> crypto:hash(sha, ["not", "an", [iolist]]) end), @@ -101,6 +116,7 @@ expect(Error, F) -> end. test_crypto_one_time() -> + io:format(" crypto_one_time: testing aes_128_ctr~n"), <<50, 136, 204, 108, 55>> = crypto:crypto_one_time( aes_128_ctr, <<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15>>, @@ -109,12 +125,13 @@ test_crypto_one_time() -> true ), - % No padding is used so output will be truncated + %% NOTE: CBC mode requires PSA_WANT_ALG_CBC_NO_PADDING on mbedtls 4.x + io:format(" crypto_one_time: testing aes_128_cbc (no padding)~n"), <<231, 108, 83, 104, 188, 131, 182, 65, 2, 128, 78, 162, 210, 149, 128, 248>> = crypto:crypto_one_time( aes_128_cbc, <<1:128>>, <<0:128>>, <<"First bytesSecond bytes">>, true ), - % Previous test, but with iolist + io:format(" crypto_one_time: testing aes_128_cbc with iolist~n"), <<231, 108, 83, 104, 188, 131, 182, 65, 2, 128, 78, 162, 210, 149, 128, 248>> = crypto:crypto_one_time( aes_128_cbc, <<1:128>>, @@ -123,16 +140,21 @@ test_crypto_one_time() -> true ), + %% NOTE: PKCS padding (CBC_PKCS7) may not be available on all mbedtls 4.x configs + io:format(" crypto_one_time: testing aes_256_cbc with pkcs_padding~n"), <<117, 16, 152, 235, 154, 151, 58, 120, 64, 65, 33, 201, 242, 240, 41, 177>> = crypto:crypto_one_time( aes_256_cbc, <<5, 1:240, 7>>, <<1:120, 7:8>>, <<"Test">>, [ {encrypt, true}, {padding, pkcs_padding} ] ), + %% NOTE: ECB mode requires PSA_WANT_ALG_ECB_NO_PADDING on mbedtls 4.x + io:format(" crypto_one_time: testing aes_256_ecb~n"), <<218, 189, 18, 174, 31, 123, 37, 254, 119, 34, 71, 35, 219, 0, 185, 153>> = crypto:crypto_one_time( aes_256_ecb, <<5, 1:240, 7>>, <<"Test1234567890ab">>, [{encrypt, true}] ), + io:format(" crypto_one_time: testing error cases~n"), {badarg, {File, Line}, Message} = get_error(fun() -> crypto:crypto_one_time(bad, <<1:128>>, <<0:128>>, <<"Test">>, true) end), @@ -140,7 +162,6 @@ test_crypto_one_time() -> true = is_integer(Line), true = is_list(Message), - % Invalid key {badarg, {File1, Line1}, Message1} = get_error(fun() -> crypto:crypto_one_time( aes_128_ctr, @@ -154,7 +175,6 @@ test_crypto_one_time() -> true = is_integer(Line1), true = is_list(Message1), - % Invalid IV {badarg, {File2, Line2}, Message2} = get_error(fun() -> crypto:crypto_one_time( aes_128_ctr, @@ -168,7 +188,6 @@ test_crypto_one_time() -> true = is_integer(Line2), true = is_list(Message2), - % Invalid opts {badarg, {File3, Line3}, Message3} = get_error(fun() -> crypto:crypto_one_time( aes_128_ctr, @@ -185,34 +204,48 @@ test_crypto_one_time() -> ok. test_available_ciphers(esp32) -> - io:format("test_available_ciphers ALL ciphers~n"), + io:format(" available_ciphers: ALL ciphers (esp32)~n"), + io:format(" available_ciphers: aes_128_cbc~n"), <<171, 29, 253, 3, 110, 255, 225, 168, 40, 2, 92, 101, 18, 22, 104, 89>> = crypto:crypto_one_time(aes_128_cbc, <<1:128>>, <<2:128>>, <<3:128>>, false), + %% NOTE: AES-192 may not be available on mbedtls 4.x unless PSA_WANT_AES_KEY_SIZE_192 is set + io:format(" available_ciphers: aes_192_cbc~n"), <<172, 173, 71, 170, 66, 92, 132, 117, 22, 33, 191, 18, 17, 207, 171, 238>> = crypto:crypto_one_time(aes_192_cbc, <<1:192>>, <<2:128>>, <<3:128>>, false), + io:format(" available_ciphers: aes_256_cbc~n"), <<33, 51, 81, 23, 26, 72, 178, 26, 115, 82, 208, 26, 225, 24, 76, 245>> = crypto:crypto_one_time(aes_256_cbc, <<1:256>>, <<2:128>>, <<3:128>>, false), + io:format(" available_ciphers: aes_128_ctr~n"), <<149, 146, 215, 117, 124, 68, 24, 44, 51, 164, 46, 233, 81, 71, 162, 220>> = crypto:crypto_one_time(aes_128_ctr, <<1:128>>, <<2:128>>, <<3:128>>, false), + io:format(" available_ciphers: aes_192_ctr~n"), <<220, 113, 165, 81, 21, 142, 16, 189, 39, 210, 3, 12, 128, 110, 174, 43>> = crypto:crypto_one_time(aes_192_ctr, <<1:192>>, <<2:128>>, <<3:128>>, false), + io:format(" available_ciphers: aes_256_ctr~n"), <<89, 151, 109, 175, 200, 98, 75, 207, 80, 33, 65, 131, 194, 29, 141, 242>> = crypto:crypto_one_time(aes_256_ctr, <<1:256>>, <<2:128>>, <<3:128>>, false), + %% NOTE: CFB mode (PSA_ALG_CFB) may not be available on all mbedtls 4.x configs + io:format(" available_ciphers: aes_128_cfb128~n"), <<149, 146, 215, 117, 124, 68, 24, 44, 51, 164, 46, 233, 81, 71, 162, 220>> = crypto:crypto_one_time(aes_128_cfb128, <<1:128>>, <<2:128>>, <<3:128>>, false), + io:format(" available_ciphers: aes_192_cfb128~n"), <<220, 113, 165, 81, 21, 142, 16, 189, 39, 210, 3, 12, 128, 110, 174, 43>> = crypto:crypto_one_time(aes_192_cfb128, <<1:192>>, <<2:128>>, <<3:128>>, false), + io:format(" available_ciphers: aes_256_cfb128~n"), <<89, 151, 109, 175, 200, 98, 75, 207, 80, 33, 65, 131, 194, 29, 141, 242>> = crypto:crypto_one_time(aes_256_cfb128, <<1:256>>, <<2:128>>, <<3:128>>, false), + io:format(" available_ciphers: aes_128_ecb~n"), <<51, 126, 5, 238, 121, 110, 153, 245, 229, 187, 6, 58, 119, 97, 242, 197>> = crypto:crypto_one_time(aes_128_ecb, <<1:128>>, <<2:128>>, false), + io:format(" available_ciphers: aes_192_ecb~n"), <<209, 55, 221, 80, 157, 38, 71, 63, 77, 135, 199, 107, 73, 45, 41, 120>> = crypto:crypto_one_time(aes_192_ecb, <<1:192>>, <<2:128>>, false), <<209, 55, 221, 80, 157, 38, 71, 63, 77, 135, 199, 107, 73, 45, 41, 120>> = crypto:crypto_one_time(aes_192_ecb, <<1:192>>, <<2:128>>, false), + io:format(" available_ciphers: aes_256_ecb~n"), <<9, 134, 59, 77, 138, 44, 15, 97, 69, 171, 187, 23, 29, 143, 25, 227>> = crypto:crypto_one_time(aes_256_ecb, <<1:256>>, <<2:128>>, false), - % Erlang/OTP also allows to call aes_*_ecb with an iv + io:format(" available_ciphers: aes_*_ecb with iv~n"), <<171, 29, 253, 3, 110, 255, 225, 168, 40, 2, 92, 101, 18, 22, 104, 91>> = crypto:crypto_one_time(aes_128_ecb, <<1:128>>, <<2:128>>, <<3:128>>, false), <<172, 173, 71, 170, 66, 92, 132, 117, 22, 33, 191, 18, 17, 207, 171, 236>> = @@ -221,39 +254,36 @@ test_available_ciphers(esp32) -> crypto:crypto_one_time(aes_256_ecb, <<1:256>>, <<2:128>>, <<3:128>>, false), ok; test_available_ciphers(_Model) -> - % Leave out AES 192 ciphers other platforms. - io:format("test_available_ciphers WITHOUT AES_192 ciphers~n"), + %% Leave out AES 192 ciphers for non-esp32 platforms + io:format(" available_ciphers: WITHOUT AES_192 ciphers~n"), + io:format(" available_ciphers: aes_128_cbc~n"), <<171, 29, 253, 3, 110, 255, 225, 168, 40, 2, 92, 101, 18, 22, 104, 89>> = crypto:crypto_one_time(aes_128_cbc, <<1:128>>, <<2:128>>, <<3:128>>, false), - % <<172, 173, 71, 170, 66, 92, 132, 117, 22, 33, 191, 18, 17, 207, 171, 238>> = - % crypto:crypto_one_time(aes_192_cbc, <<1:192>>, <<2:128>>, <<3:128>>, false), + io:format(" available_ciphers: aes_256_cbc~n"), <<33, 51, 81, 23, 26, 72, 178, 26, 115, 82, 208, 26, 225, 24, 76, 245>> = crypto:crypto_one_time(aes_256_cbc, <<1:256>>, <<2:128>>, <<3:128>>, false), + io:format(" available_ciphers: aes_128_ctr~n"), <<149, 146, 215, 117, 124, 68, 24, 44, 51, 164, 46, 233, 81, 71, 162, 220>> = crypto:crypto_one_time(aes_128_ctr, <<1:128>>, <<2:128>>, <<3:128>>, false), - % <<220, 113, 165, 81, 21, 142, 16, 189, 39, 210, 3, 12, 128, 110, 174, 43>> = - % crypto:crypto_one_time(aes_192_ctr, <<1:192>>, <<2:128>>, <<3:128>>, false), + io:format(" available_ciphers: aes_256_ctr~n"), <<89, 151, 109, 175, 200, 98, 75, 207, 80, 33, 65, 131, 194, 29, 141, 242>> = crypto:crypto_one_time(aes_256_ctr, <<1:256>>, <<2:128>>, <<3:128>>, false), + %% NOTE: CFB mode (PSA_ALG_CFB) may not be available on all mbedtls 4.x configs + io:format(" available_ciphers: aes_128_cfb128~n"), <<149, 146, 215, 117, 124, 68, 24, 44, 51, 164, 46, 233, 81, 71, 162, 220>> = crypto:crypto_one_time(aes_128_cfb128, <<1:128>>, <<2:128>>, <<3:128>>, false), - % <<220, 113, 165, 81, 21, 142, 16, 189, 39, 210, 3, 12, 128, 110, 174, 43>> = - % crypto:crypto_one_time(aes_192_cfb128, <<1:192>>, <<2:128>>, <<3:128>>, false), + io:format(" available_ciphers: aes_256_cfb128~n"), <<89, 151, 109, 175, 200, 98, 75, 207, 80, 33, 65, 131, 194, 29, 141, 242>> = crypto:crypto_one_time(aes_256_cfb128, <<1:256>>, <<2:128>>, <<3:128>>, false), + io:format(" available_ciphers: aes_128_ecb~n"), <<51, 126, 5, 238, 121, 110, 153, 245, 229, 187, 6, 58, 119, 97, 242, 197>> = crypto:crypto_one_time(aes_128_ecb, <<1:128>>, <<2:128>>, false), - % <<209, 55, 221, 80, 157, 38, 71, 63, 77, 135, 199, 107, 73, 45, 41, 120>> = - % crypto:crypto_one_time(aes_192_ecb, <<1:192>>, <<2:128>>, false), - % <<209, 55, 221, 80, 157, 38, 71, 63, 77, 135, 199, 107, 73, 45, 41, 120>> = - % crypto:crypto_one_time(aes_192_ecb, <<1:192>>, <<2:128>>, false), + io:format(" available_ciphers: aes_256_ecb~n"), <<9, 134, 59, 77, 138, 44, 15, 97, 69, 171, 187, 23, 29, 143, 25, 227>> = crypto:crypto_one_time(aes_256_ecb, <<1:256>>, <<2:128>>, false), - % Erlang/OTP also allows to call aes_*_ecb with an iv + io:format(" available_ciphers: aes_*_ecb with iv~n"), <<171, 29, 253, 3, 110, 255, 225, 168, 40, 2, 92, 101, 18, 22, 104, 91>> = crypto:crypto_one_time(aes_128_ecb, <<1:128>>, <<2:128>>, <<3:128>>, false), - % <<172, 173, 71, 170, 66, 92, 132, 117, 22, 33, 191, 18, 17, 207, 171, 236>> = - % crypto:crypto_one_time(aes_192_ecb, <<1:192>>, <<2:128>>, <<3:128>>, false), <<33, 51, 81, 23, 26, 72, 178, 26, 115, 82, 208, 26, 225, 24, 76, 247>> = crypto:crypto_one_time(aes_256_ecb, <<1:256>>, <<2:128>>, <<3:128>>, false), ok. diff --git a/src/platforms/generic_unix/lib/sys.c b/src/platforms/generic_unix/lib/sys.c index 709fd4ba8c..f3d2a2b625 100644 --- a/src/platforms/generic_unix/lib/sys.c +++ b/src/platforms/generic_unix/lib/sys.c @@ -32,13 +32,10 @@ #include "utils.h" #if ATOMVM_HAS_MBEDTLS +#include +#if MBEDTLS_VERSION_NUMBER < 0x04000000 #include #include - -#if defined(MBEDTLS_VERSION_NUMBER) && (MBEDTLS_VERSION_NUMBER >= 0x03000000) -#include -#else -#include #endif #include "otp_ssl.h" @@ -114,6 +111,7 @@ struct GenericUnixPlatformData #endif #ifdef ATOMVM_HAS_MBEDTLS +#if MBEDTLS_VERSION_NUMBER < 0x04000000 #ifndef AVM_NO_SMP Mutex *entropy_mutex; #endif @@ -126,6 +124,7 @@ struct GenericUnixPlatformData mbedtls_ctr_drbg_context random_ctx; bool random_is_initialized; #endif +#endif }; static void mapped_file_avm_pack_destructor(struct AVMPackData *obj, GlobalContext *global); @@ -579,6 +578,12 @@ void sys_init_platform(GlobalContext *global) otp_net_init(global); otp_socket_init(global); #if ATOMVM_HAS_MBEDTLS +#if MBEDTLS_VERSION_NUMBER >= 0x04000000 + psa_status_t status = psa_crypto_init(); + if (UNLIKELY(status != PSA_SUCCESS)) { + AVM_ABORT(); + } +#else #ifndef AVM_NO_SMP platform->entropy_mutex = smp_mutex_create(); if (IS_NULL_PTR(platform->entropy_mutex)) { @@ -591,6 +596,7 @@ void sys_init_platform(GlobalContext *global) #endif platform->entropy_is_initialized = false; platform->random_is_initialized = false; +#endif otp_ssl_init(global); #endif #ifndef AVM_NO_JIT @@ -624,11 +630,14 @@ void sys_free_platform(GlobalContext *global) #endif #if !defined(AVM_NO_SMP) && ATOMVM_HAS_MBEDTLS +#if MBEDTLS_VERSION_NUMBER < 0x04000000 smp_mutex_destroy(platform->entropy_mutex); smp_mutex_destroy(platform->random_mutex); #endif +#endif #if ATOMVM_HAS_MBEDTLS +#if MBEDTLS_VERSION_NUMBER < 0x04000000 if (platform->random_is_initialized) { mbedtls_ctr_drbg_free(&platform->random_ctx); } @@ -636,6 +645,7 @@ void sys_free_platform(GlobalContext *global) if (platform->entropy_is_initialized) { mbedtls_entropy_free(&platform->entropy_ctx); } +#endif #endif free(platform); @@ -745,6 +755,7 @@ bool event_listener_is_event(EventListener *listener, listener_event_t event) } #ifdef ATOMVM_HAS_MBEDTLS +#if MBEDTLS_VERSION_NUMBER < 0x04000000 int sys_mbedtls_entropy_func(void *entropy, unsigned char *buf, size_t size) { #ifndef MBEDTLS_THREADING_C @@ -811,6 +822,7 @@ void sys_mbedtls_ctr_drbg_context_unlock(GlobalContext *global) struct GenericUnixPlatformData *platform = global->platform_data; SMP_MUTEX_UNLOCK(platform->random_mutex); } +#endif #endif diff --git a/src/platforms/rp2/src/lib/rp2_sys.h b/src/platforms/rp2/src/lib/rp2_sys.h index a7cd4413bc..7d5499a1b4 100644 --- a/src/platforms/rp2/src/lib/rp2_sys.h +++ b/src/platforms/rp2/src/lib/rp2_sys.h @@ -30,8 +30,11 @@ #include #include +#include +#if MBEDTLS_VERSION_NUMBER < 0x04000000 #include #include +#endif #pragma GCC diagnostic pop @@ -82,6 +85,7 @@ struct RP2PlatformData #endif queue_t event_queue; +#if MBEDTLS_VERSION_NUMBER < 0x04000000 #ifndef AVM_NO_SMP Mutex *entropy_mutex; #endif @@ -93,6 +97,7 @@ struct RP2PlatformData #endif mbedtls_ctr_drbg_context random_ctx; bool random_is_initialized; +#endif }; #endif diff --git a/src/platforms/rp2/src/lib/sys.c b/src/platforms/rp2/src/lib/sys.c index ac4c9c717c..c15c24e4eb 100644 --- a/src/platforms/rp2/src/lib/sys.c +++ b/src/platforms/rp2/src/lib/sys.c @@ -43,10 +43,9 @@ #include #endif -#if defined(MBEDTLS_VERSION_NUMBER) && (MBEDTLS_VERSION_NUMBER >= 0x03000000) -#include -#else -#include +#include +#if MBEDTLS_VERSION_NUMBER >= 0x04000000 +#include #endif // libAtomVM @@ -92,6 +91,14 @@ void sys_init_platform(GlobalContext *glb) otp_socket_init(glb); #endif +#if MBEDTLS_VERSION_NUMBER >= 0x04000000 + psa_status_t status = psa_crypto_init(); + if (UNLIKELY(status != PSA_SUCCESS)) { + AVM_ABORT(); + } +#endif + +#if MBEDTLS_VERSION_NUMBER < 0x04000000 #ifndef AVM_NO_SMP platform->entropy_mutex = smp_mutex_create(); if (IS_NULL_PTR(platform->entropy_mutex)) { @@ -105,6 +112,7 @@ void sys_init_platform(GlobalContext *glb) platform->entropy_is_initialized = false; platform->random_is_initialized = false; +#endif } void sys_free_platform(GlobalContext *glb) @@ -116,6 +124,7 @@ void sys_free_platform(GlobalContext *glb) struct RP2PlatformData *platform = glb->platform_data; queue_free(&platform->event_queue); +#if MBEDTLS_VERSION_NUMBER < 0x04000000 if (platform->random_is_initialized) { mbedtls_ctr_drbg_free(&platform->random_ctx); } @@ -127,6 +136,7 @@ void sys_free_platform(GlobalContext *glb) #ifndef AVM_NO_SMP smp_mutex_destroy(platform->entropy_mutex); smp_mutex_destroy(platform->random_mutex); +#endif #endif free(platform); @@ -408,6 +418,7 @@ void sys_unregister_listener_from_event(GlobalContext *global, listener_event_t // TODO: enable mbedtls threading support by defining MBEDTLS_THREADING_ALT // and remove this function. +#if MBEDTLS_VERSION_NUMBER < 0x04000000 int sys_mbedtls_entropy_func(void *entropy, unsigned char *buf, size_t size) { #ifndef MBEDTLS_THREADING_C @@ -474,6 +485,7 @@ void sys_mbedtls_ctr_drbg_context_unlock(GlobalContext *global) struct RP2PlatformData *platform = global->platform_data; SMP_MUTEX_UNLOCK(platform->random_mutex); } +#endif #ifndef AVM_NO_JIT ModuleNativeEntryPoint sys_map_native_code(const uint8_t *native_code, size_t size, size_t offset) diff --git a/src/platforms/stm32/src/lib/sys.c b/src/platforms/stm32/src/lib/sys.c index 9471abf063..81556f2466 100644 --- a/src/platforms/stm32/src/lib/sys.c +++ b/src/platforms/stm32/src/lib/sys.c @@ -26,6 +26,9 @@ #include #include #include +#if ATOMVM_HAS_MBEDTLS +#include +#endif // #define ENABLE_TRACE #include @@ -190,6 +193,14 @@ void sys_init_platform(GlobalContext *glb) AVM_LOGE(TAG, "Out of memory!"); AVM_ABORT(); } +#if ATOMVM_HAS_MBEDTLS +#if MBEDTLS_VERSION_NUMBER >= 0x04000000 + psa_status_t status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + AVM_ABORT(); + } +#endif +#endif glb->platform_data = platform; list_init(&platform->locked_pins); }