mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-13 11:09:01 +00:00
NRF
This commit is contained in:
parent
6fc8d67f39
commit
64675f36f4
2
core/.gitignore
vendored
2
core/.gitignore
vendored
@ -11,3 +11,5 @@ mypy_report
|
||||
/CMakeLists.txt
|
||||
/cmake-build-debug/
|
||||
tools/gdb_scripts/*.log
|
||||
/embed/ble_bootloader/jlink.jdebug.user
|
||||
/embed/ble_firmware/jlink.jdebug.user
|
||||
|
@ -5,6 +5,8 @@ MAKE = make -j $(JOBS)
|
||||
SCONS = scons -Q -j $(JOBS)
|
||||
|
||||
BUILD_DIR = build
|
||||
BLE_BOOTLOADER_BUILD_DIR = $(BUILD_DIR)/ble_bootloader
|
||||
BLE_FIRMWARE_BUILD_DIR = $(BUILD_DIR)/ble_firmware
|
||||
BOARDLOADER_BUILD_DIR = $(BUILD_DIR)/boardloader
|
||||
BOOTLOADER_BUILD_DIR = $(BUILD_DIR)/bootloader
|
||||
BOOTLOADER_CI_BUILD_DIR = $(BUILD_DIR)/bootloader_ci
|
||||
@ -172,6 +174,13 @@ build: build_boardloader build_bootloader build_firmware build_prodtest build_un
|
||||
|
||||
build_embed: build_boardloader build_bootloader build_firmware # build boardloader, bootloader, firmware
|
||||
|
||||
|
||||
build_ble_bootloader: ## build ble_bootloader
|
||||
$(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" $(BLE_BOOTLOADER_BUILD_DIR)/ble_bootloader.bin
|
||||
|
||||
build_ble_firmware: ## build ble_firmware
|
||||
$(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" $(BLE_FIRMWARE_BUILD_DIR)/ble_firmware.bin
|
||||
|
||||
build_boardloader: ## build boardloader
|
||||
$(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" \
|
||||
CMAKELISTS="$(CMAKELISTS)" $(BOARDLOADER_BUILD_DIR)/boardloader.bin
|
||||
@ -224,9 +233,16 @@ build_cross: ## build mpy-cross port
|
||||
|
||||
## clean commands:
|
||||
|
||||
clean: clean_boardloader clean_bootloader clean_bootloader_emu clean_bootloader_ci clean_prodtest clean_reflash clean_firmware clean_unix clean_cross ## clean all
|
||||
clean: clean_ble_bootloader clean_ble_firmware clean_boardloader clean_bootloader clean_bootloader_emu clean_bootloader_ci clean_prodtest clean_reflash clean_firmware clean_unix clean_cross ## clean all
|
||||
rm -f ".sconsign.dblite"
|
||||
|
||||
|
||||
clean_ble_bootloader: ## clean ble_bootloader build
|
||||
rm -rf $(BLE_BOOTLOADER_BUILD_DIR)
|
||||
|
||||
clean_ble_firmware: ## clean ble_bootloader build
|
||||
rm -rf $(BLE_FIRMWARE_BUILD_DIR)
|
||||
|
||||
clean_boardloader: ## clean boardloader build
|
||||
rm -rf $(BOARDLOADER_BUILD_DIR)
|
||||
|
||||
@ -258,6 +274,24 @@ clean_cross: ## clean mpy-cross build
|
||||
|
||||
flash: flash_boardloader flash_bootloader flash_firmware ## flash everything using OpenOCD
|
||||
|
||||
flash_ble: flash_ble_bootloader flash_softdevice flash_ble_firmware
|
||||
|
||||
flash_ble_bootloader:
|
||||
@echo Flashing: $(BLE_BOOTLOADER_BUILD_DIR)/ble_bootloader.hex
|
||||
nrfjprog -f nrf52 --program $(BLE_BOOTLOADER_BUILD_DIR)/ble_bootloader.hex --sectorerase
|
||||
|
||||
flash_ble_firmware:
|
||||
@echo Flashing: $(BLE_FIRMWARE_BUILD_DIR)/ble_firmware_merged.hex
|
||||
nrfjprog -f nrf52 --program $(BLE_FIRMWARE_BUILD_DIR)/ble_firmware_merged.hex --sectorerase
|
||||
|
||||
flash_ble_bl_settings:
|
||||
@echo Flashing: $(BLE_BOOTLOADER_BUILD_DIR)/settings.hex
|
||||
nrfjprog -f nrf52 --program $(BLE_BOOTLOADER_BUILD_DIR)/settings.hex --sectorerase
|
||||
|
||||
flash_softdevice:
|
||||
@echo Flashing: s140_nrf52_7.2.0_softdevice.hex
|
||||
nrfjprog -f nrf52 --program embed/sdk/nrf52/components/softdevice/s140/hex/s140_nrf52_7.2.0_softdevice.hex --sectorerase
|
||||
|
||||
flash_boardloader: $(BOARDLOADER_BUILD_DIR)/boardloader.bin ## flash boardloader using OpenOCD
|
||||
$(OPENOCD) -c "init; reset halt; flash write_image erase $< $(BOARDLOADER_START); exit"
|
||||
|
||||
@ -282,6 +316,9 @@ flash_combine: $(PRODTEST_BUILD_DIR)/combined.bin ## flash combined using OpenOC
|
||||
flash_erase: ## erase all sectors in flash bank 0
|
||||
$(OPENOCD) -c "init; reset halt; flash info 0; flash erase_sector 0 0 last; flash erase_check 0; exit"
|
||||
|
||||
flash_erase_ble:
|
||||
nrfjprog -f nrf52 --eraseall
|
||||
|
||||
flash_read_storage: ## read storage sectors from flash
|
||||
$(OPENOCD) -c "init; flash read_bank 0 storage1.data 0x10000 65536; flash read_bank 0 storage2.data 0x110000 65536; exit"
|
||||
|
||||
@ -310,6 +347,10 @@ openocd: ## start openocd which connects to the device
|
||||
openocd_reset: ## cause a system reset using OpenOCD
|
||||
$(OPENOCD) -c "init; reset; exit"
|
||||
|
||||
# nrfjprog debug commands:
|
||||
nrfjprog_reset:
|
||||
nrfjprog -f nrf52 --reset
|
||||
|
||||
GDB = arm-none-eabi-gdb --nx -ex 'set remotetimeout unlimited' -ex 'set confirm off' -ex 'target remote 127.0.0.1:3333' -ex 'monitor reset halt'
|
||||
|
||||
gdb_boardloader: $(BOARDLOADER_BUILD_DIR)/boardloader.elf ## start remote gdb session to openocd with boardloader symbols
|
||||
|
341
core/SConscript.ble_bootloader
Normal file
341
core/SConscript.ble_bootloader
Normal file
@ -0,0 +1,341 @@
|
||||
# pylint: disable=E0602
|
||||
|
||||
import os
|
||||
import tools
|
||||
|
||||
TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T')
|
||||
CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0))
|
||||
|
||||
if TREZOR_MODEL in ('1', ):
|
||||
# skip boardloader build
|
||||
env = Environment()
|
||||
def build_ble_bootloader(target,source,env):
|
||||
print(f'BLE BOOTLOADER: nothing to build for Model {TREZOR_MODEL}')
|
||||
program_bin = env.Command(
|
||||
target='ble_bootloader.bin',
|
||||
source=None,
|
||||
action=build_ble_bootloader
|
||||
)
|
||||
Return()
|
||||
|
||||
CCFLAGS_MOD = ''
|
||||
CPPPATH_MOD = []
|
||||
CPPDEFINES_MOD = []
|
||||
SOURCE_MOD = []
|
||||
|
||||
CCFLAGS_MOD += '-Wno-sequence-point '
|
||||
|
||||
|
||||
if int(ARGUMENTS.get('PRODUCTION', 0)) == 0:
|
||||
# Build for monitor debug mode and RTT.
|
||||
DEBUG = True
|
||||
else:
|
||||
DEBUG = False
|
||||
|
||||
|
||||
|
||||
# C flags common to all targets
|
||||
CPPDEFINES_MOD += [
|
||||
'CONFIG_GPIO_AS_PINRESET',
|
||||
'FLOAT_ABI_HARD',
|
||||
'NRF52833_XXAA',
|
||||
('NRF_DFU_SETTINGS_VERSION','2'),
|
||||
'MBR_PRESENT',
|
||||
'SVC_INTERFACE_CALL_AS_NORMAL_FUNCTION',
|
||||
('__HEAP_SIZE','0'),
|
||||
|
||||
('uECC_ENABLE_VLI_API', '0'),
|
||||
('uECC_OPTIMIZATION_LEVEL', '3'),
|
||||
('uECC_SQUARE_FUNC', '0'),
|
||||
('uECC_SUPPORT_COMPRESSED_POINT', '0'),
|
||||
('uECC_VLI_NATIVE_LITTLE_ENDIAN', '1'),
|
||||
]
|
||||
|
||||
|
||||
|
||||
|
||||
CPPPATH_MOD += [
|
||||
]
|
||||
CPPDEFINES_MOD += [
|
||||
]
|
||||
SOURCE_MOD += [
|
||||
|
||||
]
|
||||
|
||||
CPPPATH_MOD += [
|
||||
'embed/sdk/nrf52/modules/nrfx/drivers/include',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/micro_ecc',
|
||||
'embed/sdk/nrf52/components/libraries/memobj',
|
||||
'embed/sdk/nrf52/components/libraries/crc32',
|
||||
'embed/sdk/nrf52/components/libraries/sha256',
|
||||
'embed/sdk/nrf52/components/libraries/experimental_section_vars',
|
||||
'embed/sdk/nrf52/components/libraries/mem_manager',
|
||||
'embed/sdk/nrf52/components/libraries/fstorage',
|
||||
'embed/sdk/nrf52/components/libraries/util',
|
||||
'embed/sdk/nrf52/modules/nrfx',
|
||||
'embed/sdk/nrf52/external/nrf_oberon/include',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/oberon',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/cifra',
|
||||
'embed/sdk/nrf52/components/libraries/atomic',
|
||||
'embed/sdk/nrf52/integration/nrfx',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/cc310_bl',
|
||||
'embed/sdk/nrf52/components/drivers_nrf/nrf_soc_nosd',
|
||||
'embed/sdk/nrf52/components/libraries/log/src',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/dfu',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/serial_dfu',
|
||||
'embed/sdk/nrf52/external/nrf_cc310_bl/include',
|
||||
'embed/sdk/nrf52/external/segger_rtt',
|
||||
'embed/sdk/nrf52/components/libraries/delay',
|
||||
'embed/sdk/nrf52/integration/nrfx/legacy',
|
||||
'embed/sdk/nrf52/modules/nrfx/hal',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/nrf_hw',
|
||||
'embed/sdk/nrf52/components/libraries/log',
|
||||
'embed/sdk/nrf52/external/nrf_oberon',
|
||||
'embed/sdk/nrf52/components/libraries/strerror',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/mbedtls',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/cc310',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader',
|
||||
'embed/sdk/nrf52/components/softdevice/mbr/headers',
|
||||
'embed/sdk/nrf52/components/libraries/crypto',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/optiga',
|
||||
'embed/sdk/nrf52/components/libraries/scheduler',
|
||||
'embed/sdk/nrf52/components/libraries/slip',
|
||||
'embed/sdk/nrf52/external/fprintf',
|
||||
'embed/sdk/nrf52/components/toolchain/cmsis/include',
|
||||
'embed/sdk/nrf52/components/libraries/balloc',
|
||||
'embed/sdk/nrf52/components/libraries/stack_info',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/nrf_sw',
|
||||
'embed/sdk/nrf52/modules/nrfx/mdk',
|
||||
'embed/sdk/nrf52/external/nrf_cc310/include',
|
||||
'embed/sdk/nrf52/external/nano-pb',
|
||||
'embed/sdk/nrf52/components/libraries/queue',
|
||||
'embed/sdk/nrf52/components/libraries/mutex',
|
||||
'embed/sdk/nrf52/components/libraries/ringbuf',
|
||||
|
||||
'embed/trezorhal/boards',
|
||||
]
|
||||
SOURCE_MOD += [
|
||||
]
|
||||
|
||||
|
||||
SOURCE_NRFHAL_AS = [
|
||||
'embed/sdk/nrf52/modules/nrfx/mdk/gcc_startup_nrf52833.S',
|
||||
]
|
||||
|
||||
|
||||
|
||||
SOURCE_NRFHAL = [
|
||||
'embed/sdk/nrf52/components/libraries/log/src/nrf_log_frontend.c',
|
||||
'embed/sdk/nrf52/components/libraries/log/src/nrf_log_str_formatter.c',
|
||||
'embed/sdk/nrf52/modules/nrfx/mdk/system_nrf52833.c',
|
||||
'embed/sdk/nrf52/components/libraries/util/app_error_weak.c',
|
||||
'embed/sdk/nrf52/components/libraries/scheduler/app_scheduler.c',
|
||||
'embed/sdk/nrf52/components/libraries/util/app_util_platform.c',
|
||||
'embed/sdk/nrf52/components/libraries/crc32/crc32.c',
|
||||
'embed/sdk/nrf52/components/libraries/sha256/sha256.c',
|
||||
'embed/sdk/nrf52/components/libraries/mem_manager/mem_manager.c',
|
||||
'embed/sdk/nrf52/components/libraries/util/nrf_assert.c',
|
||||
'embed/sdk/nrf52/components/libraries/atomic/nrf_atomic.c',
|
||||
'embed/sdk/nrf52/components/libraries/balloc/nrf_balloc.c',
|
||||
'embed/sdk/nrf52/external/fprintf/nrf_fprintf.c',
|
||||
'embed/sdk/nrf52/external/fprintf/nrf_fprintf_format.c',
|
||||
'embed/sdk/nrf52/components/libraries/fstorage/nrf_fstorage.c',
|
||||
'embed/sdk/nrf52/components/libraries/fstorage/nrf_fstorage_nvmc.c',
|
||||
'embed/sdk/nrf52/components/libraries/memobj/nrf_memobj.c',
|
||||
'embed/sdk/nrf52/components/libraries/queue/nrf_queue.c',
|
||||
'embed/sdk/nrf52/components/libraries/ringbuf/nrf_ringbuf.c',
|
||||
'embed/sdk/nrf52/components/libraries/strerror/nrf_strerror.c',
|
||||
'embed/sdk/nrf52/components/libraries/slip/slip.c',
|
||||
'embed/sdk/nrf52/integration/nrfx/legacy/nrf_drv_uart.c',
|
||||
'embed/sdk/nrf52/components/drivers_nrf/nrf_soc_nosd/nrf_nvic.c',
|
||||
'embed/sdk/nrf52/modules/nrfx/hal/nrf_nvmc.c',
|
||||
'embed/sdk/nrf52/components/drivers_nrf/nrf_soc_nosd/nrf_soc.c',
|
||||
'embed/sdk/nrf52/modules/nrfx/soc/nrfx_atomic.c',
|
||||
'embed/sdk/nrf52/modules/nrfx/drivers/src/prs/nrfx_prs.c',
|
||||
'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_uart.c',
|
||||
'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_uarte.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_ecc.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_ecdsa.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_hash.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_init.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_shared.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/nrf_bootloader_app_start.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/nrf_bootloader_app_start_final.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/nrf_bootloader_dfu_timers.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/nrf_bootloader_fw_activation.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/nrf_bootloader_info.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/nrf_bootloader_wdt.c',
|
||||
'embed/sdk/nrf52/external/nano-pb/pb_common.c',
|
||||
'embed/sdk/nrf52/external/nano-pb/pb_decode.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/dfu/dfu-cc.pb.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_flash.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_handling_error.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_mbr.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_req_handler.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_settings.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_transport.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_utils.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_validation.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.c',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/serial_dfu/nrf_dfu_serial.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecc.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdh.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdsa.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/nrf_sw/nrf_sw_backend_hash.c',
|
||||
]
|
||||
|
||||
SOURCE_BLE_BOOTLOADER = [
|
||||
'embed/ble_bootloader/main.c',
|
||||
'embed/ble_bootloader/uecc/uECC.c',
|
||||
'embed/ble_bootloader/dfu_public_key.c',
|
||||
# originally embed/sdk/nrf52/components/libraries/bootloader/serial_dfu/nrf_dfu_serial_uart.c',
|
||||
'embed/ble_bootloader/nrf_dfu_serial_uart.c',
|
||||
'embed/ble_bootloader/nrf_bootloader.c',
|
||||
]
|
||||
|
||||
if DEBUG:
|
||||
CPPDEFINES_MOD += [
|
||||
'DEBUG',
|
||||
'DEBUG_NRF',
|
||||
'NRF_DFU_DEBUG_VERSION',
|
||||
'MMD'
|
||||
]
|
||||
SOURCE_BLE_BOOTLOADER += [
|
||||
'embed/segger/SEGGER_MMD/JLINK_MONITOR.c',
|
||||
'embed/segger/SEGGER_MMD/JLINK_MONITOR_ISR_SES.S'
|
||||
]
|
||||
|
||||
SOURCE_NRFHAL += [
|
||||
'embed/sdk/nrf52/components/libraries/log/src/nrf_log_backend_rtt.c',
|
||||
'embed/sdk/nrf52/components/libraries/log/src/nrf_log_backend_serial.c',
|
||||
'embed/sdk/nrf52/components/libraries/log/src/nrf_log_backend_uart.c',
|
||||
'embed/sdk/nrf52/components/libraries/log/src/nrf_log_default_backends.c',
|
||||
'embed/sdk/nrf52/external/segger_rtt/SEGGER_RTT.c',
|
||||
'embed/sdk/nrf52/external/segger_rtt/SEGGER_RTT_Syscalls_GCC.c',
|
||||
'embed/sdk/nrf52/external/segger_rtt/SEGGER_RTT_printf.c',
|
||||
]
|
||||
|
||||
|
||||
CPPPATH_MOD += [
|
||||
'embed/segger/SEGGER_MMD'
|
||||
]
|
||||
|
||||
|
||||
|
||||
env = Environment(ENV=os.environ, CFLAGS='%s -DPRODUCTION=%s' % (ARGUMENTS.get('CFLAGS', ''), ARGUMENTS.get('PRODUCTION', '0')))
|
||||
|
||||
|
||||
env.Replace(
|
||||
CP='cp',
|
||||
AS='arm-none-eabi-as',
|
||||
AR='arm-none-eabi-ar',
|
||||
CC='arm-none-eabi-gcc',
|
||||
LINK='arm-none-eabi-gcc',
|
||||
SIZE='arm-none-eabi-size',
|
||||
STRIP='arm-none-eabi-strip',
|
||||
OBJCOPY='arm-none-eabi-objcopy',
|
||||
PYTHON='python',
|
||||
MAKECMAKELISTS='$PYTHON tools/make_cmakelists.py', )
|
||||
|
||||
env.Replace(
|
||||
TREZOR_MODEL=TREZOR_MODEL, )
|
||||
|
||||
CPU_ASFLAGS = '-mthumb -mabi=aapcs -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16'
|
||||
CPU_CCFLAGS = '-mthumb -mabi=aapcs -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 '
|
||||
|
||||
|
||||
|
||||
|
||||
env.Replace(
|
||||
COPT=env.get('ENV').get('OPTIMIZE', '-Og'),
|
||||
CCFLAGS='$COPT '
|
||||
'-g3 '
|
||||
'-std=c99 -Wall -Werror -Wdouble-promotion -Wpointer-arith -Wno-missing-braces -Wno-unused-function '
|
||||
'-fdata-sections -ffunction-sections '
|
||||
'-fno-strict-aliasing '
|
||||
'-fno-builtin '
|
||||
'-fshort-enums '
|
||||
+ CPU_CCFLAGS + CCFLAGS_MOD,
|
||||
LINKFLAGS='-Lembed/sdk/nrf52/modules/nrfx/mdk -T embed/ble_bootloader/memory.ld -Wl,--gc-sections --specs=nano.specs -Wl,-Map=build/ble_bootloader/ble_bootloader.map -Wl,--warn-common -Wl,--print-memory-usage',
|
||||
CPPPATH=[
|
||||
'embed/ble_bootloader',
|
||||
'embed/ble_bootloader/uecc',
|
||||
'embed/sdk/nrf52',
|
||||
] + CPPPATH_MOD,
|
||||
CPPDEFINES=[
|
||||
'BLE_BOOTLOADER',
|
||||
'TREZOR_MODEL_'+TREZOR_MODEL,
|
||||
] + CPPDEFINES_MOD,
|
||||
ASFLAGS=CPU_ASFLAGS,
|
||||
ASPPFLAGS='$CFLAGS $CCFLAGS', )
|
||||
|
||||
#
|
||||
# Program objects
|
||||
#
|
||||
|
||||
obj_program = []
|
||||
obj_program += env.Object(source=SOURCE_BLE_BOOTLOADER)
|
||||
obj_program += env.Object(source=SOURCE_NRFHAL_AS, COPT='-O0')
|
||||
obj_program += env.Object(source=SOURCE_NRFHAL)
|
||||
obj_program += env.Object(source=SOURCE_MOD)
|
||||
|
||||
env.Replace(
|
||||
ALLSOURCES=SOURCE_NRFHAL_AS + SOURCE_MOD + SOURCE_BLE_BOOTLOADER + SOURCE_NRFHAL,
|
||||
ALLDEFS=tools.get_defs_for_cmake(env['CPPDEFINES']))
|
||||
|
||||
cmake_gen = env.Command(
|
||||
target='CMakeLists.txt',
|
||||
source='',
|
||||
action='$MAKECMAKELISTS --sources $ALLSOURCES --dirs $CPPPATH --defs $ALLDEFS',
|
||||
)
|
||||
|
||||
|
||||
LIB_FILES = [
|
||||
'embed/sdk/nrf52/external/nrf_oberon/lib/cortex-m4/hard-float/liboberon_3.0.8.a',
|
||||
'embed/sdk/nrf52/external/nrf_cc310_bl/lib/cortex-m4/hard-float/libnrf_cc310_bl_0.9.13.a',
|
||||
]
|
||||
|
||||
program_elf = env.Command(
|
||||
target='ble_bootloader.elf',
|
||||
source=obj_program,
|
||||
action=
|
||||
'$LINK -o $TARGET $CCFLAGS $CFLAGS $LINKFLAGS $SOURCES ' + ' '.join(LIB_FILES) + ' -lc -lnosys -lm',
|
||||
)
|
||||
|
||||
|
||||
|
||||
BINARY_NAME = f"build/ble_bootloader/ble_bootloader-{tools.get_model_identifier(TREZOR_MODEL)}"
|
||||
BINARY_NAME += "-" + tools.get_version('embed/ble_bootloader/version.h')
|
||||
BINARY_NAME += "-" + tools.get_git_revision_short_hash()
|
||||
BINARY_NAME += "-dirty" if tools.get_git_modified() else ""
|
||||
BINARY_NAME += ".bin"
|
||||
|
||||
if CMAKELISTS != 0:
|
||||
env.Depends(program_elf, cmake_gen)
|
||||
|
||||
|
||||
|
||||
program_hex = env.Command(
|
||||
target='ble_bootloader.hex',
|
||||
source=program_elf,
|
||||
action='$OBJCOPY -O ihex $SOURCE $TARGET',
|
||||
)
|
||||
|
||||
program_bin = env.Command(
|
||||
target='ble_bootloader.bin',
|
||||
source=program_elf,
|
||||
action=[
|
||||
'$OBJCOPY -O binary $SOURCE $TARGET',
|
||||
'$CP $TARGET ' + BINARY_NAME,
|
||||
],
|
||||
)
|
||||
|
||||
program_settings = env.Command(
|
||||
target='settings.hex',
|
||||
source=None,
|
||||
action='$CP ./embed/ble_bootloader/settings.hex $TARGET',
|
||||
)
|
||||
|
||||
env.Depends(program_bin, program_hex)
|
||||
env.Depends(program_bin, program_settings)
|
495
core/SConscript.ble_firmware
Normal file
495
core/SConscript.ble_firmware
Normal file
@ -0,0 +1,495 @@
|
||||
# pylint: disable=E0602
|
||||
|
||||
import os
|
||||
import tools
|
||||
|
||||
TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T')
|
||||
CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0))
|
||||
|
||||
if TREZOR_MODEL in ('1', ):
|
||||
# skip boardloader build
|
||||
env = Environment()
|
||||
def build_ble_firmware(target,source,env):
|
||||
print(f'BLE FIRMWARE: nothing to build for Model {TREZOR_MODEL}')
|
||||
program_bin = env.Command(
|
||||
target='ble_firmware.bin',
|
||||
source=None,
|
||||
action=build_ble_firmware
|
||||
)
|
||||
Return()
|
||||
|
||||
CCFLAGS_MOD = ''
|
||||
CPPPATH_MOD = []
|
||||
CPPDEFINES_MOD = []
|
||||
SOURCE_MOD = []
|
||||
|
||||
CCFLAGS_MOD += '-Wno-sequence-point '
|
||||
|
||||
|
||||
if int(ARGUMENTS.get('PRODUCTION', 0)) == 0:
|
||||
# Build for monitor debug mode.
|
||||
MMD = True
|
||||
else:
|
||||
MMD = False
|
||||
|
||||
|
||||
|
||||
# C flags common to all targets
|
||||
CPPDEFINES_MOD += [
|
||||
'CONFIG_GPIO_AS_PINRESET',
|
||||
'FLOAT_ABI_HARD',
|
||||
'NRF52833_XXAA',
|
||||
'SOFTDEVICE_PRESENT',
|
||||
('NRF_SD_BLE_API_VERSION', '7'),
|
||||
'APP_TIMER_V2',
|
||||
'APP_TIMER_V2_RTC1_ENABLED',
|
||||
'S140',
|
||||
('__HEAP_SIZE','8192'),
|
||||
('__STACK_SIZE','8192'),
|
||||
|
||||
('uECC_ENABLE_VLI_API', '0'),
|
||||
('uECC_OPTIMIZATION_LEVEL', '3'),
|
||||
('uECC_SQUARE_FUNC', '0'),
|
||||
('uECC_SUPPORT_COMPRESSED_POINT', '0'),
|
||||
('uECC_VLI_NATIVE_LITTLE_ENDIAN', '1'),
|
||||
]
|
||||
|
||||
|
||||
|
||||
CPPPATH_MOD += [
|
||||
]
|
||||
CPPDEFINES_MOD += [
|
||||
]
|
||||
SOURCE_MOD += [
|
||||
|
||||
]
|
||||
|
||||
CPPPATH_MOD += [
|
||||
'embed/sdk/nrf52/components/nfc/ndef/generic/message',
|
||||
'embed/sdk/nrf52/components/nfc/t2t_lib',
|
||||
'embed/sdk/nrf52/components/nfc/t4t_parser/hl_detection_procedure',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_ancs_c',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_ias_c',
|
||||
'embed/sdk/nrf52/components/libraries/pwm',
|
||||
'embed/sdk/nrf52/components/libraries/usbd/class/cdc/acm',
|
||||
'embed/sdk/nrf52/components/libraries/usbd/class/hid/generic',
|
||||
'embed/sdk/nrf52/components/libraries/usbd/class/msc',
|
||||
'embed/sdk/nrf52/components/libraries/usbd/class/hid',
|
||||
'embed/sdk/nrf52/modules/nrfx/hal',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/conn_hand_parser/le_oob_rec_parser',
|
||||
'embed/sdk/nrf52/components/libraries/log',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_gls',
|
||||
'embed/sdk/nrf52/components/libraries/fstorage',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/text',
|
||||
'embed/sdk/nrf52/components/libraries/mutex',
|
||||
'embed/sdk/nrf52/components/libraries/gfx',
|
||||
'embed/sdk/nrf52/components/libraries/bootloader/ble_dfu',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/connection_handover/common',
|
||||
'embed/sdk/nrf52/components/libraries/fifo',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/generic/record',
|
||||
'embed/sdk/nrf52/components/nfc/t4t_parser/cc_file',
|
||||
'embed/sdk/nrf52/components/ble/ble_advertising',
|
||||
'embed/sdk/nrf52/external/utf_converter',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_bas_c',
|
||||
'embed/sdk/nrf52/modules/nrfx/drivers/include',
|
||||
'embed/sdk/nrf52/components/libraries/experimental_task_manager',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_hrs_c',
|
||||
'embed/sdk/nrf52/components/softdevice/s140/headers/nrf52',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/connection_handover/le_oob_rec',
|
||||
'embed/sdk/nrf52/components/libraries/queue',
|
||||
'embed/sdk/nrf52/components/libraries/pwr_mgmt',
|
||||
'embed/sdk/nrf52/components/ble/ble_dtm',
|
||||
'embed/sdk/nrf52/components/toolchain/cmsis/include',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_rscs_c',
|
||||
'embed/sdk/nrf52/components/ble/common',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_lls',
|
||||
'embed/sdk/nrf52/components/nfc/platform',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/connection_handover/ac_rec',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_bas',
|
||||
'embed/sdk/nrf52/components/libraries/mpu',
|
||||
'embed/sdk/nrf52/components/libraries/experimental_section_vars',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_ans_c',
|
||||
'embed/sdk/nrf52/components/libraries/slip',
|
||||
'embed/sdk/nrf52/components/libraries/delay',
|
||||
'embed/sdk/nrf52/components/libraries/csense_drv',
|
||||
'embed/sdk/nrf52/components/libraries/memobj',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_nus_c',
|
||||
'embed/sdk/nrf52/components/softdevice/common',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_ias',
|
||||
'embed/sdk/nrf52/components/libraries/usbd/class/hid/mouse',
|
||||
'embed/sdk/nrf52/components/libraries/low_power_pwm',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/conn_hand_parser/ble_oob_advdata_parser',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_dfu',
|
||||
'embed/sdk/nrf52/external/fprintf',
|
||||
'embed/sdk/nrf52/components/libraries/svc',
|
||||
'embed/sdk/nrf52/components/libraries/atomic',
|
||||
'embed/sdk/nrf52/components',
|
||||
'embed/sdk/nrf52/components/libraries/scheduler',
|
||||
'embed/sdk/nrf52/components/libraries/cli',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_lbs',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_hts',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_cts_c',
|
||||
'embed/sdk/nrf52/components/libraries/crc16',
|
||||
'embed/sdk/nrf52/components/nfc/t4t_parser/apdu',
|
||||
'embed/sdk/nrf52/components/libraries/util',
|
||||
'embed/sdk/nrf52/components/libraries/usbd/class/cdc',
|
||||
'embed/sdk/nrf52/components/libraries/csense',
|
||||
'embed/sdk/nrf52/components/libraries/balloc',
|
||||
'embed/sdk/nrf52/components/libraries/ecc',
|
||||
'embed/sdk/nrf52/components/libraries/hardfault',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_cscs',
|
||||
'embed/sdk/nrf52/components/libraries/uart',
|
||||
'embed/sdk/nrf52/components/libraries/hci',
|
||||
'embed/sdk/nrf52/components/libraries/usbd/class/hid/kbd',
|
||||
'embed/sdk/nrf52/components/libraries/timer',
|
||||
'embed/sdk/nrf52/components/libraries/queue',
|
||||
'embed/sdk/nrf52/components/softdevice/s140/headers',
|
||||
'embed/sdk/nrf52/integration/nrfx',
|
||||
'embed/sdk/nrf52/components/nfc/t4t_parser/tlv',
|
||||
'embed/sdk/nrf52/components/libraries/sortlist',
|
||||
'embed/sdk/nrf52/components/libraries/spi_mngr',
|
||||
'embed/sdk/nrf52/components/libraries/led_softblink',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/conn_hand_parser',
|
||||
'embed/sdk/nrf52/components/libraries/sdcard',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/parser/record',
|
||||
'embed/sdk/nrf52/modules/nrfx/mdk',
|
||||
'embed/sdk/nrf52/components/ble/ble_link_ctx_manager',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_nus',
|
||||
'embed/sdk/nrf52/components/libraries/twi_mngr',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_hids',
|
||||
'embed/sdk/nrf52/components/libraries/strerror',
|
||||
'embed/sdk/nrf52/components/libraries/crc32',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/connection_handover/ble_oob_advdata',
|
||||
'embed/sdk/nrf52/components/nfc/t2t_parser',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/connection_handover/ble_pair_msg',
|
||||
'embed/sdk/nrf52/components/libraries/usbd/class/audio',
|
||||
'embed/sdk/nrf52/components/nfc/t4t_lib',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager',
|
||||
'embed/sdk/nrf52/components/libraries/mem_manager',
|
||||
'embed/sdk/nrf52/components/libraries/ringbuf',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_tps',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/parser/message',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_dis',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/uri',
|
||||
'embed/sdk/nrf52/components/ble/nrf_ble_gatt',
|
||||
'embed/sdk/nrf52/components/ble/nrf_ble_qwr',
|
||||
'embed/sdk/nrf52/components/libraries/gpiote',
|
||||
'embed/sdk/nrf52/components/libraries/button',
|
||||
'embed/sdk/nrf52/modules/nrfx',
|
||||
'embed/sdk/nrf52/components/libraries/twi_sensor',
|
||||
'embed/sdk/nrf52/integration/nrfx/legacy',
|
||||
'embed/sdk/nrf52/components/libraries/usbd',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/connection_handover/ep_oob_rec',
|
||||
'embed/sdk/nrf52/external/segger_rtt',
|
||||
'embed/sdk/nrf52/components/libraries/atomic_fifo',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_lbs_c',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/connection_handover/ble_pair_lib',
|
||||
'embed/sdk/nrf52/components/libraries/crypto',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/cc310',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/cc310_bl',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/micro_ecc',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/mbedtls',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/oberon',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/optiga',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/nrf_sw',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/nrf_hw',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/cifra',
|
||||
'embed/sdk/nrf52/components/ble/ble_racp',
|
||||
'embed/sdk/nrf52/components/libraries/fds',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/launchapp',
|
||||
'embed/sdk/nrf52/components/libraries/atomic_flags',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_hrs',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_rscs',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/connection_handover/hs_rec',
|
||||
'embed/sdk/nrf52/components/nfc/ndef/conn_hand_parser/ac_rec_parser',
|
||||
'embed/sdk/nrf52/components/libraries/stack_guard',
|
||||
'embed/sdk/nrf52/components/libraries/stack_info',
|
||||
'embed/sdk/nrf52/components/libraries/log/src',
|
||||
'embed/sdk/nrf52/external/mbedtls/include',
|
||||
'embed',
|
||||
'embed/trezorhal/boards',
|
||||
]
|
||||
SOURCE_MOD += [
|
||||
]
|
||||
|
||||
|
||||
SOURCE_NRFHAL_AS = [
|
||||
'embed/sdk/nrf52/modules/nrfx/mdk/gcc_startup_nrf52833.S',
|
||||
]
|
||||
|
||||
|
||||
|
||||
SOURCE_NRFHAL = [
|
||||
'embed/sdk/nrf52/components/libraries/log/src/nrf_log_frontend.c',
|
||||
'embed/sdk/nrf52/components/libraries/log/src/nrf_log_str_formatter.c',
|
||||
'embed/sdk/nrf52/components/libraries/button/app_button.c',
|
||||
'embed/sdk/nrf52/components/libraries/util/app_error.c',
|
||||
'embed/sdk/nrf52/components/libraries/util/app_error_handler_gcc.c',
|
||||
'embed/sdk/nrf52/components/libraries/util/app_error_weak.c',
|
||||
'embed/sdk/nrf52/components/libraries/fifo/app_fifo.c',
|
||||
'embed/sdk/nrf52/components/libraries/scheduler/app_scheduler.c',
|
||||
'embed/sdk/nrf52/components/libraries/timer/app_timer2.c',
|
||||
'embed/sdk/nrf52/components/libraries/uart/app_uart_fifo.c',
|
||||
'embed/sdk/nrf52/components/libraries/util/app_util_platform.c',
|
||||
'embed/sdk/nrf52/components/libraries/timer/drv_rtc.c',
|
||||
'embed/sdk/nrf52/components/libraries/hardfault/hardfault_implementation.c',
|
||||
'embed/sdk/nrf52/components/libraries/util/nrf_assert.c',
|
||||
'embed/sdk/nrf52/components/libraries/atomic_fifo/nrf_atfifo.c',
|
||||
'embed/sdk/nrf52/components/libraries/atomic_flags/nrf_atflags.c',
|
||||
'embed/sdk/nrf52/components/libraries/atomic/nrf_atomic.c',
|
||||
'embed/sdk/nrf52/components/libraries/balloc/nrf_balloc.c',
|
||||
'embed/sdk/nrf52/external/fprintf/nrf_fprintf.c',
|
||||
'embed/sdk/nrf52/external/fprintf/nrf_fprintf_format.c',
|
||||
'embed/sdk/nrf52/components/libraries/memobj/nrf_memobj.c',
|
||||
'embed/sdk/nrf52/components/libraries/pwr_mgmt/nrf_pwr_mgmt.c',
|
||||
'embed/sdk/nrf52/components/libraries/ringbuf/nrf_ringbuf.c',
|
||||
'embed/sdk/nrf52/components/libraries/experimental_section_vars/nrf_section_iter.c',
|
||||
'embed/sdk/nrf52/components/libraries/sortlist/nrf_sortlist.c',
|
||||
'embed/sdk/nrf52/components/libraries/strerror/nrf_strerror.c',
|
||||
'embed/sdk/nrf52/components/libraries/uart/retarget.c',
|
||||
'embed/sdk/nrf52/components/libraries/queue/nrf_queue.c',
|
||||
'embed/sdk/nrf52/modules/nrfx/mdk/system_nrf52833.c',
|
||||
'embed/sdk/nrf52/integration/nrfx/legacy/nrf_drv_clock.c',
|
||||
'embed/sdk/nrf52/integration/nrfx/legacy/nrf_drv_uart.c',
|
||||
'embed/sdk/nrf52/integration/nrfx/legacy/nrf_drv_spi.c',
|
||||
'embed/sdk/nrf52/integration/nrfx/legacy/nrf_drv_rng.c',
|
||||
'embed/sdk/nrf52/modules/nrfx/soc/nrfx_atomic.c',
|
||||
'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_clock.c',
|
||||
'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_gpiote.c',
|
||||
'embed/sdk/nrf52/modules/nrfx/drivers/src/prs/nrfx_prs.c',
|
||||
'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_uart.c',
|
||||
'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_uarte.c',
|
||||
'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_rng.c',
|
||||
'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_spi.c',
|
||||
'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_spim.c',
|
||||
'embed/sdk/nrf52/components/ble/common/ble_advdata.c',
|
||||
'embed/sdk/nrf52/components/ble/ble_advertising/ble_advertising.c',
|
||||
'embed/sdk/nrf52/components/ble/common/ble_conn_params.c',
|
||||
'embed/sdk/nrf52/components/ble/common/ble_conn_state.c',
|
||||
'embed/sdk/nrf52/components/ble/ble_link_ctx_manager/ble_link_ctx_manager.c',
|
||||
'embed/sdk/nrf52/components/ble/common/ble_srv_common.c',
|
||||
'embed/sdk/nrf52/components/ble/nrf_ble_gatt/nrf_ble_gatt.c',
|
||||
'embed/sdk/nrf52/components/ble/nrf_ble_qwr/nrf_ble_qwr.c',
|
||||
'embed/sdk/nrf52/external/utf_converter/utf.c',
|
||||
'embed/sdk/nrf52/components/softdevice/common/nrf_sdh.c',
|
||||
'embed/sdk/nrf52/components/softdevice/common/nrf_sdh_ble.c',
|
||||
'embed/sdk/nrf52/components/softdevice/common/nrf_sdh_soc.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/gatt_cache_manager.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/gatts_cache_manager.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/id_manager.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/peer_data_storage.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/peer_database.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/peer_id.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/peer_manager.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/peer_manager_handler.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/pm_buffer.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/nrf_ble_lesc.c',
|
||||
'embed/sdk/nrf52/components/libraries/fds/fds.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/security_manager.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/security_dispatcher.c',
|
||||
'embed/sdk/nrf52/components/libraries/fstorage/nrf_fstorage.c',
|
||||
'embed/sdk/nrf52/components/libraries/fstorage/nrf_fstorage_sd.c',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_dis/ble_dis.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecc.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdh.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdsa.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_rng_mbedtls.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_ecc.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_ecdsa.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_ecdh.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_hash.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_init.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_shared.c',
|
||||
'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_rng.c',
|
||||
'embed/sdk/nrf52/external/mbedtls/library/ctr_drbg.c',
|
||||
'embed/sdk/nrf52/external/mbedtls/library/aes.c',
|
||||
'embed/sdk/nrf52/external/mbedtls/library/platform.c',
|
||||
'embed/sdk/nrf52/external/mbedtls/library/platform_util.c',
|
||||
|
||||
]
|
||||
|
||||
SOURCE_NANOPB = [
|
||||
'vendor/nanopb/pb_common.c',
|
||||
'vendor/nanopb/pb_decode.c',
|
||||
'vendor/nanopb/pb_encode.c',
|
||||
]
|
||||
|
||||
SOURCE_BLE_FIRMWARE = [
|
||||
'embed/ble_firmware/main.c',
|
||||
'embed/ble_firmware/ble_nus.c',
|
||||
'embed/ble_firmware/int_comm.c',
|
||||
'embed/ble_firmware/dis.c',
|
||||
'embed/ble_firmware/pm.c',
|
||||
'embed/ble_firmware/power.c',
|
||||
'embed/ble_firmware/advertising.c',
|
||||
'embed/ble_firmware/connection.c',
|
||||
'embed/bootloader/protob/messages.pb.c',
|
||||
'embed/lib/protob_helpers.c',
|
||||
'embed/ble_bootloader/uecc/uECC.c',
|
||||
]
|
||||
|
||||
if MMD:
|
||||
CPPDEFINES_MOD += [
|
||||
'DEBUG',
|
||||
'DEBUG_NRF',
|
||||
'MMD'
|
||||
]
|
||||
SOURCE_BLE_FIRMWARE += [
|
||||
'embed/segger/SEGGER_MMD/JLINK_MONITOR.c',
|
||||
'embed/segger/SEGGER_MMD/JLINK_MONITOR_ISR_SES.S'
|
||||
]
|
||||
|
||||
SOURCE_NRFHAL += [
|
||||
'embed/sdk/nrf52/components/libraries/log/src/nrf_log_backend_rtt.c',
|
||||
'embed/sdk/nrf52/components/libraries/log/src/nrf_log_backend_serial.c',
|
||||
'embed/sdk/nrf52/components/libraries/log/src/nrf_log_backend_uart.c',
|
||||
'embed/sdk/nrf52/components/libraries/log/src/nrf_log_default_backends.c',
|
||||
'embed/sdk/nrf52/external/segger_rtt/SEGGER_RTT.c',
|
||||
'embed/sdk/nrf52/external/segger_rtt/SEGGER_RTT_Syscalls_GCC.c',
|
||||
'embed/sdk/nrf52/external/segger_rtt/SEGGER_RTT_printf.c',
|
||||
]
|
||||
|
||||
|
||||
CPPPATH_MOD += [
|
||||
'embed/segger/SEGGER_MMD'
|
||||
]
|
||||
|
||||
|
||||
|
||||
env = Environment(ENV=os.environ, CFLAGS='%s -DPRODUCTION=%s' % (ARGUMENTS.get('CFLAGS', ''), ARGUMENTS.get('PRODUCTION', '0')))
|
||||
|
||||
|
||||
env.Replace(
|
||||
CP='cp',
|
||||
AS='arm-none-eabi-as',
|
||||
AR='arm-none-eabi-ar',
|
||||
CC='arm-none-eabi-gcc',
|
||||
LINK='arm-none-eabi-gcc',
|
||||
SIZE='arm-none-eabi-size',
|
||||
STRIP='arm-none-eabi-strip',
|
||||
OBJCOPY='arm-none-eabi-objcopy',
|
||||
PYTHON='python',
|
||||
MAKECMAKELISTS='$PYTHON tools/make_cmakelists.py', )
|
||||
|
||||
env.Replace(
|
||||
TREZOR_MODEL=TREZOR_MODEL, )
|
||||
|
||||
CPU_ASFLAGS = '-mthumb -mabi=aapcs -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16'
|
||||
CPU_CCFLAGS = '-mthumb -mabi=aapcs -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 '
|
||||
|
||||
|
||||
|
||||
|
||||
env.Replace(
|
||||
COPT=env.get('ENV').get('OPTIMIZE', '-Og'),
|
||||
CCFLAGS='$COPT '
|
||||
'-g3 '
|
||||
'-std=c99 -Wall -Werror -Wdouble-promotion -Wpointer-arith -Wno-missing-braces -Wno-unused-function '
|
||||
'-fdata-sections -ffunction-sections '
|
||||
'-fno-strict-aliasing '
|
||||
'-fno-builtin '
|
||||
'-fshort-enums '
|
||||
+ CPU_CCFLAGS + CCFLAGS_MOD,
|
||||
LINKFLAGS='-Lembed/sdk/nrf52/modules/nrfx/mdk -T embed/ble_firmware/memory.ld -Wl,--gc-sections --specs=nano.specs -Wl,-Map=build/ble_firmware/ble_firmware.map -Wl,--warn-common -Wl,--print-memory-usage',
|
||||
CPPPATH=[
|
||||
'embed/ble_firmware',
|
||||
'embed/bootloader/protob',
|
||||
'embed/sdk/nrf52',
|
||||
'embed/lib',
|
||||
'vendor/nanopb',
|
||||
'embed/ble_bootloader/uecc',
|
||||
] + CPPPATH_MOD,
|
||||
CPPDEFINES=[
|
||||
'BLE_FIRMWARE',
|
||||
'TREZOR_MODEL_'+TREZOR_MODEL,
|
||||
] + CPPDEFINES_MOD,
|
||||
ASFLAGS=CPU_ASFLAGS,
|
||||
ASPPFLAGS='$CFLAGS $CCFLAGS', )
|
||||
|
||||
#
|
||||
# Program objects
|
||||
#
|
||||
|
||||
obj_program = []
|
||||
obj_program += env.Object(source=SOURCE_BLE_FIRMWARE)
|
||||
obj_program += env.Object(source=SOURCE_NRFHAL_AS, COPT='-O0')
|
||||
obj_program += env.Object(source=SOURCE_NRFHAL)
|
||||
obj_program += env.Object(source=SOURCE_NANOPB)
|
||||
obj_program += env.Object(source=SOURCE_MOD)
|
||||
|
||||
env.Replace(
|
||||
ALLSOURCES=SOURCE_NRFHAL_AS + SOURCE_MOD + SOURCE_BLE_FIRMWARE + SOURCE_NRFHAL,
|
||||
ALLDEFS=tools.get_defs_for_cmake(env['CPPDEFINES']))
|
||||
|
||||
cmake_gen = env.Command(
|
||||
target='CMakeLists.txt',
|
||||
source='',
|
||||
action='$MAKECMAKELISTS --sources $ALLSOURCES --dirs $CPPPATH --defs $ALLDEFS',
|
||||
)
|
||||
|
||||
|
||||
LIB_FILES = [
|
||||
]
|
||||
|
||||
program_elf = env.Command(
|
||||
target='ble_firmware.elf',
|
||||
source=obj_program,
|
||||
action=
|
||||
'$LINK -o $TARGET $CCFLAGS $CFLAGS $LINKFLAGS $SOURCES ' + ' '.join(LIB_FILES) + ' -lc -lnosys -lm',
|
||||
)
|
||||
|
||||
|
||||
|
||||
BINARY_NAME = f"build/ble_firmware/ble_firmware-{tools.get_model_identifier(TREZOR_MODEL)}"
|
||||
BINARY_NAME += "-" + tools.get_version('embed/ble_firmware/version.h')
|
||||
BINARY_NAME += "-" + tools.get_git_revision_short_hash()
|
||||
BINARY_NAME += "-dirty" if tools.get_git_modified() else ""
|
||||
BINARY_NAME += ".bin"
|
||||
|
||||
if CMAKELISTS != 0:
|
||||
env.Depends(program_elf, cmake_gen)
|
||||
|
||||
|
||||
|
||||
program_hex = env.Command(
|
||||
target='ble_firmware.hex',
|
||||
source=program_elf,
|
||||
action='$OBJCOPY -O ihex $SOURCE $TARGET',
|
||||
)
|
||||
|
||||
program_pkg = env.Command(
|
||||
target='ble_firmware.zip',
|
||||
source=program_hex,
|
||||
action=[
|
||||
f'nrfutil pkg generate --hw-version 52 --sd-req=0x100 --application $SOURCE --app-boot-validation VALIDATE_ECDSA_P256_SHA256 --key-file ./embed/ble_bootloader/priv.pem $TARGET --application-version-string {tools.get_version("embed/ble_firmware/version.h")}'
|
||||
],
|
||||
)
|
||||
|
||||
settings = env.Command(
|
||||
target='settings.hex',
|
||||
source=program_hex,
|
||||
action=f'nrfutil settings generate --family NRF52 --application $SOURCE --app-boot-validation VALIDATE_ECDSA_P256_SHA256 --application-version-string {tools.get_version("embed/ble_firmware/version.h")} --bootloader-version {tools.get_version_int("embed/ble_bootloader/version.h")} --bl-settings-version 2 --sd-boot-validation VALIDATE_ECDSA_P256_SHA256 --softdevice ./embed/sdk/nrf52/components/softdevice/s140/hex/s140_nrf52_7.2.0_softdevice.hex --key-file ./embed/ble_bootloader/priv.pem $TARGET',
|
||||
)
|
||||
|
||||
program_merge = env.Command(
|
||||
target='ble_firmware_merged.hex',
|
||||
source=[program_hex, settings],
|
||||
action='mergehex -m $SOURCES -o $TARGET',
|
||||
)
|
||||
|
||||
program_bin = env.Command(
|
||||
target='ble_firmware.bin',
|
||||
source=program_elf,
|
||||
action=[
|
||||
'$OBJCOPY -O binary $SOURCE $TARGET',
|
||||
'$CP $TARGET ' + BINARY_NAME,
|
||||
],
|
||||
)
|
||||
|
||||
env.Depends(program_bin, program_hex)
|
||||
env.Depends(program_pkg, program_hex)
|
||||
env.Depends(settings, program_hex)
|
||||
env.Depends(program_bin, program_pkg)
|
||||
env.Depends(program_merge, settings)
|
||||
env.Depends(program_merge, program_hex)
|
||||
env.Depends(program_bin, program_merge)
|
@ -1,5 +1,7 @@
|
||||
# pylint: disable=E0602
|
||||
|
||||
SConscript('SConscript.ble_bootloader', variant_dir='build/ble_bootloader', duplicate=False)
|
||||
SConscript('SConscript.ble_firmware', variant_dir='build/ble_firmware', duplicate=False)
|
||||
SConscript('SConscript.boardloader', variant_dir='build/boardloader', duplicate=False)
|
||||
SConscript('SConscript.bootloader', variant_dir='build/bootloader', duplicate=False)
|
||||
SConscript('SConscript.bootloader_ci', variant_dir='build/bootloader_ci', duplicate=False)
|
||||
|
16
core/embed/ble_bootloader/dfu_public_key.c
Normal file
16
core/embed/ble_bootloader/dfu_public_key.c
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
/* This file was automatically generated by nrfutil on 2023-01-23 (YY-MM-DD) at
|
||||
* 16:58:55 */
|
||||
|
||||
#include "compiler_abstraction.h"
|
||||
#include "stdint.h"
|
||||
|
||||
/** @brief Public key used to verify DFU images */
|
||||
__ALIGN(4)
|
||||
const uint8_t pk[64] = {
|
||||
0x7e, 0x2f, 0x54, 0x41, 0xb7, 0x3f, 0x0c, 0xc8, 0xa8, 0x8f, 0x29,
|
||||
0x1a, 0x91, 0x3c, 0x9f, 0x70, 0x7e, 0xc6, 0x6f, 0x69, 0x51, 0x14,
|
||||
0xa6, 0x04, 0xeb, 0x0b, 0x23, 0x61, 0xf0, 0x22, 0xa4, 0xf4, 0xad,
|
||||
0x73, 0x9b, 0xfa, 0x48, 0x2e, 0x1a, 0x90, 0xf6, 0x59, 0x28, 0x4c,
|
||||
0x73, 0x49, 0x64, 0xc5, 0x18, 0xd3, 0xb3, 0xb2, 0x1a, 0x60, 0xf0,
|
||||
0x79, 0xe8, 0x2c, 0x0a, 0x7c, 0x04, 0x84, 0xcd, 0xd6};
|
332
core/embed/ble_bootloader/jlink.jdebug
Normal file
332
core/embed/ble_bootloader/jlink.jdebug
Normal file
@ -0,0 +1,332 @@
|
||||
/*********************************************************************
|
||||
* (c) SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
* www.segger.com *
|
||||
**********************************************************************
|
||||
|
||||
File : /home/mbruna/CLionProjects/trezor-model_r/core/embed/ble_bootloader/jlink.jdebug
|
||||
Created : 6 Feb 2023 15:54
|
||||
Ozone Version : V3.28c
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* OnProjectLoad
|
||||
*
|
||||
* Function description
|
||||
* Project load routine. Required.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
void OnProjectLoad (void) {
|
||||
//
|
||||
// Dialog-generated settings
|
||||
//
|
||||
Project.AddPathSubstitute (".", "$(ProjectDir)");
|
||||
Project.AddPathSubstitute (".", "$(ProjectDir)");
|
||||
Project.SetDevice ("Cortex-M4");
|
||||
Project.SetHostIF ("USB", "");
|
||||
Project.SetTargetIF ("SWD");
|
||||
Project.SetTIFSpeed ("20 MHz");
|
||||
Project.AddSvdFile ("$(InstallDir)/Config/CPU/Cortex-M4F.svd");
|
||||
//
|
||||
// User settings
|
||||
//
|
||||
File.Open ("../../build/ble_bootloader/ble_bootloader.elf");
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* OnStartupComplete
|
||||
*
|
||||
* Function description
|
||||
* Called when program execution has reached/passed
|
||||
* the startup completion point. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void OnStartupComplete (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* TargetReset
|
||||
*
|
||||
* Function description
|
||||
* Replaces the default target device reset routine. Optional.
|
||||
*
|
||||
* Notes
|
||||
* This example demonstrates the usage when
|
||||
* debugging an application in RAM on a Cortex-M target device.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void TargetReset (void) {
|
||||
//
|
||||
// unsigned int SP;
|
||||
// unsigned int PC;
|
||||
// unsigned int VectorTableAddr;
|
||||
//
|
||||
// VectorTableAddr = Elf.GetBaseAddr();
|
||||
// //
|
||||
// // Set up initial stack pointer
|
||||
// //
|
||||
// if (VectorTableAddr != 0xFFFFFFFF) {
|
||||
// SP = Target.ReadU32(VectorTableAddr);
|
||||
// Target.SetReg("SP", SP);
|
||||
// }
|
||||
// //
|
||||
// // Set up entry point PC
|
||||
// //
|
||||
// PC = Elf.GetEntryPointPC();
|
||||
//
|
||||
// if (PC != 0xFFFFFFFF) {
|
||||
// Target.SetReg("PC", PC);
|
||||
// } else if (VectorTableAddr != 0xFFFFFFFF) {
|
||||
// PC = Target.ReadU32(VectorTableAddr + 4);
|
||||
// Target.SetReg("PC", PC);
|
||||
// } else {
|
||||
// Util.Error("Project file error: failed to set entry point PC", 1);
|
||||
// }
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* BeforeTargetReset
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void BeforeTargetReset (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* AfterTargetReset
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
* The default implementation initializes SP and PC to reset values.
|
||||
**
|
||||
**********************************************************************
|
||||
*/
|
||||
void AfterTargetReset (void) {
|
||||
_SetupTarget();
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* DebugStart
|
||||
*
|
||||
* Function description
|
||||
* Replaces the default debug session startup routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void DebugStart (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* TargetConnect
|
||||
*
|
||||
* Function description
|
||||
* Replaces the default target IF connection routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void TargetConnect (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* BeforeTargetConnect
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
void BeforeTargetConnect (void) {
|
||||
Project.SetJLinkScript("./MMDScript.JLinkScript");
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* AfterTargetConnect
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void AfterTargetConnect (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* TargetDownload
|
||||
*
|
||||
* Function description
|
||||
* Replaces the default program download routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void TargetDownload (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* BeforeTargetDownload
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void BeforeTargetDownload (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* AfterTargetDownload
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
* The default implementation initializes SP and PC to reset values.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
void AfterTargetDownload (void) {
|
||||
_SetupTarget();
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* BeforeTargetDisconnect
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void BeforeTargetDisconnect (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* AfterTargetDisconnect
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void AfterTargetDisconnect (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* AfterTargetHalt
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void AfterTargetHalt (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* BeforeTargetResume
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void BeforeTargetResume (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* OnSnapshotLoad
|
||||
*
|
||||
* Function description
|
||||
* Called upon loading a snapshot. Optional.
|
||||
*
|
||||
* Additional information
|
||||
* This function is used to restore the target state in cases
|
||||
* where values cannot simply be written to the target.
|
||||
* Typical use: GPIO clock needs to be enabled, before
|
||||
* GPIO is configured.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void OnSnapshotLoad (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* OnSnapshotSave
|
||||
*
|
||||
* Function description
|
||||
* Called upon saving a snapshot. Optional.
|
||||
*
|
||||
* Additional information
|
||||
* This function is usually used to save values of the target
|
||||
* state which can either not be trivially read,
|
||||
* or need to be restored in a specific way or order.
|
||||
* Typically use: Memory Mapped Registers,
|
||||
* such as PLL and GPIO configuration.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void OnSnapshotSave (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* OnError
|
||||
*
|
||||
* Function description
|
||||
* Called when an error ocurred. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void OnError (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* AfterProjectLoad
|
||||
*
|
||||
* Function description
|
||||
* After Project load routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void AfterProjectLoad (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _SetupTarget
|
||||
*
|
||||
* Function description
|
||||
* Setup the target.
|
||||
* Called by AfterTargetReset() and AfterTargetDownload().
|
||||
*
|
||||
* Auto-generated function. May be overridden by Ozone.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
void _SetupTarget(void) {
|
||||
//
|
||||
// this function is intentionally empty because both inital PC and
|
||||
// initial SP were chosen not to be set
|
||||
//
|
||||
}
|
169
core/embed/ble_bootloader/main.c
Normal file
169
core/embed/ble_bootloader/main.c
Normal file
@ -0,0 +1,169 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2021, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be
|
||||
* reverse engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/** @file
|
||||
*
|
||||
* @defgroup bootloader_secure_ble main.c
|
||||
* @{
|
||||
* @ingroup dfu_bootloader_api
|
||||
* @brief Bootloader project main file for secure DFU.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "app_error.h"
|
||||
#include "app_error_weak.h"
|
||||
#include "nrf_bootloader.h"
|
||||
#include "nrf_bootloader_app_start.h"
|
||||
#include "nrf_bootloader_dfu_timers.h"
|
||||
#include "nrf_bootloader_info.h"
|
||||
#include "nrf_delay.h"
|
||||
#include "nrf_dfu.h"
|
||||
#include "nrf_gpio.h"
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_log_default_backends.h"
|
||||
#include "nrf_mbr.h"
|
||||
#include "trezor_t3w1_d1_NRF.h"
|
||||
|
||||
static void on_error(void) {
|
||||
NRF_LOG_FINAL_FLUSH();
|
||||
|
||||
#if NRF_MODULE_ENABLED(NRF_LOG_BACKEND_RTT)
|
||||
// To allow the buffer to be flushed by the host.
|
||||
nrf_delay_ms(100);
|
||||
#endif
|
||||
#ifdef NRF_DFU_DEBUG_VERSION
|
||||
NRF_BREAKPOINT_COND;
|
||||
#endif
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void app_error_handler(uint32_t error_code, uint32_t line_num,
|
||||
const uint8_t* p_file_name) {
|
||||
NRF_LOG_ERROR("%s:%d, %d", p_file_name, line_num, error_code);
|
||||
on_error();
|
||||
}
|
||||
|
||||
void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) {
|
||||
NRF_LOG_ERROR("Received a fault! id: 0x%08x, pc: 0x%08x, info: 0x%08x", id,
|
||||
pc, info);
|
||||
on_error();
|
||||
}
|
||||
|
||||
void app_error_handler_bare(uint32_t error_code) {
|
||||
NRF_LOG_ERROR("Received an error: 0x%08x!", error_code);
|
||||
on_error();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function notifies certain events in DFU process.
|
||||
*/
|
||||
static void dfu_observer(nrf_dfu_evt_type_t evt_type) {
|
||||
switch (evt_type) {
|
||||
case NRF_DFU_EVT_DFU_FAILED:
|
||||
case NRF_DFU_EVT_DFU_ABORTED:
|
||||
case NRF_DFU_EVT_DFU_INITIALIZED:
|
||||
// bsp_board_init(BSP_INIT_LEDS);
|
||||
// bsp_board_led_on(BSP_BOARD_LED_0);
|
||||
// bsp_board_led_on(BSP_BOARD_LED_1);
|
||||
// bsp_board_led_off(BSP_BOARD_LED_2);
|
||||
break;
|
||||
case NRF_DFU_EVT_TRANSPORT_ACTIVATED:
|
||||
// bsp_board_led_off(BSP_BOARD_LED_1);
|
||||
// bsp_board_led_on(BSP_BOARD_LED_2);
|
||||
break;
|
||||
case NRF_DFU_EVT_DFU_STARTED:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t nrf_dfu_init_user(void) {
|
||||
// signalize DFU mode
|
||||
nrf_gpio_pin_set(GPIO_1_PIN);
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
/**@brief Function for application main entry. */
|
||||
int main(void) {
|
||||
NRF_APPROTECT->DISABLE = APPROTECT_DISABLE_DISABLE_SwDisable;
|
||||
|
||||
uint32_t ret_val;
|
||||
// Apply priority for monitor mode interrupt
|
||||
NVIC_SetPriority(DebugMonitor_IRQn, _PRIO_SD_LOW);
|
||||
|
||||
// Must happen before flash protection is applied, since it edits a protected
|
||||
// page.
|
||||
nrf_bootloader_mbr_addrs_populate();
|
||||
|
||||
// Protect MBR and bootloader code from being overwritten.
|
||||
ret_val = nrf_bootloader_flash_protect(0, MBR_SIZE);
|
||||
APP_ERROR_CHECK(ret_val);
|
||||
ret_val =
|
||||
nrf_bootloader_flash_protect(BOOTLOADER_START_ADDR, BOOTLOADER_SIZE);
|
||||
APP_ERROR_CHECK(ret_val);
|
||||
|
||||
nrf_gpio_cfg_output(GPIO_1_PIN);
|
||||
nrf_gpio_cfg_output(GPIO_2_PIN);
|
||||
nrf_gpio_pin_clear(GPIO_1_PIN);
|
||||
nrf_gpio_pin_clear(GPIO_2_PIN);
|
||||
|
||||
(void)NRF_LOG_INIT(nrf_bootloader_dfu_timer_counter_get);
|
||||
NRF_LOG_DEFAULT_BACKENDS_INIT();
|
||||
|
||||
NRF_LOG_INFO("Inside main");
|
||||
|
||||
ret_val = nrf_bootloader_init(dfu_observer);
|
||||
APP_ERROR_CHECK(ret_val);
|
||||
|
||||
NRF_LOG_FLUSH();
|
||||
|
||||
NRF_LOG_ERROR("After main, should never be reached.");
|
||||
NRF_LOG_FLUSH();
|
||||
|
||||
APP_ERROR_CHECK_BOOL(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
156
core/embed/ble_bootloader/memory.ld
Normal file
156
core/embed/ble_bootloader/memory.ld
Normal file
@ -0,0 +1,156 @@
|
||||
/* Linker script to configure memory regions. */
|
||||
|
||||
SEARCH_DIR(.)
|
||||
GROUP(-lgcc -lc -lnosys)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x70000, LENGTH = 0xe000
|
||||
RAM (rwx) : ORIGIN = 0x20002ae8, LENGTH = 0x1d518
|
||||
uicr_bootloader_start_address (r) : ORIGIN = 0x10001014, LENGTH = 0x4
|
||||
bootloader_settings_page (r) : ORIGIN = 0x0007F000, LENGTH = 0x1000
|
||||
uicr_mbr_params_page (r) : ORIGIN = 0x10001018, LENGTH = 0x4
|
||||
mbr_params_page (r) : ORIGIN = 0x0007E000, LENGTH = 0x1000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = ALIGN(4);
|
||||
.uicr_bootloader_start_address :
|
||||
{
|
||||
PROVIDE(__start_uicr_bootloader_start_address = .);
|
||||
KEEP(*(SORT(.uicr_bootloader_start_address*)))
|
||||
PROVIDE(__stop_uicr_bootloader_start_address = .);
|
||||
} > uicr_bootloader_start_address
|
||||
. = ALIGN(4);
|
||||
.bootloader_settings_page(NOLOAD) :
|
||||
{
|
||||
PROVIDE(__start_bootloader_settings_page = .);
|
||||
KEEP(*(SORT(.bootloader_settings_page*)))
|
||||
PROVIDE(__stop_bootloader_settings_page = .);
|
||||
} > bootloader_settings_page
|
||||
. = ALIGN(4);
|
||||
.uicr_mbr_params_page :
|
||||
{
|
||||
PROVIDE(__start_uicr_mbr_params_page = .);
|
||||
KEEP(*(SORT(.uicr_mbr_params_page*)))
|
||||
PROVIDE(__stop_uicr_mbr_params_page = .);
|
||||
} > uicr_mbr_params_page
|
||||
. = ALIGN(4);
|
||||
.mbr_params_page(NOLOAD) :
|
||||
{
|
||||
PROVIDE(__start_mbr_params_page = .);
|
||||
KEEP(*(SORT(.mbr_params_page*)))
|
||||
PROVIDE(__stop_mbr_params_page = .);
|
||||
} > mbr_params_page
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = ALIGN(4);
|
||||
.mem_section_dummy_ram :
|
||||
{
|
||||
}
|
||||
.log_dynamic_data :
|
||||
{
|
||||
PROVIDE(__start_log_dynamic_data = .);
|
||||
KEEP(*(SORT(.log_dynamic_data*)))
|
||||
PROVIDE(__stop_log_dynamic_data = .);
|
||||
} > RAM
|
||||
.log_filter_data :
|
||||
{
|
||||
PROVIDE(__start_log_filter_data = .);
|
||||
KEEP(*(SORT(.log_filter_data*)))
|
||||
PROVIDE(__stop_log_filter_data = .);
|
||||
} > RAM
|
||||
.fs_data :
|
||||
{
|
||||
PROVIDE(__start_fs_data = .);
|
||||
KEEP(*(.fs_data))
|
||||
PROVIDE(__stop_fs_data = .);
|
||||
} > RAM
|
||||
|
||||
} INSERT AFTER .data;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.mem_section_dummy_rom :
|
||||
{
|
||||
}
|
||||
.crypto_data :
|
||||
{
|
||||
PROVIDE(__start_crypto_data = .);
|
||||
KEEP(*(SORT(.crypto_data*)))
|
||||
PROVIDE(__stop_crypto_data = .);
|
||||
} > FLASH
|
||||
.nrf_queue :
|
||||
{
|
||||
PROVIDE(__start_nrf_queue = .);
|
||||
KEEP(*(.nrf_queue))
|
||||
PROVIDE(__stop_nrf_queue = .);
|
||||
} > FLASH
|
||||
.dfu_trans :
|
||||
{
|
||||
PROVIDE(__start_dfu_trans = .);
|
||||
KEEP(*(SORT(.dfu_trans*)))
|
||||
PROVIDE(__stop_dfu_trans = .);
|
||||
} > FLASH
|
||||
.svc_data :
|
||||
{
|
||||
PROVIDE(__start_svc_data = .);
|
||||
KEEP(*(.svc_data))
|
||||
PROVIDE(__stop_svc_data = .);
|
||||
} > FLASH
|
||||
.log_const_data :
|
||||
{
|
||||
PROVIDE(__start_log_const_data = .);
|
||||
KEEP(*(SORT(.log_const_data*)))
|
||||
PROVIDE(__stop_log_const_data = .);
|
||||
} > FLASH
|
||||
.nrf_balloc :
|
||||
{
|
||||
PROVIDE(__start_nrf_balloc = .);
|
||||
KEEP(*(.nrf_balloc))
|
||||
PROVIDE(__stop_nrf_balloc = .);
|
||||
} > FLASH
|
||||
.sdh_ble_observers :
|
||||
{
|
||||
PROVIDE(__start_sdh_ble_observers = .);
|
||||
KEEP(*(SORT(.sdh_ble_observers*)))
|
||||
PROVIDE(__stop_sdh_ble_observers = .);
|
||||
} > FLASH
|
||||
.log_backends :
|
||||
{
|
||||
PROVIDE(__start_log_backends = .);
|
||||
KEEP(*(SORT(.log_backends*)))
|
||||
PROVIDE(__stop_log_backends = .);
|
||||
} > FLASH
|
||||
.sdh_req_observers :
|
||||
{
|
||||
PROVIDE(__start_sdh_req_observers = .);
|
||||
KEEP(*(SORT(.sdh_req_observers*)))
|
||||
PROVIDE(__stop_sdh_req_observers = .);
|
||||
} > FLASH
|
||||
.sdh_state_observers :
|
||||
{
|
||||
PROVIDE(__start_sdh_state_observers = .);
|
||||
KEEP(*(SORT(.sdh_state_observers*)))
|
||||
PROVIDE(__stop_sdh_state_observers = .);
|
||||
} > FLASH
|
||||
.sdh_stack_observers :
|
||||
{
|
||||
PROVIDE(__start_sdh_stack_observers = .);
|
||||
KEEP(*(SORT(.sdh_stack_observers*)))
|
||||
PROVIDE(__stop_sdh_stack_observers = .);
|
||||
} > FLASH
|
||||
.sdh_soc_observers :
|
||||
{
|
||||
PROVIDE(__start_sdh_soc_observers = .);
|
||||
KEEP(*(SORT(.sdh_soc_observers*)))
|
||||
PROVIDE(__stop_sdh_soc_observers = .);
|
||||
} > FLASH
|
||||
|
||||
} INSERT AFTER .text
|
||||
|
||||
|
||||
INCLUDE "nrf_common.ld"
|
475
core/embed/ble_bootloader/nrf_bootloader.c
Normal file
475
core/embed/ble_bootloader/nrf_bootloader.c
Normal file
@ -0,0 +1,475 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2021, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be
|
||||
* reverse engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include "nrf_bootloader.h"
|
||||
|
||||
#include "app_scheduler.h"
|
||||
#include "compiler_abstraction.h"
|
||||
#include "nordic_common.h"
|
||||
#include "nrf.h"
|
||||
#include "nrf_bootloader_app_start.h"
|
||||
#include "nrf_bootloader_dfu_timers.h"
|
||||
#include "nrf_bootloader_fw_activation.h"
|
||||
#include "nrf_bootloader_info.h"
|
||||
#include "nrf_bootloader_wdt.h"
|
||||
#include "nrf_delay.h"
|
||||
#include "nrf_dfu.h"
|
||||
#include "nrf_dfu_settings.h"
|
||||
#include "nrf_dfu_utils.h"
|
||||
#include "nrf_dfu_validation.h"
|
||||
#include "nrf_error.h"
|
||||
#include "nrf_gpio.h"
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_power.h"
|
||||
#include "sdk_config.h"
|
||||
|
||||
static nrf_dfu_observer_t
|
||||
m_user_observer; //<! Observer callback set by the user.
|
||||
static volatile bool m_flash_write_done;
|
||||
|
||||
#define SCHED_QUEUE_SIZE \
|
||||
32 /**< Maximum number of events in the scheduler queue. */
|
||||
#define SCHED_EVENT_DATA_SIZE \
|
||||
NRF_DFU_SCHED_EVENT_DATA_SIZE /**< Maximum app_scheduler event size. */
|
||||
|
||||
#if !(defined(NRF_BL_DFU_ENTER_METHOD_BUTTON) && \
|
||||
defined(NRF_BL_DFU_ENTER_METHOD_PINRESET) && \
|
||||
defined(NRF_BL_DFU_ENTER_METHOD_GPREGRET) && \
|
||||
defined(NRF_BL_DFU_ENTER_METHOD_BUTTONLESS) && \
|
||||
defined(NRF_BL_RESET_DELAY_MS) && defined(NRF_BL_DEBUG_PORT_DISABLE))
|
||||
#error Configuration file is missing flags. Update sdk_config.h.
|
||||
#endif
|
||||
|
||||
STATIC_ASSERT((NRF_BL_DFU_INACTIVITY_TIMEOUT_MS >= 100) ||
|
||||
(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS == 0),
|
||||
"NRF_BL_DFU_INACTIVITY_TIMEOUT_MS must be 100 ms or more, or 0 "
|
||||
"to indicate that it is disabled.");
|
||||
|
||||
#if defined(NRF_LOG_BACKEND_FLASH_START_PAGE)
|
||||
STATIC_ASSERT(NRF_LOG_BACKEND_FLASH_START_PAGE != 0,
|
||||
"If nrf_log flash backend is used it cannot use space after code "
|
||||
"because it would collide with settings page.");
|
||||
#endif
|
||||
|
||||
/**@brief Weak implemenation of nrf_dfu_init
|
||||
*
|
||||
* @note This function will be overridden if nrf_dfu.c is
|
||||
* compiled and linked with the project
|
||||
*/
|
||||
#if (__LINT__ != 1)
|
||||
__WEAK uint32_t nrf_dfu_init(nrf_dfu_observer_t observer) {
|
||||
NRF_LOG_DEBUG("in weak nrf_dfu_init");
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@brief Weak implementation of nrf_dfu_init
|
||||
*
|
||||
* @note This function must be overridden in application if
|
||||
* user-specific initialization is needed.
|
||||
*/
|
||||
__WEAK uint32_t nrf_dfu_init_user(void) {
|
||||
NRF_LOG_DEBUG("in weak nrf_dfu_init_user");
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
static void flash_write_callback(void* p_context) {
|
||||
UNUSED_PARAMETER(p_context);
|
||||
m_flash_write_done = true;
|
||||
}
|
||||
|
||||
static void do_reset(void* p_context) {
|
||||
UNUSED_PARAMETER(p_context);
|
||||
|
||||
NRF_LOG_FINAL_FLUSH();
|
||||
|
||||
nrf_delay_ms(NRF_BL_RESET_DELAY_MS);
|
||||
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
static void bootloader_reset(bool do_backup) {
|
||||
NRF_LOG_DEBUG("Resetting bootloader.");
|
||||
|
||||
if (do_backup) {
|
||||
m_flash_write_done = false;
|
||||
nrf_dfu_settings_backup(do_reset);
|
||||
} else {
|
||||
do_reset(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void inactivity_timeout(void) {
|
||||
NRF_LOG_INFO("Inactivity timeout.");
|
||||
bootloader_reset(true);
|
||||
}
|
||||
|
||||
/**@brief Function for handling DFU events.
|
||||
*/
|
||||
static void dfu_observer(nrf_dfu_evt_type_t evt_type) {
|
||||
switch (evt_type) {
|
||||
case NRF_DFU_EVT_DFU_STARTED:
|
||||
case NRF_DFU_EVT_OBJECT_RECEIVED:
|
||||
nrf_bootloader_dfu_inactivity_timer_restart(
|
||||
NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS),
|
||||
inactivity_timeout);
|
||||
break;
|
||||
case NRF_DFU_EVT_DFU_COMPLETED:
|
||||
case NRF_DFU_EVT_DFU_ABORTED:
|
||||
bootloader_reset(true);
|
||||
break;
|
||||
case NRF_DFU_EVT_TRANSPORT_DEACTIVATED:
|
||||
// Reset the internal state of the DFU settings to the last stored state.
|
||||
nrf_dfu_settings_reinit();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_user_observer) {
|
||||
m_user_observer(evt_type);
|
||||
}
|
||||
}
|
||||
|
||||
/**@brief Function for initializing the event scheduler.
|
||||
*/
|
||||
static void scheduler_init(void) {
|
||||
APP_SCHED_INIT(SCHED_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
|
||||
}
|
||||
|
||||
/**@brief Suspend the CPU until an interrupt occurs.
|
||||
*/
|
||||
static void wait_for_event(void) {
|
||||
#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD)
|
||||
(void)sd_app_evt_wait();
|
||||
#else
|
||||
// Wait for an event.
|
||||
__WFE();
|
||||
// Clear the internal event register.
|
||||
__SEV();
|
||||
__WFE();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**@brief Continually sleep and process tasks whenever woken.
|
||||
*/
|
||||
static void loop_forever(void) {
|
||||
while (true) {
|
||||
// feed the watchdog if enabled.
|
||||
nrf_bootloader_wdt_feed();
|
||||
|
||||
app_sched_execute();
|
||||
|
||||
if (!NRF_LOG_PROCESS()) {
|
||||
wait_for_event();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if NRF_BL_DFU_ENTER_METHOD_BUTTON
|
||||
//#ifndef BUTTON_PULL
|
||||
// #error NRF_BL_DFU_ENTER_METHOD_BUTTON is enabled but not buttons seem to
|
||||
// be available on the board.
|
||||
//#endif
|
||||
/**@brief Function for initializing button used to enter DFU mode.
|
||||
*/
|
||||
static void dfu_enter_button_init(void) {
|
||||
nrf_gpio_cfg_sense_input(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN,
|
||||
NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool crc_on_valid_app_required(void) {
|
||||
bool ret = true;
|
||||
if (NRF_BL_APP_CRC_CHECK_SKIPPED_ON_SYSTEMOFF_RESET &&
|
||||
(nrf_power_resetreas_get() & NRF_POWER_RESETREAS_OFF_MASK)) {
|
||||
nrf_power_resetreas_clear(NRF_POWER_RESETREAS_OFF_MASK);
|
||||
ret = false;
|
||||
} else if (NRF_BL_APP_CRC_CHECK_SKIPPED_ON_GPREGRET2 &&
|
||||
((nrf_power_gpregret2_get() & BOOTLOADER_DFU_SKIP_CRC_MASK) ==
|
||||
BOOTLOADER_DFU_SKIP_CRC)) {
|
||||
nrf_power_gpregret2_set(nrf_power_gpregret2_get() &
|
||||
~BOOTLOADER_DFU_SKIP_CRC);
|
||||
ret = false;
|
||||
} else {
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool boot_validate(boot_validation_t const* p_validation,
|
||||
uint32_t data_addr, uint32_t data_len, bool do_crc) {
|
||||
if (!do_crc && (p_validation->type == VALIDATE_CRC)) {
|
||||
return true;
|
||||
}
|
||||
return nrf_dfu_validation_boot_validate(p_validation, data_addr, data_len);
|
||||
}
|
||||
|
||||
/** @brief Function for checking if the main application is valid.
|
||||
*
|
||||
* @details This function checks if there is a valid application
|
||||
* located at Bank 0.
|
||||
*
|
||||
* @param[in] do_crc Perform CRC check on application. Only CRC checks
|
||||
can be skipped. For other boot validation types,
|
||||
this parameter is ignored.
|
||||
*
|
||||
* @retval true If a valid application has been detected.
|
||||
* @retval false If there is no valid application.
|
||||
*/
|
||||
static bool app_is_valid(bool do_crc) {
|
||||
if (s_dfu_settings.bank_0.bank_code != NRF_DFU_BANK_VALID_APP) {
|
||||
NRF_LOG_INFO("Boot validation failed. No valid app to boot.");
|
||||
return false;
|
||||
} else if (NRF_BL_APP_SIGNATURE_CHECK_REQUIRED &&
|
||||
(s_dfu_settings.boot_validation_app.type !=
|
||||
VALIDATE_ECDSA_P256_SHA256)) {
|
||||
NRF_LOG_WARNING(
|
||||
"Boot validation failed. The boot validation of the app must be a "
|
||||
"signature check.");
|
||||
return false;
|
||||
} else if (SD_PRESENT &&
|
||||
!boot_validate(&s_dfu_settings.boot_validation_softdevice,
|
||||
MBR_SIZE, s_dfu_settings.sd_size, do_crc)) {
|
||||
NRF_LOG_WARNING(
|
||||
"Boot validation failed. SoftDevice is present but invalid.");
|
||||
return false;
|
||||
} else if (!boot_validate(&s_dfu_settings.boot_validation_app,
|
||||
nrf_dfu_bank0_start_addr(),
|
||||
s_dfu_settings.bank_0.image_size, do_crc)) {
|
||||
NRF_LOG_WARNING("Boot validation failed. App is invalid.");
|
||||
return false;
|
||||
}
|
||||
// The bootloader itself is not checked, since a self-check of this kind gives
|
||||
// little to no benefit compared to the cost incurred on each bootup.
|
||||
|
||||
NRF_LOG_DEBUG("App is valid");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**@brief Function for clearing all DFU enter flags that
|
||||
* preserve state during reset.
|
||||
*
|
||||
* @details This is used to make sure that each of these flags
|
||||
* is checked only once after reset.
|
||||
*/
|
||||
static void dfu_enter_flags_clear(void) {
|
||||
if (NRF_BL_DFU_ENTER_METHOD_PINRESET &&
|
||||
(NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk)) {
|
||||
// Clear RESETPIN flag.
|
||||
NRF_POWER->RESETREAS |= POWER_RESETREAS_RESETPIN_Msk;
|
||||
}
|
||||
|
||||
if (NRF_BL_DFU_ENTER_METHOD_GPREGRET &&
|
||||
((nrf_power_gpregret_get() & BOOTLOADER_DFU_START_MASK) ==
|
||||
BOOTLOADER_DFU_START)) {
|
||||
// Clear DFU mark in GPREGRET register.
|
||||
nrf_power_gpregret_set(nrf_power_gpregret_get() & ~BOOTLOADER_DFU_START);
|
||||
}
|
||||
|
||||
if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS &&
|
||||
(s_dfu_settings.enter_buttonless_dfu == 1)) {
|
||||
// Clear DFU flag in flash settings.
|
||||
s_dfu_settings.enter_buttonless_dfu = 0;
|
||||
APP_ERROR_CHECK(nrf_dfu_settings_write(NULL));
|
||||
}
|
||||
}
|
||||
|
||||
/**@brief Function for checking whether to enter DFU mode or not.
|
||||
*/
|
||||
static bool dfu_enter_check(void) {
|
||||
if (!app_is_valid(crc_on_valid_app_required())) {
|
||||
NRF_LOG_DEBUG("DFU mode because app is not valid.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NRF_BL_DFU_ENTER_METHOD_BUTTON &&
|
||||
(nrf_gpio_pin_read(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN) == 1)) {
|
||||
NRF_LOG_DEBUG("DFU mode requested via button.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NRF_BL_DFU_ENTER_METHOD_PINRESET &&
|
||||
(NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk)) {
|
||||
NRF_LOG_DEBUG("DFU mode requested via pin-reset.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NRF_BL_DFU_ENTER_METHOD_GPREGRET &&
|
||||
((nrf_power_gpregret_get() & BOOTLOADER_DFU_START_MASK) ==
|
||||
BOOTLOADER_DFU_START)) {
|
||||
NRF_LOG_DEBUG("DFU mode requested via GPREGRET.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS &&
|
||||
(s_dfu_settings.enter_buttonless_dfu == 1)) {
|
||||
NRF_LOG_DEBUG("DFU mode requested via bootloader settings.");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP
|
||||
static void postvalidate(void) {
|
||||
NRF_LOG_INFO("Postvalidating update after reset.");
|
||||
nrf_dfu_validation_init();
|
||||
|
||||
if (nrf_dfu_validation_init_cmd_present()) {
|
||||
uint32_t firmware_start_addr;
|
||||
uint32_t firmware_size;
|
||||
|
||||
// Execute a previously received init packed. Subsequent executes will have
|
||||
// no effect.
|
||||
if (nrf_dfu_validation_init_cmd_execute(
|
||||
&firmware_start_addr, &firmware_size) == NRF_DFU_RES_CODE_SUCCESS) {
|
||||
if (nrf_dfu_validation_prevalidate() == NRF_DFU_RES_CODE_SUCCESS) {
|
||||
if (nrf_dfu_validation_activation_prepare(firmware_start_addr,
|
||||
firmware_size) ==
|
||||
NRF_DFU_RES_CODE_SUCCESS) {
|
||||
NRF_LOG_INFO("Postvalidation successful.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_0;
|
||||
UNUSED_RETURN_VALUE(nrf_dfu_settings_write_and_backup(flash_write_callback));
|
||||
}
|
||||
#endif
|
||||
|
||||
ret_code_t nrf_bootloader_init(nrf_dfu_observer_t observer) {
|
||||
NRF_LOG_DEBUG("In nrf_bootloader_init");
|
||||
|
||||
ret_code_t ret_val;
|
||||
nrf_bootloader_fw_activation_result_t activation_result;
|
||||
uint32_t initial_timeout;
|
||||
bool dfu_enter = false;
|
||||
|
||||
m_user_observer = observer;
|
||||
|
||||
if (NRF_BL_DEBUG_PORT_DISABLE) {
|
||||
nrf_bootloader_debug_port_disable();
|
||||
}
|
||||
|
||||
#if NRF_BL_DFU_ENTER_METHOD_BUTTON
|
||||
dfu_enter_button_init();
|
||||
#endif
|
||||
|
||||
ret_val = nrf_dfu_settings_init(false);
|
||||
if (ret_val != NRF_SUCCESS) {
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
#if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP
|
||||
// Postvalidate if DFU has signaled that update is ready.
|
||||
if (s_dfu_settings.bank_current == NRF_DFU_CURRENT_BANK_1) {
|
||||
postvalidate();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check if an update needs to be activated and activate it.
|
||||
activation_result = nrf_bootloader_fw_activate();
|
||||
|
||||
switch (activation_result) {
|
||||
case ACTIVATION_NONE:
|
||||
initial_timeout =
|
||||
NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS);
|
||||
dfu_enter = dfu_enter_check();
|
||||
break;
|
||||
|
||||
case ACTIVATION_SUCCESS_EXPECT_ADDITIONAL_UPDATE:
|
||||
initial_timeout =
|
||||
NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_CONTINUATION_TIMEOUT_MS);
|
||||
dfu_enter = true;
|
||||
break;
|
||||
|
||||
case ACTIVATION_SUCCESS:
|
||||
bootloader_reset(true);
|
||||
NRF_LOG_ERROR("Unreachable");
|
||||
return NRF_ERROR_INTERNAL; // Should not reach this.
|
||||
|
||||
case ACTIVATION_ERROR:
|
||||
default:
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
if (dfu_enter) {
|
||||
nrf_bootloader_wdt_init();
|
||||
scheduler_init();
|
||||
dfu_enter_flags_clear();
|
||||
|
||||
// Call user-defined init function if implemented
|
||||
ret_val = nrf_dfu_init_user();
|
||||
if (ret_val != NRF_SUCCESS) {
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
nrf_bootloader_dfu_inactivity_timer_restart(initial_timeout,
|
||||
inactivity_timeout);
|
||||
|
||||
ret_val = nrf_dfu_init(dfu_observer);
|
||||
if (ret_val != NRF_SUCCESS) {
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
NRF_LOG_DEBUG("Enter main loop");
|
||||
loop_forever(); // This function will never return.
|
||||
NRF_LOG_ERROR("Unreachable");
|
||||
} else {
|
||||
// Erase additional data like peer data or advertisement name
|
||||
ret_val = nrf_dfu_settings_additional_erase();
|
||||
if (ret_val != NRF_SUCCESS) {
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
m_flash_write_done = false;
|
||||
nrf_dfu_settings_backup(flash_write_callback);
|
||||
ASSERT(m_flash_write_done);
|
||||
|
||||
nrf_bootloader_app_start();
|
||||
NRF_LOG_ERROR("Unreachable");
|
||||
}
|
||||
|
||||
// Should not be reached.
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
63
core/embed/ble_bootloader/nrf_crypto_allocator.h
Normal file
63
core/embed/ble_bootloader/nrf_crypto_allocator.h
Normal file
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2019 - 2021, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be
|
||||
* reverse engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef NRF_CRYPTO_ALLOCATOR_H__
|
||||
#define NRF_CRYPTO_ALLOCATOR_H__
|
||||
|
||||
#include "nrf_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Crypto library in bootloader case does not use dynamic allocation */
|
||||
#define NRF_CRYPTO_ALLOC(size) \
|
||||
NULL; \
|
||||
ASSERT(0)
|
||||
#define NRF_CRYPTO_ALLOC_ON_STACK(size) \
|
||||
NULL; \
|
||||
ASSERT(0)
|
||||
#define NRF_CRYPTO_FREE(ptr) (void)ptr;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NRF_CRYPTO_ALLOCATOR_H__ */
|
276
core/embed/ble_bootloader/nrf_dfu_serial_uart.c
Normal file
276
core/embed/ble_bootloader/nrf_dfu_serial_uart.c
Normal file
@ -0,0 +1,276 @@
|
||||
// clang-format off
|
||||
|
||||
/**
|
||||
* Copyright (c) 2016 - 2021, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nrf_dfu_serial.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "trezor_t3w1_d1_NRF.h"
|
||||
|
||||
#include "nrf_gpio.h"
|
||||
#include "nordic_common.h"
|
||||
#include "app_util_platform.h"
|
||||
#include "nrf_dfu_transport.h"
|
||||
#include "nrf_dfu_req_handler.h"
|
||||
#include "slip.h"
|
||||
#include "nrf_balloc.h"
|
||||
#include "nrf_drv_uart.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME nrf_dfu_serial_uart
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup nrf_dfu_serial_uart DFU Serial UART transport
|
||||
* @ingroup nrf_dfu
|
||||
* @brief Device Firmware Update (DFU) transport layer using UART.
|
||||
*/
|
||||
|
||||
#define NRF_SERIAL_OPCODE_SIZE (sizeof(uint8_t))
|
||||
#define NRF_UART_MAX_RESPONSE_SIZE_SLIP (2 * NRF_SERIAL_MAX_RESPONSE_SIZE + 1)
|
||||
#define RX_BUF_SIZE (64) //to get 64bytes payload
|
||||
#define OPCODE_OFFSET (sizeof(uint32_t) - NRF_SERIAL_OPCODE_SIZE)
|
||||
#define DATA_OFFSET (OPCODE_OFFSET + NRF_SERIAL_OPCODE_SIZE)
|
||||
#define UART_SLIP_MTU (2 * (RX_BUF_SIZE + 1) + 1)
|
||||
#define BALLOC_BUF_SIZE ((CEIL_DIV((RX_BUF_SIZE+OPCODE_SIZE),sizeof(uint32_t))*sizeof(uint32_t)))
|
||||
|
||||
NRF_BALLOC_DEF(m_payload_pool, (UART_SLIP_MTU + 1), NRF_DFU_SERIAL_UART_RX_BUFFERS);
|
||||
|
||||
static nrf_drv_uart_t m_uart = NRF_DRV_UART_INSTANCE(0);
|
||||
static uint8_t m_rx_byte;
|
||||
|
||||
static nrf_dfu_serial_t m_serial;
|
||||
static slip_t m_slip;
|
||||
static uint8_t m_rsp_buf[NRF_UART_MAX_RESPONSE_SIZE_SLIP];
|
||||
static bool m_active;
|
||||
static bool m_waiting_for_buffers = false;
|
||||
|
||||
static nrf_dfu_observer_t m_observer;
|
||||
|
||||
static uint32_t uart_dfu_transport_init(nrf_dfu_observer_t observer);
|
||||
static uint32_t uart_dfu_transport_close(nrf_dfu_transport_t const * p_exception);
|
||||
|
||||
DFU_TRANSPORT_REGISTER(nrf_dfu_transport_t const uart_dfu_transport) =
|
||||
{
|
||||
.init_func = uart_dfu_transport_init,
|
||||
.close_func = uart_dfu_transport_close,
|
||||
};
|
||||
|
||||
static void payload_free(void * p_buf)
|
||||
{
|
||||
uint8_t * p_buf_root = (uint8_t *)p_buf - DATA_OFFSET; //pointer is shifted to point to data
|
||||
nrf_balloc_free(&m_payload_pool, p_buf_root);
|
||||
uint8_t utilization = m_payload_pool.p_stack_limit - m_payload_pool.p_cb->p_stack_pointer;
|
||||
|
||||
if (m_waiting_for_buffers && utilization < NRF_DFU_SERIAL_UART_RX_BUFFERS - 2) {
|
||||
NRF_LOG_INFO("Buffer utilization: %d, resuming.", utilization);
|
||||
|
||||
nrf_gpio_pin_set(RTS_PIN_NUMBER);
|
||||
nrf_gpio_cfg_output(RTS_PIN_NUMBER);
|
||||
m_uart.uarte.p_reg->PSEL.RTS = RTS_PIN_NUMBER;
|
||||
m_waiting_for_buffers = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static ret_code_t rsp_send(uint8_t const * p_data, uint32_t length)
|
||||
{
|
||||
uint32_t slip_len;
|
||||
(void) slip_encode(m_rsp_buf, (uint8_t *)p_data, length, &slip_len);
|
||||
|
||||
return nrf_drv_uart_tx(&m_uart, m_rsp_buf, slip_len);
|
||||
}
|
||||
|
||||
static __INLINE void on_rx_complete(nrf_dfu_serial_t * p_transport, uint8_t * p_data, uint8_t len)
|
||||
{
|
||||
ret_code_t ret_code = NRF_ERROR_TIMEOUT;
|
||||
|
||||
// Check if there is byte to process. Zero length transfer means that RXTO occured.
|
||||
if (len)
|
||||
{
|
||||
ret_code = slip_decode_add_byte(&m_slip, p_data[0]);
|
||||
}
|
||||
|
||||
(void) nrf_drv_uart_rx(&m_uart, &m_rx_byte, 1);
|
||||
|
||||
if (ret_code == NRF_SUCCESS)
|
||||
{
|
||||
nrf_dfu_serial_on_packet_received(p_transport,
|
||||
(uint8_t const *)m_slip.p_buffer,
|
||||
m_slip.current_index);
|
||||
|
||||
uint8_t * p_rx_buf = nrf_balloc_alloc(&m_payload_pool);
|
||||
|
||||
uint8_t utilization = m_payload_pool.p_stack_limit - m_payload_pool.p_cb->p_stack_pointer;
|
||||
|
||||
if (!m_waiting_for_buffers && utilization >= NRF_DFU_SERIAL_UART_RX_BUFFERS - 2) {
|
||||
NRF_LOG_INFO("Buffer utilization: %d, waiting.", utilization);
|
||||
m_uart.uarte.p_reg->PSEL.RTS = NRF_UART_PSEL_DISCONNECTED;
|
||||
nrf_gpio_cfg_output(RTS_PIN_NUMBER);
|
||||
nrf_gpio_pin_set(RTS_PIN_NUMBER);
|
||||
m_waiting_for_buffers = true;
|
||||
}
|
||||
|
||||
if (p_rx_buf == NULL)
|
||||
{
|
||||
NRF_LOG_ERROR("Failed to allocate buffer");
|
||||
return;
|
||||
}
|
||||
NRF_LOG_INFO("Allocated buffer %x", p_rx_buf);
|
||||
// reset the slip decoding
|
||||
m_slip.p_buffer = &p_rx_buf[OPCODE_OFFSET];
|
||||
m_slip.current_index = 0;
|
||||
m_slip.state = SLIP_STATE_DECODING;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void uart_event_handler(nrf_drv_uart_event_t * p_event, void * p_context)
|
||||
{
|
||||
switch (p_event->type)
|
||||
{
|
||||
case NRF_DRV_UART_EVT_RX_DONE:
|
||||
on_rx_complete((nrf_dfu_serial_t*)p_context,
|
||||
p_event->data.rxtx.p_data,
|
||||
p_event->data.rxtx.bytes);
|
||||
break;
|
||||
|
||||
case NRF_DRV_UART_EVT_ERROR:
|
||||
APP_ERROR_HANDLER(p_event->data.error.error_mask);
|
||||
break;
|
||||
|
||||
default:
|
||||
// No action.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t uart_dfu_transport_init(nrf_dfu_observer_t observer)
|
||||
{
|
||||
uint32_t err_code = NRF_SUCCESS;
|
||||
|
||||
if (m_active)
|
||||
{
|
||||
return err_code;
|
||||
}
|
||||
|
||||
NRF_LOG_DEBUG("serial_dfu_transport_init()");
|
||||
|
||||
m_observer = observer;
|
||||
|
||||
err_code = nrf_balloc_init(&m_payload_pool);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
return err_code;
|
||||
}
|
||||
|
||||
uint8_t * p_rx_buf = nrf_balloc_alloc(&m_payload_pool);
|
||||
|
||||
m_slip.p_buffer = &p_rx_buf[OPCODE_OFFSET];
|
||||
m_slip.current_index = 0;
|
||||
m_slip.buffer_len = UART_SLIP_MTU;
|
||||
m_slip.state = SLIP_STATE_DECODING;
|
||||
|
||||
m_serial.rsp_func = rsp_send;
|
||||
m_serial.payload_free_func = payload_free;
|
||||
m_serial.mtu = UART_SLIP_MTU;
|
||||
m_serial.p_rsp_buf = &m_rsp_buf[NRF_UART_MAX_RESPONSE_SIZE_SLIP -
|
||||
NRF_SERIAL_MAX_RESPONSE_SIZE];
|
||||
m_serial.p_low_level_transport = &uart_dfu_transport;
|
||||
|
||||
nrf_drv_uart_config_t uart_config = NRF_DRV_UART_DEFAULT_CONFIG;
|
||||
|
||||
uart_config.pseltxd = TX_PIN_NUMBER;
|
||||
uart_config.pselrxd = RX_PIN_NUMBER;
|
||||
uart_config.pselcts = CTS_PIN_NUMBER;
|
||||
uart_config.pselrts = RTS_PIN_NUMBER;
|
||||
uart_config.hwfc = NRF_UART_HWFC_ENABLED;
|
||||
uart_config.p_context = &m_serial;
|
||||
|
||||
nrf_gpio_cfg(
|
||||
RTS_PIN_NUMBER,
|
||||
NRF_GPIO_PIN_DIR_OUTPUT,
|
||||
NRF_GPIO_PIN_INPUT_DISCONNECT,
|
||||
NRF_GPIO_PIN_NOPULL,
|
||||
NRF_GPIO_PIN_S0S1,
|
||||
NRF_GPIO_PIN_NOSENSE);
|
||||
|
||||
|
||||
nrf_gpio_pin_write(RTS_PIN_NUMBER, 0);
|
||||
|
||||
err_code = nrf_drv_uart_init(&m_uart, &uart_config, uart_event_handler);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Failed initializing uart");
|
||||
return err_code;
|
||||
}
|
||||
|
||||
err_code = nrf_drv_uart_rx(&m_uart, &m_rx_byte, 1);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Failed initializing rx");
|
||||
}
|
||||
|
||||
NRF_LOG_DEBUG("serial_dfu_transport_init() completed");
|
||||
|
||||
m_active = true;
|
||||
|
||||
if (m_observer)
|
||||
{
|
||||
m_observer(NRF_DFU_EVT_TRANSPORT_ACTIVATED);
|
||||
}
|
||||
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t uart_dfu_transport_close(nrf_dfu_transport_t const * p_exception)
|
||||
{
|
||||
if ((m_active == true) && (p_exception != &uart_dfu_transport))
|
||||
{
|
||||
nrf_drv_uart_uninit(&m_uart);
|
||||
m_active = false;
|
||||
}
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
5
core/embed/ble_bootloader/priv.pem
Normal file
5
core/embed/ble_bootloader/priv.pem
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIOSMfopjR9WnpAjLnog4xJG5XRVi5MfXk7bGGuxLanCAoAoGCCqGSM49
|
||||
AwEHoUQDQgAE9KQi8GEjC+sEphRRaW/GfnCfPJEaKY+oyAw/t0FUL37WzYQEfAos
|
||||
6HnwYBqys9MYxWRJc0woWfaQGi5I+ptzrQ==
|
||||
-----END EC PRIVATE KEY-----
|
5307
core/embed/ble_bootloader/sdk_config.h
Normal file
5307
core/embed/ble_bootloader/sdk_config.h
Normal file
File diff suppressed because it is too large
Load Diff
104
core/embed/ble_bootloader/settings.hex
Normal file
104
core/embed/ble_bootloader/settings.hex
Normal file
@ -0,0 +1,104 @@
|
||||
:020000040007F3
|
||||
:10E000005021D2AF0200000000000000000000001C
|
||||
:10E01000000000000000000080820100C0F8B7B4DA
|
||||
:10E0200001000000000000000000000000000000EF
|
||||
:10E030000000000034560200000000000000000054
|
||||
:10E0400000000000000000000000000000000000D0
|
||||
:10E0500000000000000000000000000000000000C0
|
||||
:10E0600000000000000000000000000000000000B0
|
||||
:10E0700000000000000000000000000000000000A0
|
||||
:10E080000000000000000000000000000000000090
|
||||
:10E090000000000000000000000000000000000080
|
||||
:10E0A0000000000000000000000000000000000070
|
||||
:10E0B0000000000000000000000000000000000060
|
||||
:10E0C0000000000000000000000000000000000050
|
||||
:10E0D0000000000000000000000000000000000040
|
||||
:10E0E0000000000000000000000000000000000030
|
||||
:10E0F0000000000000000000000000000000000020
|
||||
:10E10000000000000000000000000000000000000F
|
||||
:10E1100000000000000000000000000000000000FF
|
||||
:10E1200000000000000000000000000000000000EF
|
||||
:10E1300000000000000000000000000000000000DF
|
||||
:10E1400000000000000000000000000000000000CF
|
||||
:10E1500000000000000000000000000000000000BF
|
||||
:10E1600000000000000000000000000000000000AF
|
||||
:10E17000000000000000000000000000000000009F
|
||||
:10E18000000000000000000000000000000000008F
|
||||
:10E19000000000000000000000000000000000007F
|
||||
:10E1A000000000000000000000000000000000006F
|
||||
:10E1B000000000000000000000000000000000005F
|
||||
:10E1C000000000000000000000000000000000004F
|
||||
:10E1D000000000000000000000000000000000003F
|
||||
:10E1E000000000000000000000000000000000002F
|
||||
:10E1F000000000000000000000000000000000001F
|
||||
:10E20000000000000000000000000000000000000E
|
||||
:10E2100000000000000000000000000000000000FE
|
||||
:10E2200000000000000000000000000000000000EE
|
||||
:10E2300000000000000000000000000000000000DE
|
||||
:10E2400000000000000000000000000000000000CE
|
||||
:10E250000000000000000000000000008AEF67D40A
|
||||
:10E26000039C5C1C98A20BBD8ABFB9C46939106BB2
|
||||
:10E27000B47E723565915A51FAC818DE94DD6E8C01
|
||||
:10E280002BD8C489343239712A38D616C1A9482C02
|
||||
:10E29000CDA78E5E28F37D0E3AF147DF285C80170C
|
||||
:10E2A00071035B9F4D32703D914A924FB5B9142076
|
||||
:10E2B000EE2F84400F8681CD396EC8C55C811676FD
|
||||
:10E2C000EC52E336EE8EF89DB5B57AAF4C54E69736
|
||||
:10E2D000A3E5472CD695C51C2E4EB86E56EE19F503
|
||||
:10E2E00051AE00000000000000000000000000002F
|
||||
:10E2F000000000000000000000000000000000001E
|
||||
:10E30000000000000000000000000000000000000D
|
||||
:10E3100000000000000000000000000000000000FD
|
||||
:04E32000000000FFFA
|
||||
:10F000005021D2AF0200000000000000000000000C
|
||||
:10F01000000000000000000080820100C0F8B7B4CA
|
||||
:10F0200001000000000000000000000000000000DF
|
||||
:10F030000000000034560200000000000000000044
|
||||
:10F0400000000000000000000000000000000000C0
|
||||
:10F0500000000000000000000000000000000000B0
|
||||
:10F0600000000000000000000000000000000000A0
|
||||
:10F070000000000000000000000000000000000090
|
||||
:10F080000000000000000000000000000000000080
|
||||
:10F090000000000000000000000000000000000070
|
||||
:10F0A0000000000000000000000000000000000060
|
||||
:10F0B0000000000000000000000000000000000050
|
||||
:10F0C0000000000000000000000000000000000040
|
||||
:10F0D0000000000000000000000000000000000030
|
||||
:10F0E0000000000000000000000000000000000020
|
||||
:10F0F0000000000000000000000000000000000010
|
||||
:10F1000000000000000000000000000000000000FF
|
||||
:10F1100000000000000000000000000000000000EF
|
||||
:10F1200000000000000000000000000000000000DF
|
||||
:10F1300000000000000000000000000000000000CF
|
||||
:10F1400000000000000000000000000000000000BF
|
||||
:10F1500000000000000000000000000000000000AF
|
||||
:10F16000000000000000000000000000000000009F
|
||||
:10F17000000000000000000000000000000000008F
|
||||
:10F18000000000000000000000000000000000007F
|
||||
:10F19000000000000000000000000000000000006F
|
||||
:10F1A000000000000000000000000000000000005F
|
||||
:10F1B000000000000000000000000000000000004F
|
||||
:10F1C000000000000000000000000000000000003F
|
||||
:10F1D000000000000000000000000000000000002F
|
||||
:10F1E000000000000000000000000000000000001F
|
||||
:10F1F000000000000000000000000000000000000F
|
||||
:10F2000000000000000000000000000000000000FE
|
||||
:10F2100000000000000000000000000000000000EE
|
||||
:10F2200000000000000000000000000000000000DE
|
||||
:10F2300000000000000000000000000000000000CE
|
||||
:10F2400000000000000000000000000000000000BE
|
||||
:10F250000000000000000000000000008AEF67D4FA
|
||||
:10F26000039C5C1C98A20BBD8ABFB9C46939106BA2
|
||||
:10F27000B47E723565915A51FAC818DE94DD6E8CF1
|
||||
:10F280002BD8C489343239712A38D616C1A9482CF2
|
||||
:10F29000CDA78E5E28F37D0E3AF147DF285C8017FC
|
||||
:10F2A00071035B9F4D32703D914A924FB5B9142066
|
||||
:10F2B000EE2F84400F8681CD396EC8C55C811676ED
|
||||
:10F2C000EC52E336EE8EF89DB5B57AAF4C54E69726
|
||||
:10F2D000A3E5472CD695C51C2E4EB86E56EE19F5F3
|
||||
:10F2E00051AE00000000000000000000000000001F
|
||||
:10F2F000000000000000000000000000000000000E
|
||||
:10F3000000000000000000000000000000000000FD
|
||||
:10F3100000000000000000000000000000000000ED
|
||||
:04F32000000000FFEA
|
||||
:00000001FF
|
11
core/embed/ble_bootloader/uecc/.gitignore
vendored
Normal file
11
core/embed/ble_bootloader/uecc/.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
__build__/
|
||||
__pycache__
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
*.pyz
|
||||
*.egg-info/
|
||||
*.a
|
||||
*.o
|
||||
*.so
|
||||
.DS_Store
|
21
core/embed/ble_bootloader/uecc/LICENSE.txt
Normal file
21
core/embed/ble_bootloader/uecc/LICENSE.txt
Normal file
@ -0,0 +1,21 @@
|
||||
Copyright (c) 2014, Kenneth MacKay
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
41
core/embed/ble_bootloader/uecc/README.md
Normal file
41
core/embed/ble_bootloader/uecc/README.md
Normal file
@ -0,0 +1,41 @@
|
||||
micro-ecc
|
||||
==========
|
||||
|
||||
A small and fast ECDH and ECDSA implementation for 8-bit, 32-bit, and 64-bit processors.
|
||||
|
||||
The static version of micro-ecc (ie, where the curve was selected at compile-time) can be found in the "static" branch.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Resistant to known side-channel attacks.
|
||||
* Written in C, with optional GCC inline assembly for AVR, ARM and Thumb platforms.
|
||||
* Supports 8, 32, and 64-bit architectures.
|
||||
* Small code size.
|
||||
* No dynamic memory allocation.
|
||||
* Support for 5 standard curves: secp160r1, secp192r1, secp224r1, secp256r1, and secp256k1.
|
||||
* BSD 2-clause license.
|
||||
|
||||
Usage Notes
|
||||
-----------
|
||||
### Point Representation ###
|
||||
Compressed points are represented in the standard format as defined in http://www.secg.org/sec1-v2.pdf; uncompressed points are represented in standard format, but without the `0x04` prefix. All functions except `uECC_decompress()` only accept uncompressed points; use `uECC_compress()` and `uECC_decompress()` to convert between compressed and uncompressed point representations.
|
||||
|
||||
Private keys are represented in the standard format.
|
||||
|
||||
### Using the Code ###
|
||||
|
||||
I recommend just copying (or symlink) the uECC files into your project. Then just `#include "uECC.h"` to use the micro-ecc functions.
|
||||
|
||||
For use with Arduino, you can use the Library Manager to download micro-ecc (**Sketch**=>**Include Library**=>**Manage Libraries**). You can then use uECC just like any other Arduino library (uECC should show up in the **Sketch**=>**Import Library** submenu).
|
||||
|
||||
See uECC.h for documentation for each function.
|
||||
|
||||
### Compilation Notes ###
|
||||
|
||||
* Should compile with any C/C++ compiler that supports stdint.h (this includes Visual Studio 2013).
|
||||
* If you want to change the defaults for any of the uECC compile-time options (such as `uECC_OPTIMIZATION_LEVEL`), you must change them in your Makefile or similar so that uECC.c is compiled with the desired values (ie, compile uECC.c with `-DuECC_OPTIMIZATION_LEVEL=3` or whatever).
|
||||
* When compiling for a Thumb-1 platform, you must use the `-fomit-frame-pointer` GCC option (this is enabled by default when compiling with `-O1` or higher).
|
||||
* When compiling for an ARM/Thumb-2 platform with `uECC_OPTIMIZATION_LEVEL` >= 3, you must use the `-fomit-frame-pointer` GCC option (this is enabled by default when compiling with `-O1` or higher).
|
||||
* When compiling for AVR, you must have optimizations enabled (compile with `-O1` or higher).
|
||||
* When building for Windows, you will need to link in the `advapi32.lib` system library.
|
820
core/embed/ble_bootloader/uecc/asm_arm.inc
Normal file
820
core/embed/ble_bootloader/uecc/asm_arm.inc
Normal file
@ -0,0 +1,820 @@
|
||||
/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_ASM_ARM_H_
|
||||
#define _UECC_ASM_ARM_H_
|
||||
|
||||
#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
|
||||
#define uECC_MIN_WORDS 8
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
#undef uECC_MIN_WORDS
|
||||
#define uECC_MIN_WORDS 7
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
#undef uECC_MIN_WORDS
|
||||
#define uECC_MIN_WORDS 6
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
#undef uECC_MIN_WORDS
|
||||
#define uECC_MIN_WORDS 5
|
||||
#endif
|
||||
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb)
|
||||
#define REG_RW "+&l"
|
||||
#define REG_WRITE "=&l"
|
||||
#else
|
||||
#define REG_RW "+&r"
|
||||
#define REG_WRITE "=&r"
|
||||
#endif
|
||||
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb || uECC_PLATFORM == uECC_arm_thumb2)
|
||||
#define REG_RW_LO "+&l"
|
||||
#define REG_WRITE_LO "=&l"
|
||||
#else
|
||||
#define REG_RW_LO "+&r"
|
||||
#define REG_WRITE_LO "=&r"
|
||||
#endif
|
||||
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb2)
|
||||
#define RESUME_SYNTAX
|
||||
#else
|
||||
#define RESUME_SYNTAX ".syntax divided \n\t"
|
||||
#endif
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL >= 2)
|
||||
|
||||
uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb) || (uECC_PLATFORM == uECC_arm_thumb2)
|
||||
uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 2 + 1;
|
||||
#else /* ARM */
|
||||
uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 4;
|
||||
#endif
|
||||
#endif
|
||||
uint32_t carry;
|
||||
uint32_t left_word;
|
||||
uint32_t right_word;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"movs %[carry], #0 \n\t"
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
"adr %[left], 1f \n\t"
|
||||
".align 4 \n\t"
|
||||
"adds %[jump], %[left] \n\t"
|
||||
#endif
|
||||
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"adds %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
"bx %[jump] \n\t"
|
||||
#endif
|
||||
"1: \n\t"
|
||||
REPEAT(DEC(uECC_MAX_WORDS),
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"adcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t")
|
||||
|
||||
"adcs %[carry], %[carry] \n\t"
|
||||
RESUME_SYNTAX
|
||||
: [dptr] REG_RW_LO (result), [lptr] REG_RW_LO (left), [rptr] REG_RW_LO (right),
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
[jump] REG_RW_LO (jump),
|
||||
#endif
|
||||
[carry] REG_WRITE_LO (carry), [left] REG_WRITE_LO (left_word),
|
||||
[right] REG_WRITE_LO (right_word)
|
||||
:
|
||||
: "cc", "memory"
|
||||
);
|
||||
return carry;
|
||||
}
|
||||
#define asm_add 1
|
||||
|
||||
uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb) || (uECC_PLATFORM == uECC_arm_thumb2)
|
||||
uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 2 + 1;
|
||||
#else /* ARM */
|
||||
uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 4;
|
||||
#endif
|
||||
#endif
|
||||
uint32_t carry;
|
||||
uint32_t left_word;
|
||||
uint32_t right_word;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"movs %[carry], #0 \n\t"
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
"adr %[left], 1f \n\t"
|
||||
".align 4 \n\t"
|
||||
"adds %[jump], %[left] \n\t"
|
||||
#endif
|
||||
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"subs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
"bx %[jump] \n\t"
|
||||
#endif
|
||||
"1: \n\t"
|
||||
REPEAT(DEC(uECC_MAX_WORDS),
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"sbcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t")
|
||||
|
||||
"adcs %[carry], %[carry] \n\t"
|
||||
RESUME_SYNTAX
|
||||
: [dptr] REG_RW_LO (result), [lptr] REG_RW_LO (left), [rptr] REG_RW_LO (right),
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
[jump] REG_RW_LO (jump),
|
||||
#endif
|
||||
[carry] REG_WRITE_LO (carry), [left] REG_WRITE_LO (left_word),
|
||||
[right] REG_WRITE_LO (right_word)
|
||||
:
|
||||
: "cc", "memory"
|
||||
);
|
||||
return !carry; /* Note that on ARM, carry flag set means "no borrow" when subtracting
|
||||
(for some reason...) */
|
||||
}
|
||||
#define asm_sub 1
|
||||
|
||||
#endif /* (uECC_OPTIMIZATION_LEVEL >= 2) */
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL >= 3)
|
||||
|
||||
#if (uECC_PLATFORM != uECC_arm_thumb)
|
||||
|
||||
#if uECC_ARM_USE_UMAAL
|
||||
#include "asm_arm_mult_square_umaal.inc"
|
||||
#else
|
||||
#include "asm_arm_mult_square.inc"
|
||||
#endif
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL == 3)
|
||||
|
||||
uECC_VLI_API void uECC_vli_mult(uint32_t *result,
|
||||
const uint32_t *left,
|
||||
const uint32_t *right,
|
||||
wordcount_t num_words) {
|
||||
register uint32_t *r0 __asm__("r0") = result;
|
||||
register const uint32_t *r1 __asm__("r1") = left;
|
||||
register const uint32_t *r2 __asm__("r2") = right;
|
||||
register uint32_t r3 __asm__("r3") = num_words;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
#if (uECC_MIN_WORDS == 5)
|
||||
FAST_MULT_ASM_5
|
||||
#if (uECC_MAX_WORDS > 5)
|
||||
FAST_MULT_ASM_5_TO_6
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 6)
|
||||
FAST_MULT_ASM_6_TO_7
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_MULT_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 6)
|
||||
FAST_MULT_ASM_6
|
||||
#if (uECC_MAX_WORDS > 6)
|
||||
FAST_MULT_ASM_6_TO_7
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_MULT_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 7)
|
||||
FAST_MULT_ASM_7
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_MULT_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 8)
|
||||
FAST_MULT_ASM_8
|
||||
#endif
|
||||
"1: \n\t"
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2)
|
||||
: "r" (r3)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
}
|
||||
#define asm_mult 1
|
||||
|
||||
#if uECC_SQUARE_FUNC
|
||||
uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
wordcount_t num_words) {
|
||||
register uint32_t *r0 __asm__("r0") = result;
|
||||
register const uint32_t *r1 __asm__("r1") = left;
|
||||
register uint32_t r2 __asm__("r2") = num_words;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
#if (uECC_MIN_WORDS == 5)
|
||||
FAST_SQUARE_ASM_5
|
||||
#if (uECC_MAX_WORDS > 5)
|
||||
FAST_SQUARE_ASM_5_TO_6
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 6)
|
||||
FAST_SQUARE_ASM_6_TO_7
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_SQUARE_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 6)
|
||||
FAST_SQUARE_ASM_6
|
||||
#if (uECC_MAX_WORDS > 6)
|
||||
FAST_SQUARE_ASM_6_TO_7
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_SQUARE_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 7)
|
||||
FAST_SQUARE_ASM_7
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_SQUARE_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 8)
|
||||
FAST_SQUARE_ASM_8
|
||||
#endif
|
||||
|
||||
"1: \n\t"
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1)
|
||||
: "r" (r2)
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
}
|
||||
#define asm_square 1
|
||||
#endif /* uECC_SQUARE_FUNC */
|
||||
|
||||
#else /* (uECC_OPTIMIZATION_LEVEL > 3) */
|
||||
|
||||
uECC_VLI_API void uECC_vli_mult(uint32_t *result,
|
||||
const uint32_t *left,
|
||||
const uint32_t *right,
|
||||
wordcount_t num_words) {
|
||||
register uint32_t *r0 __asm__("r0") = result;
|
||||
register const uint32_t *r1 __asm__("r1") = left;
|
||||
register const uint32_t *r2 __asm__("r2") = right;
|
||||
register uint32_t r3 __asm__("r3") = num_words;
|
||||
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
if (num_words == 5) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_MULT_ASM_5
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2)
|
||||
: "r" (r3)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
if (num_words == 6) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_MULT_ASM_6
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2)
|
||||
: "r" (r3)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
if (num_words == 7) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_MULT_ASM_7
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2)
|
||||
: "r" (r3)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
|
||||
if (num_words == 8) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_MULT_ASM_8
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2)
|
||||
: "r" (r3)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#define asm_mult 1
|
||||
|
||||
#if uECC_SQUARE_FUNC
|
||||
uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
wordcount_t num_words) {
|
||||
register uint32_t *r0 __asm__("r0") = result;
|
||||
register const uint32_t *r1 __asm__("r1") = left;
|
||||
register uint32_t r2 __asm__("r2") = num_words;
|
||||
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
if (num_words == 5) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_SQUARE_ASM_5
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1)
|
||||
: "r" (r2)
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
if (num_words == 6) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_SQUARE_ASM_6
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1)
|
||||
: "r" (r2)
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
if (num_words == 7) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_SQUARE_ASM_7
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1)
|
||||
: "r" (r2)
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
|
||||
if (num_words == 8) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_SQUARE_ASM_8
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1)
|
||||
: "r" (r2)
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#define asm_square 1
|
||||
#endif /* uECC_SQUARE_FUNC */
|
||||
|
||||
#endif /* (uECC_OPTIMIZATION_LEVEL > 3) */
|
||||
|
||||
#endif /* uECC_PLATFORM != uECC_arm_thumb */
|
||||
|
||||
#endif /* (uECC_OPTIMIZATION_LEVEL >= 3) */
|
||||
|
||||
/* ---- "Small" implementations ---- */
|
||||
|
||||
#if !asm_add
|
||||
uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
uint32_t carry = 0;
|
||||
uint32_t left_word;
|
||||
uint32_t right_word;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"1: \n\t"
|
||||
"ldmia %[lptr]!, {%[left]} \n\t" /* Load left word. */
|
||||
"ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */
|
||||
"lsrs %[carry], #1 \n\t" /* Set up carry flag (carry = 0 after this). */
|
||||
"adcs %[left], %[left], %[right] \n\t" /* Add with carry. */
|
||||
"adcs %[carry], %[carry], %[carry] \n\t" /* Store carry bit. */
|
||||
"stmia %[dptr]!, {%[left]} \n\t" /* Store result word. */
|
||||
"subs %[ctr], #1 \n\t" /* Decrement counter. */
|
||||
"bne 1b \n\t" /* Loop until counter == 0. */
|
||||
RESUME_SYNTAX
|
||||
: [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right),
|
||||
[ctr] REG_RW (num_words), [carry] REG_RW (carry),
|
||||
[left] REG_WRITE (left_word), [right] REG_WRITE (right_word)
|
||||
:
|
||||
: "cc", "memory"
|
||||
);
|
||||
return carry;
|
||||
}
|
||||
#define asm_add 1
|
||||
#endif
|
||||
|
||||
#if !asm_sub
|
||||
uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
uint32_t carry = 1; /* carry = 1 initially (means don't borrow) */
|
||||
uint32_t left_word;
|
||||
uint32_t right_word;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"1: \n\t"
|
||||
"ldmia %[lptr]!, {%[left]} \n\t" /* Load left word. */
|
||||
"ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */
|
||||
"lsrs %[carry], #1 \n\t" /* Set up carry flag (carry = 0 after this). */
|
||||
"sbcs %[left], %[left], %[right] \n\t" /* Subtract with borrow. */
|
||||
"adcs %[carry], %[carry], %[carry] \n\t" /* Store carry bit. */
|
||||
"stmia %[dptr]!, {%[left]} \n\t" /* Store result word. */
|
||||
"subs %[ctr], #1 \n\t" /* Decrement counter. */
|
||||
"bne 1b \n\t" /* Loop until counter == 0. */
|
||||
RESUME_SYNTAX
|
||||
: [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right),
|
||||
[ctr] REG_RW (num_words), [carry] REG_RW (carry),
|
||||
[left] REG_WRITE (left_word), [right] REG_WRITE (right_word)
|
||||
:
|
||||
: "cc", "memory"
|
||||
);
|
||||
return !carry;
|
||||
}
|
||||
#define asm_sub 1
|
||||
#endif
|
||||
|
||||
#if !asm_mult
|
||||
uECC_VLI_API void uECC_vli_mult(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
#if (uECC_PLATFORM != uECC_arm_thumb)
|
||||
uint32_t c0 = 0;
|
||||
uint32_t c1 = 0;
|
||||
uint32_t c2 = 0;
|
||||
uint32_t k = 0;
|
||||
uint32_t i;
|
||||
uint32_t t0, t1;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
|
||||
"1: \n\t" /* outer loop (k < num_words) */
|
||||
"movs %[i], #0 \n\t" /* i = 0 */
|
||||
"b 3f \n\t"
|
||||
|
||||
"2: \n\t" /* outer loop (k >= num_words) */
|
||||
"movs %[i], %[k] \n\t" /* i = k */
|
||||
"subs %[i], %[last_word] \n\t" /* i = k - (num_words - 1) (times 4) */
|
||||
|
||||
"3: \n\t" /* inner loop */
|
||||
"subs %[t0], %[k], %[i] \n\t" /* t0 = k-i */
|
||||
|
||||
"ldr %[t1], [%[right], %[t0]] \n\t" /* t1 = right[k - i] */
|
||||
"ldr %[t0], [%[left], %[i]] \n\t" /* t0 = left[i] */
|
||||
|
||||
"umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = left[i] * right[k - i] */
|
||||
|
||||
"adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */
|
||||
"adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */
|
||||
"adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */
|
||||
|
||||
"adds %[i], #4 \n\t" /* i += 4 */
|
||||
"cmp %[i], %[last_word] \n\t" /* i > (num_words - 1) (times 4)? */
|
||||
"bgt 4f \n\t" /* if so, exit the loop */
|
||||
"cmp %[i], %[k] \n\t" /* i <= k? */
|
||||
"ble 3b \n\t" /* if so, continue looping */
|
||||
|
||||
"4: \n\t" /* end inner loop */
|
||||
|
||||
"str %[c0], [%[result], %[k]] \n\t" /* result[k] = c0 */
|
||||
"mov %[c0], %[c1] \n\t" /* c0 = c1 */
|
||||
"mov %[c1], %[c2] \n\t" /* c1 = c2 */
|
||||
"movs %[c2], #0 \n\t" /* c2 = 0 */
|
||||
"adds %[k], #4 \n\t" /* k += 4 */
|
||||
"cmp %[k], %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */
|
||||
"ble 1b \n\t" /* if so, loop back, start with i = 0 */
|
||||
"cmp %[k], %[last_word], lsl #1 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
|
||||
"ble 2b \n\t" /* if so, loop back, start with i = (k + 1) - num_words */
|
||||
/* end outer loop */
|
||||
|
||||
"str %[c0], [%[result], %[k]] \n\t" /* result[num_words * 2 - 1] = c0 */
|
||||
RESUME_SYNTAX
|
||||
: [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2),
|
||||
[k] "+r" (k), [i] "=&r" (i), [t0] "=&r" (t0), [t1] "=&r" (t1)
|
||||
: [result] "r" (result), [left] "r" (left), [right] "r" (right),
|
||||
[last_word] "r" ((num_words - 1) * 4)
|
||||
: "cc", "memory"
|
||||
);
|
||||
|
||||
#else /* Thumb-1 */
|
||||
uint32_t r4, r5, r6, r7;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"subs %[r3], #1 \n\t" /* r3 = num_words - 1 */
|
||||
"lsls %[r3], #2 \n\t" /* r3 = (num_words - 1) * 4 */
|
||||
"mov r8, %[r3] \n\t" /* r8 = (num_words - 1) * 4 */
|
||||
"lsls %[r3], #1 \n\t" /* r3 = (num_words - 1) * 8 */
|
||||
"mov r9, %[r3] \n\t" /* r9 = (num_words - 1) * 8 */
|
||||
"movs %[r3], #0 \n\t" /* c0 = 0 */
|
||||
"movs %[r4], #0 \n\t" /* c1 = 0 */
|
||||
"movs %[r5], #0 \n\t" /* c2 = 0 */
|
||||
"movs %[r6], #0 \n\t" /* k = 0 */
|
||||
|
||||
"push {%[r0]} \n\t" /* keep result on the stack */
|
||||
|
||||
"1: \n\t" /* outer loop (k < num_words) */
|
||||
"movs %[r7], #0 \n\t" /* r7 = i = 0 */
|
||||
"b 3f \n\t"
|
||||
|
||||
"2: \n\t" /* outer loop (k >= num_words) */
|
||||
"movs %[r7], %[r6] \n\t" /* r7 = k */
|
||||
"mov %[r0], r8 \n\t" /* r0 = (num_words - 1) * 4 */
|
||||
"subs %[r7], %[r0] \n\t" /* r7 = i = k - (num_words - 1) (times 4) */
|
||||
|
||||
"3: \n\t" /* inner loop */
|
||||
"mov r10, %[r3] \n\t"
|
||||
"mov r11, %[r4] \n\t"
|
||||
"mov r12, %[r5] \n\t"
|
||||
"mov r14, %[r6] \n\t"
|
||||
"subs %[r0], %[r6], %[r7] \n\t" /* r0 = k - i */
|
||||
|
||||
"ldr %[r4], [%[r2], %[r0]] \n\t" /* r4 = right[k - i] */
|
||||
"ldr %[r0], [%[r1], %[r7]] \n\t" /* r0 = left[i] */
|
||||
|
||||
"lsrs %[r3], %[r0], #16 \n\t" /* r3 = a1 */
|
||||
"uxth %[r0], %[r0] \n\t" /* r0 = a0 */
|
||||
|
||||
"lsrs %[r5], %[r4], #16 \n\t" /* r5 = b1 */
|
||||
"uxth %[r4], %[r4] \n\t" /* r4 = b0 */
|
||||
|
||||
"movs %[r6], %[r3] \n\t" /* r6 = a1 */
|
||||
"muls %[r6], %[r5], %[r6] \n\t" /* r6 = a1 * b1 */
|
||||
"muls %[r3], %[r4], %[r3] \n\t" /* r3 = b0 * a1 */
|
||||
"muls %[r5], %[r0], %[r5] \n\t" /* r5 = a0 * b1 */
|
||||
"muls %[r0], %[r4], %[r0] \n\t" /* r0 = a0 * b0 */
|
||||
|
||||
/* Add middle terms */
|
||||
"lsls %[r4], %[r3], #16 \n\t"
|
||||
"lsrs %[r3], %[r3], #16 \n\t"
|
||||
"adds %[r0], %[r4] \n\t"
|
||||
"adcs %[r6], %[r3] \n\t"
|
||||
|
||||
"lsls %[r4], %[r5], #16 \n\t"
|
||||
"lsrs %[r5], %[r5], #16 \n\t"
|
||||
"adds %[r0], %[r4] \n\t"
|
||||
"adcs %[r6], %[r5] \n\t"
|
||||
|
||||
"mov %[r3], r10\n\t"
|
||||
"mov %[r4], r11\n\t"
|
||||
"mov %[r5], r12\n\t"
|
||||
"adds %[r3], %[r0] \n\t" /* add low word to c0 */
|
||||
"adcs %[r4], %[r6] \n\t" /* add high word to c1, including carry */
|
||||
"movs %[r0], #0 \n\t" /* r0 = 0 (does not affect carry bit) */
|
||||
"adcs %[r5], %[r0] \n\t" /* add carry to c2 */
|
||||
|
||||
"mov %[r6], r14\n\t" /* r6 = k */
|
||||
|
||||
"adds %[r7], #4 \n\t" /* i += 4 */
|
||||
"cmp %[r7], r8 \n\t" /* i > (num_words - 1) (times 4)? */
|
||||
"bgt 4f \n\t" /* if so, exit the loop */
|
||||
"cmp %[r7], %[r6] \n\t" /* i <= k? */
|
||||
"ble 3b \n\t" /* if so, continue looping */
|
||||
|
||||
"4: \n\t" /* end inner loop */
|
||||
|
||||
"ldr %[r0], [sp, #0] \n\t" /* r0 = result */
|
||||
|
||||
"str %[r3], [%[r0], %[r6]] \n\t" /* result[k] = c0 */
|
||||
"mov %[r3], %[r4] \n\t" /* c0 = c1 */
|
||||
"mov %[r4], %[r5] \n\t" /* c1 = c2 */
|
||||
"movs %[r5], #0 \n\t" /* c2 = 0 */
|
||||
"adds %[r6], #4 \n\t" /* k += 4 */
|
||||
"cmp %[r6], r8 \n\t" /* k <= (num_words - 1) (times 4) ? */
|
||||
"ble 1b \n\t" /* if so, loop back, start with i = 0 */
|
||||
"cmp %[r6], r9 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
|
||||
"ble 2b \n\t" /* if so, loop back, with i = (k + 1) - num_words */
|
||||
/* end outer loop */
|
||||
|
||||
"str %[r3], [%[r0], %[r6]] \n\t" /* result[num_words * 2 - 1] = c0 */
|
||||
"pop {%[r0]} \n\t" /* pop result off the stack */
|
||||
|
||||
RESUME_SYNTAX
|
||||
: [r3] "+l" (num_words), [r4] "=&l" (r4),
|
||||
[r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7)
|
||||
: [r0] "l" (result), [r1] "l" (left), [r2] "l" (right)
|
||||
: "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
#define asm_mult 1
|
||||
#endif
|
||||
|
||||
#if uECC_SQUARE_FUNC
|
||||
#if !asm_square
|
||||
uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
wordcount_t num_words) {
|
||||
#if (uECC_PLATFORM != uECC_arm_thumb)
|
||||
uint32_t c0 = 0;
|
||||
uint32_t c1 = 0;
|
||||
uint32_t c2 = 0;
|
||||
uint32_t k = 0;
|
||||
uint32_t i, tt;
|
||||
uint32_t t0, t1;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
|
||||
"1: \n\t" /* outer loop (k < num_words) */
|
||||
"movs %[i], #0 \n\t" /* i = 0 */
|
||||
"b 3f \n\t"
|
||||
|
||||
"2: \n\t" /* outer loop (k >= num_words) */
|
||||
"movs %[i], %[k] \n\t" /* i = k */
|
||||
"subs %[i], %[last_word] \n\t" /* i = k - (num_words - 1) (times 4) */
|
||||
|
||||
"3: \n\t" /* inner loop */
|
||||
"subs %[tt], %[k], %[i] \n\t" /* tt = k-i */
|
||||
|
||||
"ldr %[t1], [%[left], %[tt]] \n\t" /* t1 = left[k - i] */
|
||||
"ldr %[t0], [%[left], %[i]] \n\t" /* t0 = left[i] */
|
||||
|
||||
"umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = left[i] * right[k - i] */
|
||||
|
||||
"cmp %[i], %[tt] \n\t" /* (i < k - i) ? */
|
||||
"bge 4f \n\t" /* if i >= k - i, skip */
|
||||
"adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */
|
||||
"adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */
|
||||
"adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */
|
||||
|
||||
"4: \n\t"
|
||||
"adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */
|
||||
"adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */
|
||||
"adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */
|
||||
|
||||
"adds %[i], #4 \n\t" /* i += 4 */
|
||||
"cmp %[i], %[k] \n\t" /* i >= k? */
|
||||
"bge 5f \n\t" /* if so, exit the loop */
|
||||
"subs %[tt], %[k], %[i] \n\t" /* tt = k - i */
|
||||
"cmp %[i], %[tt] \n\t" /* i <= k - i? */
|
||||
"ble 3b \n\t" /* if so, continue looping */
|
||||
|
||||
"5: \n\t" /* end inner loop */
|
||||
|
||||
"str %[c0], [%[result], %[k]] \n\t" /* result[k] = c0 */
|
||||
"mov %[c0], %[c1] \n\t" /* c0 = c1 */
|
||||
"mov %[c1], %[c2] \n\t" /* c1 = c2 */
|
||||
"movs %[c2], #0 \n\t" /* c2 = 0 */
|
||||
"adds %[k], #4 \n\t" /* k += 4 */
|
||||
"cmp %[k], %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */
|
||||
"ble 1b \n\t" /* if so, loop back, start with i = 0 */
|
||||
"cmp %[k], %[last_word], lsl #1 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
|
||||
"ble 2b \n\t" /* if so, loop back, start with i = (k + 1) - num_words */
|
||||
/* end outer loop */
|
||||
|
||||
"str %[c0], [%[result], %[k]] \n\t" /* result[num_words * 2 - 1] = c0 */
|
||||
RESUME_SYNTAX
|
||||
: [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2),
|
||||
[k] "+r" (k), [i] "=&r" (i), [tt] "=&r" (tt), [t0] "=&r" (t0), [t1] "=&r" (t1)
|
||||
: [result] "r" (result), [left] "r" (left), [last_word] "r" ((num_words - 1) * 4)
|
||||
: "cc", "memory"
|
||||
);
|
||||
|
||||
#else
|
||||
uint32_t r3, r4, r5, r6, r7;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"subs %[r2], #1 \n\t" /* r2 = num_words - 1 */
|
||||
"lsls %[r2], #2 \n\t" /* r2 = (num_words - 1) * 4 */
|
||||
"mov r8, %[r2] \n\t" /* r8 = (num_words - 1) * 4 */
|
||||
"lsls %[r2], #1 \n\t" /* r2 = (num_words - 1) * 8 */
|
||||
"mov r9, %[r2] \n\t" /* r9 = (num_words - 1) * 8 */
|
||||
"movs %[r2], #0 \n\t" /* c0 = 0 */
|
||||
"movs %[r3], #0 \n\t" /* c1 = 0 */
|
||||
"movs %[r4], #0 \n\t" /* c2 = 0 */
|
||||
"movs %[r5], #0 \n\t" /* k = 0 */
|
||||
|
||||
"push {%[r0]} \n\t" /* keep result on the stack */
|
||||
|
||||
"1: \n\t" /* outer loop (k < num_words) */
|
||||
"movs %[r6], #0 \n\t" /* r6 = i = 0 */
|
||||
"b 3f \n\t"
|
||||
|
||||
"2: \n\t" /* outer loop (k >= num_words) */
|
||||
"movs %[r6], %[r5] \n\t" /* r6 = k */
|
||||
"mov %[r0], r8 \n\t" /* r0 = (num_words - 1) * 4 */
|
||||
"subs %[r6], %[r0] \n\t" /* r6 = i = k - (num_words - 1) (times 4) */
|
||||
|
||||
"3: \n\t" /* inner loop */
|
||||
"mov r10, %[r2] \n\t"
|
||||
"mov r11, %[r3] \n\t"
|
||||
"mov r12, %[r4] \n\t"
|
||||
"mov r14, %[r5] \n\t"
|
||||
"subs %[r7], %[r5], %[r6] \n\t" /* r7 = k - i */
|
||||
|
||||
"ldr %[r3], [%[r1], %[r7]] \n\t" /* r3 = left[k - i] */
|
||||
"ldr %[r0], [%[r1], %[r6]] \n\t" /* r0 = left[i] */
|
||||
|
||||
"lsrs %[r2], %[r0], #16 \n\t" /* r2 = a1 */
|
||||
"uxth %[r0], %[r0] \n\t" /* r0 = a0 */
|
||||
|
||||
"lsrs %[r4], %[r3], #16 \n\t" /* r4 = b1 */
|
||||
"uxth %[r3], %[r3] \n\t" /* r3 = b0 */
|
||||
|
||||
"movs %[r5], %[r2] \n\t" /* r5 = a1 */
|
||||
"muls %[r5], %[r4], %[r5] \n\t" /* r5 = a1 * b1 */
|
||||
"muls %[r2], %[r3], %[r2] \n\t" /* r2 = b0 * a1 */
|
||||
"muls %[r4], %[r0], %[r4] \n\t" /* r4 = a0 * b1 */
|
||||
"muls %[r0], %[r3], %[r0] \n\t" /* r0 = a0 * b0 */
|
||||
|
||||
/* Add middle terms */
|
||||
"lsls %[r3], %[r2], #16 \n\t"
|
||||
"lsrs %[r2], %[r2], #16 \n\t"
|
||||
"adds %[r0], %[r3] \n\t"
|
||||
"adcs %[r5], %[r2] \n\t"
|
||||
|
||||
"lsls %[r3], %[r4], #16 \n\t"
|
||||
"lsrs %[r4], %[r4], #16 \n\t"
|
||||
"adds %[r0], %[r3] \n\t"
|
||||
"adcs %[r5], %[r4] \n\t"
|
||||
|
||||
/* Add to acc, doubling if necessary */
|
||||
"mov %[r2], r10\n\t"
|
||||
"mov %[r3], r11\n\t"
|
||||
"mov %[r4], r12\n\t"
|
||||
|
||||
"cmp %[r6], %[r7] \n\t" /* (i < k - i) ? */
|
||||
"bge 4f \n\t" /* if i >= k - i, skip */
|
||||
"movs %[r7], #0 \n\t" /* r7 = 0 */
|
||||
"adds %[r2], %[r0] \n\t" /* add low word to c0 */
|
||||
"adcs %[r3], %[r5] \n\t" /* add high word to c1, including carry */
|
||||
"adcs %[r4], %[r7] \n\t" /* add carry to c2 */
|
||||
"4: \n\t"
|
||||
"movs %[r7], #0 \n\t" /* r7 = 0 */
|
||||
"adds %[r2], %[r0] \n\t" /* add low word to c0 */
|
||||
"adcs %[r3], %[r5] \n\t" /* add high word to c1, including carry */
|
||||
"adcs %[r4], %[r7] \n\t" /* add carry to c2 */
|
||||
|
||||
"mov %[r5], r14\n\t" /* r5 = k */
|
||||
|
||||
"adds %[r6], #4 \n\t" /* i += 4 */
|
||||
"cmp %[r6], %[r5] \n\t" /* i >= k? */
|
||||
"bge 5f \n\t" /* if so, exit the loop */
|
||||
"subs %[r7], %[r5], %[r6] \n\t" /* r7 = k - i */
|
||||
"cmp %[r6], %[r7] \n\t" /* i <= k - i? */
|
||||
"ble 3b \n\t" /* if so, continue looping */
|
||||
|
||||
"5: \n\t" /* end inner loop */
|
||||
|
||||
"ldr %[r0], [sp, #0] \n\t" /* r0 = result */
|
||||
|
||||
"str %[r2], [%[r0], %[r5]] \n\t" /* result[k] = c0 */
|
||||
"mov %[r2], %[r3] \n\t" /* c0 = c1 */
|
||||
"mov %[r3], %[r4] \n\t" /* c1 = c2 */
|
||||
"movs %[r4], #0 \n\t" /* c2 = 0 */
|
||||
"adds %[r5], #4 \n\t" /* k += 4 */
|
||||
"cmp %[r5], r8 \n\t" /* k <= (num_words - 1) (times 4) ? */
|
||||
"ble 1b \n\t" /* if so, loop back, start with i = 0 */
|
||||
"cmp %[r5], r9 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
|
||||
"ble 2b \n\t" /* if so, loop back, with i = (k + 1) - num_words */
|
||||
/* end outer loop */
|
||||
|
||||
"str %[r2], [%[r0], %[r5]] \n\t" /* result[num_words * 2 - 1] = c0 */
|
||||
"pop {%[r0]} \n\t" /* pop result off the stack */
|
||||
|
||||
RESUME_SYNTAX
|
||||
: [r2] "+l" (num_words), [r3] "=&l" (r3), [r4] "=&l" (r4),
|
||||
[r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7)
|
||||
: [r0] "l" (result), [r1] "l" (left)
|
||||
: "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
#define asm_square 1
|
||||
#endif
|
||||
#endif /* uECC_SQUARE_FUNC */
|
||||
|
||||
#endif /* _UECC_ASM_ARM_H_ */
|
2311
core/embed/ble_bootloader/uecc/asm_arm_mult_square.inc
Normal file
2311
core/embed/ble_bootloader/uecc/asm_arm_mult_square.inc
Normal file
File diff suppressed because it is too large
Load Diff
1202
core/embed/ble_bootloader/uecc/asm_arm_mult_square_umaal.inc
Normal file
1202
core/embed/ble_bootloader/uecc/asm_arm_mult_square_umaal.inc
Normal file
File diff suppressed because it is too large
Load Diff
1089
core/embed/ble_bootloader/uecc/asm_avr.inc
Normal file
1089
core/embed/ble_bootloader/uecc/asm_avr.inc
Normal file
File diff suppressed because it is too large
Load Diff
26311
core/embed/ble_bootloader/uecc/asm_avr_mult_square.inc
Normal file
26311
core/embed/ble_bootloader/uecc/asm_avr_mult_square.inc
Normal file
File diff suppressed because it is too large
Load Diff
1248
core/embed/ble_bootloader/uecc/curve-specific.inc
Normal file
1248
core/embed/ble_bootloader/uecc/curve-specific.inc
Normal file
File diff suppressed because it is too large
Load Diff
132
core/embed/ble_bootloader/uecc/emk_project.py
Normal file
132
core/embed/ble_bootloader/uecc/emk_project.py
Normal file
@ -0,0 +1,132 @@
|
||||
import os
|
||||
|
||||
c, link, asm, utils = emk.module("c", "link", "asm", "utils")
|
||||
|
||||
default_compile_flags = ["-fvisibility=hidden", "-Wall", "-Wextra", "-Wshadow", "-Werror", "-Wno-missing-field-initializers", "-Wno-unused-parameter", \
|
||||
"-Wno-comment", "-Wno-unused", "-Wno-unknown-pragmas"]
|
||||
default_link_flags = []
|
||||
opt_flags = {"dbg":["-g"], "std":["-O2"], "max":["-O3"], "small":["-Os"]}
|
||||
opt_link_flags = {"dbg":[], "std":[], "max":[], "small":[]}
|
||||
c_flags = ["-std=c99"]
|
||||
cxx_flags = ["-std=c++11", "-Wno-reorder", "-fno-rtti", "-fno-exceptions"]
|
||||
c_link_flags = []
|
||||
cxx_link_flags = ["-fno-rtti", "-fno-exceptions"]
|
||||
|
||||
if "root" in emk.options:
|
||||
root = emk.options["root"]
|
||||
else:
|
||||
root = "/"
|
||||
|
||||
def setup_build_dir():
|
||||
build_arch = None
|
||||
if "arch" in emk.options:
|
||||
build_arch = emk.options["arch"]
|
||||
elif not emk.cleaning:
|
||||
build_arch = "osx"
|
||||
emk.options["arch"] = build_arch
|
||||
|
||||
opt_level = None
|
||||
if "opt" in emk.options:
|
||||
level = emk.options["opt"]
|
||||
if level in opt_flags:
|
||||
opt_level = level
|
||||
else:
|
||||
emk.log.warning("Unknown optimization level '%s'" % (level))
|
||||
elif not emk.cleaning:
|
||||
opt_level = "dbg"
|
||||
emk.options["opt"] = opt_level
|
||||
|
||||
dirs = ["__build__"]
|
||||
if build_arch:
|
||||
dirs.append(build_arch)
|
||||
if opt_level:
|
||||
dirs.append(opt_level)
|
||||
emk.build_dir = os.path.join(*dirs)
|
||||
|
||||
def setup_osx():
|
||||
global c
|
||||
global link
|
||||
|
||||
flags = [("-arch", "x86_64"), "-fno-common", "-Wnewline-eof"]
|
||||
c.flags.extend(flags)
|
||||
c.cxx.flags += ["-stdlib=libc++"]
|
||||
link.cxx.flags += ["-stdlib=libc++"]
|
||||
|
||||
link_flags = [("-arch", "x86_64")]
|
||||
link.local_flags.extend(link_flags)
|
||||
|
||||
def setup_avr():
|
||||
global c
|
||||
global link
|
||||
|
||||
c.compiler = c.GccCompiler(root + "Projects/avr-tools/bin/avr-")
|
||||
c.flags += ["-mmcu=atmega256rfr2", "-ffunction-sections", "-fdata-sections"]
|
||||
link.linker = link.GccLinker(root + "Projects/avr-tools/bin/avr-")
|
||||
link.flags += ["-mmcu=atmega256rfr2", "-mrelax", "-Wl,--gc-sections"]
|
||||
link.strip = True
|
||||
|
||||
def setup_arm_thumb():
|
||||
global c
|
||||
global link
|
||||
global asm
|
||||
global utils
|
||||
|
||||
asm.assembler = asm.GccAssembler(root + "cross/arm_cortex/bin/arm-none-eabi-")
|
||||
c.compiler = c.GccCompiler(root + "cross/arm_cortex/bin/arm-none-eabi-")
|
||||
link.linker = link.GccLinker(root + "cross/arm_cortex/bin/arm-none-eabi-")
|
||||
|
||||
c.flags.extend(["-mcpu=cortex-m0", "-mthumb", "-ffunction-sections", "-fdata-sections", "-fno-builtin-fprintf", "-fno-builtin-printf"])
|
||||
c.defines["LPC11XX"] = 1
|
||||
|
||||
link.local_flags.extend(["-mcpu=cortex-m0", "-mthumb", "-nostartfiles", "-nostdlib", "-Wl,--gc-sections"])
|
||||
link.local_flags.extend(["-Tflash.lds", "-L" + root + "Projects/lpc11xx/core", root + "Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o"])
|
||||
link.local_syslibs += ["gcc"]
|
||||
link.depdirs += [root + "Projects/lpc11xx/stdlib"]
|
||||
|
||||
def do_objcopy(produces, requires):
|
||||
utils.call(root + "cross/arm_cortex/bin/arm-none-eabi-objcopy", "-O", "binary", requires[0], produces[0])
|
||||
|
||||
def handle_exe(path):
|
||||
emk.depend(path, root + "Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o")
|
||||
emk.rule(do_objcopy, path + ".bin", path, cwd_safe=True, ex_safe=True)
|
||||
emk.autobuild(path + ".bin")
|
||||
|
||||
link.exe_funcs.append(handle_exe)
|
||||
link.strip = True
|
||||
|
||||
emk.recurse(root + "Projects/lpc11xx/core")
|
||||
|
||||
def setup_linux_rpi():
|
||||
global c
|
||||
global link
|
||||
|
||||
c.compiler = c.GccCompiler("/Volumes/xtools/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-")
|
||||
link.linker = link.GccLinker("/Volumes/xtools/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-")
|
||||
|
||||
c.flags.extend(["-fomit-frame-pointer"])
|
||||
|
||||
setup_build_dir()
|
||||
|
||||
setup_funcs = {"osx":setup_osx, "avr":setup_avr, "arm_thumb":setup_arm_thumb, "rpi": setup_linux_rpi}
|
||||
|
||||
if not emk.cleaning:
|
||||
build_arch = emk.options["arch"]
|
||||
opt_level = emk.options["opt"]
|
||||
|
||||
c.flags.extend(default_compile_flags)
|
||||
c.flags.extend(opt_flags[opt_level])
|
||||
c.c.flags.extend(c_flags)
|
||||
c.cxx.flags.extend(cxx_flags)
|
||||
link.local_flags.extend(default_link_flags)
|
||||
link.local_flags.extend(opt_link_flags[opt_level])
|
||||
link.c.local_flags.extend(c_link_flags)
|
||||
link.cxx.local_flags.extend(cxx_link_flags)
|
||||
|
||||
c.include_dirs.append("$:proj:$")
|
||||
|
||||
if build_arch in setup_funcs:
|
||||
setup_funcs[build_arch]()
|
||||
else:
|
||||
raise emk.BuildError("Unknown target arch '%s'" % (build_arch))
|
||||
|
||||
c.defines["TARGET_ARCH_" + build_arch.upper()] = 1
|
3
core/embed/ble_bootloader/uecc/emk_rules.py
Normal file
3
core/embed/ble_bootloader/uecc/emk_rules.py
Normal file
@ -0,0 +1,3 @@
|
||||
c, link = emk.module("c", "link")
|
||||
|
||||
emk.subdir("test")
|
@ -0,0 +1,80 @@
|
||||
#include <uECC.h>
|
||||
|
||||
static int RNG(uint8_t *dest, unsigned size) {
|
||||
// Use the least-significant bits from the ADC for an unconnected pin (or connected to a source of
|
||||
// random noise). This can take a long time to generate random data if the result of analogRead(0)
|
||||
// doesn't change very frequently.
|
||||
while (size) {
|
||||
uint8_t val = 0;
|
||||
for (unsigned i = 0; i < 8; ++i) {
|
||||
int init = analogRead(0);
|
||||
int count = 0;
|
||||
while (analogRead(0) == init) {
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
val = (val << 1) | (init & 0x01);
|
||||
} else {
|
||||
val = (val << 1) | (count & 0x01);
|
||||
}
|
||||
}
|
||||
*dest = val;
|
||||
++dest;
|
||||
--size;
|
||||
}
|
||||
// NOTE: it would be a good idea to hash the resulting random data using SHA-256 or similar.
|
||||
return 1;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.print("Testing ecc\n");
|
||||
uECC_set_rng(&RNG);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
const struct uECC_Curve_t * curve = uECC_secp160r1();
|
||||
uint8_t private1[21];
|
||||
uint8_t private2[21];
|
||||
|
||||
uint8_t public1[40];
|
||||
uint8_t public2[40];
|
||||
|
||||
uint8_t secret1[20];
|
||||
uint8_t secret2[20];
|
||||
|
||||
unsigned long a = millis();
|
||||
uECC_make_key(public1, private1, curve);
|
||||
unsigned long b = millis();
|
||||
|
||||
Serial.print("Made key 1 in "); Serial.println(b-a);
|
||||
a = millis();
|
||||
uECC_make_key(public2, private2, curve);
|
||||
b = millis();
|
||||
Serial.print("Made key 2 in "); Serial.println(b-a);
|
||||
|
||||
a = millis();
|
||||
int r = uECC_shared_secret(public2, private1, secret1, curve);
|
||||
b = millis();
|
||||
Serial.print("Shared secret 1 in "); Serial.println(b-a);
|
||||
if (!r) {
|
||||
Serial.print("shared_secret() failed (1)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
a = millis();
|
||||
r = uECC_shared_secret(public1, private2, secret2, curve);
|
||||
b = millis();
|
||||
Serial.print("Shared secret 2 in "); Serial.println(b-a);
|
||||
if (!r) {
|
||||
Serial.print("shared_secret() failed (2)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (memcmp(secret1, secret2, 20) != 0) {
|
||||
Serial.print("Shared secrets are not identical!\n");
|
||||
} else {
|
||||
Serial.print("Shared secrets are identical\n");
|
||||
}
|
||||
}
|
9
core/embed/ble_bootloader/uecc/library.properties
Normal file
9
core/embed/ble_bootloader/uecc/library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
name=micro-ecc
|
||||
version=1.0.0
|
||||
author=Kenneth MacKay
|
||||
maintainer=Kenneth MacKay
|
||||
sentence=uECC
|
||||
paragraph=A small and fast ECDH and ECDSA implementation for 8-bit, 32-bit, and 64-bit processors.
|
||||
category=Other
|
||||
url=https://github.com/kmackay/micro-ecc
|
||||
architectures=*
|
94
core/embed/ble_bootloader/uecc/platform-specific.inc
Normal file
94
core/embed/ble_bootloader/uecc/platform-specific.inc
Normal file
@ -0,0 +1,94 @@
|
||||
/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_PLATFORM_SPECIFIC_H_
|
||||
#define _UECC_PLATFORM_SPECIFIC_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#if (defined(_WIN32) || defined(_WIN64))
|
||||
/* Windows */
|
||||
|
||||
// use pragma syntax to prevent tweaking the linker script for getting CryptXYZ function
|
||||
#pragma comment(lib, "crypt32.lib")
|
||||
#pragma comment(lib, "advapi32.lib")
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
static int default_RNG(uint8_t *dest, unsigned size) {
|
||||
HCRYPTPROV prov;
|
||||
if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
CryptGenRandom(prov, size, (BYTE *)dest);
|
||||
CryptReleaseContext(prov, 0);
|
||||
return 1;
|
||||
}
|
||||
#define default_RNG_defined 1
|
||||
|
||||
#elif defined(unix) || defined(__linux__) || defined(__unix__) || defined(__unix) || \
|
||||
(defined(__APPLE__) && defined(__MACH__)) || defined(uECC_POSIX)
|
||||
|
||||
/* Some POSIX-like system with /dev/urandom or /dev/random. */
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
static int default_RNG(uint8_t *dest, unsigned size) {
|
||||
int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
char *ptr = (char *)dest;
|
||||
size_t left = size;
|
||||
while (left > 0) {
|
||||
ssize_t bytes_read = read(fd, ptr, left);
|
||||
if (bytes_read <= 0) { // read failed
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
left -= bytes_read;
|
||||
ptr += bytes_read;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
#define default_RNG_defined 1
|
||||
|
||||
#elif defined(RIOT_VERSION)
|
||||
|
||||
#include <random.h>
|
||||
|
||||
static int default_RNG(uint8_t *dest, unsigned size) {
|
||||
random_bytes(dest, size);
|
||||
return 1;
|
||||
}
|
||||
#define default_RNG_defined 1
|
||||
|
||||
#elif defined(NRF52_SERIES)
|
||||
|
||||
#include "app_error.h"
|
||||
#include "nrf_crypto_rng.h"
|
||||
|
||||
static int default_RNG(uint8_t *dest, unsigned size)
|
||||
{
|
||||
// make sure to call nrf_crypto_init and nrf_crypto_rng_init first
|
||||
ret_code_t ret_code = nrf_crypto_rng_vector_generate(dest, size);
|
||||
return (ret_code == NRF_SUCCESS) ? 1 : 0;
|
||||
}
|
||||
#define default_RNG_defined 1
|
||||
|
||||
#endif /* platform */
|
||||
|
||||
#endif /* _UECC_PLATFORM_SPECIFIC_H_ */
|
188
core/embed/ble_bootloader/uecc/scripts/mult_arm.py
Executable file
188
core/embed/ble_bootloader/uecc/scripts/mult_arm.py
Executable file
@ -0,0 +1,188 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print "Provide the integer size in 32-bit words"
|
||||
sys.exit(1)
|
||||
|
||||
size = int(sys.argv[1])
|
||||
|
||||
full_rows = size // 3
|
||||
init_size = size % 3
|
||||
|
||||
if init_size == 0:
|
||||
full_rows = full_rows - 1
|
||||
init_size = 3
|
||||
|
||||
def emit(line, *args):
|
||||
s = '"' + line + r' \n\t"'
|
||||
print s % args
|
||||
|
||||
rx = [3, 4, 5]
|
||||
ry = [6, 7, 8]
|
||||
|
||||
#### set up registers
|
||||
emit("add r0, %s", (size - init_size) * 4) # move z
|
||||
emit("add r2, %s", (size - init_size) * 4) # move y
|
||||
|
||||
emit("ldmia r1!, {%s}", ", ".join(["r%s" % (rx[i]) for i in xrange(init_size)]))
|
||||
emit("ldmia r2!, {%s}", ", ".join(["r%s" % (ry[i]) for i in xrange(init_size)]))
|
||||
|
||||
print ""
|
||||
if init_size == 1:
|
||||
emit("umull r9, r10, r3, r6")
|
||||
emit("stmia r0!, {r9, r10}")
|
||||
else:
|
||||
#### first two multiplications of initial block
|
||||
emit("umull r11, r12, r3, r6")
|
||||
emit("stmia r0!, {r11}")
|
||||
print ""
|
||||
emit("mov r10, #0")
|
||||
emit("umull r11, r9, r3, r7")
|
||||
emit("adds r12, r12, r11")
|
||||
emit("adc r9, r9, #0")
|
||||
emit("umull r11, r14, r4, r6")
|
||||
emit("adds r12, r12, r11")
|
||||
emit("adcs r9, r9, r14")
|
||||
emit("adc r10, r10, #0")
|
||||
emit("stmia r0!, {r12}")
|
||||
print ""
|
||||
|
||||
#### rest of initial block, with moving accumulator registers
|
||||
acc = [9, 10, 11, 12, 14]
|
||||
if init_size == 3:
|
||||
emit("mov r%s, #0", acc[2])
|
||||
for i in xrange(0, 3):
|
||||
emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[i], ry[2 - i])
|
||||
emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
|
||||
emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
emit("stmia r0!, {r%s}", acc[0])
|
||||
print ""
|
||||
acc = acc[1:] + acc[:1]
|
||||
|
||||
emit("mov r%s, #0", acc[2])
|
||||
for i in xrange(0, 2):
|
||||
emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[i + 1], ry[2 - i])
|
||||
emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
|
||||
emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
emit("stmia r0!, {r%s}", acc[0])
|
||||
print ""
|
||||
acc = acc[1:] + acc[:1]
|
||||
|
||||
emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[init_size-1], ry[init_size-1])
|
||||
emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
|
||||
emit("adc r%s, r%s, r%s", acc[1], acc[1], acc[4])
|
||||
emit("stmia r0!, {r%s}", acc[0])
|
||||
emit("stmia r0!, {r%s}", acc[1])
|
||||
print ""
|
||||
|
||||
#### reset y and z pointers
|
||||
emit("sub r0, %s", (2 * init_size + 3) * 4)
|
||||
emit("sub r2, %s", (init_size + 3) * 4)
|
||||
|
||||
#### load y registers
|
||||
emit("ldmia r2!, {%s}", ", ".join(["r%s" % (ry[i]) for i in xrange(3)]))
|
||||
|
||||
#### load additional x registers
|
||||
if init_size != 3:
|
||||
emit("ldmia r1!, {%s}", ", ".join(["r%s" % (rx[i]) for i in xrange(init_size, 3)]))
|
||||
print ""
|
||||
|
||||
prev_size = init_size
|
||||
for row in xrange(full_rows):
|
||||
emit("umull r11, r12, r3, r6")
|
||||
emit("stmia r0!, {r11}")
|
||||
print ""
|
||||
emit("mov r10, #0")
|
||||
emit("umull r11, r9, r3, r7")
|
||||
emit("adds r12, r12, r11")
|
||||
emit("adc r9, r9, #0")
|
||||
emit("umull r11, r14, r4, r6")
|
||||
emit("adds r12, r12, r11")
|
||||
emit("adcs r9, r9, r14")
|
||||
emit("adc r10, r10, #0")
|
||||
emit("stmia r0!, {r12}")
|
||||
print ""
|
||||
|
||||
acc = [9, 10, 11, 12, 14]
|
||||
emit("mov r%s, #0", acc[2])
|
||||
for i in xrange(0, 3):
|
||||
emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[i], ry[2 - i])
|
||||
emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
|
||||
emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
emit("stmia r0!, {r%s}", acc[0])
|
||||
print ""
|
||||
acc = acc[1:] + acc[:1]
|
||||
|
||||
#### now we need to start shifting x and loading from z
|
||||
x_regs = [3, 4, 5]
|
||||
for r in xrange(0, prev_size):
|
||||
x_regs = x_regs[1:] + x_regs[:1]
|
||||
emit("ldmia r1!, {r%s}", x_regs[2])
|
||||
emit("mov r%s, #0", acc[2])
|
||||
for i in xrange(0, 3):
|
||||
emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[i], ry[2 - i])
|
||||
emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
|
||||
emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
emit("ldr r%s, [r0]", acc[3]) # load stored value from initial block, and add to accumulator
|
||||
emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
|
||||
emit("adcs r%s, r%s, #0", acc[1], acc[1])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
emit("stmia r0!, {r%s}", acc[0])
|
||||
print ""
|
||||
acc = acc[1:] + acc[:1]
|
||||
|
||||
# done shifting x, start shifting y
|
||||
y_regs = [6, 7, 8]
|
||||
for r in xrange(0, prev_size):
|
||||
y_regs = y_regs[1:] + y_regs[:1]
|
||||
emit("ldmia r2!, {r%s}", y_regs[2])
|
||||
emit("mov r%s, #0", acc[2])
|
||||
for i in xrange(0, 3):
|
||||
emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[i], y_regs[2 - i])
|
||||
emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
|
||||
emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
emit("ldr r%s, [r0]", acc[3]) # load stored value from initial block, and add to accumulator
|
||||
emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
|
||||
emit("adcs r%s, r%s, #0", acc[1], acc[1])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
emit("stmia r0!, {r%s}", acc[0])
|
||||
print ""
|
||||
acc = acc[1:] + acc[:1]
|
||||
|
||||
# done both shifts, do remaining corner
|
||||
emit("mov r%s, #0", acc[2])
|
||||
for i in xrange(0, 2):
|
||||
emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[i + 1], y_regs[2 - i])
|
||||
emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
|
||||
emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
emit("stmia r0!, {r%s}", acc[0])
|
||||
print ""
|
||||
acc = acc[1:] + acc[:1]
|
||||
|
||||
emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[2], y_regs[2])
|
||||
emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
|
||||
emit("adc r%s, r%s, r%s", acc[1], acc[1], acc[4])
|
||||
emit("stmia r0!, {r%s}", acc[0])
|
||||
emit("stmia r0!, {r%s}", acc[1])
|
||||
print ""
|
||||
|
||||
prev_size = prev_size + 3
|
||||
if row < full_rows - 1:
|
||||
#### reset x, y and z pointers
|
||||
emit("sub r0, %s", (2 * prev_size + 3) * 4)
|
||||
emit("sub r1, %s", prev_size * 4)
|
||||
emit("sub r2, %s", (prev_size + 3) * 4)
|
||||
|
||||
#### load x and y registers
|
||||
emit("ldmia r1!, {%s}", ",".join(["r%s" % (rx[i]) for i in xrange(3)]))
|
||||
emit("ldmia r2!, {%s}", ",".join(["r%s" % (ry[i]) for i in xrange(3)]))
|
||||
|
||||
print ""
|
203
core/embed/ble_bootloader/uecc/scripts/mult_avr.py
Executable file
203
core/embed/ble_bootloader/uecc/scripts/mult_avr.py
Executable file
@ -0,0 +1,203 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print "Provide the integer size in bytes"
|
||||
sys.exit(1)
|
||||
|
||||
size = int(sys.argv[1])
|
||||
|
||||
full_rows = size // 10
|
||||
init_size = size % 10
|
||||
|
||||
if init_size == 0:
|
||||
full_rows = full_rows - 1
|
||||
init_size = 10
|
||||
|
||||
def rx(i):
|
||||
return i + 2
|
||||
|
||||
def ry(i):
|
||||
return i + 12
|
||||
|
||||
def emit(line, *args):
|
||||
s = '"' + line + r' \n\t"'
|
||||
print s % args
|
||||
|
||||
#### set up registers
|
||||
emit("adiw r30, %s", size - init_size) # move z
|
||||
emit("adiw r28, %s", size - init_size) # move y
|
||||
|
||||
for i in xrange(init_size):
|
||||
emit("ld r%s, x+", rx(i))
|
||||
for i in xrange(init_size):
|
||||
emit("ld r%s, y+", ry(i))
|
||||
|
||||
emit("ldi r25, 0")
|
||||
print ""
|
||||
if init_size == 1:
|
||||
emit("mul r2, r12")
|
||||
emit("st z+, r0")
|
||||
emit("st z+, r1")
|
||||
else:
|
||||
#### first two multiplications of initial block
|
||||
emit("ldi r23, 0")
|
||||
emit("mul r2, r12")
|
||||
emit("st z+, r0")
|
||||
emit("mov r22, r1")
|
||||
print ""
|
||||
emit("ldi r24, 0")
|
||||
emit("mul r2, r13")
|
||||
emit("add r22, r0")
|
||||
emit("adc r23, r1")
|
||||
emit("mul r3, r12")
|
||||
emit("add r22, r0")
|
||||
emit("adc r23, r1")
|
||||
emit("adc r24, r25")
|
||||
emit("st z+, r22")
|
||||
print ""
|
||||
|
||||
#### rest of initial block, with moving accumulator registers
|
||||
acc = [23, 24, 22]
|
||||
for r in xrange(2, init_size):
|
||||
emit("ldi r%s, 0", acc[2])
|
||||
for i in xrange(0, r+1):
|
||||
emit("mul r%s, r%s", rx(i), ry(r - i))
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, r25", acc[2])
|
||||
emit("st z+, r%s", acc[0])
|
||||
print ""
|
||||
acc = acc[1:] + acc[:1]
|
||||
for r in xrange(1, init_size-1):
|
||||
emit("ldi r%s, 0", acc[2])
|
||||
for i in xrange(0, init_size-r):
|
||||
emit("mul r%s, r%s", rx(r+i), ry((init_size-1) - i))
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, r25", acc[2])
|
||||
emit("st z+, r%s", acc[0])
|
||||
print ""
|
||||
acc = acc[1:] + acc[:1]
|
||||
emit("mul r%s, r%s", rx(init_size-1), ry(init_size-1))
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("st z+, r%s", acc[0])
|
||||
emit("st z+, r%s", acc[1])
|
||||
print ""
|
||||
|
||||
#### reset y and z pointers
|
||||
emit("sbiw r30, %s", 2 * init_size + 10)
|
||||
emit("sbiw r28, %s", init_size + 10)
|
||||
|
||||
#### load y registers
|
||||
for i in xrange(10):
|
||||
emit("ld r%s, y+", ry(i))
|
||||
|
||||
#### load additional x registers
|
||||
for i in xrange(init_size, 10):
|
||||
emit("ld r%s, x+", rx(i))
|
||||
print ""
|
||||
|
||||
prev_size = init_size
|
||||
for row in xrange(full_rows):
|
||||
#### do x = 0-9, y = 0-9 multiplications
|
||||
emit("ldi r23, 0")
|
||||
emit("mul r2, r12")
|
||||
emit("st z+, r0")
|
||||
emit("mov r22, r1")
|
||||
print ""
|
||||
emit("ldi r24, 0")
|
||||
emit("mul r2, r13")
|
||||
emit("add r22, r0")
|
||||
emit("adc r23, r1")
|
||||
emit("mul r3, r12")
|
||||
emit("add r22, r0")
|
||||
emit("adc r23, r1")
|
||||
emit("adc r24, r25")
|
||||
emit("st z+, r22")
|
||||
print ""
|
||||
|
||||
acc = [23, 24, 22]
|
||||
for r in xrange(2, 10):
|
||||
emit("ldi r%s, 0", acc[2])
|
||||
for i in xrange(0, r+1):
|
||||
emit("mul r%s, r%s", rx(i), ry(r - i))
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, r25", acc[2])
|
||||
emit("st z+, r%s", acc[0])
|
||||
print ""
|
||||
acc = acc[1:] + acc[:1]
|
||||
|
||||
#### now we need to start shifting x and loading from z
|
||||
x_regs = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
||||
for r in xrange(0, prev_size):
|
||||
x_regs = x_regs[1:] + x_regs[:1]
|
||||
emit("ld r%s, x+", x_regs[9]) # load next byte of left
|
||||
emit("ldi r%s, 0", acc[2])
|
||||
for i in xrange(0, 10):
|
||||
emit("mul r%s, r%s", x_regs[i], ry(9 - i))
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, r25", acc[2])
|
||||
emit("ld r0, z") # load stored value from initial block, and add to accumulator (note z does not increment)
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r25", acc[1])
|
||||
emit("adc r%s, r25", acc[2])
|
||||
emit("st z+, r%s", acc[0]) # store next byte (z increments)
|
||||
print ""
|
||||
acc = acc[1:] + acc[:1]
|
||||
|
||||
# done shifting x, start shifting y
|
||||
y_regs = [12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
|
||||
for r in xrange(0, prev_size):
|
||||
y_regs = y_regs[1:] + y_regs[:1]
|
||||
emit("ld r%s, y+", y_regs[9]) # load next byte of right
|
||||
emit("ldi r%s, 0", acc[2])
|
||||
for i in xrange(0, 10):
|
||||
emit("mul r%s, r%s", x_regs[i], y_regs[9 -i])
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, r25", acc[2])
|
||||
emit("ld r0, z") # load stored value from initial block, and add to accumulator (note z does not increment)
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r25", acc[1])
|
||||
emit("adc r%s, r25", acc[2])
|
||||
emit("st z+, r%s", acc[0]) # store next byte (z increments)
|
||||
print ""
|
||||
acc = acc[1:] + acc[:1]
|
||||
|
||||
# done both shifts, do remaining corner
|
||||
for r in xrange(1, 9):
|
||||
emit("ldi r%s, 0", acc[2])
|
||||
for i in xrange(0, 10-r):
|
||||
emit("mul r%s, r%s", x_regs[r+i], y_regs[9 - i])
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, r25", acc[2])
|
||||
emit("st z+, r%s", acc[0])
|
||||
print ""
|
||||
acc = acc[1:] + acc[:1]
|
||||
emit("mul r%s, r%s", x_regs[9], y_regs[9])
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("st z+, r%s", acc[0])
|
||||
emit("st z+, r%s", acc[1])
|
||||
print ""
|
||||
|
||||
prev_size = prev_size + 10
|
||||
if row < full_rows - 1:
|
||||
#### reset x, y and z pointers
|
||||
emit("sbiw r30, %s", 2 * prev_size + 10)
|
||||
emit("sbiw r28, %s", prev_size + 10)
|
||||
emit("sbiw r26, %s", prev_size)
|
||||
|
||||
#### load x and y registers
|
||||
for i in xrange(10):
|
||||
emit("ld r%s, x+", rx(i))
|
||||
emit("ld r%s, y+", ry(i))
|
||||
print ""
|
||||
|
||||
emit("eor r1, r1")
|
143
core/embed/ble_bootloader/uecc/scripts/mult_avr_extra.py
Executable file
143
core/embed/ble_bootloader/uecc/scripts/mult_avr_extra.py
Executable file
@ -0,0 +1,143 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print "Provide the integer size in bytes"
|
||||
sys.exit(1)
|
||||
|
||||
size = int(sys.argv[1])
|
||||
|
||||
def lhi(i):
|
||||
return i + 2
|
||||
|
||||
def rhi(i):
|
||||
return i + 6
|
||||
|
||||
left_lo = [10, 11, 12, 13]
|
||||
right_lo = [14, 15, 16, 17]
|
||||
|
||||
def llo(i):
|
||||
return left_lo[i]
|
||||
|
||||
def rlo(i):
|
||||
return right_lo[i]
|
||||
|
||||
def emit(line, *args):
|
||||
s = '"' + line + r' \n\t"'
|
||||
print s % args
|
||||
|
||||
def update_low():
|
||||
global left_lo
|
||||
global right_lo
|
||||
left_lo = left_lo[1:] + left_lo[:1]
|
||||
right_lo = right_lo[1:] + right_lo[:1]
|
||||
emit("ld r%s, x+", left_lo[3])
|
||||
emit("ld r%s, y+", right_lo[3])
|
||||
|
||||
accum = [19, 20, 21]
|
||||
|
||||
def acc(i):
|
||||
return accum[i]
|
||||
|
||||
def rotate_acc():
|
||||
global accum
|
||||
accum = accum[1:] + accum[:1]
|
||||
|
||||
# Load high values
|
||||
for i in xrange(4):
|
||||
emit("ld r%s, x+", lhi(i))
|
||||
emit("ld r%s, y+", rhi(i))
|
||||
|
||||
emit("sbiw r26, %s", size + 4)
|
||||
emit("sbiw r28, %s", size + 4)
|
||||
emit("sbiw r30, %s", size)
|
||||
|
||||
# Load low values
|
||||
for i in xrange(4):
|
||||
emit("ld r%s, x+", llo(i))
|
||||
emit("ld r%s, y+", rlo(i))
|
||||
print ""
|
||||
|
||||
# Compute initial triangles
|
||||
emit("mul r%s, r%s", lhi(0), rlo(0))
|
||||
emit("mov r%s, r0", acc(0))
|
||||
emit("mov r%s, r1", acc(1))
|
||||
emit("ldi r%s, 0", acc(2))
|
||||
emit("ld r0, z")
|
||||
emit("add r%s, r0", acc(0))
|
||||
emit("adc r%s, r25", acc(1))
|
||||
emit("mul r%s, r%s", rhi(0), llo(0))
|
||||
emit("add r%s, r0", acc(0))
|
||||
emit("adc r%s, r1", acc(1))
|
||||
emit("adc r%s, r25", acc(2))
|
||||
emit("st z+, r%s", acc(0))
|
||||
print ""
|
||||
rotate_acc()
|
||||
|
||||
for i in xrange(1, 4):
|
||||
emit("ldi r%s, 0", acc(2))
|
||||
emit("ld r0, z")
|
||||
emit("add r%s, r0", acc(0))
|
||||
emit("adc r%s, r25", acc(1))
|
||||
for j in xrange(i + 1):
|
||||
emit("mul r%s, r%s", lhi(j), rlo(i-j))
|
||||
emit("add r%s, r0", acc(0))
|
||||
emit("adc r%s, r1", acc(1))
|
||||
emit("adc r%s, r25", acc(2))
|
||||
emit("mul r%s, r%s", rhi(j), llo(i-j))
|
||||
emit("add r%s, r0", acc(0))
|
||||
emit("adc r%s, r1", acc(1))
|
||||
emit("adc r%s, r25", acc(2))
|
||||
emit("st z+, r%s", acc(0))
|
||||
print ""
|
||||
rotate_acc()
|
||||
|
||||
# Compute rows overlapping old block
|
||||
for i in xrange(4, size):
|
||||
emit("ldi r%s, 0", acc(2))
|
||||
emit("ld r0, z")
|
||||
emit("add r%s, r0", acc(0))
|
||||
emit("adc r%s, r25", acc(1))
|
||||
update_low()
|
||||
for j in xrange(4):
|
||||
emit("mul r%s, r%s", lhi(j), rlo(3-j))
|
||||
emit("add r%s, r0", acc(0))
|
||||
emit("adc r%s, r1", acc(1))
|
||||
emit("adc r%s, r25", acc(2))
|
||||
emit("mul r%s, r%s", rhi(j), llo(3-j))
|
||||
emit("add r%s, r0", acc(0))
|
||||
emit("adc r%s, r1", acc(1))
|
||||
emit("adc r%s, r25", acc(2))
|
||||
emit("st z+, r%s", acc(0))
|
||||
print ""
|
||||
rotate_acc()
|
||||
|
||||
# Compute new triangle
|
||||
left_combined = [llo(1), llo(2), llo(3), lhi(0), lhi(1), lhi(2), lhi(3)]
|
||||
right_combined = [rlo(1), rlo(2), rlo(3), rhi(0), rhi(1), rhi(2), rhi(3)]
|
||||
|
||||
def left(i):
|
||||
return left_combined[i]
|
||||
|
||||
def right(i):
|
||||
return right_combined[i]
|
||||
|
||||
for i in xrange(6):
|
||||
emit("ldi r%s, 0", acc(2))
|
||||
for j in xrange(7 - i):
|
||||
emit("mul r%s, r%s", left(i+j), right(6-j))
|
||||
emit("add r%s, r0", acc(0))
|
||||
emit("adc r%s, r1", acc(1))
|
||||
emit("adc r%s, r25", acc(2))
|
||||
emit("st z+, r%s", acc(0))
|
||||
print ""
|
||||
rotate_acc()
|
||||
|
||||
emit("mul r%s, r%s", left(6), right(6))
|
||||
emit("add r%s, r0", acc(0))
|
||||
emit("adc r%s, r1", acc(1))
|
||||
emit("st z+, r%s", acc(0))
|
||||
emit("st z+, r%s", acc(1))
|
||||
emit("adiw r26, 4")
|
||||
emit("adiw r28, 4")
|
242
core/embed/ble_bootloader/uecc/scripts/square_arm.py
Executable file
242
core/embed/ble_bootloader/uecc/scripts/square_arm.py
Executable file
@ -0,0 +1,242 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print "Provide the integer size in 32-bit words"
|
||||
sys.exit(1)
|
||||
|
||||
size = int(sys.argv[1])
|
||||
|
||||
if size > 8:
|
||||
print "This script doesn't work with integer size %s due to laziness" % (size)
|
||||
sys.exit(1)
|
||||
|
||||
init_size = 0
|
||||
if size > 6:
|
||||
init_size = size - 6
|
||||
|
||||
def emit(line, *args):
|
||||
s = '"' + line + r' \n\t"'
|
||||
print s % args
|
||||
|
||||
def mulacc(acc, r1, r2):
|
||||
if size <= 6:
|
||||
emit("umull r1, r14, r%s, r%s", r1, r2)
|
||||
emit("adds r%s, r%s, r1", acc[0], acc[0])
|
||||
emit("adcs r%s, r%s, r14", acc[1], acc[1])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
else:
|
||||
emit("mov r14, r%s", acc[1])
|
||||
emit("umlal r%s, r%s, r%s, r%s", acc[0], acc[1], r1, r2)
|
||||
emit("cmp r14, r%s", acc[1])
|
||||
emit("it hi")
|
||||
emit("adchi r%s, r%s, #0", acc[2], acc[2])
|
||||
|
||||
r = [2, 3, 4, 5, 6, 7]
|
||||
|
||||
s = size - init_size
|
||||
|
||||
if init_size == 1:
|
||||
emit("ldmia r1!, {r2}")
|
||||
emit("add r1, %s", (size - init_size * 2) * 4)
|
||||
emit("ldmia r1!, {r5}")
|
||||
|
||||
emit("add r0, %s", (size - init_size) * 4)
|
||||
emit("umull r8, r9, r2, r5")
|
||||
emit("stmia r0!, {r8, r9}")
|
||||
|
||||
emit("sub r0, %s", (size + init_size) * 4)
|
||||
emit("sub r1, %s", (size) * 4)
|
||||
print ""
|
||||
elif init_size == 2:
|
||||
emit("ldmia r1!, {r2, r3}")
|
||||
emit("add r1, %s", (size - init_size * 2) * 4)
|
||||
emit("ldmia r1!, {r5, r6}")
|
||||
|
||||
emit("add r0, %s", (size - init_size) * 4)
|
||||
print ""
|
||||
|
||||
emit("umull r8, r9, r2, r5")
|
||||
emit("stmia r0!, {r8}")
|
||||
print ""
|
||||
|
||||
emit("umull r12, r10, r2, r6")
|
||||
emit("adds r9, r9, r12")
|
||||
emit("adc r10, r10, #0")
|
||||
emit("stmia r0!, {r9}")
|
||||
print ""
|
||||
|
||||
emit("umull r8, r9, r3, r6")
|
||||
emit("adds r10, r10, r8")
|
||||
emit("adc r11, r9, #0")
|
||||
emit("stmia r0!, {r10, r11}")
|
||||
print ""
|
||||
|
||||
emit("sub r0, %s", (size + init_size) * 4)
|
||||
emit("sub r1, %s", (size) * 4)
|
||||
|
||||
# load input words
|
||||
emit("ldmia r1!, {%s}", ", ".join(["r%s" % (r[i]) for i in xrange(s)]))
|
||||
print ""
|
||||
|
||||
emit("umull r11, r12, r2, r2")
|
||||
emit("stmia r0!, {r11}")
|
||||
print ""
|
||||
emit("mov r9, #0")
|
||||
emit("umull r10, r11, r2, r3")
|
||||
emit("adds r12, r12, r10")
|
||||
emit("adcs r8, r11, #0")
|
||||
emit("adc r9, r9, #0")
|
||||
emit("adds r12, r12, r10")
|
||||
emit("adcs r8, r8, r11")
|
||||
emit("adc r9, r9, #0")
|
||||
emit("stmia r0!, {r12}")
|
||||
print ""
|
||||
emit("mov r10, #0")
|
||||
emit("umull r11, r12, r2, r4")
|
||||
emit("adds r11, r11, r11")
|
||||
emit("adcs r12, r12, r12")
|
||||
emit("adc r10, r10, #0")
|
||||
emit("adds r8, r8, r11")
|
||||
emit("adcs r9, r9, r12")
|
||||
emit("adc r10, r10, #0")
|
||||
emit("umull r11, r12, r3, r3")
|
||||
emit("adds r8, r8, r11")
|
||||
emit("adcs r9, r9, r12")
|
||||
emit("adc r10, r10, #0")
|
||||
emit("stmia r0!, {r8}")
|
||||
print ""
|
||||
|
||||
acc = [8, 9, 10]
|
||||
old_acc = [11, 12]
|
||||
for i in xrange(3, s):
|
||||
emit("mov r%s, #0", old_acc[1])
|
||||
tmp = [acc[1], acc[2]]
|
||||
acc = [acc[0], old_acc[0], old_acc[1]]
|
||||
old_acc = tmp
|
||||
|
||||
# gather non-equal words
|
||||
emit("umull r%s, r%s, r%s, r%s", acc[0], acc[1], r[0], r[i])
|
||||
for j in xrange(1, (i+1)//2):
|
||||
mulacc(acc, r[j], r[i-j])
|
||||
# multiply by 2
|
||||
emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[0])
|
||||
emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[1])
|
||||
emit("adc r%s, r%s, r%s", acc[2], acc[2], acc[2])
|
||||
|
||||
# add equal word (if any)
|
||||
if ((i+1) % 2) != 0:
|
||||
mulacc(acc, r[i//2], r[i//2])
|
||||
|
||||
# add old accumulator
|
||||
emit("adds r%s, r%s, r%s", acc[0], acc[0], old_acc[0])
|
||||
emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
|
||||
# store
|
||||
emit("stmia r0!, {r%s}", acc[0])
|
||||
print ""
|
||||
|
||||
regs = list(r)
|
||||
for i in xrange(init_size):
|
||||
regs = regs[1:] + regs[:1]
|
||||
emit("ldmia r1!, {r%s}", regs[5])
|
||||
|
||||
for limit in [4, 5]:
|
||||
emit("mov r%s, #0", old_acc[1])
|
||||
tmp = [acc[1], acc[2]]
|
||||
acc = [acc[0], old_acc[0], old_acc[1]]
|
||||
old_acc = tmp
|
||||
|
||||
# gather non-equal words
|
||||
emit("umull r%s, r%s, r%s, r%s", acc[0], acc[1], regs[0], regs[limit])
|
||||
for j in xrange(1, (limit+1)//2):
|
||||
mulacc(acc, regs[j], regs[limit-j])
|
||||
|
||||
emit("ldr r14, [r0]") # load stored value from initial block, and add to accumulator
|
||||
emit("adds r%s, r%s, r14", acc[0], acc[0])
|
||||
emit("adcs r%s, r%s, #0", acc[1], acc[1])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
|
||||
# multiply by 2
|
||||
emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[0])
|
||||
emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[1])
|
||||
emit("adc r%s, r%s, r%s", acc[2], acc[2], acc[2])
|
||||
|
||||
# add equal word
|
||||
if limit == 4:
|
||||
mulacc(acc, regs[2], regs[2])
|
||||
|
||||
# add old accumulator
|
||||
emit("adds r%s, r%s, r%s", acc[0], acc[0], old_acc[0])
|
||||
emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
|
||||
# store
|
||||
emit("stmia r0!, {r%s}", acc[0])
|
||||
print ""
|
||||
|
||||
for i in xrange(1, s-3):
|
||||
emit("mov r%s, #0", old_acc[1])
|
||||
tmp = [acc[1], acc[2]]
|
||||
acc = [acc[0], old_acc[0], old_acc[1]]
|
||||
old_acc = tmp
|
||||
|
||||
# gather non-equal words
|
||||
emit("umull r%s, r%s, r%s, r%s", acc[0], acc[1], regs[i], regs[s - 1])
|
||||
for j in xrange(1, (s-i)//2):
|
||||
mulacc(acc, regs[i+j], regs[s - 1 - j])
|
||||
|
||||
# multiply by 2
|
||||
emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[0])
|
||||
emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[1])
|
||||
emit("adc r%s, r%s, r%s", acc[2], acc[2], acc[2])
|
||||
|
||||
# add equal word (if any)
|
||||
if ((s-i) % 2) != 0:
|
||||
mulacc(acc, regs[i + (s-i)//2], regs[i + (s-i)//2])
|
||||
|
||||
# add old accumulator
|
||||
emit("adds r%s, r%s, r%s", acc[0], acc[0], old_acc[0])
|
||||
emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
|
||||
# store
|
||||
emit("stmia r0!, {r%s}", acc[0])
|
||||
print ""
|
||||
|
||||
acc = acc[1:] + acc[:1]
|
||||
emit("mov r%s, #0", acc[2])
|
||||
emit("umull r1, r%s, r%s, r%s", old_acc[1], regs[s - 3], regs[s - 1])
|
||||
emit("adds r1, r1, r1")
|
||||
emit("adcs r%s, r%s, r%s", old_acc[1], old_acc[1], old_acc[1])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
emit("adds r%s, r%s, r1", acc[0], acc[0])
|
||||
emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
emit("umull r1, r%s, r%s, r%s", old_acc[1], regs[s - 2], regs[s - 2])
|
||||
emit("adds r%s, r%s, r1", acc[0], acc[0])
|
||||
emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
emit("stmia r0!, {r%s}", acc[0])
|
||||
print ""
|
||||
|
||||
acc = acc[1:] + acc[:1]
|
||||
emit("mov r%s, #0", acc[2])
|
||||
emit("umull r1, r%s, r%s, r%s", old_acc[1], regs[s - 2], regs[s - 1])
|
||||
emit("adds r1, r1, r1")
|
||||
emit("adcs r%s, r%s, r%s", old_acc[1], old_acc[1], old_acc[1])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
emit("adds r%s, r%s, r1", acc[0], acc[0])
|
||||
emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1])
|
||||
emit("adc r%s, r%s, #0", acc[2], acc[2])
|
||||
emit("stmia r0!, {r%s}", acc[0])
|
||||
print ""
|
||||
|
||||
acc = acc[1:] + acc[:1]
|
||||
emit("umull r1, r%s, r%s, r%s", old_acc[1], regs[s - 1], regs[s - 1])
|
||||
emit("adds r%s, r%s, r1", acc[0], acc[0])
|
||||
emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1])
|
||||
emit("stmia r0!, {r%s}", acc[0])
|
||||
emit("stmia r0!, {r%s}", acc[1])
|
327
core/embed/ble_bootloader/uecc/scripts/square_avr.py
Executable file
327
core/embed/ble_bootloader/uecc/scripts/square_avr.py
Executable file
@ -0,0 +1,327 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print "Provide the integer size in bytes"
|
||||
sys.exit(1)
|
||||
|
||||
size = int(sys.argv[1])
|
||||
|
||||
if size > 40:
|
||||
print "This script doesn't work with integer size %s due to laziness" % (size)
|
||||
sys.exit(1)
|
||||
|
||||
init_size = size - 20
|
||||
if size < 20:
|
||||
init_size = 0
|
||||
|
||||
def rg(i):
|
||||
return i + 2
|
||||
|
||||
def lo(i):
|
||||
return i + 2
|
||||
|
||||
def hi(i):
|
||||
return i + 12
|
||||
|
||||
def emit(line, *args):
|
||||
s = '"' + line + r' \n\t"'
|
||||
print s % args
|
||||
|
||||
#### set up registers
|
||||
zero = "r25"
|
||||
emit("ldi %s, 0", zero) # zero register
|
||||
|
||||
if init_size > 0:
|
||||
emit("movw r28, r26") # y = x
|
||||
h = (init_size + 1)//2
|
||||
|
||||
for i in xrange(h):
|
||||
emit("ld r%s, x+", lo(i))
|
||||
emit("adiw r28, %s", size - init_size) # move y to other end
|
||||
for i in xrange(h):
|
||||
emit("ld r%s, y+", hi(i))
|
||||
|
||||
emit("adiw r30, %s", size - init_size) # move z
|
||||
|
||||
if init_size == 1:
|
||||
emit("mul %s, %s", lo(0), hi(0))
|
||||
emit("st z+, r0")
|
||||
emit("st z+, r1")
|
||||
else:
|
||||
#### first one
|
||||
print ""
|
||||
emit("ldi r23, 0")
|
||||
emit("mul %s, %s", lo(0), hi(0))
|
||||
emit("st z+, r0")
|
||||
emit("mov r22, r1")
|
||||
print ""
|
||||
|
||||
#### rest of initial block, with moving accumulator registers
|
||||
acc = [22, 23, 24]
|
||||
for r in xrange(1, h):
|
||||
emit("ldi r%s, 0", acc[2])
|
||||
for i in xrange(0, (r+2)//2):
|
||||
emit("mul r%s, r%s", lo(i), hi(r - i))
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
emit("st z+, r%s", acc[0])
|
||||
print ""
|
||||
acc = acc[1:] + acc[:1]
|
||||
|
||||
lo_r = range(2, 2 + h)
|
||||
hi_r = range(12, 12 + h)
|
||||
|
||||
# now we need to start loading more from the high end
|
||||
for r in xrange(h, init_size):
|
||||
hi_r = hi_r[1:] + hi_r[:1]
|
||||
emit("ld r%s, y+", hi_r[h-1])
|
||||
|
||||
emit("ldi r%s, 0", acc[2])
|
||||
for i in xrange(0, (r+2)//2):
|
||||
emit("mul r%s, r%s", lo(i), hi_r[h - 1 - i])
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
emit("st z+, r%s", acc[0])
|
||||
print ""
|
||||
acc = acc[1:] + acc[:1]
|
||||
|
||||
# loaded all of the high end bytes; now need to start loading the rest of the low end
|
||||
for r in xrange(1, init_size-h):
|
||||
lo_r = lo_r[1:] + lo_r[:1]
|
||||
emit("ld r%s, x+", lo_r[h-1])
|
||||
|
||||
emit("ldi r%s, 0", acc[2])
|
||||
for i in xrange(0, (init_size+1 - r)//2):
|
||||
emit("mul r%s, r%s", lo_r[i], hi_r[h - 1 - i])
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
emit("st z+, r%s", acc[0])
|
||||
print ""
|
||||
acc = acc[1:] + acc[:1]
|
||||
|
||||
lo_r = lo_r[1:] + lo_r[:1]
|
||||
emit("ld r%s, x+", lo_r[h-1])
|
||||
|
||||
# now we have loaded everything, and we just need to finish the last corner
|
||||
for r in xrange(init_size-h, init_size-1):
|
||||
emit("ldi r%s, 0", acc[2])
|
||||
for i in xrange(0, (init_size+1 - r)//2):
|
||||
emit("mul r%s, r%s", lo_r[i], hi_r[h - 1 - i])
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
emit("st z+, r%s", acc[0])
|
||||
print ""
|
||||
acc = acc[1:] + acc[:1]
|
||||
lo_r = lo_r[1:] + lo_r[:1] # make the indexing easy
|
||||
|
||||
emit("mul r%s, r%s", lo_r[0], hi_r[h - 1])
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("st z+, r%s", acc[0])
|
||||
emit("st z+, r%s", acc[1])
|
||||
print ""
|
||||
emit("sbiw r26, %s", init_size) # reset x
|
||||
emit("sbiw r30, %s", size + init_size) # reset z
|
||||
|
||||
# TODO you could do more rows of size 20 here if your integers are larger than 40 bytes
|
||||
|
||||
s = size - init_size
|
||||
|
||||
for i in xrange(s):
|
||||
emit("ld r%s, x+", rg(i))
|
||||
|
||||
#### first few columns
|
||||
# NOTE: this is only valid if size >= 3
|
||||
print ""
|
||||
emit("ldi r23, 0")
|
||||
emit("mul r%s, r%s", rg(0), rg(0))
|
||||
emit("st z+, r0")
|
||||
emit("mov r22, r1")
|
||||
print ""
|
||||
emit("ldi r24, 0")
|
||||
emit("mul r%s, r%s", rg(0), rg(1))
|
||||
emit("add r22, r0")
|
||||
emit("adc r23, r1")
|
||||
emit("adc r24, %s", zero)
|
||||
emit("add r22, r0")
|
||||
emit("adc r23, r1")
|
||||
emit("adc r24, %s", zero)
|
||||
emit("st z+, r22")
|
||||
print ""
|
||||
emit("ldi r22, 0")
|
||||
emit("mul r%s, r%s", rg(0), rg(2))
|
||||
emit("add r23, r0")
|
||||
emit("adc r24, r1")
|
||||
emit("adc r22, %s", zero)
|
||||
emit("add r23, r0")
|
||||
emit("adc r24, r1")
|
||||
emit("adc r22, %s", zero)
|
||||
emit("mul r%s, r%s", rg(1), rg(1))
|
||||
emit("add r23, r0")
|
||||
emit("adc r24, r1")
|
||||
emit("adc r22, %s", zero)
|
||||
emit("st z+, r23")
|
||||
print ""
|
||||
|
||||
acc = [23, 24, 22]
|
||||
old_acc = [28, 29]
|
||||
for i in xrange(3, s):
|
||||
emit("ldi r%s, 0", old_acc[1])
|
||||
tmp = [acc[1], acc[2]]
|
||||
acc = [acc[0], old_acc[0], old_acc[1]]
|
||||
old_acc = tmp
|
||||
|
||||
# gather non-equal words
|
||||
emit("mul r%s, r%s", rg(0), rg(i))
|
||||
emit("mov r%s, r0", acc[0])
|
||||
emit("mov r%s, r1", acc[1])
|
||||
for j in xrange(1, (i+1)//2):
|
||||
emit("mul r%s, r%s", rg(j), rg(i-j))
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
# multiply by 2
|
||||
emit("lsl r%s", acc[0])
|
||||
emit("rol r%s", acc[1])
|
||||
emit("rol r%s", acc[2])
|
||||
|
||||
# add equal word (if any)
|
||||
if ((i+1) % 2) != 0:
|
||||
emit("mul r%s, r%s", rg(i//2), rg(i//2))
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
|
||||
# add old accumulator
|
||||
emit("add r%s, r%s", acc[0], old_acc[0])
|
||||
emit("adc r%s, r%s", acc[1], old_acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
|
||||
# store
|
||||
emit("st z+, r%s", acc[0])
|
||||
print ""
|
||||
|
||||
regs = range(2, 22)
|
||||
for i in xrange(init_size):
|
||||
regs = regs[1:] + regs[:1]
|
||||
emit("ld r%s, x+", regs[19])
|
||||
|
||||
for limit in [18, 19]:
|
||||
emit("ldi r%s, 0", old_acc[1])
|
||||
tmp = [acc[1], acc[2]]
|
||||
acc = [acc[0], old_acc[0], old_acc[1]]
|
||||
old_acc = tmp
|
||||
|
||||
# gather non-equal words
|
||||
emit("mul r%s, r%s", regs[0], regs[limit])
|
||||
emit("mov r%s, r0", acc[0])
|
||||
emit("mov r%s, r1", acc[1])
|
||||
for j in xrange(1, (limit+1)//2):
|
||||
emit("mul r%s, r%s", regs[j], regs[limit-j])
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
|
||||
emit("ld r0, z") # load stored value from initial block, and add to accumulator (note z does not increment)
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r25", acc[1])
|
||||
emit("adc r%s, r25", acc[2])
|
||||
|
||||
# multiply by 2
|
||||
emit("lsl r%s", acc[0])
|
||||
emit("rol r%s", acc[1])
|
||||
emit("rol r%s", acc[2])
|
||||
|
||||
# add equal word
|
||||
if limit == 18:
|
||||
emit("mul r%s, r%s", regs[9], regs[9])
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
|
||||
# add old accumulator
|
||||
emit("add r%s, r%s", acc[0], old_acc[0])
|
||||
emit("adc r%s, r%s", acc[1], old_acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
|
||||
# store
|
||||
emit("st z+, r%s", acc[0])
|
||||
print ""
|
||||
|
||||
for i in xrange(1, s-3):
|
||||
emit("ldi r%s, 0", old_acc[1])
|
||||
tmp = [acc[1], acc[2]]
|
||||
acc = [acc[0], old_acc[0], old_acc[1]]
|
||||
old_acc = tmp
|
||||
|
||||
# gather non-equal words
|
||||
emit("mul r%s, r%s", regs[i], regs[s - 1])
|
||||
emit("mov r%s, r0", acc[0])
|
||||
emit("mov r%s, r1", acc[1])
|
||||
for j in xrange(1, (s-i)//2):
|
||||
emit("mul r%s, r%s", regs[i+j], regs[s - 1 - j])
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
# multiply by 2
|
||||
emit("lsl r%s", acc[0])
|
||||
emit("rol r%s", acc[1])
|
||||
emit("rol r%s", acc[2])
|
||||
|
||||
# add equal word (if any)
|
||||
if ((s-i) % 2) != 0:
|
||||
emit("mul r%s, r%s", regs[i + (s-i)//2], regs[i + (s-i)//2])
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
|
||||
# add old accumulator
|
||||
emit("add r%s, r%s", acc[0], old_acc[0])
|
||||
emit("adc r%s, r%s", acc[1], old_acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
|
||||
# store
|
||||
emit("st z+, r%s", acc[0])
|
||||
print ""
|
||||
|
||||
acc = acc[1:] + acc[:1]
|
||||
emit("ldi r%s, 0", acc[2])
|
||||
emit("mul r%s, r%s", regs[17], regs[19])
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
emit("mul r%s, r%s", regs[18], regs[18])
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
emit("st z+, r%s", acc[0])
|
||||
print ""
|
||||
|
||||
acc = acc[1:] + acc[:1]
|
||||
emit("ldi r%s, 0", acc[2])
|
||||
emit("mul r%s, r%s", regs[18], regs[19])
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
emit("add r%s, r0", acc[0])
|
||||
emit("adc r%s, r1", acc[1])
|
||||
emit("adc r%s, %s", acc[2], zero)
|
||||
emit("st z+, r%s", acc[0])
|
||||
print ""
|
||||
|
||||
emit("mul r%s, r%s", regs[19], regs[19])
|
||||
emit("add r%s, r0", acc[1])
|
||||
emit("adc r%s, r1", acc[2])
|
||||
emit("st z+, r%s", acc[1])
|
||||
|
||||
emit("st z+, r%s", acc[2])
|
||||
emit("eor r1, r1")
|
128
core/embed/ble_bootloader/uecc/test/ecdsa_test_vectors.c
Normal file
128
core/embed/ble_bootloader/uecc/test/ecdsa_test_vectors.c
Normal file
@ -0,0 +1,128 @@
|
||||
/* Copyright 2020, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#include "uECC.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
const char* private_key;
|
||||
const char* public_key;
|
||||
const char* k;
|
||||
const char* hash;
|
||||
const char* r;
|
||||
const char* s;
|
||||
} Test;
|
||||
|
||||
Test secp256k1_tests[] = {
|
||||
{
|
||||
"ebb2c082fd7727890a28ac82f6bdf97bad8de9f5d7c9028692de1a255cad3e0f",
|
||||
"779dd197a5df977ed2cf6cb31d82d43328b790dc6b3b7d4437a427bd5847dfcde94b724a555b6d017bb7607c3e3281daf5b1699d6ef4124975c9237b917d426f",
|
||||
"49a0d7b786ec9cde0d0721d72804befd06571c974b191efb42ecf322ba9ddd9a",
|
||||
"4b688df40bcedbe641ddb16ff0a1842d9c67ea1c3bf63f3e0471baa664531d1a",
|
||||
"241097efbf8b63bf145c8961dbdf10c310efbb3b2676bbc0f8b08505c9e2f795",
|
||||
"021006b7838609339e8b415a7f9acb1b661828131aef1ecbc7955dfb01f3ca0e"
|
||||
},
|
||||
};
|
||||
|
||||
extern int uECC_sign_with_k(const uint8_t *private_key,
|
||||
const uint8_t *message_hash,
|
||||
unsigned hash_size,
|
||||
const uint8_t *k,
|
||||
uint8_t *signature,
|
||||
uECC_Curve curve);
|
||||
|
||||
|
||||
void vli_print(uint8_t *vli, unsigned int size) {
|
||||
for(unsigned i=0; i<size; ++i) {
|
||||
printf("%02X ", (unsigned)vli[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void strtobytes(const char* str, uint8_t* bytes, int count) {
|
||||
for (int c = 0; c < count; ++c) {
|
||||
if (sscanf(str, "%2hhx", &bytes[c]) != 1) {
|
||||
printf("Failed to read string to bytes");
|
||||
exit(1);
|
||||
}
|
||||
str += 2;
|
||||
}
|
||||
}
|
||||
|
||||
int run(Test* tests, int num_tests, uECC_Curve curve) {
|
||||
uint8_t private[32] = {0};
|
||||
uint8_t public[64] = {0};
|
||||
uint8_t k[32] = {0};
|
||||
uint8_t hash[32] = {0};
|
||||
uint8_t r[32] = {0};
|
||||
uint8_t s[32] = {0};
|
||||
|
||||
uint8_t signature[64] = {0};
|
||||
|
||||
int result;
|
||||
int i;
|
||||
int private_key_size;
|
||||
int public_key_size;
|
||||
int all_success = 1;
|
||||
|
||||
private_key_size = uECC_curve_private_key_size(curve);
|
||||
public_key_size = uECC_curve_public_key_size(curve);
|
||||
|
||||
for (i = 0; i < num_tests; ++i) {
|
||||
strtobytes(tests[i].private_key, private, private_key_size);
|
||||
strtobytes(tests[i].public_key, public, public_key_size);
|
||||
strtobytes(tests[i].k, k, private_key_size);
|
||||
strtobytes(tests[i].hash, hash, private_key_size);
|
||||
strtobytes(tests[i].r, r, private_key_size);
|
||||
strtobytes(tests[i].s, s, private_key_size);
|
||||
|
||||
result = uECC_sign_with_k(private, hash, private_key_size, k, signature, curve);
|
||||
if (!result) {
|
||||
all_success = 0;
|
||||
printf(" Sign failed for test %d\n", i);
|
||||
}
|
||||
if (result) {
|
||||
if (memcmp(signature, r, private_key_size) != 0) {
|
||||
all_success = 0;
|
||||
printf(" Got incorrect r for test %d\n", i);
|
||||
printf(" Expected: ");
|
||||
vli_print(r, private_key_size);
|
||||
printf(" Calculated: ");
|
||||
vli_print(signature, private_key_size);
|
||||
}
|
||||
if (memcmp(signature + private_key_size, s, private_key_size) != 0) {
|
||||
all_success = 0;
|
||||
printf(" Got incorrect s for test %d\n", i);
|
||||
printf(" Expected: ");
|
||||
vli_print(s, private_key_size);
|
||||
printf(" Calculated: ");
|
||||
vli_print(signature + private_key_size, private_key_size);
|
||||
}
|
||||
|
||||
result = uECC_verify(public, hash, private_key_size, signature, curve);
|
||||
if (!result) {
|
||||
printf(" Verify failed for test %d\n", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return all_success;
|
||||
}
|
||||
|
||||
#define RUN_TESTS(curve) \
|
||||
printf(#curve ":\n"); \
|
||||
if (run(curve##_tests, sizeof(curve##_tests) / sizeof(curve##_tests[0]), uECC_##curve()) ) { \
|
||||
printf(" All passed\n"); \
|
||||
} else { \
|
||||
printf(" Failed\n"); \
|
||||
}
|
||||
|
||||
int main() {
|
||||
#if uECC_SUPPORTS_secp256k1
|
||||
RUN_TESTS(secp256k1)
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
4
core/embed/ble_bootloader/uecc/test/emk_rules.py
Normal file
4
core/embed/ble_bootloader/uecc/test/emk_rules.py
Normal file
@ -0,0 +1,4 @@
|
||||
c, link = emk.module("c", "link")
|
||||
link.depdirs += [
|
||||
"$:proj:$"
|
||||
]
|
338
core/embed/ble_bootloader/uecc/test/public_key_test_vectors.c
Normal file
338
core/embed/ble_bootloader/uecc/test/public_key_test_vectors.c
Normal file
@ -0,0 +1,338 @@
|
||||
/* Copyright 2020, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#include "uECC.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
const char* k;
|
||||
const char* Q;
|
||||
int success;
|
||||
} Test;
|
||||
|
||||
Test secp160r1_tests[] = {
|
||||
/* Note, I couldn't find any test vectors for secp160r1 online, so these are just
|
||||
generated on my desktop using uECC. */
|
||||
{
|
||||
"000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
0
|
||||
},
|
||||
{
|
||||
"000000000000000000000000000000000000000001",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
0
|
||||
},
|
||||
{
|
||||
"000000000000000000000000000000000000000002",
|
||||
"02F997F33C5ED04C55D3EDF8675D3E92E8F46686F083A323482993E9440E817E21CFB7737DF8797B",
|
||||
1
|
||||
},
|
||||
{
|
||||
"000000000000000000000000000000000000000003",
|
||||
"7B76FF541EF363F2DF13DE1650BD48DAA958BC59C915CA790D8C8877B55BE0079D12854FFE9F6F5A",
|
||||
1
|
||||
},
|
||||
{ /* n - 4 */
|
||||
"0100000000000000000001F4C8F927AED3CA752253",
|
||||
"B4041D8683BE99F0AFE01C307B1AD4C100CF2A88C0CD35127BE0F73FF99F338B350B5A42864112F7",
|
||||
1
|
||||
},
|
||||
{ /* n - 3 */
|
||||
"0100000000000000000001F4C8F927AED3CA752254",
|
||||
"7B76FF541EF363F2DF13DE1650BD48DAA958BC5936EA3586F27377884AA41FF862ED7AAF816090A5",
|
||||
1
|
||||
},
|
||||
{ /* n - 2 */
|
||||
"0100000000000000000001F4C8F927AED3CA752255",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
0
|
||||
},
|
||||
{ /* n - 1 */
|
||||
"0100000000000000000001F4C8F927AED3CA752256",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
0
|
||||
},
|
||||
{ /* n */
|
||||
"0100000000000000000001F4C8F927AED3CA752257",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
0
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Test secp192r1_tests[] = {
|
||||
{
|
||||
"000000000000000000000000000000000000000000000000",
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
0
|
||||
},
|
||||
{
|
||||
"000000000000000000000000000000000000000000000001",
|
||||
"188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
|
||||
0
|
||||
},
|
||||
{
|
||||
"000000000000000000000000000000000000000000000002",
|
||||
"DAFEBF5828783F2AD35534631588A3F629A70FB16982A888DD6BDA0D993DA0FA46B27BBC141B868F59331AFA5C7E93AB",
|
||||
1
|
||||
},
|
||||
{
|
||||
"000000000000000000000000000000000000000000000003",
|
||||
"76E32A2557599E6EDCD283201FB2B9AADFD0D359CBB263DA782C37E372BA4520AA62E0FED121D49EF3B543660CFD05FD",
|
||||
1
|
||||
},
|
||||
{ /* n - 4 */
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D2282D",
|
||||
"35433907297CC378B0015703374729D7A4FE46647084E4BA5D9B667B0DECA3CFE15C534F88932B0DDAC764CEE24C41CD",
|
||||
1
|
||||
},
|
||||
{ /* n - 3 */
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D2282E",
|
||||
"76E32A2557599E6EDCD283201FB2B9AADFD0D359CBB263DA87D3C81C8D45BADF559D1F012EDE2B600C4ABC99F302FA02",
|
||||
1
|
||||
},
|
||||
{ /* n - 2 */
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D2282F",
|
||||
"DAFEBF5828783F2AD35534631588A3F629A70FB16982A888229425F266C25F05B94D8443EBE4796FA6CCE505A3816C54",
|
||||
0
|
||||
},
|
||||
{ /* n - 1 */
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830",
|
||||
"188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012F8E6D46A003725879CEFEE1294DB32298C06885EE186B7EE",
|
||||
0
|
||||
},
|
||||
{ /* n */
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
0
|
||||
},
|
||||
};
|
||||
|
||||
Test secp224r1_tests[] = {
|
||||
{
|
||||
"00000000000000000000000000000000000000000000000000000000",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
0
|
||||
},
|
||||
{
|
||||
"00000000000000000000000000000000000000000000000000000001",
|
||||
"B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
|
||||
0
|
||||
},
|
||||
{
|
||||
"00000000000000000000000000000000000000000000000000000002",
|
||||
"706A46DC76DCB76798E60E6D89474788D16DC18032D268FD1A704FA61C2B76A7BC25E7702A704FA986892849FCA629487ACF3709D2E4E8BB",
|
||||
1
|
||||
},
|
||||
{
|
||||
"00000000000000000000000000000000000000000000000000000003",
|
||||
"DF1B1D66A551D0D31EFF822558B9D2CC75C2180279FE0D08FD896D04A3F7F03CADD0BE444C0AA56830130DDF77D317344E1AF3591981A925",
|
||||
1
|
||||
},
|
||||
{ /* n - 4 */
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A39",
|
||||
"AE99FEEBB5D26945B54892092A8AEE02912930FA41CD114E40447301FB7DA7F5F13A43B81774373C879CD32D6934C05FA758EEB14FCFAB38",
|
||||
1
|
||||
},
|
||||
{ /* n - 3 */
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3A",
|
||||
"DF1B1D66A551D0D31EFF822558B9D2CC75C2180279FE0D08FD896D045C080FC3522F41BBB3F55A97CFECF21F882CE8CBB1E50CA6E67E56DC",
|
||||
1
|
||||
},
|
||||
{ /* n - 2 */
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3B",
|
||||
"706A46DC76DCB76798E60E6D89474788D16DC18032D268FD1A704FA6E3D4895843DA188FD58FB0567976D7B50359D6B78530C8F62D1B1746",
|
||||
0
|
||||
},
|
||||
{ /* n - 1 */
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3C",
|
||||
"B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D2142C89C774A08DC04B3DD201932BC8A5EA5F8B89BBB2A7E667AFF81CD",
|
||||
0
|
||||
},
|
||||
{ /* n */
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
0
|
||||
},
|
||||
};
|
||||
|
||||
Test secp256r1_tests[] = {
|
||||
{
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
0
|
||||
},
|
||||
{
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
|
||||
0
|
||||
},
|
||||
{
|
||||
"0000000000000000000000000000000000000000000000000000000000000002",
|
||||
"7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC4766997807775510DB8ED040293D9AC69F7430DBBA7DADE63CE982299E04B79D227873D1",
|
||||
1
|
||||
},
|
||||
{
|
||||
"0000000000000000000000000000000000000000000000000000000000000003",
|
||||
"5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C8734640C4998FF7E374B06CE1A64A2ECD82AB036384FB83D9A79B127A27D5032",
|
||||
1
|
||||
},
|
||||
{ /* n - 4 */
|
||||
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254D",
|
||||
"E2534A3532D08FBBA02DDE659EE62BD0031FE2DB785596EF509302446B0308521F0EA8A4B39CC339E62011A02579D289B103693D0CF11FFAA3BD3DC0E7B12739",
|
||||
1
|
||||
},
|
||||
{ /* n - 3 */
|
||||
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254E",
|
||||
"5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C78CB9BF2B6670082C8B4F931E59B5D1327D54FCAC7B047C265864ED85D82AFCD",
|
||||
1
|
||||
},
|
||||
{ /* n - 2 */
|
||||
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254F",
|
||||
"7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978F888AAEE24712FC0D6C26539608BCF244582521AC3167DD661FB4862DD878C2E",
|
||||
0
|
||||
},
|
||||
{ /* n - 1 */
|
||||
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632550",
|
||||
"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296B01CBD1C01E58065711814B583F061E9D431CCA994CEA1313449BF97C840AE0A",
|
||||
0
|
||||
},
|
||||
{ /* n */
|
||||
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
0
|
||||
},
|
||||
};
|
||||
|
||||
Test secp256k1_tests[] = {
|
||||
{
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
0
|
||||
},
|
||||
{
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
"79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
|
||||
0
|
||||
},
|
||||
{
|
||||
"0000000000000000000000000000000000000000000000000000000000000002",
|
||||
"C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE51AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A",
|
||||
1
|
||||
},
|
||||
{
|
||||
"0000000000000000000000000000000000000000000000000000000000000003",
|
||||
"F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9388F7B0F632DE8140FE337E62A37F3566500A99934C2231B6CB9FD7584B8E672",
|
||||
1
|
||||
},
|
||||
{ /* n - 4 */
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413D",
|
||||
"E493DBF1C10D80F3581E4904930B1404CC6C13900EE0758474FA94ABE8C4CD13AE1266C15F2BAA48A9BD1DF6715AEBB7269851CC404201BF30168422B88C630D",
|
||||
1
|
||||
},
|
||||
{ /* n - 3 */
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413E",
|
||||
"F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9C77084F09CD217EBF01CC819D5C80CA99AFF5666CB3DDCE4934602897B4715BD",
|
||||
1
|
||||
},
|
||||
{ /* n - 2 */
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413F",
|
||||
"C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5E51E970159C23CC65C3A7BE6B99315110809CD9ACD992F1EDC9BCE55AF301705",
|
||||
0
|
||||
},
|
||||
{ /* n - 1 */
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140",
|
||||
"79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798B7C52588D95C3B9AA25B0403F1EEF75702E84BB7597AABE663B82F6F04EF2777",
|
||||
0
|
||||
},
|
||||
{ /* n */
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
0
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
void vli_print(uint8_t *vli, unsigned int size) {
|
||||
for(unsigned i=0; i<size; ++i) {
|
||||
printf("%02X ", (unsigned)vli[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void strtobytes(const char* str, uint8_t* bytes, int count) {
|
||||
for (int c = 0; c < count; ++c) {
|
||||
if (sscanf(str, "%2hhx", &bytes[c]) != 1) {
|
||||
printf("Failed to read string to bytes");
|
||||
exit(1);
|
||||
}
|
||||
str += 2;
|
||||
}
|
||||
}
|
||||
|
||||
int run(Test* tests, int num_tests, uECC_Curve curve) {
|
||||
uint8_t private[32] = {0};
|
||||
uint8_t public[64] = {0};
|
||||
uint8_t expected[64] = {0};
|
||||
int result;
|
||||
int i;
|
||||
int private_key_size;
|
||||
int public_key_size;
|
||||
int all_success = 1;
|
||||
|
||||
private_key_size = uECC_curve_private_key_size(curve);
|
||||
public_key_size = uECC_curve_public_key_size(curve);
|
||||
|
||||
for (i = 0; i < num_tests; ++i) {
|
||||
strtobytes(tests[i].k, private, private_key_size);
|
||||
result = uECC_compute_public_key(private, public, curve);
|
||||
if (result != tests[i].success) {
|
||||
all_success = 0;
|
||||
printf(" Got unexpected result from test %d: %d\n", i, result);
|
||||
}
|
||||
if (result) {
|
||||
strtobytes(tests[i].Q, expected, public_key_size);
|
||||
if (memcmp(public, expected, public_key_size) != 0) {
|
||||
all_success = 0;
|
||||
printf(" Got incorrect public key for test %d\n", i);
|
||||
printf(" Expected: ");
|
||||
vli_print(expected, public_key_size);
|
||||
printf(" Calculated: ");
|
||||
vli_print(public, public_key_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return all_success;
|
||||
}
|
||||
|
||||
#define RUN_TESTS(curve) \
|
||||
printf(#curve ":\n"); \
|
||||
if (run(curve##_tests, sizeof(curve##_tests) / sizeof(curve##_tests[0]), uECC_##curve()) ) { \
|
||||
printf(" All passed\n"); \
|
||||
} else { \
|
||||
printf(" Failed\n"); \
|
||||
}
|
||||
|
||||
int main() {
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
RUN_TESTS(secp160r1)
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
RUN_TESTS(secp192r1)
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
RUN_TESTS(secp224r1)
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256r1
|
||||
RUN_TESTS(secp256r1)
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256k1
|
||||
RUN_TESTS(secp256k1)
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
79
core/embed/ble_bootloader/uecc/test/test_compress.c
Normal file
79
core/embed/ble_bootloader/uecc/test/test_compress.c
Normal file
@ -0,0 +1,79 @@
|
||||
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#include "uECC.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef uECC_TEST_NUMBER_OF_ITERATIONS
|
||||
#define uECC_TEST_NUMBER_OF_ITERATIONS 256
|
||||
#endif
|
||||
|
||||
void vli_print(char *str, uint8_t *vli, unsigned int size) {
|
||||
printf("%s ", str);
|
||||
for(unsigned i=0; i<size; ++i) {
|
||||
printf("%02X ", (unsigned)vli[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main() {
|
||||
uint8_t public[64];
|
||||
uint8_t private[32];
|
||||
uint8_t compressed_point[33];
|
||||
uint8_t decompressed_point[64];
|
||||
|
||||
int i;
|
||||
int c;
|
||||
|
||||
const struct uECC_Curve_t * curves[5];
|
||||
int num_curves = 0;
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
curves[num_curves++] = uECC_secp160r1();
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
curves[num_curves++] = uECC_secp192r1();
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
curves[num_curves++] = uECC_secp224r1();
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256r1
|
||||
curves[num_curves++] = uECC_secp256r1();
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256k1
|
||||
curves[num_curves++] = uECC_secp256k1();
|
||||
#endif
|
||||
|
||||
printf("Testing compression and decompression of %d random EC points\n",
|
||||
uECC_TEST_NUMBER_OF_ITERATIONS);
|
||||
|
||||
for (c = 0; c < num_curves; ++c) {
|
||||
for (i = 0; i < uECC_TEST_NUMBER_OF_ITERATIONS; ++i) {
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
|
||||
memset(public, 0, sizeof(public));
|
||||
memset(decompressed_point, 0, sizeof(decompressed_point));
|
||||
|
||||
/* Generate arbitrary EC point (public) on Curve */
|
||||
if (!uECC_make_key(public, private, curves[c])) {
|
||||
printf("uECC_make_key() failed\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* compress and decompress point */
|
||||
uECC_compress(public, compressed_point, curves[c]);
|
||||
uECC_decompress(compressed_point, decompressed_point, curves[c]);
|
||||
|
||||
if (memcmp(public, decompressed_point, sizeof(public)) != 0) {
|
||||
printf("Original and decompressed points are not identical!\n");
|
||||
vli_print("Original point = ", public, sizeof(public));
|
||||
vli_print("Compressed point = ", compressed_point, sizeof(compressed_point));
|
||||
vli_print("Decompressed point = ", decompressed_point, sizeof(decompressed_point));
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
81
core/embed/ble_bootloader/uecc/test/test_compute.c
Normal file
81
core/embed/ble_bootloader/uecc/test/test_compute.c
Normal file
@ -0,0 +1,81 @@
|
||||
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#include "uECC.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void vli_print(char *str, uint8_t *vli, unsigned int size) {
|
||||
printf("%s ", str);
|
||||
for(unsigned i=0; i<size; ++i) {
|
||||
printf("%02X ", (unsigned)vli[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main() {
|
||||
int i;
|
||||
int success;
|
||||
uint8_t private[32];
|
||||
uint8_t public[64];
|
||||
uint8_t public_computed[64];
|
||||
|
||||
int c;
|
||||
|
||||
const struct uECC_Curve_t * curves[5];
|
||||
int num_curves = 0;
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
curves[num_curves++] = uECC_secp160r1();
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
curves[num_curves++] = uECC_secp192r1();
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
curves[num_curves++] = uECC_secp224r1();
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256r1
|
||||
curves[num_curves++] = uECC_secp256r1();
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256k1
|
||||
curves[num_curves++] = uECC_secp256k1();
|
||||
#endif
|
||||
|
||||
printf("Testing 256 random private key pairs\n");
|
||||
for (c = 0; c < num_curves; ++c) {
|
||||
for (i = 0; i < 256; ++i) {
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
|
||||
memset(public, 0, sizeof(public));
|
||||
memset(public_computed, 0, sizeof(public_computed));
|
||||
|
||||
if (!uECC_make_key(public, private, curves[c])) {
|
||||
printf("uECC_make_key() failed\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!uECC_compute_public_key(private, public_computed, curves[c])) {
|
||||
printf("uECC_compute_public_key() failed\n");
|
||||
}
|
||||
|
||||
if (memcmp(public, public_computed, sizeof(public)) != 0) {
|
||||
printf("Computed and provided public keys are not identical!\n");
|
||||
vli_print("Computed public key = ", public_computed, sizeof(public_computed));
|
||||
vli_print("Provided public key = ", public, sizeof(public));
|
||||
vli_print("Private key = ", private, sizeof(private));
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf("Testing private key = 0\n");
|
||||
|
||||
memset(private, 0, sizeof(private));
|
||||
success = uECC_compute_public_key(private, public_computed, curves[c]);
|
||||
if (success) {
|
||||
printf("uECC_compute_public_key() should have failed\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
90
core/embed/ble_bootloader/uecc/test/test_ecdh.c
Normal file
90
core/embed/ble_bootloader/uecc/test/test_ecdh.c
Normal file
@ -0,0 +1,90 @@
|
||||
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#include "uECC.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void vli_print(uint8_t *vli, unsigned int size) {
|
||||
for(unsigned i=0; i<size; ++i) {
|
||||
printf("%02X ", (unsigned)vli[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
int i, c;
|
||||
uint8_t private1[32] = {0};
|
||||
uint8_t private2[32] = {0};
|
||||
uint8_t public1[64] = {0};
|
||||
uint8_t public2[64] = {0};
|
||||
uint8_t secret1[32] = {0};
|
||||
uint8_t secret2[32] = {0};
|
||||
|
||||
const struct uECC_Curve_t * curves[5];
|
||||
int num_curves = 0;
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
curves[num_curves++] = uECC_secp160r1();
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
curves[num_curves++] = uECC_secp192r1();
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
curves[num_curves++] = uECC_secp224r1();
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256r1
|
||||
curves[num_curves++] = uECC_secp256r1();
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256k1
|
||||
curves[num_curves++] = uECC_secp256k1();
|
||||
#endif
|
||||
|
||||
printf("Testing 256 random private key pairs\n");
|
||||
|
||||
for (c = 0; c < num_curves; ++c) {
|
||||
for (i = 0; i < 256; ++i) {
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
|
||||
if (!uECC_make_key(public1, private1, curves[c]) ||
|
||||
!uECC_make_key(public2, private2, curves[c])) {
|
||||
printf("uECC_make_key() failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!uECC_shared_secret(public2, private1, secret1, curves[c])) {
|
||||
printf("shared_secret() failed (1)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!uECC_shared_secret(public1, private2, secret2, curves[c])) {
|
||||
printf("shared_secret() failed (2)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (memcmp(secret1, secret2, sizeof(secret1)) != 0) {
|
||||
printf("Shared secrets are not identical!\n");
|
||||
printf("Private key 1 = ");
|
||||
vli_print(private1, 32);
|
||||
printf("\n");
|
||||
printf("Private key 2 = ");
|
||||
vli_print(private2, 32);
|
||||
printf("\n");
|
||||
printf("Public key 1 = ");
|
||||
vli_print(public1, 64);
|
||||
printf("\n");
|
||||
printf("Public key 2 = ");
|
||||
vli_print(public2, 64);
|
||||
printf("\n");
|
||||
printf("Shared secret 1 = ");
|
||||
vli_print(secret1, 32);
|
||||
printf("\n");
|
||||
printf("Shared secret 2 = ");
|
||||
vli_print(secret2, 32);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
59
core/embed/ble_bootloader/uecc/test/test_ecdsa.c
Normal file
59
core/embed/ble_bootloader/uecc/test/test_ecdsa.c
Normal file
@ -0,0 +1,59 @@
|
||||
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#include "uECC.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main() {
|
||||
int i, c;
|
||||
uint8_t private[32] = {0};
|
||||
uint8_t public[64] = {0};
|
||||
uint8_t hash[32] = {0};
|
||||
uint8_t sig[64] = {0};
|
||||
|
||||
const struct uECC_Curve_t * curves[5];
|
||||
int num_curves = 0;
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
curves[num_curves++] = uECC_secp160r1();
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
curves[num_curves++] = uECC_secp192r1();
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
curves[num_curves++] = uECC_secp224r1();
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256r1
|
||||
curves[num_curves++] = uECC_secp256r1();
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256k1
|
||||
curves[num_curves++] = uECC_secp256k1();
|
||||
#endif
|
||||
|
||||
printf("Testing 256 signatures\n");
|
||||
for (c = 0; c < num_curves; ++c) {
|
||||
for (i = 0; i < 256; ++i) {
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
|
||||
if (!uECC_make_key(public, private, curves[c])) {
|
||||
printf("uECC_make_key() failed\n");
|
||||
return 1;
|
||||
}
|
||||
memcpy(hash, public, sizeof(hash));
|
||||
|
||||
if (!uECC_sign(private, hash, sizeof(hash), sig, curves[c])) {
|
||||
printf("uECC_sign() failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!uECC_verify(public, hash, sizeof(hash), sig, curves[c])) {
|
||||
printf("uECC_verify() failed\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#include "uECC.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define SHA256_BLOCK_LENGTH 64
|
||||
#define SHA256_DIGEST_LENGTH 32
|
||||
|
||||
typedef struct SHA256_CTX {
|
||||
uint32_t state[8];
|
||||
uint64_t bitcount;
|
||||
uint8_t buffer[SHA256_BLOCK_LENGTH];
|
||||
} SHA256_CTX;
|
||||
|
||||
extern void SHA256_Init(SHA256_CTX *ctx);
|
||||
extern void SHA256_Update(SHA256_CTX *ctx, const uint8_t *message, size_t message_size);
|
||||
extern void SHA256_Final(uint8_t digest[SHA256_DIGEST_LENGTH], SHA256_CTX *ctx);
|
||||
|
||||
typedef struct SHA256_HashContext {
|
||||
uECC_HashContext uECC;
|
||||
SHA256_CTX ctx;
|
||||
} SHA256_HashContext;
|
||||
|
||||
static void init_SHA256(const uECC_HashContext *base) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Init(&context->ctx);
|
||||
}
|
||||
|
||||
static void update_SHA256(const uECC_HashContext *base,
|
||||
const uint8_t *message,
|
||||
unsigned message_size) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Update(&context->ctx, message, message_size);
|
||||
}
|
||||
|
||||
static void finish_SHA256(const uECC_HashContext *base, uint8_t *hash_result) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Final(hash_result, &context->ctx);
|
||||
}
|
||||
|
||||
int main() {
|
||||
int i, c;
|
||||
uint8_t private[32] = {0};
|
||||
uint8_t public[64] = {0};
|
||||
uint8_t hash[32] = {0};
|
||||
uint8_t sig[64] = {0};
|
||||
|
||||
uint8_t tmp[2 * SHA256_DIGEST_LENGTH + SHA256_BLOCK_LENGTH];
|
||||
SHA256_HashContext ctx = {{
|
||||
&init_SHA256,
|
||||
&update_SHA256,
|
||||
&finish_SHA256,
|
||||
SHA256_BLOCK_LENGTH,
|
||||
SHA256_DIGEST_LENGTH,
|
||||
tmp
|
||||
}};
|
||||
|
||||
const struct uECC_Curve_t * curves[5];
|
||||
curves[0] = uECC_secp160r1();
|
||||
curves[1] = uECC_secp192r1();
|
||||
curves[2] = uECC_secp224r1();
|
||||
curves[3] = uECC_secp256r1();
|
||||
curves[4] = uECC_secp256k1();
|
||||
|
||||
printf("Testing 256 signatures\n");
|
||||
for (c = 0; c < 5; ++c) {
|
||||
for (i = 0; i < 256; ++i) {
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
|
||||
if (!uECC_make_key(public, private, curves[c])) {
|
||||
printf("uECC_make_key() failed\n");
|
||||
return 1;
|
||||
}
|
||||
memcpy(hash, public, sizeof(hash));
|
||||
|
||||
if (!uECC_sign_deterministic(private, hash, sizeof(hash), &ctx.uECC, sig, curves[c])) {
|
||||
printf("uECC_sign() failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!uECC_verify(public, hash, sizeof(hash), sig, curves[c])) {
|
||||
printf("uECC_verify() failed\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
108
core/embed/ble_bootloader/uecc/types.h
Normal file
108
core/embed/ble_bootloader/uecc/types.h
Normal file
@ -0,0 +1,108 @@
|
||||
/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_TYPES_H_
|
||||
#define _UECC_TYPES_H_
|
||||
|
||||
#ifndef uECC_PLATFORM
|
||||
#if __AVR__
|
||||
#define uECC_PLATFORM uECC_avr
|
||||
#elif defined(__thumb2__) || defined(_M_ARMT) /* I think MSVC only supports Thumb-2 targets */
|
||||
#define uECC_PLATFORM uECC_arm_thumb2
|
||||
#elif defined(__thumb__)
|
||||
#define uECC_PLATFORM uECC_arm_thumb
|
||||
#elif defined(__arm__) || defined(_M_ARM)
|
||||
#define uECC_PLATFORM uECC_arm
|
||||
#elif defined(__aarch64__)
|
||||
#define uECC_PLATFORM uECC_arm64
|
||||
#elif defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__I86__)
|
||||
#define uECC_PLATFORM uECC_x86
|
||||
#elif defined(__amd64__) || defined(_M_X64)
|
||||
#define uECC_PLATFORM uECC_x86_64
|
||||
#else
|
||||
#define uECC_PLATFORM uECC_arch_other
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef uECC_ARM_USE_UMAAL
|
||||
#if (uECC_PLATFORM == uECC_arm) && (__ARM_ARCH >= 6)
|
||||
#define uECC_ARM_USE_UMAAL 1
|
||||
#elif (uECC_PLATFORM == uECC_arm_thumb2) && (__ARM_ARCH >= 6) && !__ARM_ARCH_7M__
|
||||
#define uECC_ARM_USE_UMAAL 1
|
||||
#else
|
||||
#define uECC_ARM_USE_UMAAL 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef uECC_WORD_SIZE
|
||||
#if uECC_PLATFORM == uECC_avr
|
||||
#define uECC_WORD_SIZE 1
|
||||
#elif (uECC_PLATFORM == uECC_x86_64 || uECC_PLATFORM == uECC_arm64)
|
||||
#define uECC_WORD_SIZE 8
|
||||
#else
|
||||
#define uECC_WORD_SIZE 4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (uECC_WORD_SIZE != 1) && (uECC_WORD_SIZE != 4) && (uECC_WORD_SIZE != 8)
|
||||
#error "Unsupported value for uECC_WORD_SIZE"
|
||||
#endif
|
||||
|
||||
#if ((uECC_PLATFORM == uECC_avr) && (uECC_WORD_SIZE != 1))
|
||||
#pragma message ("uECC_WORD_SIZE must be 1 for AVR")
|
||||
#undef uECC_WORD_SIZE
|
||||
#define uECC_WORD_SIZE 1
|
||||
#endif
|
||||
|
||||
#if ((uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \
|
||||
uECC_PLATFORM == uECC_arm_thumb2) && \
|
||||
(uECC_WORD_SIZE != 4))
|
||||
#pragma message ("uECC_WORD_SIZE must be 4 for ARM")
|
||||
#undef uECC_WORD_SIZE
|
||||
#define uECC_WORD_SIZE 4
|
||||
#endif
|
||||
|
||||
#if defined(__SIZEOF_INT128__) || ((__clang_major__ * 100 + __clang_minor__) >= 302)
|
||||
#define SUPPORTS_INT128 1
|
||||
#else
|
||||
#define SUPPORTS_INT128 0
|
||||
#endif
|
||||
|
||||
typedef int8_t wordcount_t;
|
||||
typedef int16_t bitcount_t;
|
||||
typedef int8_t cmpresult_t;
|
||||
|
||||
#if (uECC_WORD_SIZE == 1)
|
||||
|
||||
typedef uint8_t uECC_word_t;
|
||||
typedef uint16_t uECC_dword_t;
|
||||
|
||||
#define HIGH_BIT_SET 0x80
|
||||
#define uECC_WORD_BITS 8
|
||||
#define uECC_WORD_BITS_SHIFT 3
|
||||
#define uECC_WORD_BITS_MASK 0x07
|
||||
|
||||
#elif (uECC_WORD_SIZE == 4)
|
||||
|
||||
typedef uint32_t uECC_word_t;
|
||||
typedef uint64_t uECC_dword_t;
|
||||
|
||||
#define HIGH_BIT_SET 0x80000000
|
||||
#define uECC_WORD_BITS 32
|
||||
#define uECC_WORD_BITS_SHIFT 5
|
||||
#define uECC_WORD_BITS_MASK 0x01F
|
||||
|
||||
#elif (uECC_WORD_SIZE == 8)
|
||||
|
||||
typedef uint64_t uECC_word_t;
|
||||
#if SUPPORTS_INT128
|
||||
typedef unsigned __int128 uECC_dword_t;
|
||||
#endif
|
||||
|
||||
#define HIGH_BIT_SET 0x8000000000000000ull
|
||||
#define uECC_WORD_BITS 64
|
||||
#define uECC_WORD_BITS_SHIFT 6
|
||||
#define uECC_WORD_BITS_MASK 0x03F
|
||||
|
||||
#endif /* uECC_WORD_SIZE */
|
||||
|
||||
#endif /* _UECC_TYPES_H_ */
|
1669
core/embed/ble_bootloader/uecc/uECC.c
Normal file
1669
core/embed/ble_bootloader/uecc/uECC.c
Normal file
File diff suppressed because it is too large
Load Diff
367
core/embed/ble_bootloader/uecc/uECC.h
Normal file
367
core/embed/ble_bootloader/uecc/uECC.h
Normal file
@ -0,0 +1,367 @@
|
||||
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_H_
|
||||
#define _UECC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Platform selection options.
|
||||
If uECC_PLATFORM is not defined, the code will try to guess it based on compiler macros.
|
||||
Possible values for uECC_PLATFORM are defined below: */
|
||||
#define uECC_arch_other 0
|
||||
#define uECC_x86 1
|
||||
#define uECC_x86_64 2
|
||||
#define uECC_arm 3
|
||||
#define uECC_arm_thumb 4
|
||||
#define uECC_arm_thumb2 5
|
||||
#define uECC_arm64 6
|
||||
#define uECC_avr 7
|
||||
|
||||
/* If desired, you can define uECC_WORD_SIZE as appropriate for your platform (1, 4, or 8 bytes).
|
||||
If uECC_WORD_SIZE is not explicitly defined then it will be automatically set based on your
|
||||
platform. */
|
||||
|
||||
/* Optimization level; trade speed for code size.
|
||||
Larger values produce code that is faster but larger.
|
||||
Currently supported values are 0 - 4; 0 is unusably slow for most applications.
|
||||
Optimization level 4 currently only has an effect ARM platforms where more than one
|
||||
curve is enabled. */
|
||||
#ifndef uECC_OPTIMIZATION_LEVEL
|
||||
#define uECC_OPTIMIZATION_LEVEL 2
|
||||
#endif
|
||||
|
||||
/* uECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a specific function to be
|
||||
used for (scalar) squaring instead of the generic multiplication function. This can make things
|
||||
faster somewhat faster, but increases the code size. */
|
||||
#ifndef uECC_SQUARE_FUNC
|
||||
#define uECC_SQUARE_FUNC 0
|
||||
#endif
|
||||
|
||||
/* uECC_VLI_NATIVE_LITTLE_ENDIAN - If enabled (defined as nonzero), this will switch to native
|
||||
little-endian format for *all* arrays passed in and out of the public API. This includes public
|
||||
and private keys, shared secrets, signatures and message hashes.
|
||||
Using this switch reduces the amount of call stack memory used by uECC, since less intermediate
|
||||
translations are required.
|
||||
Note that this will *only* work on native little-endian processors and it will treat the uint8_t
|
||||
arrays passed into the public API as word arrays, therefore requiring the provided byte arrays
|
||||
to be word aligned on architectures that do not support unaligned accesses.
|
||||
IMPORTANT: Keys and signatures generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=1 are incompatible
|
||||
with keys and signatures generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=0; all parties must use
|
||||
the same endianness. */
|
||||
#ifndef uECC_VLI_NATIVE_LITTLE_ENDIAN
|
||||
#define uECC_VLI_NATIVE_LITTLE_ENDIAN 0
|
||||
#endif
|
||||
|
||||
/* Curve support selection. Set to 0 to remove that curve. */
|
||||
#ifndef uECC_SUPPORTS_secp160r1
|
||||
#define uECC_SUPPORTS_secp160r1 1
|
||||
#endif
|
||||
#ifndef uECC_SUPPORTS_secp192r1
|
||||
#define uECC_SUPPORTS_secp192r1 1
|
||||
#endif
|
||||
#ifndef uECC_SUPPORTS_secp224r1
|
||||
#define uECC_SUPPORTS_secp224r1 1
|
||||
#endif
|
||||
#ifndef uECC_SUPPORTS_secp256r1
|
||||
#define uECC_SUPPORTS_secp256r1 1
|
||||
#endif
|
||||
#ifndef uECC_SUPPORTS_secp256k1
|
||||
#define uECC_SUPPORTS_secp256k1 1
|
||||
#endif
|
||||
|
||||
/* Specifies whether compressed point format is supported.
|
||||
Set to 0 to disable point compression/decompression functions. */
|
||||
#ifndef uECC_SUPPORT_COMPRESSED_POINT
|
||||
#define uECC_SUPPORT_COMPRESSED_POINT 1
|
||||
#endif
|
||||
|
||||
struct uECC_Curve_t;
|
||||
typedef const struct uECC_Curve_t * uECC_Curve;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
uECC_Curve uECC_secp160r1(void);
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
uECC_Curve uECC_secp192r1(void);
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
uECC_Curve uECC_secp224r1(void);
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256r1
|
||||
uECC_Curve uECC_secp256r1(void);
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256k1
|
||||
uECC_Curve uECC_secp256k1(void);
|
||||
#endif
|
||||
|
||||
/* uECC_RNG_Function type
|
||||
The RNG function should fill 'size' random bytes into 'dest'. It should return 1 if
|
||||
'dest' was filled with random data, or 0 if the random data could not be generated.
|
||||
The filled-in values should be either truly random, or from a cryptographically-secure PRNG.
|
||||
|
||||
A correctly functioning RNG function must be set (using uECC_set_rng()) before calling
|
||||
uECC_make_key() or uECC_sign().
|
||||
|
||||
Setting a correctly functioning RNG function improves the resistance to side-channel attacks
|
||||
for uECC_shared_secret() and uECC_sign_deterministic().
|
||||
|
||||
A correct RNG function is set by default when building for Windows, Linux, or OS X.
|
||||
If you are building on another POSIX-compliant system that supports /dev/random or /dev/urandom,
|
||||
you can define uECC_POSIX to use the predefined RNG. For embedded platforms there is no predefined
|
||||
RNG function; you must provide your own.
|
||||
*/
|
||||
typedef int (*uECC_RNG_Function)(uint8_t *dest, unsigned size);
|
||||
|
||||
/* uECC_set_rng() function.
|
||||
Set the function that will be used to generate random bytes. The RNG function should
|
||||
return 1 if the random data was generated, or 0 if the random data could not be generated.
|
||||
|
||||
On platforms where there is no predefined RNG function (eg embedded platforms), this must
|
||||
be called before uECC_make_key() or uECC_sign() are used.
|
||||
|
||||
Inputs:
|
||||
rng_function - The function that will be used to generate random bytes.
|
||||
*/
|
||||
void uECC_set_rng(uECC_RNG_Function rng_function);
|
||||
|
||||
/* uECC_get_rng() function.
|
||||
|
||||
Returns the function that will be used to generate random bytes.
|
||||
*/
|
||||
uECC_RNG_Function uECC_get_rng(void);
|
||||
|
||||
/* uECC_curve_private_key_size() function.
|
||||
|
||||
Returns the size of a private key for the curve in bytes.
|
||||
*/
|
||||
int uECC_curve_private_key_size(uECC_Curve curve);
|
||||
|
||||
/* uECC_curve_public_key_size() function.
|
||||
|
||||
Returns the size of a public key for the curve in bytes.
|
||||
*/
|
||||
int uECC_curve_public_key_size(uECC_Curve curve);
|
||||
|
||||
/* uECC_make_key() function.
|
||||
Create a public/private key pair.
|
||||
|
||||
Outputs:
|
||||
public_key - Will be filled in with the public key. Must be at least 2 * the curve size
|
||||
(in bytes) long. For example, if the curve is secp256r1, public_key must be 64
|
||||
bytes long.
|
||||
private_key - Will be filled in with the private key. Must be as long as the curve order; this
|
||||
is typically the same as the curve size, except for secp160r1. For example, if the
|
||||
curve is secp256r1, private_key must be 32 bytes long.
|
||||
|
||||
For secp160r1, private_key must be 21 bytes long! Note that the first byte will
|
||||
almost always be 0 (there is about a 1 in 2^80 chance of it being non-zero).
|
||||
|
||||
Returns 1 if the key pair was generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve);
|
||||
|
||||
/* uECC_shared_secret() function.
|
||||
Compute a shared secret given your secret key and someone else's public key. If the public key
|
||||
is not from a trusted source and has not been previously verified, you should verify it first
|
||||
using uECC_valid_public_key().
|
||||
Note: It is recommended that you hash the result of uECC_shared_secret() before using it for
|
||||
symmetric encryption or HMAC.
|
||||
|
||||
Inputs:
|
||||
public_key - The public key of the remote party.
|
||||
private_key - Your private key.
|
||||
|
||||
Outputs:
|
||||
secret - Will be filled in with the shared secret value. Must be the same size as the
|
||||
curve size; for example, if the curve is secp256r1, secret must be 32 bytes long.
|
||||
|
||||
Returns 1 if the shared secret was generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_shared_secret(const uint8_t *public_key,
|
||||
const uint8_t *private_key,
|
||||
uint8_t *secret,
|
||||
uECC_Curve curve);
|
||||
|
||||
#if uECC_SUPPORT_COMPRESSED_POINT
|
||||
/* uECC_compress() function.
|
||||
Compress a public key.
|
||||
|
||||
Inputs:
|
||||
public_key - The public key to compress.
|
||||
|
||||
Outputs:
|
||||
compressed - Will be filled in with the compressed public key. Must be at least
|
||||
(curve size + 1) bytes long; for example, if the curve is secp256r1,
|
||||
compressed must be 33 bytes long.
|
||||
*/
|
||||
void uECC_compress(const uint8_t *public_key, uint8_t *compressed, uECC_Curve curve);
|
||||
|
||||
/* uECC_decompress() function.
|
||||
Decompress a compressed public key.
|
||||
|
||||
Inputs:
|
||||
compressed - The compressed public key.
|
||||
|
||||
Outputs:
|
||||
public_key - Will be filled in with the decompressed public key.
|
||||
*/
|
||||
void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve);
|
||||
#endif /* uECC_SUPPORT_COMPRESSED_POINT */
|
||||
|
||||
/* uECC_valid_public_key() function.
|
||||
Check to see if a public key is valid.
|
||||
|
||||
Note that you are not required to check for a valid public key before using any other uECC
|
||||
functions. However, you may wish to avoid spending CPU time computing a shared secret or
|
||||
verifying a signature using an invalid public key.
|
||||
|
||||
Inputs:
|
||||
public_key - The public key to check.
|
||||
|
||||
Returns 1 if the public key is valid, 0 if it is invalid.
|
||||
*/
|
||||
int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve);
|
||||
|
||||
/* uECC_compute_public_key() function.
|
||||
Compute the corresponding public key for a private key.
|
||||
|
||||
Inputs:
|
||||
private_key - The private key to compute the public key for
|
||||
|
||||
Outputs:
|
||||
public_key - Will be filled in with the corresponding public key
|
||||
|
||||
Returns 1 if the key was computed successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve);
|
||||
|
||||
/* uECC_sign() function.
|
||||
Generate an ECDSA signature for a given hash value.
|
||||
|
||||
Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to
|
||||
this function along with your private key.
|
||||
|
||||
Inputs:
|
||||
private_key - Your private key.
|
||||
message_hash - The hash of the message to sign.
|
||||
hash_size - The size of message_hash in bytes.
|
||||
|
||||
Outputs:
|
||||
signature - Will be filled in with the signature value. Must be at least 2 * curve size long.
|
||||
For example, if the curve is secp256r1, signature must be 64 bytes long.
|
||||
|
||||
Returns 1 if the signature generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_sign(const uint8_t *private_key,
|
||||
const uint8_t *message_hash,
|
||||
unsigned hash_size,
|
||||
uint8_t *signature,
|
||||
uECC_Curve curve);
|
||||
|
||||
/* uECC_HashContext structure.
|
||||
This is used to pass in an arbitrary hash function to uECC_sign_deterministic().
|
||||
The structure will be used for multiple hash computations; each time a new hash
|
||||
is computed, init_hash() will be called, followed by one or more calls to
|
||||
update_hash(), and finally a call to finish_hash() to produce the resulting hash.
|
||||
|
||||
The intention is that you will create a structure that includes uECC_HashContext
|
||||
followed by any hash-specific data. For example:
|
||||
|
||||
typedef struct SHA256_HashContext {
|
||||
uECC_HashContext uECC;
|
||||
SHA256_CTX ctx;
|
||||
} SHA256_HashContext;
|
||||
|
||||
void init_SHA256(uECC_HashContext *base) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Init(&context->ctx);
|
||||
}
|
||||
|
||||
void update_SHA256(uECC_HashContext *base,
|
||||
const uint8_t *message,
|
||||
unsigned message_size) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Update(&context->ctx, message, message_size);
|
||||
}
|
||||
|
||||
void finish_SHA256(uECC_HashContext *base, uint8_t *hash_result) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Final(hash_result, &context->ctx);
|
||||
}
|
||||
|
||||
... when signing ...
|
||||
{
|
||||
uint8_t tmp[32 + 32 + 64];
|
||||
SHA256_HashContext ctx = {{&init_SHA256, &update_SHA256, &finish_SHA256, 64, 32, tmp}};
|
||||
uECC_sign_deterministic(key, message_hash, &ctx.uECC, signature);
|
||||
}
|
||||
*/
|
||||
typedef struct uECC_HashContext {
|
||||
void (*init_hash)(const struct uECC_HashContext *context);
|
||||
void (*update_hash)(const struct uECC_HashContext *context,
|
||||
const uint8_t *message,
|
||||
unsigned message_size);
|
||||
void (*finish_hash)(const struct uECC_HashContext *context, uint8_t *hash_result);
|
||||
unsigned block_size; /* Hash function block size in bytes, eg 64 for SHA-256. */
|
||||
unsigned result_size; /* Hash function result size in bytes, eg 32 for SHA-256. */
|
||||
uint8_t *tmp; /* Must point to a buffer of at least (2 * result_size + block_size) bytes. */
|
||||
} uECC_HashContext;
|
||||
|
||||
/* uECC_sign_deterministic() function.
|
||||
Generate an ECDSA signature for a given hash value, using a deterministic algorithm
|
||||
(see RFC 6979). You do not need to set the RNG using uECC_set_rng() before calling
|
||||
this function; however, if the RNG is defined it will improve resistance to side-channel
|
||||
attacks.
|
||||
|
||||
Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it to
|
||||
this function along with your private key and a hash context. Note that the message_hash
|
||||
does not need to be computed with the same hash function used by hash_context.
|
||||
|
||||
Inputs:
|
||||
private_key - Your private key.
|
||||
message_hash - The hash of the message to sign.
|
||||
hash_size - The size of message_hash in bytes.
|
||||
hash_context - A hash context to use.
|
||||
|
||||
Outputs:
|
||||
signature - Will be filled in with the signature value.
|
||||
|
||||
Returns 1 if the signature generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_sign_deterministic(const uint8_t *private_key,
|
||||
const uint8_t *message_hash,
|
||||
unsigned hash_size,
|
||||
const uECC_HashContext *hash_context,
|
||||
uint8_t *signature,
|
||||
uECC_Curve curve);
|
||||
|
||||
/* uECC_verify() function.
|
||||
Verify an ECDSA signature.
|
||||
|
||||
Usage: Compute the hash of the signed data using the same hash as the signer and
|
||||
pass it to this function along with the signer's public key and the signature values (r and s).
|
||||
|
||||
Inputs:
|
||||
public_key - The signer's public key.
|
||||
message_hash - The hash of the signed data.
|
||||
hash_size - The size of message_hash in bytes.
|
||||
signature - The signature value.
|
||||
|
||||
Returns 1 if the signature is valid, 0 if it is invalid.
|
||||
*/
|
||||
int uECC_verify(const uint8_t *public_key,
|
||||
const uint8_t *message_hash,
|
||||
unsigned hash_size,
|
||||
const uint8_t *signature,
|
||||
uECC_Curve curve);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _UECC_H_ */
|
172
core/embed/ble_bootloader/uecc/uECC_vli.h
Normal file
172
core/embed/ble_bootloader/uecc/uECC_vli.h
Normal file
@ -0,0 +1,172 @@
|
||||
/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_VLI_H_
|
||||
#define _UECC_VLI_H_
|
||||
|
||||
#include "uECC.h"
|
||||
#include "types.h"
|
||||
|
||||
/* Functions for raw large-integer manipulation. These are only available
|
||||
if uECC.c is compiled with uECC_ENABLE_VLI_API defined to 1. */
|
||||
#ifndef uECC_ENABLE_VLI_API
|
||||
#define uECC_ENABLE_VLI_API 0
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#if uECC_ENABLE_VLI_API
|
||||
|
||||
void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words);
|
||||
|
||||
/* Constant-time comparison to zero - secure way to compare long integers */
|
||||
/* Returns 1 if vli == 0, 0 otherwise. */
|
||||
uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words);
|
||||
|
||||
/* Returns nonzero if bit 'bit' of vli is set. */
|
||||
uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit);
|
||||
|
||||
/* Counts the number of bits required to represent vli. */
|
||||
bitcount_t uECC_vli_numBits(const uECC_word_t *vli, const wordcount_t max_words);
|
||||
|
||||
/* Sets dest = src. */
|
||||
void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words);
|
||||
|
||||
/* Constant-time comparison function - secure way to compare long integers */
|
||||
/* Returns one if left == right, zero otherwise */
|
||||
uECC_word_t uECC_vli_equal(const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Constant-time comparison function - secure way to compare long integers */
|
||||
/* Returns sign of left - right, in constant time. */
|
||||
cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, wordcount_t num_words);
|
||||
|
||||
/* Computes vli = vli >> 1. */
|
||||
void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words);
|
||||
|
||||
/* Computes result = left + right, returning carry. Can modify in place. */
|
||||
uECC_word_t uECC_vli_add(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = left - right, returning borrow. Can modify in place. */
|
||||
uECC_word_t uECC_vli_sub(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = left * right. Result must be 2 * num_words long. */
|
||||
void uECC_vli_mult(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = left^2. Result must be 2 * num_words long. */
|
||||
void uECC_vli_square(uECC_word_t *result, const uECC_word_t *left, wordcount_t num_words);
|
||||
|
||||
/* Computes result = (left + right) % mod.
|
||||
Assumes that left < mod and right < mod, and that result does not overlap mod. */
|
||||
void uECC_vli_modAdd(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = (left - right) % mod.
|
||||
Assumes that left < mod and right < mod, and that result does not overlap mod. */
|
||||
void uECC_vli_modSub(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = product % mod, where product is 2N words long.
|
||||
Currently only designed to work for mod == curve->p or curve_n. */
|
||||
void uECC_vli_mmod(uECC_word_t *result,
|
||||
uECC_word_t *product,
|
||||
const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Calculates result = product (mod curve->p), where product is up to
|
||||
2 * curve->num_words long. */
|
||||
void uECC_vli_mmod_fast(uECC_word_t *result, uECC_word_t *product, uECC_Curve curve);
|
||||
|
||||
/* Computes result = (left * right) % mod.
|
||||
Currently only designed to work for mod == curve->p or curve_n. */
|
||||
void uECC_vli_modMult(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = (left * right) % curve->p. */
|
||||
void uECC_vli_modMult_fast(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
uECC_Curve curve);
|
||||
|
||||
/* Computes result = left^2 % mod.
|
||||
Currently only designed to work for mod == curve->p or curve_n. */
|
||||
void uECC_vli_modSquare(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/* Computes result = left^2 % curve->p. */
|
||||
void uECC_vli_modSquare_fast(uECC_word_t *result, const uECC_word_t *left, uECC_Curve curve);
|
||||
|
||||
/* Computes result = (1 / input) % mod.*/
|
||||
void uECC_vli_modInv(uECC_word_t *result,
|
||||
const uECC_word_t *input,
|
||||
const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
#if uECC_SUPPORT_COMPRESSED_POINT
|
||||
/* Calculates a = sqrt(a) (mod curve->p) */
|
||||
void uECC_vli_mod_sqrt(uECC_word_t *a, uECC_Curve curve);
|
||||
#endif
|
||||
|
||||
/* Converts an integer in uECC native format to big-endian bytes. */
|
||||
void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, const uECC_word_t *native);
|
||||
/* Converts big-endian bytes to an integer in uECC native format. */
|
||||
void uECC_vli_bytesToNative(uECC_word_t *native, const uint8_t *bytes, int num_bytes);
|
||||
|
||||
unsigned uECC_curve_num_words(uECC_Curve curve);
|
||||
unsigned uECC_curve_num_bytes(uECC_Curve curve);
|
||||
unsigned uECC_curve_num_bits(uECC_Curve curve);
|
||||
unsigned uECC_curve_num_n_words(uECC_Curve curve);
|
||||
unsigned uECC_curve_num_n_bytes(uECC_Curve curve);
|
||||
unsigned uECC_curve_num_n_bits(uECC_Curve curve);
|
||||
|
||||
const uECC_word_t *uECC_curve_p(uECC_Curve curve);
|
||||
const uECC_word_t *uECC_curve_n(uECC_Curve curve);
|
||||
const uECC_word_t *uECC_curve_G(uECC_Curve curve);
|
||||
const uECC_word_t *uECC_curve_b(uECC_Curve curve);
|
||||
|
||||
int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve);
|
||||
|
||||
/* Multiplies a point by a scalar. Points are represented by the X coordinate followed by
|
||||
the Y coordinate in the same array, both coordinates are curve->num_words long. Note
|
||||
that scalar must be curve->num_n_words long (NOT curve->num_words). */
|
||||
void uECC_point_mult(uECC_word_t *result,
|
||||
const uECC_word_t *point,
|
||||
const uECC_word_t *scalar,
|
||||
uECC_Curve curve);
|
||||
|
||||
/* Generates a random integer in the range 0 < random < top.
|
||||
Both random and top have num_words words. */
|
||||
int uECC_generate_random_int(uECC_word_t *random,
|
||||
const uECC_word_t *top,
|
||||
wordcount_t num_words);
|
||||
|
||||
#endif /* uECC_ENABLE_VLI_API */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _UECC_VLI_H_ */
|
4
core/embed/ble_bootloader/version.h
Normal file
4
core/embed/ble_bootloader/version.h
Normal file
@ -0,0 +1,4 @@
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 0
|
203
core/embed/ble_firmware/advertising.c
Normal file
203
core/embed/ble_firmware/advertising.c
Normal file
@ -0,0 +1,203 @@
|
||||
#include "ble_gap.h"
|
||||
|
||||
#include "advertising.h"
|
||||
#include "ble_advdata.h"
|
||||
#include "ble_advertising.h"
|
||||
#include "ble_nus.h"
|
||||
#include "connection.h"
|
||||
#include "defs.h"
|
||||
#include "int_comm.h"
|
||||
#include "nrf_log.h"
|
||||
#include "pm.h"
|
||||
#include "power.h"
|
||||
|
||||
#define APP_ADV_INTERVAL \
|
||||
64 /**< The advertising interval (in units of 0.625 ms. This value \
|
||||
corresponds to 40 ms). */
|
||||
|
||||
#define APP_ADV_DURATION \
|
||||
18000 /**< The advertising duration (180 seconds) in units of 10 \
|
||||
milliseconds. */
|
||||
|
||||
#define NUS_SERVICE_UUID_TYPE \
|
||||
BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service \
|
||||
(vendor specific). */
|
||||
|
||||
static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */
|
||||
{{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}};
|
||||
|
||||
BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */
|
||||
|
||||
/**@brief Function for handling advertising events.
|
||||
*
|
||||
* @details This function will be called for advertising events which are passed
|
||||
* to the application.
|
||||
*
|
||||
* @param[in] ble_adv_evt Advertising event.
|
||||
*/
|
||||
static void on_adv_evt(ble_adv_evt_t ble_adv_evt) {
|
||||
uint32_t err_code;
|
||||
|
||||
switch (ble_adv_evt) {
|
||||
case BLE_ADV_EVT_DIRECTED_HIGH_DUTY:
|
||||
NRF_LOG_INFO("High Duty Directed advertising.");
|
||||
send_status_event();
|
||||
break;
|
||||
|
||||
case BLE_ADV_EVT_DIRECTED:
|
||||
NRF_LOG_INFO("Directed advertising.");
|
||||
send_status_event();
|
||||
break;
|
||||
|
||||
case BLE_ADV_EVT_FAST:
|
||||
NRF_LOG_INFO("Fast advertising.");
|
||||
send_status_event();
|
||||
break;
|
||||
|
||||
case BLE_ADV_EVT_SLOW:
|
||||
NRF_LOG_INFO("Slow advertising.");
|
||||
send_status_event();
|
||||
break;
|
||||
|
||||
case BLE_ADV_EVT_FAST_WHITELIST:
|
||||
NRF_LOG_INFO("Fast advertising with whitelist.");
|
||||
send_status_event();
|
||||
break;
|
||||
|
||||
case BLE_ADV_EVT_SLOW_WHITELIST:
|
||||
NRF_LOG_INFO("Slow advertising with whitelist.");
|
||||
send_status_event();
|
||||
break;
|
||||
|
||||
case BLE_ADV_EVT_IDLE:
|
||||
send_status_event();
|
||||
// sleep_mode_enter();
|
||||
break;
|
||||
|
||||
case BLE_ADV_EVT_WHITELIST_REQUEST: {
|
||||
ble_gap_addr_t whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT];
|
||||
ble_gap_irk_t whitelist_irks[BLE_GAP_WHITELIST_ADDR_MAX_COUNT];
|
||||
uint32_t addr_cnt = BLE_GAP_WHITELIST_ADDR_MAX_COUNT;
|
||||
uint32_t irk_cnt = BLE_GAP_WHITELIST_ADDR_MAX_COUNT;
|
||||
|
||||
err_code = pm_whitelist_get(whitelist_addrs, &addr_cnt, whitelist_irks,
|
||||
&irk_cnt);
|
||||
if (err_code != NRF_ERROR_NOT_FOUND) {
|
||||
APP_ERROR_CHECK(err_code);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
NRF_LOG_DEBUG(
|
||||
"pm_whitelist_get returns %d addr in whitelist and %d irk whitelist",
|
||||
addr_cnt, irk_cnt);
|
||||
|
||||
// Set the correct identities list (no excluding peers with no Central
|
||||
// Address Resolution).
|
||||
identities_set(PM_PEER_ID_LIST_SKIP_NO_IRK);
|
||||
|
||||
// Apply the whitelist.
|
||||
err_code = ble_advertising_whitelist_reply(
|
||||
&m_advertising, whitelist_addrs, addr_cnt, whitelist_irks, irk_cnt);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
} break; // BLE_ADV_EVT_WHITELIST_REQUEST
|
||||
|
||||
case BLE_ADV_EVT_PEER_ADDR_REQUEST: {
|
||||
pm_peer_data_bonding_t peer_bonding_data;
|
||||
|
||||
// Only Give peer address if we have a handle to the bonded peer.
|
||||
if (get_peer_id() != PM_PEER_ID_INVALID) {
|
||||
err_code = pm_peer_data_bonding_load(get_peer_id(), &peer_bonding_data);
|
||||
if (err_code != NRF_ERROR_NOT_FOUND) {
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
// Manipulate identities to exclude peers with no Central Address
|
||||
// Resolution.
|
||||
identities_set(PM_PEER_ID_LIST_SKIP_ALL);
|
||||
|
||||
ble_gap_addr_t *p_peer_addr =
|
||||
&(peer_bonding_data.peer_ble_id.id_addr_info);
|
||||
err_code =
|
||||
ble_advertising_peer_addr_reply(&m_advertising, p_peer_addr);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
}
|
||||
} break; // BLE_ADV_EVT_PEER_ADDR_REQUEST
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void advertising_init(void) {
|
||||
uint32_t err_code;
|
||||
uint8_t adv_flags;
|
||||
ble_advertising_init_t init;
|
||||
|
||||
memset(&init, 0, sizeof(init));
|
||||
|
||||
adv_flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
|
||||
init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
|
||||
init.advdata.include_appearance = false;
|
||||
init.advdata.flags = adv_flags;
|
||||
init.advdata.uuids_complete.uuid_cnt = 0;
|
||||
init.advdata.uuids_complete.p_uuids = NULL;
|
||||
|
||||
init.config.ble_adv_whitelist_enabled = true;
|
||||
init.config.ble_adv_directed_high_duty_enabled = true;
|
||||
init.config.ble_adv_directed_enabled = false;
|
||||
init.config.ble_adv_directed_interval = 0;
|
||||
init.config.ble_adv_directed_timeout = 0;
|
||||
init.config.ble_adv_fast_enabled = true;
|
||||
init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
|
||||
init.config.ble_adv_fast_timeout = APP_ADV_DURATION;
|
||||
|
||||
init.evt_handler = on_adv_evt;
|
||||
|
||||
init.srdata.uuids_more_available.uuid_cnt =
|
||||
sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
|
||||
init.srdata.uuids_more_available.p_uuids = m_adv_uuids;
|
||||
|
||||
err_code = ble_advertising_init(&m_advertising, &init);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
|
||||
}
|
||||
|
||||
void advertising_start(bool whitelist) {
|
||||
m_advertising.adv_modes_config.ble_adv_on_disconnect_disabled = false;
|
||||
|
||||
if (m_advertising.adv_mode_current != BLE_ADV_MODE_DIRECTED_HIGH_DUTY) {
|
||||
if (m_advertising.adv_mode_current != BLE_ADV_MODE_FAST &&
|
||||
get_connection_handle() == BLE_CONN_HANDLE_INVALID) {
|
||||
whitelist_set(PM_PEER_ID_LIST_SKIP_NO_ID_ADDR);
|
||||
|
||||
ret_code_t ret = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
|
||||
APP_ERROR_CHECK(ret);
|
||||
}
|
||||
|
||||
if (!whitelist) {
|
||||
ret_code_t ret =
|
||||
ble_advertising_restart_without_whitelist(&m_advertising);
|
||||
APP_ERROR_CHECK(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void advertising_stop(void) {
|
||||
m_advertising.adv_modes_config.ble_adv_on_disconnect_disabled = true;
|
||||
ret_code_t ret = ble_advertising_start(&m_advertising, BLE_ADV_MODE_IDLE);
|
||||
APP_ERROR_CHECK(ret);
|
||||
// ret =sd_ble_gap_disconnect(get_connection_handle(),
|
||||
// BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(ret);
|
||||
}
|
||||
|
||||
void advertising_restart_without_whitelist(void) {
|
||||
ret_code_t ret = ble_advertising_restart_without_whitelist(&m_advertising);
|
||||
APP_ERROR_CHECK(ret);
|
||||
}
|
||||
|
||||
bool is_advertising(void) {
|
||||
return m_advertising.adv_mode_current != BLE_ADV_MODE_IDLE;
|
||||
}
|
||||
|
||||
bool is_advertising_wl(void) { return m_advertising.whitelist_in_use; }
|
18
core/embed/ble_firmware/advertising.h
Normal file
18
core/embed/ble_firmware/advertising.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef __ADVERTISING__
|
||||
#define __ADVERTISING__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
void advertising_init(void);
|
||||
|
||||
void advertising_start(bool whitelist);
|
||||
|
||||
void advertising_stop(void);
|
||||
|
||||
void advertising_restart_without_whitelist(void);
|
||||
|
||||
bool is_advertising(void);
|
||||
|
||||
bool is_advertising_wl(void);
|
||||
|
||||
#endif
|
356
core/embed/ble_firmware/ble_nus.c
Normal file
356
core/embed/ble_firmware/ble_nus.c
Normal file
@ -0,0 +1,356 @@
|
||||
// clang-format off
|
||||
|
||||
/**
|
||||
* Copyright (c) 2012 - 2021, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include "sdk_common.h"
|
||||
#if NRF_MODULE_ENABLED(BLE_NUS)
|
||||
#include "ble.h"
|
||||
#include "ble_nus.h"
|
||||
#include "ble_srv_common.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME ble_nus
|
||||
#if BLE_NUS_CONFIG_LOG_ENABLED
|
||||
#define NRF_LOG_LEVEL BLE_NUS_CONFIG_LOG_LEVEL
|
||||
#define NRF_LOG_INFO_COLOR BLE_NUS_CONFIG_INFO_COLOR
|
||||
#define NRF_LOG_DEBUG_COLOR BLE_NUS_CONFIG_DEBUG_COLOR
|
||||
#else // BLE_NUS_CONFIG_LOG_ENABLED
|
||||
#define NRF_LOG_LEVEL 0
|
||||
#endif // BLE_NUS_CONFIG_LOG_ENABLED
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
|
||||
#define BLE_UUID_NUS_TX_CHARACTERISTIC 0x0003 /**< The UUID of the TX Characteristic. */
|
||||
#define BLE_UUID_NUS_RX_CHARACTERISTIC 0x0002 /**< The UUID of the RX Characteristic. */
|
||||
|
||||
#define BLE_NUS_MAX_RX_CHAR_LEN BLE_NUS_MAX_DATA_LEN /**< Maximum length of the RX Characteristic (in bytes). */
|
||||
#define BLE_NUS_MAX_TX_CHAR_LEN BLE_NUS_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */
|
||||
|
||||
#define NUS_BASE_UUID {{0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E}} /**< Used vendor specific UUID. */
|
||||
|
||||
|
||||
/**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the SoftDevice.
|
||||
*
|
||||
* @param[in] p_nus Nordic UART Service structure.
|
||||
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
|
||||
*/
|
||||
static void on_connect(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
ble_nus_evt_t evt;
|
||||
ble_gatts_value_t gatts_val;
|
||||
uint8_t cccd_value[2];
|
||||
ble_nus_client_context_t * p_client = NULL;
|
||||
|
||||
err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage,
|
||||
p_ble_evt->evt.gap_evt.conn_handle,
|
||||
(void *) &p_client);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
|
||||
p_ble_evt->evt.gap_evt.conn_handle);
|
||||
}
|
||||
|
||||
/* Check the hosts CCCD value to inform of readiness to send data using the RX characteristic */
|
||||
memset(&gatts_val, 0, sizeof(ble_gatts_value_t));
|
||||
gatts_val.p_value = cccd_value;
|
||||
gatts_val.len = sizeof(cccd_value);
|
||||
gatts_val.offset = 0;
|
||||
|
||||
err_code = sd_ble_gatts_value_get(p_ble_evt->evt.gap_evt.conn_handle,
|
||||
p_nus->tx_handles.cccd_handle,
|
||||
&gatts_val);
|
||||
|
||||
if ((err_code == NRF_SUCCESS) &&
|
||||
(p_nus->data_handler != NULL) &&
|
||||
ble_srv_is_notification_enabled(gatts_val.p_value))
|
||||
{
|
||||
if (p_client != NULL)
|
||||
{
|
||||
p_client->is_notification_enabled = true;
|
||||
}
|
||||
|
||||
memset(&evt, 0, sizeof(ble_nus_evt_t));
|
||||
evt.type = BLE_NUS_EVT_COMM_STARTED;
|
||||
evt.p_nus = p_nus;
|
||||
evt.conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
|
||||
evt.p_link_ctx = p_client;
|
||||
|
||||
p_nus->data_handler(&evt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the SoftDevice.
|
||||
*
|
||||
* @param[in] p_nus Nordic UART Service structure.
|
||||
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
|
||||
*/
|
||||
static void on_write(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
ble_nus_evt_t evt;
|
||||
ble_nus_client_context_t * p_client;
|
||||
ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
|
||||
|
||||
err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage,
|
||||
p_ble_evt->evt.gatts_evt.conn_handle,
|
||||
(void *) &p_client);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
|
||||
p_ble_evt->evt.gatts_evt.conn_handle);
|
||||
}
|
||||
|
||||
memset(&evt, 0, sizeof(ble_nus_evt_t));
|
||||
evt.p_nus = p_nus;
|
||||
evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
|
||||
evt.p_link_ctx = p_client;
|
||||
|
||||
if ((p_evt_write->handle == p_nus->tx_handles.cccd_handle) &&
|
||||
(p_evt_write->len == 2))
|
||||
{
|
||||
if (p_client != NULL)
|
||||
{
|
||||
if (ble_srv_is_notification_enabled(p_evt_write->data))
|
||||
{
|
||||
p_client->is_notification_enabled = true;
|
||||
evt.type = BLE_NUS_EVT_COMM_STARTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_client->is_notification_enabled = false;
|
||||
evt.type = BLE_NUS_EVT_COMM_STOPPED;
|
||||
}
|
||||
|
||||
if (p_nus->data_handler != NULL)
|
||||
{
|
||||
p_nus->data_handler(&evt);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if ((p_evt_write->handle == p_nus->rx_handles.value_handle) &&
|
||||
(p_nus->data_handler != NULL))
|
||||
{
|
||||
evt.type = BLE_NUS_EVT_RX_DATA;
|
||||
evt.params.rx_data.p_data = p_evt_write->data;
|
||||
evt.params.rx_data.length = p_evt_write->len;
|
||||
|
||||
p_nus->data_handler(&evt);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do Nothing. This event is not relevant for this service.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling the @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event from the SoftDevice.
|
||||
*
|
||||
* @param[in] p_nus Nordic UART Service structure.
|
||||
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
|
||||
*/
|
||||
static void on_hvx_tx_complete(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
ble_nus_evt_t evt;
|
||||
ble_nus_client_context_t * p_client;
|
||||
|
||||
err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage,
|
||||
p_ble_evt->evt.gatts_evt.conn_handle,
|
||||
(void *) &p_client);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
|
||||
p_ble_evt->evt.gatts_evt.conn_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((p_client->is_notification_enabled) && (p_nus->data_handler != NULL))
|
||||
{
|
||||
memset(&evt, 0, sizeof(ble_nus_evt_t));
|
||||
evt.type = BLE_NUS_EVT_TX_RDY;
|
||||
evt.p_nus = p_nus;
|
||||
evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
|
||||
evt.p_link_ctx = p_client;
|
||||
|
||||
p_nus->data_handler(&evt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ble_nus_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
|
||||
{
|
||||
if ((p_context == NULL) || (p_ble_evt == NULL))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ble_nus_t * p_nus = (ble_nus_t *)p_context;
|
||||
|
||||
switch (p_ble_evt->header.evt_id)
|
||||
{
|
||||
case BLE_GAP_EVT_CONNECTED:
|
||||
on_connect(p_nus, p_ble_evt);
|
||||
break;
|
||||
|
||||
case BLE_GATTS_EVT_WRITE:
|
||||
on_write(p_nus, p_ble_evt);
|
||||
break;
|
||||
|
||||
case BLE_GATTS_EVT_HVN_TX_COMPLETE:
|
||||
on_hvx_tx_complete(p_nus, p_ble_evt);
|
||||
break;
|
||||
|
||||
default:
|
||||
// No implementation needed.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
ble_uuid_t ble_uuid;
|
||||
ble_uuid128_t nus_base_uuid = NUS_BASE_UUID;
|
||||
ble_add_char_params_t add_char_params;
|
||||
|
||||
VERIFY_PARAM_NOT_NULL(p_nus);
|
||||
VERIFY_PARAM_NOT_NULL(p_nus_init);
|
||||
|
||||
// Initialize the service structure.
|
||||
p_nus->data_handler = p_nus_init->data_handler;
|
||||
|
||||
/**@snippet [Adding proprietary Service to the SoftDevice] */
|
||||
// Add a custom base UUID.
|
||||
err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type);
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
ble_uuid.type = p_nus->uuid_type;
|
||||
ble_uuid.uuid = BLE_UUID_NUS_SERVICE;
|
||||
|
||||
// Add the service.
|
||||
err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
|
||||
&ble_uuid,
|
||||
&p_nus->service_handle);
|
||||
/**@snippet [Adding proprietary Service to the SoftDevice] */
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
// Add the RX Characteristic.
|
||||
memset(&add_char_params, 0, sizeof(add_char_params));
|
||||
add_char_params.uuid = BLE_UUID_NUS_RX_CHARACTERISTIC;
|
||||
add_char_params.uuid_type = p_nus->uuid_type;
|
||||
add_char_params.max_len = BLE_NUS_MAX_RX_CHAR_LEN;
|
||||
add_char_params.init_len = sizeof(uint8_t);
|
||||
add_char_params.is_var_len = true;
|
||||
add_char_params.char_props.write = 1;
|
||||
add_char_params.char_props.write_wo_resp = 1;
|
||||
|
||||
add_char_params.read_access = SEC_MITM;
|
||||
add_char_params.write_access = SEC_MITM;
|
||||
|
||||
err_code = characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->rx_handles);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
return err_code;
|
||||
}
|
||||
|
||||
// Add the TX Characteristic.
|
||||
/**@snippet [Adding proprietary characteristic to the SoftDevice] */
|
||||
memset(&add_char_params, 0, sizeof(add_char_params));
|
||||
add_char_params.uuid = BLE_UUID_NUS_TX_CHARACTERISTIC;
|
||||
add_char_params.uuid_type = p_nus->uuid_type;
|
||||
add_char_params.max_len = BLE_NUS_MAX_TX_CHAR_LEN;
|
||||
add_char_params.init_len = sizeof(uint8_t);
|
||||
add_char_params.is_var_len = true;
|
||||
add_char_params.char_props.notify = 1;
|
||||
|
||||
add_char_params.read_access = SEC_MITM;
|
||||
add_char_params.write_access = SEC_MITM;
|
||||
add_char_params.cccd_write_access = SEC_MITM;
|
||||
|
||||
return characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->tx_handles);
|
||||
/**@snippet [Adding proprietary characteristic to the SoftDevice] */
|
||||
}
|
||||
|
||||
|
||||
uint32_t ble_nus_data_send(ble_nus_t * p_nus,
|
||||
uint8_t * p_data,
|
||||
uint16_t * p_length,
|
||||
uint16_t conn_handle)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
ble_gatts_hvx_params_t hvx_params;
|
||||
ble_nus_client_context_t * p_client;
|
||||
|
||||
VERIFY_PARAM_NOT_NULL(p_nus);
|
||||
|
||||
err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, conn_handle, (void *) &p_client);
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
if ((conn_handle == BLE_CONN_HANDLE_INVALID) || (p_client == NULL))
|
||||
{
|
||||
return NRF_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (!p_client->is_notification_enabled)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (*p_length > BLE_NUS_MAX_DATA_LEN)
|
||||
{
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
memset(&hvx_params, 0, sizeof(hvx_params));
|
||||
|
||||
hvx_params.handle = p_nus->tx_handles.value_handle;
|
||||
hvx_params.p_data = p_data;
|
||||
hvx_params.p_len = p_length;
|
||||
hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
|
||||
|
||||
return sd_ble_gatts_hvx(conn_handle, &hvx_params);
|
||||
}
|
||||
|
||||
|
||||
#endif // NRF_MODULE_ENABLED(BLE_NUS)
|
17
core/embed/ble_firmware/connection.c
Normal file
17
core/embed/ble_firmware/connection.c
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
#include "ble_gap.h"
|
||||
|
||||
#include "connection.h"
|
||||
|
||||
static uint16_t m_conn_handle =
|
||||
BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */
|
||||
|
||||
void set_connection_handle(uint16_t val) { m_conn_handle = val; }
|
||||
uint16_t get_connection_handle(void) { return m_conn_handle; }
|
||||
|
||||
void disconnect(void) {
|
||||
if (m_conn_handle != BLE_CONN_HANDLE_INVALID) {
|
||||
sd_ble_gap_disconnect(m_conn_handle,
|
||||
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
|
||||
}
|
||||
}
|
11
core/embed/ble_firmware/connection.h
Normal file
11
core/embed/ble_firmware/connection.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef BLE_CONNECTION_H__
|
||||
#define BLE_CONNECTION_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void set_connection_handle(uint16_t val);
|
||||
uint16_t get_connection_handle(void);
|
||||
|
||||
void disconnect(void);
|
||||
|
||||
#endif
|
3
core/embed/ble_firmware/defs.h
Normal file
3
core/embed/ble_firmware/defs.h
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
#define APP_BLE_CONN_CFG_TAG \
|
||||
1 /**< A tag identifying the SoftDevice BLE configuration. */
|
23
core/embed/ble_firmware/dis.c
Normal file
23
core/embed/ble_firmware/dis.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include "dis.h"
|
||||
#include <string.h>
|
||||
#include "app_error.h"
|
||||
#include "ble_dis.h"
|
||||
#include "sdk_errors.h"
|
||||
|
||||
#define MANUFACTURER_NAME \
|
||||
"SatoshiLabs" /**< Manufacturer. Will be passed to Device Information \
|
||||
Service. */
|
||||
|
||||
void dis_init(void) {
|
||||
ret_code_t err_code;
|
||||
ble_dis_init_t dis_init_obj;
|
||||
|
||||
memset(&dis_init_obj, 0, sizeof(dis_init_obj));
|
||||
|
||||
ble_srv_ascii_to_utf8(&dis_init_obj.manufact_name_str, MANUFACTURER_NAME);
|
||||
|
||||
dis_init_obj.dis_char_rd_sec = SEC_JUST_WORKS;
|
||||
|
||||
err_code = ble_dis_init(&dis_init_obj);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
6
core/embed/ble_firmware/dis.h
Normal file
6
core/embed/ble_firmware/dis.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef __DIS__
|
||||
#define __DIS__
|
||||
|
||||
void dis_init(void);
|
||||
|
||||
#endif
|
458
core/embed/ble_firmware/int_comm.c
Normal file
458
core/embed/ble_firmware/int_comm.c
Normal file
@ -0,0 +1,458 @@
|
||||
#include "int_comm.h"
|
||||
#include "advertising.h"
|
||||
#include "app_error.h"
|
||||
#include "app_uart.h"
|
||||
#include "ble/int_comm_defs.h"
|
||||
#include "ble_advertising.h"
|
||||
#include "ble_nus.h"
|
||||
#include "connection.h"
|
||||
#include "messages.pb.h"
|
||||
#include "nrf_drv_spi.h"
|
||||
#include "nrf_log.h"
|
||||
#include "pm.h"
|
||||
#include "protob_helpers.h"
|
||||
#include "stdint.h"
|
||||
#include "trezor_t3w1_d1_NRF.h"
|
||||
|
||||
#define SPI_INSTANCE 0 /**< SPI instance index. */
|
||||
|
||||
static uint8_t m_uart_rx_data[BLE_NUS_MAX_DATA_LEN];
|
||||
static uint8_t m_spi_tx_data[BLE_PACKET_SIZE];
|
||||
static bool m_uart_rx_data_ready_internal = false;
|
||||
|
||||
BLE_NUS_DEF(m_nus,
|
||||
NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE NUS service instance. */
|
||||
|
||||
static const nrf_drv_spi_t spi =
|
||||
NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); /**< SPI instance. */
|
||||
static volatile bool spi_xfer_done = true; /**< Flag used to indicate that SPI
|
||||
instance completed the transfer. */
|
||||
|
||||
/**
|
||||
* @brief SPI user event handler.
|
||||
* @param event
|
||||
*/
|
||||
void spi_event_handler(nrf_drv_spi_evt_t const *p_event, void *p_context) {
|
||||
spi_xfer_done = true;
|
||||
NRF_LOG_INFO("Transfer completed.");
|
||||
}
|
||||
|
||||
void spi_init(void) {
|
||||
nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
|
||||
spi_config.ss_pin = SPI_SS_PIN;
|
||||
spi_config.miso_pin = SPI_MISO_PIN;
|
||||
spi_config.mosi_pin = SPI_MOSI_PIN;
|
||||
spi_config.sck_pin = SPI_SCK_PIN;
|
||||
spi_config.frequency = NRF_DRV_SPI_FREQ_8M;
|
||||
APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
|
||||
}
|
||||
|
||||
void nus_init() {
|
||||
uint32_t err_code;
|
||||
|
||||
ble_nus_init_t nus_init;
|
||||
|
||||
memset(&nus_init, 0, sizeof(nus_init));
|
||||
|
||||
nus_init.data_handler = nus_data_handler;
|
||||
|
||||
err_code = ble_nus_init(&m_nus, &nus_init);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
void send_byte(uint8_t byte) {
|
||||
uint32_t err_code;
|
||||
|
||||
do {
|
||||
err_code = app_uart_put(byte);
|
||||
if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) {
|
||||
NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code);
|
||||
}
|
||||
} while (err_code == NRF_ERROR_BUSY);
|
||||
}
|
||||
|
||||
void send_packet(uint8_t message_type, const uint8_t *tx_data, uint16_t len) {
|
||||
uint16_t total_len = len + OVERHEAD_SIZE;
|
||||
send_byte(message_type);
|
||||
send_byte((total_len >> 8) & 0xFF);
|
||||
send_byte(total_len & 0xFF);
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
send_byte(tx_data[i]);
|
||||
}
|
||||
send_byte(EOM);
|
||||
}
|
||||
|
||||
bool write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) {
|
||||
write_state *state = (write_state *)(stream->state);
|
||||
|
||||
size_t written = 0;
|
||||
// while we have data left
|
||||
while (written < count) {
|
||||
size_t remaining = count - written;
|
||||
// if all remaining data fit into our packet
|
||||
if (state->packet_pos + remaining <= USB_PACKET_SIZE) {
|
||||
// append data from buf to state->buf
|
||||
memcpy(state->buf + state->packet_pos, buf + written, remaining);
|
||||
// advance position
|
||||
state->packet_pos += remaining;
|
||||
// and return
|
||||
return true;
|
||||
} else {
|
||||
// append data that fits
|
||||
memcpy(state->buf + state->packet_pos, buf + written,
|
||||
USB_PACKET_SIZE - state->packet_pos);
|
||||
written += USB_PACKET_SIZE - state->packet_pos;
|
||||
|
||||
// send packet
|
||||
send_packet(state->iface_num, state->buf, USB_PACKET_SIZE);
|
||||
|
||||
// prepare new packet
|
||||
state->packet_index++;
|
||||
memset(state->buf, 0, USB_PACKET_SIZE);
|
||||
state->buf[0] = '?';
|
||||
state->packet_pos = MSG_HEADER2_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
void write_flush(write_state *state) {
|
||||
// if packet is not filled up completely
|
||||
if (state->packet_pos < USB_PACKET_SIZE) {
|
||||
// pad it with zeroes
|
||||
memset(state->buf + state->packet_pos, 0,
|
||||
USB_PACKET_SIZE - state->packet_pos);
|
||||
}
|
||||
// send packet
|
||||
send_packet(state->iface_num, state->buf, USB_PACKET_SIZE);
|
||||
}
|
||||
|
||||
/* we don't use secbool/sectrue/secfalse here as it is a nanopb api */
|
||||
static bool read(pb_istream_t *stream, uint8_t *buf, size_t count) {
|
||||
read_state *state = (read_state *)(stream->state);
|
||||
|
||||
size_t read = 0;
|
||||
// while we have data left
|
||||
while (read < count) {
|
||||
size_t remaining = count - read;
|
||||
// if all remaining data fit into our packet
|
||||
if (state->packet_pos + remaining <= state->packet_size) {
|
||||
// append data from buf to state->buf
|
||||
memcpy(buf + read, state->buf + state->packet_pos, remaining);
|
||||
// advance position
|
||||
state->packet_pos += remaining;
|
||||
// and return
|
||||
return true;
|
||||
} else {
|
||||
// append data that fits
|
||||
memcpy(buf + read, state->buf + state->packet_pos,
|
||||
state->packet_size - state->packet_pos);
|
||||
read += state->packet_size - state->packet_pos;
|
||||
// read next packet
|
||||
|
||||
while (!m_uart_rx_data_ready_internal)
|
||||
;
|
||||
m_uart_rx_data_ready_internal = false;
|
||||
memcpy(state->buf, m_uart_rx_data, USB_PACKET_SIZE);
|
||||
|
||||
// prepare next packet
|
||||
state->packet_index++;
|
||||
state->packet_pos = MSG_HEADER2_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void read_flush(read_state *state) { (void)state; }
|
||||
|
||||
#define MSG_SEND_NRF(msg) (MSG_SEND(msg, write, write_flush))
|
||||
|
||||
void process_command(uint8_t *data, uint16_t len) {
|
||||
uint8_t cmd = data[0];
|
||||
switch (cmd) {
|
||||
case INTERNAL_CMD_SEND_STATE:
|
||||
send_status_event();
|
||||
break;
|
||||
case INTERNAL_CMD_ADVERTISING_ON:
|
||||
advertising_start(data[1] != 0);
|
||||
send_status_event();
|
||||
break;
|
||||
case INTERNAL_CMD_ADVERTISING_OFF:
|
||||
advertising_stop();
|
||||
send_status_event();
|
||||
break;
|
||||
case INTERNAL_CMD_ERASE_BONDS:
|
||||
delete_bonds();
|
||||
send_success_event();
|
||||
break;
|
||||
case INTERNAL_CMD_DISCONNECT:
|
||||
disconnect();
|
||||
send_success_event();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
secbool process_auth_key(uint8_t *data, uint32_t len, void *msg) {
|
||||
recv_protob_msg(INTERNAL_MESSAGE, len, data, AuthKey_fields, msg, read,
|
||||
read_flush, USB_PACKET_SIZE);
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool process_success(uint8_t *data, uint32_t len, void *msg) {
|
||||
recv_protob_msg(INTERNAL_MESSAGE, len, data, Success_fields, msg, read,
|
||||
read_flush, USB_PACKET_SIZE);
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
void process_unexpected(uint8_t *data, uint32_t len) {}
|
||||
|
||||
secbool await_response(uint16_t expected,
|
||||
secbool (*process)(uint8_t *data, uint32_t len,
|
||||
void *msg),
|
||||
void *msg_recv) {
|
||||
while (!m_uart_rx_data_ready_internal)
|
||||
;
|
||||
|
||||
m_uart_rx_data_ready_internal = false;
|
||||
|
||||
uint16_t id = 0;
|
||||
uint32_t msg_size = 0;
|
||||
|
||||
msg_parse_header(m_uart_rx_data, &id, &msg_size);
|
||||
|
||||
if (id == expected) {
|
||||
if (process != NULL) {
|
||||
return process(m_uart_rx_data, msg_size, msg_recv);
|
||||
}
|
||||
return sectrue;
|
||||
} else {
|
||||
process_unexpected(m_uart_rx_data, msg_size);
|
||||
}
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
/**@brief Function for handling app_uart events.
|
||||
*
|
||||
* @details This function will receive a single character from the app_uart
|
||||
* module and append it to a string. The string will be be sent over BLE when
|
||||
* the last character received was a 'new line' '\n' (hex 0x0A) or if the string
|
||||
* has reached the maximum data length.
|
||||
*/
|
||||
/**@snippet [Handling the data received over UART] */
|
||||
void uart_event_handle(app_uart_evt_t *p_event) {
|
||||
static uint8_t index = 0;
|
||||
static uint8_t message_type = 0;
|
||||
static uint16_t len = 0;
|
||||
uint32_t err_code;
|
||||
uint8_t rx_byte = 0;
|
||||
|
||||
switch (p_event->evt_type) {
|
||||
case APP_UART_DATA_READY:
|
||||
while (app_uart_get(&rx_byte) == NRF_SUCCESS) {
|
||||
if (index == 0) {
|
||||
if (rx_byte == INTERNAL_MESSAGE || rx_byte == INTERNAL_EVENT ||
|
||||
rx_byte == EXTERNAL_MESSAGE) {
|
||||
message_type = rx_byte;
|
||||
index += 1;
|
||||
continue;
|
||||
} else {
|
||||
// unknown message
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == 1) {
|
||||
// len HI
|
||||
len = rx_byte << 8;
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (index == 2) {
|
||||
// len LO
|
||||
len |= rx_byte;
|
||||
index += 1;
|
||||
if (len > sizeof(m_uart_rx_data) + OVERHEAD_SIZE) {
|
||||
// message too long
|
||||
index = 0;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (index < (len - 1)) {
|
||||
// command
|
||||
m_uart_rx_data[index - COMM_HEADER_SIZE] = rx_byte;
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (index >= (len - 1)) {
|
||||
if (rx_byte == EOM) {
|
||||
if (message_type == EXTERNAL_MESSAGE) {
|
||||
NRF_LOG_DEBUG("Ready to send data over BLE NUS");
|
||||
NRF_LOG_HEXDUMP_DEBUG(m_uart_rx_data, index);
|
||||
|
||||
do {
|
||||
uint16_t length = (uint16_t)len - OVERHEAD_SIZE;
|
||||
err_code = ble_nus_data_send(&m_nus, m_uart_rx_data, &length,
|
||||
get_connection_handle());
|
||||
if ((err_code != NRF_ERROR_INVALID_STATE) &&
|
||||
(err_code != NRF_ERROR_RESOURCES) &&
|
||||
(err_code != NRF_ERROR_NOT_FOUND)) {
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
} while (err_code == NRF_ERROR_RESOURCES);
|
||||
} else if (message_type == INTERNAL_MESSAGE) {
|
||||
m_uart_rx_data_ready_internal = true;
|
||||
} else if (message_type == INTERNAL_EVENT) {
|
||||
process_command(m_uart_rx_data, len - OVERHEAD_SIZE);
|
||||
}
|
||||
}
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**@snippet [Handling the data received over UART] */
|
||||
|
||||
/**@brief Function for handling the data from the Nordic UART Service.
|
||||
*
|
||||
* @details This function will process the data received from the Nordic UART
|
||||
* BLE Service and forward it to Trezor
|
||||
*
|
||||
* @param[in] p_evt Nordic UART Service event.
|
||||
*/
|
||||
/**@snippet [Handling the data received over BLE] */
|
||||
void nus_data_handler(ble_nus_evt_t *p_evt) {
|
||||
if (p_evt->type == BLE_NUS_EVT_RX_DATA) {
|
||||
NRF_LOG_DEBUG("Received data from BLE NUS. Forwarding.");
|
||||
NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data,
|
||||
p_evt->params.rx_data.length);
|
||||
|
||||
if (p_evt->params.rx_data.length != BLE_PACKET_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (!spi_xfer_done)
|
||||
;
|
||||
spi_xfer_done = false;
|
||||
|
||||
memcpy(m_spi_tx_data, p_evt->params.rx_data.p_data, BLE_PACKET_SIZE);
|
||||
|
||||
nrf_drv_spi_transfer(&spi, m_spi_tx_data, BLE_PACKET_SIZE, NULL, 0);
|
||||
}
|
||||
}
|
||||
/**@snippet [Handling the data received over BLE] */
|
||||
|
||||
void send_status_event(void) {
|
||||
uint8_t tx_data[] = {
|
||||
INTERNAL_EVENT_STATUS,
|
||||
(get_connection_handle() != BLE_CONN_HANDLE_INVALID) ? 1
|
||||
: 0, // connected
|
||||
is_advertising() ? 1 : 0, // advertising
|
||||
is_advertising_wl() ? 1 : 0, // advertising whitelist
|
||||
pm_peer_count(), // peer count
|
||||
};
|
||||
send_packet(INTERNAL_EVENT, tx_data, sizeof(tx_data));
|
||||
}
|
||||
|
||||
void send_success_event(void) {
|
||||
uint8_t tx_data[] = {
|
||||
INTERNAL_EVENT_SUCCESS,
|
||||
};
|
||||
send_packet(INTERNAL_EVENT, tx_data, sizeof(tx_data));
|
||||
}
|
||||
|
||||
uint16_t get_message_type(const uint8_t *rx_data) {
|
||||
return (rx_data[3] << 8) | rx_data[4];
|
||||
}
|
||||
|
||||
static bool read_authkey(pb_istream_t *stream, const pb_field_t *field,
|
||||
void **arg) {
|
||||
uint8_t *key_buffer = (uint8_t *)(*arg);
|
||||
|
||||
if (stream->bytes_left > BLE_GAP_PASSKEY_LEN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(key_buffer, 0, BLE_GAP_PASSKEY_LEN);
|
||||
|
||||
while (stream->bytes_left) {
|
||||
// read data
|
||||
if (!pb_read(stream, (pb_byte_t *)(key_buffer),
|
||||
(stream->bytes_left > BLE_GAP_PASSKEY_LEN)
|
||||
? BLE_GAP_PASSKEY_LEN
|
||||
: stream->bytes_left)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool write_authkey(pb_ostream_t *stream, const pb_field_t *field,
|
||||
void *const *arg) {
|
||||
uint8_t *key = (uint8_t *)(*arg);
|
||||
if (!pb_encode_tag_for_field(stream, field)) return false;
|
||||
|
||||
return pb_encode_string(stream, (uint8_t *)key, BLE_GAP_PASSKEY_LEN);
|
||||
}
|
||||
|
||||
bool send_comparison_request(uint8_t *p_key, int8_t p_key_len) {
|
||||
uint8_t iface_num = INTERNAL_MESSAGE;
|
||||
MSG_SEND_INIT(ComparisonRequest);
|
||||
MSG_SEND_CALLBACK(key, write_authkey, p_key);
|
||||
MSG_SEND_NRF(ComparisonRequest);
|
||||
|
||||
MSG_RECV_INIT(Success);
|
||||
secbool result = await_response(MessageType_MessageType_Success,
|
||||
process_success, &msg_recv);
|
||||
|
||||
if (result != sectrue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool send_auth_key_request(uint8_t *p_key, uint8_t p_key_len) {
|
||||
uint8_t iface_num = INTERNAL_MESSAGE;
|
||||
MSG_SEND_INIT(PairingRequest);
|
||||
MSG_SEND_NRF(PairingRequest);
|
||||
|
||||
uint8_t buffer[BLE_GAP_PASSKEY_LEN];
|
||||
MSG_RECV_INIT(AuthKey);
|
||||
MSG_RECV_CALLBACK(key, read_authkey, buffer);
|
||||
secbool result = await_response(MessageType_MessageType_AuthKey,
|
||||
process_auth_key, &msg_recv);
|
||||
|
||||
if (result != sectrue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(p_key, buffer,
|
||||
BLE_GAP_PASSKEY_LEN > p_key_len ? p_key_len : BLE_GAP_PASSKEY_LEN);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool send_repair_request(void) {
|
||||
uint8_t iface_num = INTERNAL_MESSAGE;
|
||||
MSG_SEND_INIT(RepairRequest);
|
||||
MSG_SEND_NRF(RepairRequest);
|
||||
|
||||
MSG_RECV_INIT(Success);
|
||||
|
||||
secbool result = await_response(MessageType_MessageType_Success,
|
||||
process_success, &msg_recv);
|
||||
|
||||
return result == sectrue;
|
||||
}
|
27
core/embed/ble_firmware/int_comm.h
Normal file
27
core/embed/ble_firmware/int_comm.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef __INT_COMM__
|
||||
#define __INT_COMM__
|
||||
|
||||
#include "app_uart.h"
|
||||
#include "ble_nus.h"
|
||||
#include "stdint.h"
|
||||
|
||||
void spi_init(void);
|
||||
|
||||
void nus_init(void);
|
||||
|
||||
void nus_data_handler(ble_nus_evt_t *p_evt);
|
||||
|
||||
void uart_event_handle(app_uart_evt_t *p_event);
|
||||
|
||||
void send_status_event(void);
|
||||
void send_success_event(void);
|
||||
|
||||
bool send_comparison_request(uint8_t *p_key, int8_t p_key_len);
|
||||
|
||||
bool send_auth_key_request(uint8_t *p_key, uint8_t p_key_len);
|
||||
|
||||
bool send_repair_request(void);
|
||||
|
||||
void send_initialized(void);
|
||||
|
||||
#endif
|
332
core/embed/ble_firmware/jlink.jdebug
Normal file
332
core/embed/ble_firmware/jlink.jdebug
Normal file
@ -0,0 +1,332 @@
|
||||
/*********************************************************************
|
||||
* (c) SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
* www.segger.com *
|
||||
**********************************************************************
|
||||
|
||||
File : /home/mbruna/CLionProjects/trezor-model_r/core/embed/ble_firmware/jlink.jdebug
|
||||
Created : 6 Feb 2023 15:54
|
||||
Ozone Version : V3.28c
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* OnProjectLoad
|
||||
*
|
||||
* Function description
|
||||
* Project load routine. Required.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
void OnProjectLoad (void) {
|
||||
//
|
||||
// Dialog-generated settings
|
||||
//
|
||||
Project.AddPathSubstitute (".", "$(ProjectDir)");
|
||||
Project.AddPathSubstitute (".", "$(ProjectDir)");
|
||||
Project.SetDevice ("Cortex-M4");
|
||||
Project.SetHostIF ("USB", "");
|
||||
Project.SetTargetIF ("SWD");
|
||||
Project.SetTIFSpeed ("20 MHz");
|
||||
Project.AddSvdFile ("$(InstallDir)/Config/CPU/Cortex-M4F.svd");
|
||||
//
|
||||
// User settings
|
||||
//
|
||||
File.Open ("../../build/ble_firmware/ble_firmware.elf");
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* OnStartupComplete
|
||||
*
|
||||
* Function description
|
||||
* Called when program execution has reached/passed
|
||||
* the startup completion point. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void OnStartupComplete (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* TargetReset
|
||||
*
|
||||
* Function description
|
||||
* Replaces the default target device reset routine. Optional.
|
||||
*
|
||||
* Notes
|
||||
* This example demonstrates the usage when
|
||||
* debugging an application in RAM on a Cortex-M target device.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void TargetReset (void) {
|
||||
//
|
||||
// unsigned int SP;
|
||||
// unsigned int PC;
|
||||
// unsigned int VectorTableAddr;
|
||||
//
|
||||
// VectorTableAddr = Elf.GetBaseAddr();
|
||||
// //
|
||||
// // Set up initial stack pointer
|
||||
// //
|
||||
// if (VectorTableAddr != 0xFFFFFFFF) {
|
||||
// SP = Target.ReadU32(VectorTableAddr);
|
||||
// Target.SetReg("SP", SP);
|
||||
// }
|
||||
// //
|
||||
// // Set up entry point PC
|
||||
// //
|
||||
// PC = Elf.GetEntryPointPC();
|
||||
//
|
||||
// if (PC != 0xFFFFFFFF) {
|
||||
// Target.SetReg("PC", PC);
|
||||
// } else if (VectorTableAddr != 0xFFFFFFFF) {
|
||||
// PC = Target.ReadU32(VectorTableAddr + 4);
|
||||
// Target.SetReg("PC", PC);
|
||||
// } else {
|
||||
// Util.Error("Project file error: failed to set entry point PC", 1);
|
||||
// }
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* BeforeTargetReset
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void BeforeTargetReset (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* AfterTargetReset
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
* The default implementation initializes SP and PC to reset values.
|
||||
**
|
||||
**********************************************************************
|
||||
*/
|
||||
void AfterTargetReset (void) {
|
||||
_SetupTarget();
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* DebugStart
|
||||
*
|
||||
* Function description
|
||||
* Replaces the default debug session startup routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void DebugStart (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* TargetConnect
|
||||
*
|
||||
* Function description
|
||||
* Replaces the default target IF connection routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void TargetConnect (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* BeforeTargetConnect
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
void BeforeTargetConnect (void) {
|
||||
Project.SetJLinkScript("./MMDScript.JLinkScript");
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* AfterTargetConnect
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void AfterTargetConnect (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* TargetDownload
|
||||
*
|
||||
* Function description
|
||||
* Replaces the default program download routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void TargetDownload (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* BeforeTargetDownload
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void BeforeTargetDownload (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* AfterTargetDownload
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
* The default implementation initializes SP and PC to reset values.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
void AfterTargetDownload (void) {
|
||||
_SetupTarget();
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* BeforeTargetDisconnect
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void BeforeTargetDisconnect (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* AfterTargetDisconnect
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void AfterTargetDisconnect (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* AfterTargetHalt
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void AfterTargetHalt (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* BeforeTargetResume
|
||||
*
|
||||
* Function description
|
||||
* Event handler routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void BeforeTargetResume (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* OnSnapshotLoad
|
||||
*
|
||||
* Function description
|
||||
* Called upon loading a snapshot. Optional.
|
||||
*
|
||||
* Additional information
|
||||
* This function is used to restore the target state in cases
|
||||
* where values cannot simply be written to the target.
|
||||
* Typical use: GPIO clock needs to be enabled, before
|
||||
* GPIO is configured.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void OnSnapshotLoad (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* OnSnapshotSave
|
||||
*
|
||||
* Function description
|
||||
* Called upon saving a snapshot. Optional.
|
||||
*
|
||||
* Additional information
|
||||
* This function is usually used to save values of the target
|
||||
* state which can either not be trivially read,
|
||||
* or need to be restored in a specific way or order.
|
||||
* Typically use: Memory Mapped Registers,
|
||||
* such as PLL and GPIO configuration.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void OnSnapshotSave (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* OnError
|
||||
*
|
||||
* Function description
|
||||
* Called when an error ocurred. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void OnError (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* AfterProjectLoad
|
||||
*
|
||||
* Function description
|
||||
* After Project load routine. Optional.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//void AfterProjectLoad (void) {
|
||||
//}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _SetupTarget
|
||||
*
|
||||
* Function description
|
||||
* Setup the target.
|
||||
* Called by AfterTargetReset() and AfterTargetDownload().
|
||||
*
|
||||
* Auto-generated function. May be overridden by Ozone.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
void _SetupTarget(void) {
|
||||
//
|
||||
// this function is intentionally empty because both inital PC and
|
||||
// initial SP were chosen not to be set
|
||||
//
|
||||
}
|
631
core/embed/ble_firmware/main.c
Normal file
631
core/embed/ble_firmware/main.c
Normal file
@ -0,0 +1,631 @@
|
||||
/**
|
||||
* Copyright (c) 2014 - 2021, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be
|
||||
* reverse engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/** @file
|
||||
*
|
||||
* @defgroup ble_sdk_uart_over_ble_main main.c
|
||||
* @{
|
||||
* @ingroup ble_sdk_app_nus_eval
|
||||
* @brief UART over BLE application main file.
|
||||
*
|
||||
* This file contains the source code for a sample application that uses the
|
||||
* Nordic UART service. This application uses the @ref srvlib_conn_params
|
||||
* module.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "app_scheduler.h"
|
||||
#include "app_timer.h"
|
||||
#include "app_uart.h"
|
||||
#include "app_util_platform.h"
|
||||
#include "ble_conn_params.h"
|
||||
#include "ble_hci.h"
|
||||
#include "nordic_common.h"
|
||||
#include "nrf.h"
|
||||
#include "nrf_ble_gatt.h"
|
||||
#include "nrf_ble_qwr.h"
|
||||
#include "nrf_drv_uart.h"
|
||||
#include "nrf_gpio.h"
|
||||
#include "nrf_pwr_mgmt.h"
|
||||
#include "nrf_sdh.h"
|
||||
#include "nrf_sdh_ble.h"
|
||||
#include "nrf_sdh_soc.h"
|
||||
#include "trezor_t3w1_d1_NRF.h"
|
||||
|
||||
#if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT
|
||||
#include "nrf_sdm.h"
|
||||
#endif
|
||||
|
||||
#if defined(UART_PRESENT)
|
||||
#include "nrf_uart.h"
|
||||
#endif
|
||||
#if defined(UARTE_PRESENT)
|
||||
#include "nrf_uarte.h"
|
||||
#endif
|
||||
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_log_default_backends.h"
|
||||
|
||||
#include "advertising.h"
|
||||
#include "ble_nus.h"
|
||||
#include "connection.h"
|
||||
#include "defs.h"
|
||||
#include "dis.h"
|
||||
#include "int_comm.h"
|
||||
#include "nrf_ble_lesc.h"
|
||||
#include "pm.h"
|
||||
#include "power.h"
|
||||
|
||||
#define DEVICE_NAME \
|
||||
"Trezor" /**< Name of device. Will be included in the advertising data. \
|
||||
*/
|
||||
|
||||
#define APP_BLE_OBSERVER_PRIO \
|
||||
3 /**< Application's BLE observer priority. You shouldn't need to modify \
|
||||
this value. */
|
||||
|
||||
#define MIN_CONN_INTERVAL \
|
||||
MSEC_TO_UNITS( \
|
||||
7.5, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), \
|
||||
Connection interval uses 1.25 ms units. */
|
||||
#define MAX_CONN_INTERVAL \
|
||||
MSEC_TO_UNITS( \
|
||||
7.5, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), \
|
||||
Connection interval uses 1.25 ms units. */
|
||||
#define SLAVE_LATENCY 0 /**< Slave latency. */
|
||||
#define CONN_SUP_TIMEOUT \
|
||||
MSEC_TO_UNITS(4000, \
|
||||
UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), \
|
||||
Supervision Timeout uses 10 ms units. */
|
||||
#define FIRST_CONN_PARAMS_UPDATE_DELAY \
|
||||
APP_TIMER_TICKS( \
|
||||
5000) /**< Time from initiating event (connect or start of notification) \
|
||||
to first time sd_ble_gap_conn_param_update is called (5 \
|
||||
seconds). */
|
||||
#define NEXT_CONN_PARAMS_UPDATE_DELAY \
|
||||
APP_TIMER_TICKS( \
|
||||
30000) /**< Time between each call to sd_ble_gap_conn_param_update after \
|
||||
the first call (30 seconds). */
|
||||
#define MAX_CONN_PARAMS_UPDATE_COUNT \
|
||||
3 /**< Number of attempts before giving up the connection parameter \
|
||||
negotiation. */
|
||||
|
||||
#define DEAD_BEEF \
|
||||
0xDEADBEEF /**< Value used as error code on stack dump, can be used to \
|
||||
identify stack location on stack unwind. */
|
||||
|
||||
#define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */
|
||||
#define UART_RX_BUF_SIZE 256 /**< UART RX buffer size. */
|
||||
|
||||
NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */
|
||||
NRF_BLE_QWR_DEF(m_qwr); /**< Context for the Queued Write module.*/
|
||||
|
||||
#define SCHED_MAX_EVENT_DATA_SIZE \
|
||||
APP_TIMER_SCHED_EVENT_DATA_SIZE /**< Maximum size of scheduler events. */
|
||||
#ifdef SVCALL_AS_NORMAL_FUNCTION
|
||||
#define SCHED_QUEUE_SIZE \
|
||||
20 /**< Maximum number of events in the scheduler queue. More is needed in \
|
||||
case of Serialization. */
|
||||
#else
|
||||
#define SCHED_QUEUE_SIZE \
|
||||
10 /**< Maximum number of events in the scheduler queue. */
|
||||
#endif
|
||||
|
||||
static uint16_t m_ble_nus_max_data_len =
|
||||
BLE_GATT_ATT_MTU_DEFAULT -
|
||||
3; /**< Maximum length of data (in bytes) that can be transmitted to the
|
||||
peer by the Nordic UART service module. */
|
||||
|
||||
/**@brief Function for assert macro callback.
|
||||
*
|
||||
* @details This function will be called in case of an assert in the SoftDevice.
|
||||
*
|
||||
* @warning On assert from the SoftDevice, the system can only recover on reset.
|
||||
*
|
||||
* @param[in] line_num Line number of the failing ASSERT call.
|
||||
* @param[in] p_file_name File name of the failing ASSERT call.
|
||||
*/
|
||||
void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name) {
|
||||
app_error_handler(DEAD_BEEF, line_num, p_file_name);
|
||||
}
|
||||
|
||||
/*lint -save -e14 */
|
||||
/**
|
||||
* Function is implemented as weak so that it can be overwritten by custom
|
||||
* application error handler when needed.
|
||||
*/
|
||||
void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) {
|
||||
__disable_irq();
|
||||
|
||||
// signalize firmware not running
|
||||
nrf_gpio_pin_clear(GPIO_2_PIN);
|
||||
|
||||
NRF_LOG_FINAL_FLUSH();
|
||||
|
||||
#ifndef DEBUG
|
||||
NRF_LOG_ERROR("Fatal error");
|
||||
#else
|
||||
switch (id) {
|
||||
#if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT
|
||||
case NRF_FAULT_ID_SD_ASSERT:
|
||||
NRF_LOG_ERROR("SOFTDEVICE: ASSERTION FAILED");
|
||||
break;
|
||||
case NRF_FAULT_ID_APP_MEMACC:
|
||||
NRF_LOG_ERROR("SOFTDEVICE: INVALID MEMORY ACCESS");
|
||||
break;
|
||||
#endif
|
||||
case NRF_FAULT_ID_SDK_ASSERT: {
|
||||
assert_info_t *p_info = (assert_info_t *)info;
|
||||
NRF_LOG_ERROR("ASSERTION FAILED at %s:%u", p_info->p_file_name,
|
||||
p_info->line_num);
|
||||
break;
|
||||
}
|
||||
case NRF_FAULT_ID_SDK_ERROR: {
|
||||
error_info_t *p_info = (error_info_t *)info;
|
||||
NRF_LOG_ERROR("ERROR %u [%s] at %s:%u\r\nPC at: 0x%08x", p_info->err_code,
|
||||
nrf_strerror_get(p_info->err_code), p_info->p_file_name,
|
||||
p_info->line_num, pc);
|
||||
NRF_LOG_ERROR("End of error report");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NRF_LOG_ERROR("UNKNOWN FAULT at 0x%08X", pc);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
NRF_BREAKPOINT_COND;
|
||||
// On assert, the system can only recover with a reset.
|
||||
|
||||
#ifndef DEBUG
|
||||
NRF_LOG_WARNING("System reset");
|
||||
NVIC_SystemReset();
|
||||
#else
|
||||
app_error_save_and_stop(id, pc, info);
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
/**@brief Function for initializing the timer module.
|
||||
*/
|
||||
static void timers_init(void) {
|
||||
ret_code_t err_code = app_timer_init();
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
/**@brief Function for the GAP initialization.
|
||||
*
|
||||
* @details This function will set up all the necessary GAP (Generic Access
|
||||
* Profile) parameters of the device. It also sets the permissions and
|
||||
* appearance.
|
||||
*/
|
||||
static void gap_params_init(void) {
|
||||
uint32_t err_code;
|
||||
ble_gap_conn_params_t gap_conn_params;
|
||||
ble_gap_conn_sec_mode_t sec_mode;
|
||||
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
|
||||
|
||||
err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *)DEVICE_NAME,
|
||||
strlen(DEVICE_NAME));
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_UNKNOWN);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
memset(&gap_conn_params, 0, sizeof(gap_conn_params));
|
||||
|
||||
gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
|
||||
gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
|
||||
gap_conn_params.slave_latency = SLAVE_LATENCY;
|
||||
gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT;
|
||||
|
||||
err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
/**@brief Function for handling Queued Write Module errors.
|
||||
*
|
||||
* @details A pointer to this function will be passed to each service which may
|
||||
* need to inform the application about an error.
|
||||
*
|
||||
* @param[in] nrf_error Error code containing information about what went
|
||||
* wrong.
|
||||
*/
|
||||
static void nrf_qwr_error_handler(uint32_t nrf_error) {
|
||||
APP_ERROR_HANDLER(nrf_error);
|
||||
}
|
||||
|
||||
/**@brief Function for initializing services that will be used by the
|
||||
* application.
|
||||
*/
|
||||
static void services_init(void) {
|
||||
uint32_t err_code;
|
||||
nrf_ble_qwr_init_t qwr_init = {0};
|
||||
|
||||
// Initialize Queued Write Module.
|
||||
qwr_init.error_handler = nrf_qwr_error_handler;
|
||||
|
||||
err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
dis_init();
|
||||
nus_init();
|
||||
}
|
||||
|
||||
/**@brief Function for handling errors from the Connection Parameters module.
|
||||
*
|
||||
* @param[in] nrf_error Error code containing information about what went
|
||||
* wrong.
|
||||
*/
|
||||
static void conn_params_error_handler(uint32_t nrf_error) {
|
||||
APP_ERROR_HANDLER(nrf_error);
|
||||
}
|
||||
|
||||
/**@brief Function for initializing the Connection Parameters module.
|
||||
*/
|
||||
static void conn_params_init(void) {
|
||||
uint32_t err_code;
|
||||
ble_conn_params_init_t cp_init;
|
||||
|
||||
memset(&cp_init, 0, sizeof(cp_init));
|
||||
|
||||
cp_init.p_conn_params = NULL;
|
||||
cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
|
||||
cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY;
|
||||
cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT;
|
||||
cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID;
|
||||
cp_init.disconnect_on_fail = false;
|
||||
cp_init.evt_handler = NULL;
|
||||
cp_init.error_handler = conn_params_error_handler;
|
||||
|
||||
err_code = ble_conn_params_init(&cp_init);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
/**@brief Function for handling BLE events.
|
||||
*
|
||||
* @param[in] p_ble_evt Bluetooth stack event.
|
||||
* @param[in] p_context Unused.
|
||||
*/
|
||||
static void ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) {
|
||||
uint32_t err_code;
|
||||
char passkey[BLE_GAP_PASSKEY_LEN + 1] = {0};
|
||||
|
||||
switch (p_ble_evt->header.evt_id) {
|
||||
case BLE_GAP_EVT_CONNECTED:
|
||||
NRF_LOG_INFO("Connected");
|
||||
// err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
|
||||
// APP_ERROR_CHECK(err_code);
|
||||
|
||||
uint16_t handle = p_ble_evt->evt.gap_evt.conn_handle;
|
||||
set_connection_handle(handle);
|
||||
send_status_event();
|
||||
err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, handle);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVT_DISCONNECTED:
|
||||
NRF_LOG_INFO("Disconnected");
|
||||
// bsp_indication_set(BSP_INDICATE_IDLE);
|
||||
set_connection_handle(BLE_CONN_HANDLE_INVALID);
|
||||
send_status_event();
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVT_PHY_UPDATE_REQUEST: {
|
||||
NRF_LOG_DEBUG("PHY update request.");
|
||||
ble_gap_phys_t const phys = {
|
||||
.rx_phys = BLE_GAP_PHY_AUTO,
|
||||
.tx_phys = BLE_GAP_PHY_AUTO,
|
||||
};
|
||||
err_code =
|
||||
sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
} break;
|
||||
|
||||
case BLE_GAP_EVT_PASSKEY_DISPLAY:
|
||||
memcpy(passkey, p_ble_evt->evt.gap_evt.params.passkey_display.passkey,
|
||||
BLE_GAP_PASSKEY_LEN);
|
||||
|
||||
NRF_LOG_INFO("BLE_GAP_EVT_PASSKEY_DISPLAY: passkey=%s match_req=%d",
|
||||
nrf_log_push(passkey),
|
||||
p_ble_evt->evt.gap_evt.params.passkey_display.match_request);
|
||||
|
||||
if (p_ble_evt->evt.gap_evt.params.passkey_display.match_request) {
|
||||
bool ok =
|
||||
send_comparison_request((uint8_t *)passkey, BLE_GAP_PASSKEY_LEN);
|
||||
|
||||
if (ok) {
|
||||
sd_ble_gap_auth_key_reply(p_ble_evt->evt.gap_evt.conn_handle,
|
||||
BLE_GAP_AUTH_KEY_TYPE_PASSKEY, NULL);
|
||||
} else {
|
||||
sd_ble_gap_auth_key_reply(p_ble_evt->evt.gap_evt.conn_handle,
|
||||
BLE_GAP_AUTH_KEY_TYPE_NONE, NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BLE_GAP_EVT_LESC_DHKEY_REQUEST:
|
||||
NRF_LOG_INFO("BLE_GAP_EVT_LESC_DHKEY_REQUEST");
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVT_AUTH_KEY_REQUEST: {
|
||||
NRF_LOG_INFO("Key requested.");
|
||||
|
||||
bool ok = send_auth_key_request((uint8_t *)passkey, BLE_GAP_PASSKEY_LEN);
|
||||
|
||||
sd_ble_gap_auth_key_reply(p_ble_evt->evt.gap_evt.conn_handle,
|
||||
BLE_GAP_AUTH_KEY_TYPE_PASSKEY,
|
||||
(uint8_t *)passkey);
|
||||
|
||||
if (ok) {
|
||||
NRF_LOG_INFO("Received data: %c", passkey);
|
||||
} else {
|
||||
NRF_LOG_INFO("Auth key request failed.");
|
||||
}
|
||||
|
||||
// APP_ERROR_CHECK(err_code);
|
||||
break;
|
||||
}
|
||||
case BLE_GATTC_EVT_TIMEOUT:
|
||||
// Disconnect on GATT Client timeout event.
|
||||
err_code =
|
||||
sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
|
||||
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
break;
|
||||
|
||||
case BLE_GATTS_EVT_TIMEOUT:
|
||||
// Disconnect on GATT Server timeout event.
|
||||
err_code =
|
||||
sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
|
||||
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
break;
|
||||
|
||||
default:
|
||||
// No implementation needed.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**@brief Function for the SoftDevice initialization.
|
||||
*
|
||||
* @details This function initializes the SoftDevice and the BLE event
|
||||
* interrupt.
|
||||
*/
|
||||
static void ble_stack_init(void) {
|
||||
ret_code_t err_code;
|
||||
|
||||
err_code = nrf_sdh_enable_request();
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
// Configure the BLE stack using the default settings.
|
||||
// Fetch the start address of the application RAM.
|
||||
uint32_t ram_start = 0;
|
||||
err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
// Enable BLE stack.
|
||||
err_code = nrf_sdh_ble_enable(&ram_start);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
// Register a handler for BLE events.
|
||||
NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**@brief Function for handling events from the GATT library. */
|
||||
void gatt_evt_handler(nrf_ble_gatt_t *p_gatt, nrf_ble_gatt_evt_t const *p_evt) {
|
||||
if ((get_connection_handle() == p_evt->conn_handle) &&
|
||||
(p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)) {
|
||||
m_ble_nus_max_data_len =
|
||||
p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
|
||||
NRF_LOG_INFO("Data len is set to 0x%X(%d)", m_ble_nus_max_data_len,
|
||||
m_ble_nus_max_data_len);
|
||||
}
|
||||
NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x",
|
||||
p_gatt->att_mtu_desired_central,
|
||||
p_gatt->att_mtu_desired_periph);
|
||||
}
|
||||
|
||||
/**@brief Function for initializing the GATT library. */
|
||||
void gatt_init(void) {
|
||||
ret_code_t err_code;
|
||||
|
||||
err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
err_code =
|
||||
nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
///**@brief Function for handling events from the BSP module.
|
||||
// *
|
||||
// * @param[in] event Event generated by button press.
|
||||
// */
|
||||
// void bsp_event_handler(bsp_event_t event) {
|
||||
// uint32_t err_code;
|
||||
// switch (event) {
|
||||
// case BSP_EVENT_SLEEP:
|
||||
// sleep_mode_enter();
|
||||
// break;
|
||||
//
|
||||
// case BSP_EVENT_DISCONNECT:
|
||||
// err_code = sd_ble_gap_disconnect(
|
||||
// get_connection_handle(), BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
|
||||
// if (err_code != NRF_ERROR_INVALID_STATE) {
|
||||
// APP_ERROR_CHECK(err_code);
|
||||
// }
|
||||
// break;
|
||||
//
|
||||
// case BSP_EVENT_WHITELIST_OFF:
|
||||
// if (get_connection_handle() == BLE_CONN_HANDLE_INVALID) {
|
||||
// advertising_restart_without_whitelist();
|
||||
// }
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
/**@brief Function for initializing the UART module.
|
||||
*/
|
||||
/**@snippet [UART Initialization] */
|
||||
static void uart_init(void) {
|
||||
uint32_t err_code;
|
||||
app_uart_comm_params_t const comm_params = {
|
||||
.rx_pin_no = RX_PIN_NUMBER,
|
||||
.tx_pin_no = TX_PIN_NUMBER,
|
||||
.rts_pin_no = RTS_PIN_NUMBER,
|
||||
.cts_pin_no = CTS_PIN_NUMBER,
|
||||
.flow_control = APP_UART_FLOW_CONTROL_ENABLED,
|
||||
.use_parity = false,
|
||||
#if defined(UART_PRESENT)
|
||||
.baud_rate = NRF_UART_BAUDRATE_1000000
|
||||
#else
|
||||
.baud_rate = NRF_UARTE_BAUDRATE_1000000
|
||||
#endif
|
||||
};
|
||||
|
||||
APP_UART_FIFO_INIT(&comm_params, UART_RX_BUF_SIZE, UART_TX_BUF_SIZE,
|
||||
uart_event_handle, APP_IRQ_PRIORITY_LOWEST, err_code);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
/**@snippet [UART Initialization] */
|
||||
|
||||
///**@brief Function for initializing buttons and leds.
|
||||
// *
|
||||
// * @param[out] p_erase_bonds Will be true if the clear bonding button was
|
||||
// * pressed to wake the application up.
|
||||
// */
|
||||
// static void buttons_leds_init(bool *p_erase_bonds) {
|
||||
// bsp_event_t startup_event;
|
||||
//
|
||||
// uint32_t err_code =
|
||||
// bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler);
|
||||
// APP_ERROR_CHECK(err_code);
|
||||
//
|
||||
// err_code = bsp_btn_ble_init(NULL, &startup_event);
|
||||
// APP_ERROR_CHECK(err_code);
|
||||
//
|
||||
// *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA);
|
||||
//}
|
||||
|
||||
/**@brief Function for initializing the nrf log module.
|
||||
*/
|
||||
static void log_init(void) {
|
||||
ret_code_t err_code = NRF_LOG_INIT(NULL);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
NRF_LOG_DEFAULT_BACKENDS_INIT();
|
||||
}
|
||||
|
||||
/**@brief Function for initializing power management.
|
||||
*/
|
||||
static void power_management_init(void) {
|
||||
ret_code_t err_code;
|
||||
err_code = nrf_pwr_mgmt_init();
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
/**@brief Function for handling the idle state (main loop).
|
||||
*
|
||||
* @details If there is no pending log operation, then sleep until next the next
|
||||
* event occurs.
|
||||
*/
|
||||
static void idle_state_handle(void) {
|
||||
app_sched_execute();
|
||||
if (NRF_LOG_PROCESS() == false) {
|
||||
nrf_pwr_mgmt_run();
|
||||
}
|
||||
}
|
||||
|
||||
/**@brief Function for the Event Scheduler initialization.
|
||||
*/
|
||||
static void scheduler_init(void) {
|
||||
APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
|
||||
}
|
||||
|
||||
/**@brief Application main function.
|
||||
*/
|
||||
int main(void) {
|
||||
bool erase_bonds = false;
|
||||
|
||||
nrf_gpio_cfg_output(GPIO_1_PIN);
|
||||
nrf_gpio_cfg_output(GPIO_2_PIN);
|
||||
nrf_gpio_pin_clear(GPIO_1_PIN);
|
||||
|
||||
// Initialize.
|
||||
spi_init();
|
||||
uart_init();
|
||||
log_init();
|
||||
timers_init();
|
||||
// buttons_leds_init(&erase_bonds);
|
||||
power_management_init();
|
||||
ble_stack_init();
|
||||
scheduler_init();
|
||||
gap_params_init();
|
||||
gatt_init();
|
||||
services_init();
|
||||
advertising_init();
|
||||
conn_params_init();
|
||||
peer_manager_init();
|
||||
|
||||
// signalize firmware running
|
||||
nrf_gpio_pin_set(GPIO_2_PIN);
|
||||
send_status_event();
|
||||
|
||||
if (erase_bonds) {
|
||||
delete_bonds();
|
||||
}
|
||||
|
||||
// Enter main loop.
|
||||
for (;;) {
|
||||
nrf_ble_lesc_request_handler();
|
||||
idle_state_handle();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
130
core/embed/ble_firmware/memory.ld
Normal file
130
core/embed/ble_firmware/memory.ld
Normal file
@ -0,0 +1,130 @@
|
||||
/* Linker script to configure memory regions. */
|
||||
|
||||
SEARCH_DIR(.)
|
||||
GROUP(-lgcc -lc -lnosys)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0x49000
|
||||
RAM (rwx) : ORIGIN = 0x20002ae8, LENGTH = 0x1d518
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = ALIGN(4);
|
||||
.mem_section_dummy_ram :
|
||||
{
|
||||
}
|
||||
.cli_sorted_cmd_ptrs :
|
||||
{
|
||||
PROVIDE(__start_cli_sorted_cmd_ptrs = .);
|
||||
KEEP(*(.cli_sorted_cmd_ptrs))
|
||||
PROVIDE(__stop_cli_sorted_cmd_ptrs = .);
|
||||
} > RAM
|
||||
.fs_data :
|
||||
{
|
||||
PROVIDE(__start_fs_data = .);
|
||||
KEEP(*(.fs_data))
|
||||
PROVIDE(__stop_fs_data = .);
|
||||
} > RAM
|
||||
.log_dynamic_data :
|
||||
{
|
||||
PROVIDE(__start_log_dynamic_data = .);
|
||||
KEEP(*(SORT(.log_dynamic_data*)))
|
||||
PROVIDE(__stop_log_dynamic_data = .);
|
||||
} > RAM
|
||||
.log_filter_data :
|
||||
{
|
||||
PROVIDE(__start_log_filter_data = .);
|
||||
KEEP(*(SORT(.log_filter_data*)))
|
||||
PROVIDE(__stop_log_filter_data = .);
|
||||
} > RAM
|
||||
|
||||
} INSERT AFTER .data;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.mem_section_dummy_rom :
|
||||
{
|
||||
}
|
||||
.sdh_soc_observers :
|
||||
{
|
||||
PROVIDE(__start_sdh_soc_observers = .);
|
||||
KEEP(*(SORT(.sdh_soc_observers*)))
|
||||
PROVIDE(__stop_sdh_soc_observers = .);
|
||||
} > FLASH
|
||||
.sdh_ble_observers :
|
||||
{
|
||||
PROVIDE(__start_sdh_ble_observers = .);
|
||||
KEEP(*(SORT(.sdh_ble_observers*)))
|
||||
PROVIDE(__stop_sdh_ble_observers = .);
|
||||
} > FLASH
|
||||
.pwr_mgmt_data :
|
||||
{
|
||||
PROVIDE(__start_pwr_mgmt_data = .);
|
||||
KEEP(*(SORT(.pwr_mgmt_data*)))
|
||||
PROVIDE(__stop_pwr_mgmt_data = .);
|
||||
} > FLASH
|
||||
.sdh_req_observers :
|
||||
{
|
||||
PROVIDE(__start_sdh_req_observers = .);
|
||||
KEEP(*(SORT(.sdh_req_observers*)))
|
||||
PROVIDE(__stop_sdh_req_observers = .);
|
||||
} > FLASH
|
||||
.sdh_state_observers :
|
||||
{
|
||||
PROVIDE(__start_sdh_state_observers = .);
|
||||
KEEP(*(SORT(.sdh_state_observers*)))
|
||||
PROVIDE(__stop_sdh_state_observers = .);
|
||||
} > FLASH
|
||||
.sdh_stack_observers :
|
||||
{
|
||||
PROVIDE(__start_sdh_stack_observers = .);
|
||||
KEEP(*(SORT(.sdh_stack_observers*)))
|
||||
PROVIDE(__stop_sdh_stack_observers = .);
|
||||
} > FLASH
|
||||
.nrf_queue :
|
||||
{
|
||||
PROVIDE(__start_nrf_queue = .);
|
||||
KEEP(*(.nrf_queue))
|
||||
PROVIDE(__stop_nrf_queue = .);
|
||||
} > FLASH
|
||||
.nrf_balloc :
|
||||
{
|
||||
PROVIDE(__start_nrf_balloc = .);
|
||||
KEEP(*(.nrf_balloc))
|
||||
PROVIDE(__stop_nrf_balloc = .);
|
||||
} > FLASH
|
||||
.cli_command :
|
||||
{
|
||||
PROVIDE(__start_cli_command = .);
|
||||
KEEP(*(.cli_command))
|
||||
PROVIDE(__stop_cli_command = .);
|
||||
} > FLASH
|
||||
.crypto_data :
|
||||
{
|
||||
PROVIDE(__start_crypto_data = .);
|
||||
KEEP(*(SORT(.crypto_data*)))
|
||||
PROVIDE(__stop_crypto_data = .);
|
||||
} > FLASH
|
||||
.log_const_data :
|
||||
{
|
||||
PROVIDE(__start_log_const_data = .);
|
||||
KEEP(*(SORT(.log_const_data*)))
|
||||
PROVIDE(__stop_log_const_data = .);
|
||||
} > FLASH
|
||||
.log_backends :
|
||||
{
|
||||
PROVIDE(__start_log_backends = .);
|
||||
KEEP(*(SORT(.log_backends*)))
|
||||
PROVIDE(__stop_log_backends = .);
|
||||
} > FLASH
|
||||
|
||||
} INSERT AFTER .text
|
||||
|
||||
|
||||
INCLUDE "nrf_common.ld"
|
156
core/embed/ble_firmware/pm.c
Normal file
156
core/embed/ble_firmware/pm.c
Normal file
@ -0,0 +1,156 @@
|
||||
|
||||
|
||||
#include "nrf_log.h"
|
||||
#include "peer_manager_handler.h"
|
||||
|
||||
#include "int_comm.h"
|
||||
#include "pm.h"
|
||||
|
||||
#define SEC_PARAM_BOND 1 /**< Perform bonding. */
|
||||
#define SEC_PARAM_MITM 1 /**< Man In The Middle protection not required. */
|
||||
#define SEC_PARAM_LESC 1 /**< LE Secure Connections not enabled. */
|
||||
#define SEC_PARAM_KEYPRESS 0 /**< Keypress notifications not enabled. */
|
||||
#define SEC_PARAM_IO_CAPABILITIES \
|
||||
BLE_GAP_IO_CAPS_KEYBOARD_DISPLAY /**< No I/O capabilities. */
|
||||
#define SEC_PARAM_OOB 0 /**< Out Of Band data not available. */
|
||||
#define SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */
|
||||
#define SEC_PARAM_MAX_KEY_SIZE 16 /**< Maximum encryption key size. */
|
||||
|
||||
static pm_peer_id_t
|
||||
m_peer_id; /**< Device reference handle to the current bonded central. */
|
||||
|
||||
pm_peer_id_t get_peer_id(void) { return m_peer_id; }
|
||||
|
||||
/**@brief Function for setting filtered whitelist.
|
||||
*
|
||||
* @param[in] skip Filter passed to @ref pm_peer_id_list.
|
||||
*/
|
||||
void whitelist_set(pm_peer_id_list_skip_t skip) {
|
||||
pm_peer_id_t peer_ids[BLE_GAP_WHITELIST_ADDR_MAX_COUNT];
|
||||
uint32_t peer_id_count = BLE_GAP_WHITELIST_ADDR_MAX_COUNT;
|
||||
|
||||
ret_code_t err_code =
|
||||
pm_peer_id_list(peer_ids, &peer_id_count, PM_PEER_ID_INVALID, skip);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
NRF_LOG_INFO("\tm_whitelist_peer_cnt %d, MAX_PEERS_WLIST %d",
|
||||
peer_id_count + 1, BLE_GAP_WHITELIST_ADDR_MAX_COUNT);
|
||||
|
||||
err_code = pm_whitelist_set(peer_ids, peer_id_count);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
/**@brief Function for handling Peer Manager events.
|
||||
*
|
||||
* @param[in] p_evt Peer Manager event.
|
||||
*/
|
||||
void pm_evt_handler(pm_evt_t const *p_evt) {
|
||||
pm_handler_on_pm_evt(p_evt);
|
||||
pm_handler_disconnect_on_sec_failure(p_evt);
|
||||
pm_handler_flash_clean(p_evt);
|
||||
|
||||
switch (p_evt->evt_id) {
|
||||
case PM_EVT_CONN_SEC_SUCCEEDED:
|
||||
m_peer_id = p_evt->peer_id;
|
||||
break;
|
||||
|
||||
case PM_EVT_PEERS_DELETE_SUCCEEDED:
|
||||
// advertising_start(false);
|
||||
break;
|
||||
|
||||
case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
|
||||
if (p_evt->params.peer_data_update_succeeded.flash_changed &&
|
||||
(p_evt->params.peer_data_update_succeeded.data_id ==
|
||||
PM_PEER_DATA_ID_BONDING)) {
|
||||
NRF_LOG_INFO("New Bond, add the peer to the whitelist if possible");
|
||||
// Note: You should check on what kind of white list policy your
|
||||
// application should use.
|
||||
|
||||
whitelist_set(PM_PEER_ID_LIST_SKIP_NO_ID_ADDR);
|
||||
}
|
||||
break;
|
||||
case PM_EVT_CONN_SEC_CONFIG_REQ: {
|
||||
bool ok = send_repair_request();
|
||||
|
||||
if (ok) {
|
||||
// Allow pairing request from an already bonded peer.
|
||||
pm_conn_sec_config_t conn_sec_config = {.allow_repairing = true};
|
||||
pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config);
|
||||
} else {
|
||||
// Reject pairing request from an already bonded peer.
|
||||
pm_conn_sec_config_t conn_sec_config = {.allow_repairing = false};
|
||||
pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config);
|
||||
}
|
||||
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**@brief Function for the Peer Manager initialization.
|
||||
*/
|
||||
void peer_manager_init(void) {
|
||||
ble_gap_sec_params_t sec_param;
|
||||
pm_privacy_params_t privacy_params;
|
||||
ret_code_t err_code;
|
||||
|
||||
err_code = pm_init();
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));
|
||||
|
||||
// Security parameters to be used for all security procedures.
|
||||
sec_param.bond = SEC_PARAM_BOND;
|
||||
sec_param.mitm = SEC_PARAM_MITM;
|
||||
sec_param.lesc = SEC_PARAM_LESC;
|
||||
sec_param.keypress = SEC_PARAM_KEYPRESS;
|
||||
sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES;
|
||||
sec_param.oob = SEC_PARAM_OOB;
|
||||
sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE;
|
||||
sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE;
|
||||
sec_param.kdist_own.enc = 1;
|
||||
sec_param.kdist_own.id = 1;
|
||||
sec_param.kdist_peer.enc = 1;
|
||||
sec_param.kdist_peer.id = 1;
|
||||
|
||||
err_code = pm_sec_params_set(&sec_param);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
privacy_params.p_device_irk = NULL;
|
||||
privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY;
|
||||
privacy_params.private_addr_cycle_s = 0;
|
||||
privacy_params.private_addr_type =
|
||||
BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE;
|
||||
pm_privacy_set(&privacy_params);
|
||||
|
||||
err_code = pm_register(pm_evt_handler);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
/**@brief Function for setting filtered device identities.
|
||||
*
|
||||
* @param[in] skip Filter passed to @ref pm_peer_id_list.
|
||||
*/
|
||||
void identities_set(pm_peer_id_list_skip_t skip) {
|
||||
pm_peer_id_t peer_ids[BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT];
|
||||
uint32_t peer_id_count = BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT;
|
||||
|
||||
ret_code_t err_code =
|
||||
pm_peer_id_list(peer_ids, &peer_id_count, PM_PEER_ID_INVALID, skip);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
err_code = pm_device_identities_list_set(peer_ids, peer_id_count);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
/////**@brief Clear bond information from persistent storage. */
|
||||
void delete_bonds(void) {
|
||||
ret_code_t err_code;
|
||||
|
||||
NRF_LOG_INFO("Erase bonds!");
|
||||
|
||||
// pm_whitelist_set(NULL, 0);
|
||||
err_code = pm_peers_delete();
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
18
core/embed/ble_firmware/pm.h
Normal file
18
core/embed/ble_firmware/pm.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef __PEER_MANAGER__
|
||||
#define __PEER_MANAGER__
|
||||
|
||||
#include "peer_manager.h"
|
||||
|
||||
pm_peer_id_t get_peer_id(void);
|
||||
|
||||
void whitelist_set(pm_peer_id_list_skip_t skip);
|
||||
|
||||
void identities_set(pm_peer_id_list_skip_t skip);
|
||||
|
||||
/**@brief Function for the Peer Manager initialization.
|
||||
*/
|
||||
void peer_manager_init(void);
|
||||
|
||||
void delete_bonds(void);
|
||||
|
||||
#endif
|
21
core/embed/ble_firmware/power.c
Normal file
21
core/embed/ble_firmware/power.c
Normal file
@ -0,0 +1,21 @@
|
||||
#include "power.h"
|
||||
#include "app_error.h"
|
||||
|
||||
/**@brief Function for putting the chip into sleep mode.
|
||||
*
|
||||
* @note This function will not return.
|
||||
*/
|
||||
// void sleep_mode_enter(void) {
|
||||
// uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE);
|
||||
// APP_ERROR_CHECK(err_code);
|
||||
//
|
||||
// // Prepare wakeup buttons.
|
||||
// err_code = bsp_btn_ble_sleep_mode_prepare();
|
||||
// APP_ERROR_CHECK(err_code);
|
||||
//
|
||||
// // Go to system-off mode (this function will not return; wakeup will cause
|
||||
// a
|
||||
// // reset).
|
||||
// err_code = sd_power_system_off();
|
||||
// APP_ERROR_CHECK(err_code);
|
||||
// }
|
6
core/embed/ble_firmware/power.h
Normal file
6
core/embed/ble_firmware/power.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef __POWER__
|
||||
#define __POWER__
|
||||
|
||||
void sleep_mode_enter(void);
|
||||
|
||||
#endif
|
12147
core/embed/ble_firmware/sdk_config.h
Normal file
12147
core/embed/ble_firmware/sdk_config.h
Normal file
File diff suppressed because it is too large
Load Diff
4
core/embed/ble_firmware/version.h
Normal file
4
core/embed/ble_firmware/version.h
Normal file
@ -0,0 +1,4 @@
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 0
|
@ -98,6 +98,25 @@ def get_version(file: str) -> str:
|
||||
return f"{major}.{minor}.{patch}"
|
||||
|
||||
|
||||
def get_version_int(file):
|
||||
major = 0
|
||||
minor = 0
|
||||
patch = 0
|
||||
|
||||
file = PROJECT_ROOT / file
|
||||
with open(file, 'r') as f:
|
||||
for line in f:
|
||||
if line.startswith('#define VERSION_MAJOR '):
|
||||
major = int(line.split('VERSION_MAJOR')[1].strip())
|
||||
if line.startswith('#define VERSION_MINOR '):
|
||||
minor = int(line.split('VERSION_MINOR')[1].strip())
|
||||
if line.startswith('#define VERSION_PATCH '):
|
||||
patch = int(line.split('VERSION_PATCH')[1].strip())
|
||||
if major > 99 or minor > 99 or patch > 99:
|
||||
raise Exception("Version number too large")
|
||||
return major * 10000 + minor * 100 + patch
|
||||
|
||||
|
||||
def get_git_revision_hash() -> str:
|
||||
return subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("ascii").strip()
|
||||
|
||||
|
35
core/tools/convert_ble_firmware.py
Normal file
35
core/tools/convert_ble_firmware.py
Normal file
@ -0,0 +1,35 @@
|
||||
import click
|
||||
import zipfile
|
||||
|
||||
|
||||
def convert_file(archive, infile, outfile, name):
|
||||
data = archive.read(infile)
|
||||
with open(outfile, "w") as outfile:
|
||||
outfile.write("// Firmware BLOB - automatically generated\n")
|
||||
outfile.write("\n")
|
||||
outfile.write(f"#ifndef __FW_BLOB_{name}_H__\n")
|
||||
outfile.write(f"#define __FW_BLOB_{name}_H__ 1\n")
|
||||
outfile.write("\n")
|
||||
|
||||
outfile.write(f"uint8_t {name}[] = " + "{")
|
||||
|
||||
for i, byte in enumerate(data):
|
||||
if i % 16 == 0:
|
||||
outfile.write("\n ")
|
||||
outfile.write("0x{:02x}, ".format(byte))
|
||||
|
||||
outfile.write("\n};\n")
|
||||
outfile.write("\n")
|
||||
outfile.write("#endif\n")
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument("infile", type=click.File("rb"))
|
||||
def convert(infile):
|
||||
with zipfile.ZipFile(infile) as archive:
|
||||
convert_file(archive, "ble_firmware.bin", "./embed/firmware/dfu/ble_firmware_bin.h", "binfile")
|
||||
convert_file(archive, "ble_firmware.dat", "./embed/firmware/dfu/ble_firmware_dat.h", "datfile")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
convert()
|
1
core/tools/generate_ble_bl_settings.sh
Normal file
1
core/tools/generate_ble_bl_settings.sh
Normal file
@ -0,0 +1 @@
|
||||
nrfutil settings generate --family NRF52 --bootloader-version 0 --bl-settings-version 2 --app-boot-validation VALIDATE_ECDSA_P256_SHA256 --application ./build/ble_firmware/ble_firmware.hex --application-version 0 --sd-boot-validation VALIDATE_ECDSA_P256_SHA256 --softdevice ./embed/sdk/nrf52/components/softdevice/s140/hex/s140_nrf52_7.2.0_softdevice.hex --key-file ./embed/ble_bootloader/priv.pem ./build/ble_bootloader/settings.hex
|
@ -12,3 +12,5 @@
|
||||
^\./crypto/sha3
|
||||
^\./legacy/vendor
|
||||
^\./core/embed/segger
|
||||
^\./core/embed/ble_bootloader/uecc
|
||||
^\./core/embed/sdk
|
||||
|
Loading…
Reference in New Issue
Block a user