I'm developing a secure bootloader for the LPC55S28 and have run into a significant code size issue when implementing ECDSA signature verification.
Current Issue
My bootloader needs to verify ECDSA P-256 signatures, and it must fit within a 32KB flash region. When using mbedTLS for ECDSA verification (even with a minimal configuration that only enables ECDSA), my code size explodes from approximately 13KB to 56KB:
Name Run address Load address Size Type .text 0x0 n/a 56412 section mpi_mul_hlp 0x9ae2 n/a 6388 local function ecp_mod_p256 0x839c n/a 2032 local function shiftleft 0x2bd0 n/a 1792 local function MultprecCiosMul521_ct 0x4fdc n/a 1772 local function shiftright 0x2514 n/a 1724 local function double_scalar_multiplication 0x3fb4 n/a 1580 global function MultprecCiosMul_ct 0x1b4c n/a 1444 local function mbedtls_mpi_div_mpi 0xb69c n/a 1316 global function mbedtls_mpi_inv_mod 0xbdfa n/a 1090 global function precompute_double_scalar_LUT16 0x3aac n/a 1084 local function invert_mod_p384 0x4884 n/a 1062 local function ecp_double_jac 0x7d6c n/a 972 local function ecp_add_mixed 0xac8 n/a 912 local function mbedtls_ecp_muladd_restartable 0xea8 n/a 868 global function Jac_addition 0x33ec n/a 776 global function StrFormatPrintf 0x735c n/a 700 global function invert_mod_p521 0x4d14 n/a 616 local function invert_mod_p256 0x45e0 n/a 576 local function verify_ecdsa_signature 0x4a4 n/a 544 local function Jac_add_affine 0x36f4 n/a 536 global function ecdsa_verify_restartable 0x12c0 n/a 504 local function USART_Init 0x6404 n/a 460 global function mbedtls_mpi_gcd 0xbc4a n/a 432 global function CASPER_montadd 0x21f0 n/a 428 local function hashcrypt_sha_process_message_data 0x5ddc n/a 420 local function Jac_double 0x390c n/a 416 global function USART_SetBaudRate 0x6650 n/a 396 global function mbedtls_mpi_mul_mpi 0xb3d6 n/a 382 global function CLOCK_SetFLASHAccessCyclesForFreq 0x5888 n/a 380 global function __aeabi_uldivmod 0xd048 n/a 372 global function mbedtls_mpi_add_abs 0x96ba n/a 366 global function read_and_verify_toc 0x6c4 n/a 364 local function CASPER_ECC_SECP521R1_MulAdd 0x19f4 n/a 344 global function CASPER_half 0x239c n/a 340 local function lowpower_set_system_voltage 0x6024 n/a 340 local function mbedtls_mpi_shift_l 0x91bc n/a 330 global function mbedtls_mpi_sub_abs 0x98ba n/a 326 global function CASPER_ECC_SECP256R1_MulAdd 0x179c n/a 324 global function DbgConsole_Init 0x2b0 n/a 312 global function mbedtls_mpi_shift_r 0x9306 n/a 310 global function mbedtls_mpi_cmp_mpi 0x9540 n/a 310 global function __Vectors 0x0 n/a 304 global object g_pfnVectors 0x0 n/a 304 global object CASPER_ECC_SECP384R1_MulAdd 0x18e0 n/a 276 global function HAL_UartInitCommon 0x68cc n/a 272 local function mbedtls_mpi_cmp_abs 0x943c n/a 260 global function CASPER_montsub 0x20f0 n/a 256 local function CASPER_MEMCPY 0x14e0 n/a 252 global function fseek 0x6d50 n/a 248 global function ecp_normalize_jac 0x7c78 n/a 244 local function hashcrypt_sha_finalize 0xc5e2 n/a 238 local function lowpower_set_dcdc_power_profile 0x6178 n/a 236 local function mbedtls_mpi_copy 0x8cf6 n/a 210 global function ecp_modp 0x9f8 n/a 208 local function HASHCRYPT_SHA_Update 0xc7ac n/a 208 global function precompute_double_scalar_LUT4 0x3ee8 n/a 204 local function mbedtls_ecp_point_read_binary 0x930 n/a 200 global function malloc 0x6b2c n/a 200 global function mbedtls_mpi_write_binary 0x90f4 n/a 200 global function ConvertRadixNumToString 0x7208 n/a 194 local function HASHCRYPT_SHA_Finish 0xc87c n/a 184 global function mbedtls_int_div_int 0xb5e8 n/a 180 local function mbedtls_ecp_fix_negative 0x82f0 n/a 172 local function lowpower_set_voltage_for_process 0xc934 n/a 170 local function Jac_toAffine 0x3348 n/a 164 global function HASHCRYPT_DriverIRQHandler 0x5f80 n/a 164 global function ecp_group_load 0x81c2 n/a 162 local function CLOCK_AttachClk 0x56e8 n/a 160 global function add_sub_mpi 0x9a00 n/a 156 local function mbedtls_ecp_group_free 0x7966 n/a 152 global function lowpower_get_part_process_corner 0x6264 n/a 148 local function mbedtls_mpi_mul_int 0xb554 n/a 148 global function derive_mpi 0xc23c n/a 148 local function mpi_sub_hlp 0x9828 n/a 146 local function casper_select 0x15dc n/a 144 local function hashcrypt_get_data 0xc454 n/a 144 local function USART_WriteBlocking 0x67dc n/a 140 global function PrintGetPrecision 0x6fba n/a 140 local function mbedtls_mpi_mod_mpi 0xbbc0 n/a 138 global function mbedtls_ecp_group_load 0x1238 n/a 136 global function main 0x8ac n/a 132 global function mbedtls_mpi_grow 0x8c1c n/a 132 global function CLOCK_SetClkDiv 0x5788 n/a 128 global function CLOCK_SetupFROClocking 0x5808 n/a 128 global function USART_GetDefaultConfig 0x65d0 n/a 128 global function mbedtls_ecp_group_init 0x7888 n/a 126 global function jump_to_application 0x830 n/a 124 local function mbedtls_mpi_read_binary 0x907a n/a 122 global function CASPER_ecc_init 0x166c n/a 120 global function multiply_casper 0x32d0 n/a 120 local function _initio 0x6bf4 n/a 120 global function FLEXCOMM_SetPeriph 0xc3e0 n/a 116 local function CASPER_ECC_equal 0x16e4 n/a 112 global function _Cwritebuf 0x6ca8 n/a 108 global function hashcrypt_sha_one_block 0xc576 n/a 108 local function PrintGetWidth 0x6f50 n/a 106 local function DbgConsole_Vprintf 0x3e8 n/a 104 global function toMontgomery_ECC_P384 0x4cac n/a 104 local function mbedtls_mpi_bitlen 0x8f30 n/a 104 global function _fdopen 0xcee2 n/a 104 global function DbgConsole_PrintCallback 0x6ebe n/a 102 local function mbedtls_mpi_lsb 0x8e88 n/a 102 global function mpi_bigendian_to_host 0x9014 n/a 102 local function ResetISR 0x180 n/a 100 global function toMontgomery_ECC_P256 0x4820 n/a 100 local function SystemInit 0x6868 n/a 100 weak function HAL_UartSendBlocking 0x69dc n/a 100 global function FLEXCOMM_PeripheralIsPresent 0xc37c n/a 100 local function mbedtls_ecp_copy 0x7a48 n/a 98 global function toMontgomery_ECC_P521 0x4f7c n/a 96 local function RESET_ClearPeripheralReset 0x63a4 n/a 96 global function mbedtls_mpi_sub_mod 0x7b64 n/a 96 local function SerialManager_Init 0xcb56 n/a 96 global function SerialManager_OpenReadHandle 0xcc06 n/a 96 global function reverse_array 0x8138 n/a 94 local function HASHCRYPT_SHA 0xc6fe n/a 94 global function FLEXCOMM0_DriverIRQHandler 0x5aa0 n/a 92 global function FLEXCOMM1_DriverIRQHandler 0x5afc n/a 92 global function FLEXCOMM2_DriverIRQHandler 0x5b58 n/a 92 global function FLEXCOMM3_DriverIRQHandler 0x5bb4 n/a 92 global function FLEXCOMM4_DriverIRQHandler 0x5c10 n/a 92 global function FLEXCOMM5_DriverIRQHandler 0x5c6c n/a 92 global function FLEXCOMM6_DriverIRQHandler 0x5cc8 n/a 92 global function FLEXCOMM7_DriverIRQHandler 0x5d24 n/a 92 global function FLEXCOMM8_DriverIRQHandler 0x5d80 n/a 92 global function RESET_SetPeripheralReset 0x6348 n/a 92 global function mbedtls_mpi_add_mod 0x7bc4 n/a 92 local function mbedtls_mpi_lset 0x8dea n/a 92 global function BOARD_BootClockFROHF96M 0x6a98 n/a 88 global function mbedtls_mpi_shift_l_mod 0x7c20 n/a 88 local function fclose 0xcf9c n/a 88 global function mbedtls_mpi_resize_clear 0x8ca0 n/a 86 local function DbgConsole_SendDataReliable 0x25c n/a 84 global function calculate_sha256 0x450 n/a 84 local function mbedtls_ecp_set_zero 0x7aaa n/a 82 global function _fflush 0xcf4a n/a 82 global function ecp_add 0xe58 n/a 80 global function FLEXCOMM_Init 0x5a50 n/a 80 global function POWER_SetVoltageForFreq 0x62f8 n/a 80 global function HASHCRYPT_SHA_Init 0xc75c n/a 80 global function SerialManager_OpenWriteHandle 0xcbb6 n/a 80 global function calloc 0xcdc6 n/a 80 global function strlen 0xce54 n/a 78 global function FLEXCOMM_GetInstance 0x5a04 n/a 76 global function mbedtls_mpi_free 0x8bd0 n/a 76 global function CASPER_ECC_equal_to_zero 0x1754 n/a 72 global function mpi_uint_bigendian_to_host_c 0x8fb4 n/a 72 local function add32 0x8264 n/a 70 local function sub32 0x82aa n/a 70 local function ftell 0x6e48 n/a 68 global function PrintOutputdifFobpu 0x70aa n/a 68 local function PrintOutputxX 0x70ee n/a 68 local function mbedtls_mpi_cmp_int 0x9676 n/a 68 global function SerialManager_Write 0xcb12 n/a 68 local function mbedtls_mpi_get_bit 0x8e46 n/a 66 global function mbedtls_clz 0x8eee n/a 66 local function PrintGetRadixFromobpu 0x71c8 n/a 64 local function mbedtls_mpi_mul_mod 0x7b24 n/a 64 local function _deferredlazyseek 0xcea2 n/a 64 global function _do_fflush 0xd008 n/a 64 global function toc_verification_key 0xda84 n/a 64 local object PrintFilterLengthFlag 0x718a n/a 62 local function Serial_UartInit 0xcc86 n/a 62 global function setvbuf 0xce16 n/a 62 global function BOARD_InitDEBUG_UARTPins 0x6af0 n/a 60 global function _sbrk 0x6c6c n/a 60 global function fflush 0x6d14 n/a 60 global function hashcrypt_sha_check_input_args 0xc53a n/a 60 local function BOARD_InitDebugConsole 0x6a40 n/a 56 global function PrintIsobpu 0x7046 n/a 56 local function USART_EnableContinuousSCLK 0xc9fa n/a 56 local function SerialManager_StartWriting 0xcada n/a 56 local function Serial_UartWrite 0xccc4 n/a 56 global function HardFault_Handler 0x77f8 n/a 54 global function HAL_UartInit 0xca62 n/a 54 global function mbedtls_ecp_point_free 0x7932 n/a 52 global function mbedtls_ecp_keypair_free_o 0x79fe n/a 52 global function __aeabi_lowlevel_memset 0xd1f2 n/a 50 global function mbedtls_ecdsa_verify 0xc2e8 n/a 48 global function CLOCK_EnableClock 0xc34c n/a 48 local function free 0xcd96 n/a 48 global function mbedtls_ecp_get_type 0x782e n/a 46 global function IOCON_PinMuxSet 0xcd46 n/a 46 local function __assertion_failed 0x230 n/a 44 global function ecp_mpi_set1 0x120c n/a 44 local function DbgConsole_Printf 0x6f24 n/a 44 global function PrintIsdi 0x707e n/a 44 local function PrintIsfF 0x7132 n/a 44 local function PrintIsxX 0x715e n/a 44 local function mbedtls_ecp_point_init 0x785c n/a 44 global function mbedtls_ecp_keypair_init 0x7906 n/a 44 global function ecp_mpi_load 0x8196 n/a 44 local function hashcrypt_engine_init 0xc4e4 n/a 44 local function hashcrypt_sha_check_input_alg 0xc510 n/a 42 local function __aeabi_memcpy4 0xd1c8 n/a 42 global function __aeabi_memcpy8 0xd1c8 n/a 42 global function mbedtls_platform_zeroize 0x14b8 n/a 40 global function mbedtls_ecp_is_zero 0x7afc n/a 40 global function StrFormatExaminedi 0x72ca n/a 38 local function StrFormatExaminexX 0x72f0 n/a 38 local function StrFormatExamineobpu 0x7316 n/a 38 local function mbedtls_mpi_init 0x8baa n/a 38 global function casper_get_word 0x24f0 n/a 36 local function mbedtls_mpi_sub_mpi 0x9abe n/a 36 global function s_flexcommBaseAddrs 0xdbd8 n/a 36 local object s_flexcommResets 0xdc10 n/a 36 local object mpi_sint_abs 0x8dc8 n/a 34 local function mbedtls_mpi_add_mpi 0x9a9c n/a 34 global function HAL_UartGetStatus 0xca40 n/a 34 local function DisableGlobalIRQ 0xca98 n/a 34 local function POWER_DisablePD 0x56c8 n/a 32 local function ConvertPrecisionWidthToLength 0x733c n/a 32 local function EnableGlobalIRQ 0xcaba n/a 32 local function SerialManager_WriteBlocking 0xcc66 n/a 32 global function secp256r1_p 0xdac4 n/a 32 local object secp256r1_a 0xdae4 n/a 32 local object secp256r1_b 0xdb04 n/a 32 local object secp256r1_gx 0xdb24 n/a 32 local object secp256r1_gy 0xdb44 n/a 32 local object secp256r1_n 0xdb64 n/a 32 local object s_UsartAdapterBase 0xdc34 n/a 32 local object data_init 0x1e8 n/a 30 global function mbedtls_mpi_zeroize 0x8b8c n/a 30 local function mbedtls_ecdsa_free 0xc32e n/a 30 global function mbedtls_mpi_size 0x8f98 n/a 28 global function RESET_PeripheralReset 0xc9de n/a 28 global function fsl_assert_hook 0x6ea4 n/a 26 weak function __check_heap_overflow 0x6e8c n/a 24 global function mpi_uint_bigendian_to_host 0x8ffc n/a 24 local function mbedtls_ecdsa_can_do 0xc2d0 n/a 24 global function hashcrypt_save_running_hash 0xc6d0 n/a 24 local function mbedtls_ecp_keypair_free 0x7a32 n/a 22 global function mbedtls_ecdsa_init 0xc318 n/a 22 global function hashcrypt_restore_running_hash 0xc6e8 n/a 22 local function remove 0xcff4 n/a 20 global function bss_init 0x206 n/a 18 global function s_flexcommClocks 0xdbfc n/a 18 local object SystemInitHook 0xca32 n/a 14 weak function BOARD_InitPeripherals 0xccfc n/a 14 global function __main 0xcd80 n/a 14 global function BOARD_InitBootPeripherals 0xcd0a n/a 12 global function BOARD_InitBootPins 0xcd74 n/a 12 global function __aeabi_memcpy 0xd1be n/a 10 global function
As far as I know, the CASPER can't perform ECDSA verification on its own - it seems to require mbedTLS as a wrapper, which brings in all the additional code.
I've deactivated almost everything in the ksdk_mbedtls_config.h file.
Questions
Is there a way to use the CASPER hardware directly for ECDSA verification without the mbedTLS overhead?
Are there any ROM-based cryptographic functions in the LPC55S28 that could handle ECDSA verification?
Does anyone have a minimal implementation of ECDSA P-256 verification for the LPC55S28 that could fit within my 32KB constraint?
Are there alternatives to mbedTLS with a smaller footprint?