2525
2626#include < type_traits>
2727
28+ #include < mbedtls/version.h>
29+ #if (MBEDTLS_VERSION_NUMBER >= 0x04000000)
30+ // mbedTLS 4 / TF-PSA-Crypto gates legacy crypto APIs behind this macro.
31+ // Must be set before including md.h and private/* headers.
32+ #define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
33+ #endif
34+
35+ #include < mbedtls/error.h>
36+ #include < mbedtls/md.h>
37+ #include < mbedtls/pk.h>
38+ #include < mbedtls/platform_util.h>
39+ #if (MBEDTLS_VERSION_NUMBER >= 0x04000000)
40+ #include < mbedtls/private/bignum.h>
41+ #include < mbedtls/private/ccm.h>
42+ #include < mbedtls/private/ctr_drbg.h>
43+ #include < mbedtls/private/ecdsa.h>
44+ #include < mbedtls/private/ecp.h>
45+ #include < mbedtls/private/entropy.h>
46+ #include < mbedtls/private/pkcs5.h>
47+ #include < mbedtls/private/sha1.h>
48+ #include < mbedtls/private/sha256.h>
49+ #else
2850#include < mbedtls/bignum.h>
2951#include < mbedtls/ccm.h>
3052#include < mbedtls/ctr_drbg.h>
3153#include < mbedtls/ecdh.h>
3254#include < mbedtls/ecdsa.h>
3355#include < mbedtls/ecp.h>
3456#include < mbedtls/entropy.h>
35- #include < mbedtls/error.h>
3657#include < mbedtls/hkdf.h>
37- #include < mbedtls/md.h>
38- #include < mbedtls/pk.h>
3958#include < mbedtls/pkcs5.h>
4059#include < mbedtls/sha1.h>
4160#include < mbedtls/sha256.h>
61+ #endif // (MBEDTLS_VERSION_NUMBER >= 0x04000000)
4262#if defined(MBEDTLS_X509_CRT_PARSE_C)
4363#include < mbedtls/x509_crt.h>
4464#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
@@ -348,6 +368,98 @@ CHIP_ERROR HKDF_sha::HKDF_SHA256(const uint8_t * secret, const size_t secret_len
348368 VerifyOrReturnError (out_length > 0 , CHIP_ERROR_INVALID_ARGUMENT );
349369 VerifyOrReturnError (out_buffer != nullptr , CHIP_ERROR_INVALID_ARGUMENT );
350370
371+ #if (MBEDTLS_VERSION_NUMBER >= 0x04000000)
372+ // mbedtls_hkdf was removed in mbedTLS 4; implement HKDF-Extract/Expand with HMAC-SHA256.
373+ CHIP_ERROR error = CHIP_NO_ERROR ;
374+ const mbedtls_md_info_t * const md = mbedtls_md_info_from_type (MBEDTLS_MD_SHA256 );
375+ VerifyOrReturnError (md != nullptr , CHIP_ERROR_INTERNAL );
376+
377+ uint8_t prk[NUM_BYTES_IN_SHA256_HASH ];
378+ uint8_t t[NUM_BYTES_IN_SHA256_HASH ];
379+ uint8_t empty_salt[NUM_BYTES_IN_SHA256_HASH ] = { 0 };
380+ const uint8_t * const salt_ptr = (salt_length > 0 ) ? salt : empty_salt;
381+ const size_t salt_len = (salt_length > 0 ) ? salt_length : sizeof (empty_salt);
382+
383+ int result = mbedtls_md_hmac (md, Uint8::to_const_uchar (salt_ptr), salt_len, Uint8::to_const_uchar (secret), secret_length, prk);
384+ VerifyOrReturnError (result == 0 , CHIP_ERROR_INTERNAL );
385+
386+ mbedtls_md_context_t ctx;
387+ mbedtls_md_init (&ctx);
388+ // mbedTLS 4 rejects hmac=1 in mbedtls_md_setup(); HMAC needs a separate setup.
389+ result = mbedtls_md_setup (&ctx, md, /* hmac=*/ 0 );
390+ if (result != 0 )
391+ {
392+ error = CHIP_ERROR_INTERNAL ;
393+ goto exit;
394+ }
395+ result = mbedtls_md_hmac_setup (&ctx, md);
396+ if (result != 0 )
397+ {
398+ error = CHIP_ERROR_INTERNAL ;
399+ goto exit;
400+ }
401+
402+ {
403+ size_t done = 0 ;
404+ size_t t_len = 0 ;
405+ uint8_t counter = 1 ;
406+
407+ while (done < out_length)
408+ {
409+ result = mbedtls_md_hmac_starts (&ctx, prk, sizeof (prk));
410+ if (result != 0 )
411+ {
412+ error = CHIP_ERROR_INTERNAL ;
413+ goto exit;
414+ }
415+ if (t_len > 0 )
416+ {
417+ result = mbedtls_md_hmac_update (&ctx, t, t_len);
418+ if (result != 0 )
419+ {
420+ error = CHIP_ERROR_INTERNAL ;
421+ goto exit;
422+ }
423+ }
424+ result = mbedtls_md_hmac_update (&ctx, Uint8::to_const_uchar (info), info_length);
425+ if (result != 0 )
426+ {
427+ error = CHIP_ERROR_INTERNAL ;
428+ goto exit;
429+ }
430+ result = mbedtls_md_hmac_update (&ctx, &counter, 1 );
431+ if (result != 0 )
432+ {
433+ error = CHIP_ERROR_INTERNAL ;
434+ goto exit;
435+ }
436+ result = mbedtls_md_hmac_finish (&ctx, t);
437+ if (result != 0 )
438+ {
439+ error = CHIP_ERROR_INTERNAL ;
440+ goto exit;
441+ }
442+ t_len = sizeof (t);
443+
444+ const size_t to_copy = (out_length - done > t_len) ? t_len : (out_length - done);
445+ memcpy (out_buffer + done, t, to_copy);
446+ done += to_copy;
447+ counter++;
448+ if (counter == 0 )
449+ {
450+ error = CHIP_ERROR_INTERNAL ;
451+ goto exit;
452+ }
453+ }
454+ }
455+
456+ exit:
457+ _log_mbedTLS_error (result);
458+ mbedtls_md_free (&ctx);
459+ mbedtls_platform_zeroize (prk, sizeof (prk));
460+ mbedtls_platform_zeroize (t, sizeof (t));
461+ return error;
462+ #else
351463 const mbedtls_md_info_t * const md = mbedtls_md_info_from_type (MBEDTLS_MD_SHA256 );
352464 VerifyOrReturnError (md != nullptr , CHIP_ERROR_INTERNAL );
353465
@@ -357,6 +469,7 @@ CHIP_ERROR HKDF_sha::HKDF_SHA256(const uint8_t * secret, const size_t secret_len
357469 VerifyOrReturnError (result == 0 , CHIP_ERROR_INTERNAL );
358470
359471 return CHIP_NO_ERROR ;
472+ #endif // (MBEDTLS_VERSION_NUMBER >= 0x04000000)
360473}
361474
362475CHIP_ERROR HMAC_sha::HMAC_SHA256 (const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length,
@@ -393,11 +506,12 @@ CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t plen, c
393506{
394507 CHIP_ERROR error = CHIP_NO_ERROR ;
395508 int result = 0 ;
509+ #if (MBEDTLS_VERSION_NUMBER < 0x04000000) && (!defined(MBEDTLS_DEPRECATED_REMOVED) || MBEDTLS_VERSION_NUMBER < 0x03030000)
396510 const mbedtls_md_info_t * md_info;
397511 mbedtls_md_context_t md_ctxt;
398512 constexpr int use_hmac = 1 ;
399-
400- bool free_md_ctxt = false ;
513+ bool free_md_ctxt = false ;
514+ # endif
401515
402516 VerifyOrExit (password != nullptr , error = CHIP_ERROR_INVALID_ARGUMENT );
403517 VerifyOrExit (plen > 0 , error = CHIP_ERROR_INVALID_ARGUMENT );
@@ -407,6 +521,7 @@ CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t plen, c
407521 VerifyOrExit (key_length > 0 , error = CHIP_ERROR_INVALID_ARGUMENT );
408522 VerifyOrExit (output != nullptr , error = CHIP_ERROR_INVALID_ARGUMENT );
409523
524+ #if (MBEDTLS_VERSION_NUMBER < 0x04000000) && (!defined(MBEDTLS_DEPRECATED_REMOVED) || MBEDTLS_VERSION_NUMBER < 0x03030000)
410525 md_info = mbedtls_md_info_from_type (MBEDTLS_MD_SHA256 );
411526 VerifyOrExit (md_info != nullptr , error = CHIP_ERROR_INTERNAL );
412527
@@ -418,16 +533,22 @@ CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t plen, c
418533
419534 result = mbedtls_pkcs5_pbkdf2_hmac (&md_ctxt, Uint8::to_const_uchar (password), plen, Uint8::to_const_uchar (salt), slen,
420535 iteration_count, key_length, Uint8::to_uchar (output));
536+ #else
537+ result = mbedtls_pkcs5_pbkdf2_hmac_ext (MBEDTLS_MD_SHA256 , Uint8::to_const_uchar (password), plen, Uint8::to_const_uchar (salt),
538+ slen, iteration_count, key_length, Uint8::to_uchar (output));
539+ #endif
421540
422541 VerifyOrExit (result == 0 , error = CHIP_ERROR_INTERNAL );
423542
424543exit:
425544 _log_mbedTLS_error (result);
426545
546+ #if (MBEDTLS_VERSION_NUMBER < 0x04000000) && (!defined(MBEDTLS_DEPRECATED_REMOVED) || MBEDTLS_VERSION_NUMBER < 0x03030000)
427547 if (free_md_ctxt)
428548 {
429549 mbedtls_md_free (&md_ctxt);
430550 }
551+ #endif
431552
432553 return error;
433554}
@@ -724,8 +845,6 @@ CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr_buf, size_t csr_l
724845 CHIP_ERROR error = CHIP_NO_ERROR ;
725846 size_t pubkey_size = 0 ;
726847
727- mbedtls_ecp_keypair * keypair = nullptr ;
728-
729848 P256ECDSASignature signature;
730849 MutableByteSpan out_raw_sig_span (signature.Bytes (), signature.Capacity ());
731850
@@ -737,16 +856,26 @@ CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr_buf, size_t csr_l
737856
738857 // Verify the signature algorithm and public key type
739858 VerifyOrExit (csr.CHIP_CRYPTO_PAL_PRIVATE (sig_md) == MBEDTLS_MD_SHA256 , error = CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE );
740- VerifyOrExit (csr.CHIP_CRYPTO_PAL_PRIVATE (sig_pk) == MBEDTLS_PK_ECDSA , error = CHIP_ERROR_WRONG_KEY_TYPE );
741-
742- keypair = mbedtls_pk_ec (csr.CHIP_CRYPTO_PAL_PRIVATE_X509 (pk));
743-
744- // Copy the public key from the CSR
745- result = mbedtls_ecp_point_write_binary (&keypair->CHIP_CRYPTO_PAL_PRIVATE (grp), &keypair->CHIP_CRYPTO_PAL_PRIVATE (Q),
746- MBEDTLS_ECP_PF_UNCOMPRESSED , &pubkey_size, Uint8::to_uchar (pubkey), pubkey.Length ());
859+ #if (MBEDTLS_VERSION_NUMBER >= 0x04000000)
860+ VerifyOrExit (csr.CHIP_CRYPTO_PAL_PRIVATE (sig_pk) == MBEDTLS_PK_SIGALG_ECDSA , error = CHIP_ERROR_WRONG_KEY_TYPE );
747861
862+ // Tinycrypt builds omit the PSA crypto core; export the raw EC point from PK pub_raw.
863+ result = mbedtls_pk_write_pubkey_psa (&csr.CHIP_CRYPTO_PAL_PRIVATE_X509 (pk), Uint8::to_uchar (pubkey), pubkey.Length (),
864+ &pubkey_size);
748865 VerifyOrExit (result == 0 , error = CHIP_ERROR_INTERNAL );
749866 VerifyOrExit (pubkey_size == pubkey.Length (), error = CHIP_ERROR_INTERNAL );
867+ #else
868+ {
869+ mbedtls_ecp_keypair * keypair = mbedtls_pk_ec (csr.CHIP_CRYPTO_PAL_PRIVATE_X509 (pk));
870+ VerifyOrExit (keypair != nullptr , error = CHIP_ERROR_WRONG_KEY_TYPE );
871+
872+ result = mbedtls_ecp_point_write_binary (&keypair->CHIP_CRYPTO_PAL_PRIVATE (grp), &keypair->CHIP_CRYPTO_PAL_PRIVATE (Q),
873+ MBEDTLS_ECP_PF_UNCOMPRESSED , &pubkey_size, Uint8::to_uchar (pubkey), pubkey.Length ());
874+
875+ VerifyOrExit (result == 0 , error = CHIP_ERROR_INTERNAL );
876+ VerifyOrExit (pubkey_size == pubkey.Length (), error = CHIP_ERROR_INTERNAL );
877+ }
878+ #endif // (MBEDTLS_VERSION_NUMBER >= 0x04000000)
750879
751880 // Convert DER signature to raw signature
752881 error = EcdsaAsn1SignatureToRaw (kP256_FE_Length ,
@@ -1449,23 +1578,33 @@ CHIP_ERROR IsCertificateValidAtCurrentTime(const ByteSpan & certificate)
14491578CHIP_ERROR ExtractPubkeyFromX509Cert (const ByteSpan & certificate, Crypto::P256PublicKey & pubkey)
14501579{
14511580#if defined(MBEDTLS_X509_CRT_PARSE_C)
1452- CHIP_ERROR error = CHIP_NO_ERROR ;
1581+ CHIP_ERROR error = CHIP_NO_ERROR ;
1582+ size_t pubkey_size = 0 ;
14531583 mbedtls_x509_crt mbed_cert;
1454- mbedtls_uecc_keypair * keypair = nullptr ;
14551584
14561585 mbedtls_x509_crt_init (&mbed_cert);
14571586
14581587 int result = mbedtls_x509_crt_parse (&mbed_cert, Uint8::to_const_uchar (certificate.data ()), certificate.size ());
14591588 VerifyOrExit (result == 0 , error = CHIP_ERROR_INTERNAL );
14601589
1461- VerifyOrExit (mbedtls_pk_get_type (&(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509 (pk))) == MBEDTLS_PK_ECKEY ,
1462- error = CHIP_ERROR_INVALID_ARGUMENT );
1590+ #if (MBEDTLS_VERSION_NUMBER >= 0x04000000)
1591+ // Tinycrypt builds omit the PSA crypto core; export the raw EC point from PK pub_raw.
1592+ result = mbedtls_pk_write_pubkey_psa (&mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509 (pk), Uint8::to_uchar (pubkey.Bytes ()),
1593+ pubkey.Length (), &pubkey_size);
1594+ VerifyOrExit (result == 0 , error = CHIP_ERROR_INTERNAL );
1595+ VerifyOrExit (pubkey_size == pubkey.Length (), error = CHIP_ERROR_INTERNAL );
1596+ #else
1597+ {
1598+ mbedtls_uecc_keypair * keypair = nullptr ;
14631599
1464- keypair = (mbedtls_uecc_keypair *) (mbedtls_pk_ec (mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509 (pk)));
1465- Uint8::to_uchar (pubkey)[0 ] = 0x04 ; // uncompressed type
1466- memcpy (Uint8::to_uchar (pubkey) + 1 , keypair->public_key , 2 * NUM_ECC_BYTES );
1600+ VerifyOrExit (mbedtls_pk_get_type (&(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509 (pk))) == MBEDTLS_PK_ECKEY ,
1601+ error = CHIP_ERROR_INVALID_ARGUMENT );
14671602
1468- VerifyOrExit (result == 0 , error = CHIP_ERROR_INTERNAL );
1603+ keypair = (mbedtls_uecc_keypair *) (mbedtls_pk_ec (mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509 (pk)));
1604+ Uint8::to_uchar (pubkey)[0 ] = 0x04 ; // uncompressed type
1605+ memcpy (Uint8::to_uchar (pubkey) + 1 , keypair->public_key , 2 * NUM_ECC_BYTES );
1606+ }
1607+ #endif // (MBEDTLS_VERSION_NUMBER >= 0x04000000)
14691608
14701609exit:
14711610 _log_mbedTLS_error (result);
0 commit comments