77#ifdef UPDATE_SIGN
88
99#include " Updater_Signing.h"
10+ #include " mbedtls/build_info.h"
1011#include " mbedtls/pk.h"
12+ #include " mbedtls/md.h"
13+ #include " mbedtls/asn1.h"
14+ #if MBEDTLS_VERSION_MAJOR >= 4
15+ #include " psa/crypto.h"
16+ #else
1117#include " mbedtls/rsa.h"
1218#include " mbedtls/ecdsa.h"
1319#include " mbedtls/ecp.h"
14- #include " mbedtls/md.h"
15- #include " mbedtls/asn1.h"
20+ #endif
1621#include " esp32-hal-log.h"
1722
1823// ==================== UpdaterRSAVerifier (using mbedtls) ====================
1924
2025UpdaterRSAVerifier::UpdaterRSAVerifier (const uint8_t *pubkey, size_t pubkeyLen, int hashType) : _hashType(hashType), _valid(false ) {
26+ #if MBEDTLS_VERSION_MAJOR >= 4
27+ // mbedtls 4.x routes PK operations through PSA; PSA must be initialized before
28+ // any cryptographic operation, including parsing a public key.
29+ psa_status_t psa_ret = psa_crypto_init ();
30+ if (psa_ret != PSA_SUCCESS) {
31+ log_e (" PSA crypto init failed: %d" , (int )psa_ret);
32+ _ctx = nullptr ;
33+ return ;
34+ }
35+ #endif
36+
2137 _ctx = new mbedtls_pk_context;
2238 mbedtls_pk_init ((mbedtls_pk_context *)_ctx);
2339
@@ -29,10 +45,18 @@ UpdaterRSAVerifier::UpdaterRSAVerifier(const uint8_t *pubkey, size_t pubkeyLen,
2945 }
3046
3147 // Verify it's an RSA key
48+ #if MBEDTLS_VERSION_MAJOR >= 4
49+ // mbedtls_pk_get_type was removed in 4.x; use the PSA can_do query instead.
50+ if (!mbedtls_pk_can_do_psa ((mbedtls_pk_context *)_ctx, PSA_ALG_RSA_PSS_ANY_SALT (PSA_ALG_SHA_256), PSA_KEY_USAGE_VERIFY_HASH)) {
51+ log_e (" Public key is not RSA" );
52+ return ;
53+ }
54+ #else
3255 if (mbedtls_pk_get_type ((mbedtls_pk_context *)_ctx) != MBEDTLS_PK_RSA) {
3356 log_e (" Public key is not RSA" );
3457 return ;
3558 }
59+ #endif
3660
3761 _valid = true ;
3862 log_i (" RSA public key loaded successfully" );
@@ -65,21 +89,38 @@ bool UpdaterRSAVerifier::verify(SHA2Builder *hash, const void *signature, size_t
6589 hash->getBytes (hashBytes);
6690 size_t hash_size = hash->getHashSize ();
6791
68- // Use RSA-PSS verification to match bin_signing.py which signs with PSS padding
69- // and salt_length=PSS.MAX_LENGTH (which equals key_len - hash_size - 2)
92+ // RSA signatures are always exactly key_len bytes. The buffer may be
93+ // zero-padded to a larger size (e.g. 512), so use key_len as the actual
94+ // signature length to avoid MBEDTLS_ERR_PK_SIG_LEN_MISMATCH.
95+ #if MBEDTLS_VERSION_MAJOR >= 4
96+ // mbedtls 4.x removed mbedtls_rsa_get_len / direct RSA context access;
97+ // derive the modulus byte length from the PK bit length instead.
98+ size_t key_len = (mbedtls_pk_get_bitlen ((mbedtls_pk_context *)_ctx) + 7 ) / 8 ;
99+ #else
70100 mbedtls_rsa_context *rsa_ctx = mbedtls_pk_rsa (*(mbedtls_pk_context *)_ctx);
71101 if (!rsa_ctx) {
72102 log_e (" Failed to get RSA context" );
73103 return false ;
74104 }
105+ size_t key_len = mbedtls_rsa_get_len (rsa_ctx);
106+ #endif
75107
76- int key_len = (int )mbedtls_rsa_get_len (rsa_ctx);
77- if ((size_t )key_len > signatureLen) {
78- log_e (" Signature buffer (%u bytes) smaller than RSA key length (%d bytes)" , (unsigned )signatureLen, key_len);
108+ if (key_len == 0 || key_len > signatureLen) {
109+ log_e (" Signature buffer (%u bytes) smaller than RSA key length (%u bytes)" , (unsigned )signatureLen, (unsigned )key_len);
79110 return false ;
80111 }
112+
113+ // Use RSA-PSS verification to match bin_signing.py which signs with PSS padding
114+ // and salt_length=PSS.MAX_LENGTH (which equals key_len - hash_size - 2).
115+ #if MBEDTLS_VERSION_MAJOR >= 4
116+ // In mbedtls 4.x, MBEDTLS_PK_SIGALG_RSA_PSS maps to PSA_ALG_RSA_PSS_ANY_SALT,
117+ // which accepts any salt length used during signing. This matches the
118+ // PSS.MAX_LENGTH salt produced by bin_signing.py.
119+ int ret =
120+ mbedtls_pk_verify_ext (MBEDTLS_PK_SIGALG_RSA_PSS, (mbedtls_pk_context *)_ctx, md_type, hashBytes, hash_size, (const unsigned char *)signature, key_len);
121+ #else
81122 // PSS.MAX_LENGTH salt = key_len - hash_size - 2
82- int expected_salt_len = key_len - (int )hash_size - 2 ;
123+ int expected_salt_len = ( int ) key_len - (int )hash_size - 2 ;
83124 if (expected_salt_len < 0 ) {
84125 log_e (" RSA key too small for hash algorithm" );
85126 return false ;
@@ -89,12 +130,10 @@ bool UpdaterRSAVerifier::verify(SHA2Builder *hash, const void *signature, size_t
89130 pss_opts.mgf1_hash_id = md_type;
90131 pss_opts.expected_salt_len = expected_salt_len;
91132
92- // RSA signatures are always exactly key_len bytes. The buffer may be
93- // zero-padded to a larger size (e.g. 512), so use key_len as the actual
94- // signature length to avoid MBEDTLS_ERR_PK_SIG_LEN_MISMATCH.
95133 int ret = mbedtls_pk_verify_ext (
96134 MBEDTLS_PK_RSASSA_PSS, &pss_opts, (mbedtls_pk_context *)_ctx, md_type, hashBytes, hash_size, (const unsigned char *)signature, key_len
97135 );
136+ #endif
98137
99138 if (ret == 0 ) {
100139 log_i (" RSA signature verified successfully" );
@@ -108,6 +147,17 @@ bool UpdaterRSAVerifier::verify(SHA2Builder *hash, const void *signature, size_t
108147// ==================== UpdaterECDSAVerifier (using mbedtls) ====================
109148
110149UpdaterECDSAVerifier::UpdaterECDSAVerifier (const uint8_t *pubkey, size_t pubkeyLen, int hashType) : _hashType(hashType), _valid(false ) {
150+ #if MBEDTLS_VERSION_MAJOR >= 4
151+ // mbedtls 4.x routes PK operations through PSA; PSA must be initialized before
152+ // any cryptographic operation, including parsing a public key.
153+ psa_status_t psa_ret = psa_crypto_init ();
154+ if (psa_ret != PSA_SUCCESS) {
155+ log_e (" PSA crypto init failed: %d" , (int )psa_ret);
156+ _ctx = nullptr ;
157+ return ;
158+ }
159+ #endif
160+
111161 _ctx = new mbedtls_pk_context;
112162 mbedtls_pk_init ((mbedtls_pk_context *)_ctx);
113163
@@ -119,11 +169,19 @@ UpdaterECDSAVerifier::UpdaterECDSAVerifier(const uint8_t *pubkey, size_t pubkeyL
119169 }
120170
121171 // Verify it's an ECDSA key
172+ #if MBEDTLS_VERSION_MAJOR >= 4
173+ // mbedtls_pk_get_type was removed in 4.x; use the PSA can_do query instead.
174+ if (!mbedtls_pk_can_do_psa ((mbedtls_pk_context *)_ctx, PSA_ALG_ECDSA (PSA_ALG_SHA_256), PSA_KEY_USAGE_VERIFY_HASH)) {
175+ log_e (" Public key is not ECDSA" );
176+ return ;
177+ }
178+ #else
122179 mbedtls_pk_type_t type = mbedtls_pk_get_type ((mbedtls_pk_context *)_ctx);
123180 if (type != MBEDTLS_PK_ECKEY && type != MBEDTLS_PK_ECDSA) {
124181 log_e (" Public key is not ECDSA" );
125182 return ;
126183 }
184+ #endif
127185
128186 _valid = true ;
129187 log_i (" ECDSA public key loaded successfully" );
@@ -171,6 +229,8 @@ bool UpdaterECDSAVerifier::verify(SHA2Builder *hash, const void *signature, size
171229 }
172230 }
173231
232+ // mbedtls_pk_verify accepts the legacy DER-encoded ECDSA signature format in
233+ // both 3.x and 4.x, so the same call works across versions.
174234 int ret = mbedtls_pk_verify ((mbedtls_pk_context *)_ctx, md_type, hashBytes, hash->getHashSize (), sig_start, actualSigLen);
175235
176236 if (ret == 0 ) {
0 commit comments