From 17ee1f273dc3fa973c22222fb2b4fd68a3ad2eb2 Mon Sep 17 00:00:00 2001 From: "Zhibin (Ryan) Wen" Date: Fri, 29 May 2026 21:14:49 +0800 Subject: [PATCH] feat: use PSA crypto with mbedTLS 4 Signed-off-by: Zhibin (Ryan) Wen --- src/nfc/crypto/aes.cpp | 95 ++++++++++++++++++++++++++ src/nfc/isoDEP/desfire_file_system.cpp | 37 +--------- src/nfc/layer/a/nfc_layer_a.cpp | 73 +++----------------- 3 files changed, 106 insertions(+), 99 deletions(-) diff --git a/src/nfc/crypto/aes.cpp b/src/nfc/crypto/aes.cpp index 460da4d..926be28 100644 --- a/src/nfc/crypto/aes.cpp +++ b/src/nfc/crypto/aes.cpp @@ -11,7 +11,14 @@ #include #include +#include + +#if MBEDTLS_VERSION_MAJOR >= 4 +#include +#include +#else #include +#endif namespace m5 { namespace nfc { @@ -29,6 +36,31 @@ void left_shift_128(const uint8_t in[16], uint8_t out[16]) } } +#if MBEDTLS_VERSION_MAJOR >= 4 +bool psa_import_aes_key(psa_key_id_t& key_id, const uint8_t key[16], const psa_algorithm_t alg, + const psa_key_usage_t usage) +{ + if (psa_crypto_init() != PSA_SUCCESS) { + M5_LIB_LOGE("PSA crypto init failed"); + return false; + } + + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attributes, 128); + psa_set_key_algorithm(&attributes, alg); + psa_set_key_usage_flags(&attributes, usage); + + const psa_status_t status = psa_import_key(&attributes, key, 16, &key_id); + psa_reset_key_attributes(&attributes); + if (status != PSA_SUCCESS) { + M5_LIB_LOGE("PSA AES import failed: %d", static_cast(status)); + return false; + } + return true; +} +#endif + } // namespace bool aes_ecb_encrypt(uint8_t out[16], const uint8_t key[16], const uint8_t in[16]) @@ -36,6 +68,23 @@ bool aes_ecb_encrypt(uint8_t out[16], const uint8_t key[16], const uint8_t in[16 if (!out || !key || !in) { return false; } +#if MBEDTLS_VERSION_MAJOR >= 4 + psa_key_id_t key_id = PSA_KEY_ID_NULL; + if (!psa_import_aes_key(key_id, key, PSA_ALG_ECB_NO_PADDING, PSA_KEY_USAGE_ENCRYPT)) { + std::memset(out, 0, 16); + return false; + } + + size_t out_len = 0; + const psa_status_t status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING, in, 16, out, 16, &out_len); + psa_destroy_key(key_id); + if (status != PSA_SUCCESS || out_len != 16) { + M5_LIB_LOGE("PSA AES ECB encrypt failed: %d", static_cast(status)); + std::memset(out, 0, 16); + return false; + } + return true; +#else mbedtls_aes_context aes; mbedtls_aes_init(&aes); if (mbedtls_aes_setkey_enc(&aes, key, 128) != 0) { @@ -52,6 +101,7 @@ bool aes_ecb_encrypt(uint8_t out[16], const uint8_t key[16], const uint8_t in[16 } mbedtls_aes_free(&aes); return true; +#endif } bool aes_cbc_crypt(uint8_t* out, const uint8_t key[16], const uint8_t iv_in[16], const uint8_t* in, const size_t len, @@ -60,6 +110,50 @@ bool aes_cbc_crypt(uint8_t* out, const uint8_t key[16], const uint8_t iv_in[16], if (!out || !key || !iv_in || (!in && len)) { return false; } + if (len % 16 != 0) { + return false; + } + if (len == 0) { + return true; + } +#if MBEDTLS_VERSION_MAJOR >= 4 + psa_key_id_t key_id = PSA_KEY_ID_NULL; + if (!psa_import_aes_key(key_id, key, PSA_ALG_CBC_NO_PADDING, + encrypt ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT)) { + std::memset(out, 0, len); + return false; + } + + std::vector tmp(len + PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE); + + psa_cipher_operation_t operation = psa_cipher_operation_init(); + psa_status_t status = encrypt ? psa_cipher_encrypt_setup(&operation, key_id, PSA_ALG_CBC_NO_PADDING) + : psa_cipher_decrypt_setup(&operation, key_id, PSA_ALG_CBC_NO_PADDING); + if (status == PSA_SUCCESS) { + status = psa_cipher_set_iv(&operation, iv_in, 16); + } + + size_t update_len = 0; + if (status == PSA_SUCCESS) { + status = psa_cipher_update(&operation, in, len, tmp.data(), len, &update_len); + } + + size_t finish_len = 0; + if (status == PSA_SUCCESS) { + status = psa_cipher_finish(&operation, tmp.data() + update_len, tmp.size() - update_len, &finish_len); + } + + psa_cipher_abort(&operation); + psa_destroy_key(key_id); + + if (status != PSA_SUCCESS || update_len + finish_len != len) { + M5_LIB_LOGE("PSA AES CBC crypt failed: %d", static_cast(status)); + std::memset(out, 0, len); + return false; + } + std::memcpy(out, tmp.data(), len); + return true; +#else mbedtls_aes_context aes; mbedtls_aes_init(&aes); if (encrypt) { @@ -87,6 +181,7 @@ bool aes_cbc_crypt(uint8_t* out, const uint8_t key[16], const uint8_t iv_in[16], } mbedtls_aes_free(&aes); return true; +#endif } bool cmac_subkeys(uint8_t k1[16], uint8_t k2[16], const uint8_t key[16]) diff --git a/src/nfc/isoDEP/desfire_file_system.cpp b/src/nfc/isoDEP/desfire_file_system.cpp index 817c310..8575db8 100644 --- a/src/nfc/isoDEP/desfire_file_system.cpp +++ b/src/nfc/isoDEP/desfire_file_system.cpp @@ -16,7 +16,6 @@ #include "nfc/apdu/apdu.hpp" #include #include -#include #include #include #include @@ -1362,22 +1361,12 @@ bool DESFireFileSystem::authenticateAES(const uint8_t key_no, const uint8_t key[ m5::nfc::crypto::secure_zero(ek_AB, sizeof(ek_AB)); }; { - mbedtls_aes_context aes; - mbedtls_aes_init(&aes); - if (mbedtls_aes_setkey_dec(&aes, key, 128) != 0) { - M5_LIB_LOGE("AuthAES setkey_dec failed"); - mbedtls_aes_free(&aes); - wipe(); - return false; - } uint8_t iv[16]{}; - if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, 16, iv, ek_rndB, rndB) != 0) { + if (!aes_cbc_crypt(rndB, key, iv, ek_rndB, 16, false)) { M5_LIB_LOGE("AuthAES crypt_cbc failed"); - mbedtls_aes_free(&aes); wipe(); return false; } - mbedtls_aes_free(&aes); } for (int i = 0; i < 15; ++i) { @@ -1393,23 +1382,13 @@ bool DESFireFileSystem::authenticateAES(const uint8_t key_no, const uint8_t key[ std::memcpy(plain_AB + 16, rndB_rot, 16); { - mbedtls_aes_context aes; - mbedtls_aes_init(&aes); - if (mbedtls_aes_setkey_enc(&aes, key, 128) != 0) { - M5_LIB_LOGE("AuthAES setkey_enc failed"); - mbedtls_aes_free(&aes); - wipe(); - return false; - } uint8_t iv[16]{}; std::memcpy(iv, ek_rndB, 16); - if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, sizeof(plain_AB), iv, plain_AB, ek_AB) != 0) { + if (!aes_cbc_crypt(ek_AB, key, iv, plain_AB, sizeof(plain_AB), true)) { M5_LIB_LOGE("AuthAES crypt_cbc failed"); - mbedtls_aes_free(&aes); wipe(); return false; } - mbedtls_aes_free(&aes); } auto cmd2 = make_native_wrap_command(0xAF, ek_AB, sizeof(ek_AB)); @@ -1427,23 +1406,13 @@ bool DESFireFileSystem::authenticateAES(const uint8_t key_no, const uint8_t key[ uint8_t rndA_rot_from_card[16]{}; { - mbedtls_aes_context aes; - mbedtls_aes_init(&aes); - if (mbedtls_aes_setkey_dec(&aes, key, 128) != 0) { - M5_LIB_LOGE("AuthAES setkey_dec failed"); - mbedtls_aes_free(&aes); - wipe(); - return false; - } uint8_t iv[16]{}; std::memcpy(iv, ek_AB + 16, 16); - if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, 16, iv, rx.data(), rndA_rot_from_card) != 0) { + if (!aes_cbc_crypt(rndA_rot_from_card, key, iv, rx.data(), 16, false)) { M5_LIB_LOGE("AuthAES crypt_cbc failed"); - mbedtls_aes_free(&aes); wipe(); return false; } - mbedtls_aes_free(&aes); } uint8_t rndA_rot[16]{}; diff --git a/src/nfc/layer/a/nfc_layer_a.cpp b/src/nfc/layer/a/nfc_layer_a.cpp index 3abeceb..72c3b13 100644 --- a/src/nfc/layer/a/nfc_layer_a.cpp +++ b/src/nfc/layer/a/nfc_layer_a.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -30,6 +29,8 @@ using namespace m5::nfc::ndef; namespace { +using m5::nfc::crypto::aes_cbc_crypt; + constexpr char dump_sector_header[] = "Sec[Blk]:00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F [Access]\n" "-----------------------------------------------------------------"; @@ -2247,21 +2248,11 @@ bool NFCLayerA::mifare_plus_authenticateAES(const uint16_t key_no, const mifare: uint8_t rndB[16]{}; { uint8_t iv[16]{}; - mbedtls_aes_context aes{}; - mbedtls_aes_init(&aes); - if (mbedtls_aes_setkey_dec(&aes, key.data(), 128) != 0) { - M5_LIB_LOGE("AuthAES setkey_dec failed"); - mbedtls_aes_free(&aes); - m5::nfc::crypto::secure_zero(rndB, sizeof(rndB)); - return false; - } - if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, sizeof(rndB), iv, step1_payload, rndB) != 0) { + if (!aes_cbc_crypt(rndB, key.data(), iv, step1_payload, sizeof(rndB), false)) { M5_LIB_LOGE("AuthAES crypt_cbc failed"); - mbedtls_aes_free(&aes); m5::nfc::crypto::secure_zero(rndB, sizeof(rndB)); return false; } - mbedtls_aes_free(&aes); } uint8_t rndA[16]{}; @@ -2281,27 +2272,14 @@ bool NFCLayerA::mifare_plus_authenticateAES(const uint16_t key_no, const mifare: cmd2[0] = 0x72; { uint8_t iv[16]{}; - mbedtls_aes_context aes{}; - mbedtls_aes_init(&aes); - if (mbedtls_aes_setkey_enc(&aes, key.data(), 128) != 0) { - M5_LIB_LOGE("AuthAES setkey_enc failed"); - mbedtls_aes_free(&aes); - m5::nfc::crypto::secure_zero(rndA, sizeof(rndA)); - m5::nfc::crypto::secure_zero(rndB, sizeof(rndB)); - m5::nfc::crypto::secure_zero(rndB_rot, sizeof(rndB_rot)); - m5::nfc::crypto::secure_zero(ab_plain, sizeof(ab_plain)); - return false; - } - if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, sizeof(ab_plain), iv, ab_plain, cmd2 + 1) != 0) { + if (!aes_cbc_crypt(cmd2 + 1, key.data(), iv, ab_plain, sizeof(ab_plain), true)) { M5_LIB_LOGE("AuthAES crypt_cbc failed"); - mbedtls_aes_free(&aes); m5::nfc::crypto::secure_zero(rndA, sizeof(rndA)); m5::nfc::crypto::secure_zero(rndB, sizeof(rndB)); m5::nfc::crypto::secure_zero(rndB_rot, sizeof(rndB_rot)); m5::nfc::crypto::secure_zero(ab_plain, sizeof(ab_plain)); return false; } - mbedtls_aes_free(&aes); } rx_len = sizeof(rx); @@ -2341,21 +2319,8 @@ bool NFCLayerA::mifare_plus_authenticateAES(const uint16_t key_no, const mifare: uint8_t ab_resp[32]{}; { uint8_t iv[16]{}; - mbedtls_aes_context aes{}; - mbedtls_aes_init(&aes); - if (mbedtls_aes_setkey_dec(&aes, key.data(), 128) != 0) { - M5_LIB_LOGE("AuthAES setkey_dec failed"); - mbedtls_aes_free(&aes); - m5::nfc::crypto::secure_zero(rndA, sizeof(rndA)); - m5::nfc::crypto::secure_zero(rndB, sizeof(rndB)); - m5::nfc::crypto::secure_zero(rndB_rot, sizeof(rndB_rot)); - m5::nfc::crypto::secure_zero(ab_plain, sizeof(ab_plain)); - m5::nfc::crypto::secure_zero(ab_resp, sizeof(ab_resp)); - return false; - } - if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, sizeof(ab_resp), iv, step2_payload, ab_resp) != 0) { + if (!aes_cbc_crypt(ab_resp, key.data(), iv, step2_payload, sizeof(ab_resp), false)) { M5_LIB_LOGE("AuthAES crypt_cbc failed"); - mbedtls_aes_free(&aes); m5::nfc::crypto::secure_zero(rndA, sizeof(rndA)); m5::nfc::crypto::secure_zero(rndB, sizeof(rndB)); m5::nfc::crypto::secure_zero(rndB_rot, sizeof(rndB_rot)); @@ -2363,7 +2328,6 @@ bool NFCLayerA::mifare_plus_authenticateAES(const uint16_t key_no, const mifare: m5::nfc::crypto::secure_zero(ab_resp, sizeof(ab_resp)); return false; } - mbedtls_aes_free(&aes); } uint8_t rndA_rot[16]{}; @@ -2397,31 +2361,19 @@ bool NFCLayerA::mifare_plus_authenticateAES(const uint16_t key_no, const mifare: { uint8_t iv[16]{}; - mbedtls_aes_context aes{}; - mbedtls_aes_init(&aes); - if (mbedtls_aes_setkey_enc(&aes, key.data(), 128) != 0) { - M5_LIB_LOGE("AuthAES setkey_enc failed"); - mbedtls_aes_free(&aes); - m5::nfc::crypto::secure_zero(kenc, sizeof(kenc)); - m5::nfc::crypto::secure_zero(kmac, sizeof(kmac)); - return false; - } - if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, sizeof(kenc), iv, kenc, kenc) != 0) { + if (!aes_cbc_crypt(kenc, key.data(), iv, kenc, sizeof(kenc), true)) { M5_LIB_LOGE("AuthAES crypt_cbc failed"); - mbedtls_aes_free(&aes); m5::nfc::crypto::secure_zero(kenc, sizeof(kenc)); m5::nfc::crypto::secure_zero(kmac, sizeof(kmac)); return false; } memset(iv, 0, sizeof(iv)); - if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, sizeof(kmac), iv, kmac, kmac) != 0) { + if (!aes_cbc_crypt(kmac, key.data(), iv, kmac, sizeof(kmac), true)) { M5_LIB_LOGE("AuthAES crypt_cbc failed"); - mbedtls_aes_free(&aes); m5::nfc::crypto::secure_zero(kenc, sizeof(kenc)); m5::nfc::crypto::secure_zero(kmac, sizeof(kmac)); return false; } - mbedtls_aes_free(&aes); } _mfp_session.authenticated = true; @@ -2562,13 +2514,6 @@ bool NFCLayerA::mifare_plus_read_plain_mac(const uint16_t block, const uint8_t c std::vector payload(rx + 1, rx + 1 + data_len); if (!plain) { - mbedtls_aes_context aes{}; - mbedtls_aes_init(&aes); - if (mbedtls_aes_setkey_dec(&aes, _mfp_session.kenc.data(), 128) != 0) { - M5_LIB_LOGE("AES setkey_dec failed"); - mbedtls_aes_free(&aes); - return false; - } for (uint8_t i = 0; i < count; ++i) { uint8_t iv[16]{}; const uint8_t ctr = (uint8_t)(r_ctr & 0xFF); @@ -2577,13 +2522,11 @@ bool NFCLayerA::mifare_plus_read_plain_mac(const uint16_t block, const uint8_t c iv[8] = ctr; memcpy(&iv[12], _mfp_session.ti.data(), 4); uint8_t* blk = payload.data() + i * 16; - if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, 16, iv, blk, blk) != 0) { + if (!aes_cbc_crypt(blk, _mfp_session.kenc.data(), iv, blk, 16, false)) { M5_LIB_LOGE("AES crypt_cbc failed"); - mbedtls_aes_free(&aes); return false; } } - mbedtls_aes_free(&aes); } out.insert(out.end(), payload.begin(), payload.end());