diff --git a/Makefile.defines b/Makefile.defines index 51072926..3d539c60 100644 --- a/Makefile.defines +++ b/Makefile.defines @@ -16,7 +16,7 @@ #******************************************************************************* #extract TARGET_NAME/TARGET_ID from the SDK to allow for makefile choices -TARGET := "nanos" +TARGET := nanos TARGET_ID:=$(shell cat $(BOLOS_SDK)/include/bolos_target.h | grep TARGET_ID | cut -f3 -d' ') TARGET_NAME:=$(shell cat $(BOLOS_SDK)/include/bolos_target.h | grep TARGET_ | grep -v TARGET_ID | cut -f2 -d' ') TARGET_VERSION:=$(shell cat $(BOLOS_SDK)/include/bolos_version.h | grep define | cut -f2 -d'"') diff --git a/Makefile.rules b/Makefile.rules index ccdd6a6b..98ebb81f 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -22,6 +22,17 @@ ifeq ($(DISABLE_UI),0) endif endif +define uniq = + $(eval seen :=) + $(foreach _,$1,$(if $(filter $_,${seen}),,$(eval seen += $_))) + ${seen} +endef + +define check_duplicate = + $(eval LIST := $(sort $(foreach file_h, $(notdir $1), $(notdir $(shell find $2 -name $(file_h)))))) + $(if $(LIST), $(info [WARNING] Found duplicate files in SDK and APP: ${LIST})) +endef + # Expose all SDK header files with their full relative path to the SDK root folder INCLUDES_PATH += ${BOLOS_SDK} @@ -30,12 +41,49 @@ ifeq ($(NO_CXNG),) INCLUDES_PATH += $(BOLOS_SDK)/lib_cxng/include endif -SOURCE_PATH += $(BOLOS_SDK)/src $(foreach libdir, $(SDK_SOURCE_PATH), $(dir $(shell find $(BOLOS_SDK)/$(libdir) -name '*.[csS]'))) $(dir $(shell find $(APP_SOURCE_PATH) -name '*.[csS]')) -SOURCE_FILES += $(shell find $(SOURCE_PATH) -name '*.[csS]') $(GLYPH_DESTC) $(APP_SOURCE_FILES) -INCLUDES_PATH += $(dir $(foreach libdir, $(SDK_SOURCE_PATH), $(dir $(shell find $(BOLOS_SDK)/$(libdir) -name '*.h')))) include $(BOLOS_SDK)/include $(BOLOS_SDK)/include/arm $(dir $(shell find $(APP_SOURCE_PATH) -name '*.h')) $(GLYPH_SRC_DIR) +# Get absolute App root directory to ensure correct stem replacement +APP_DIR := $(shell git rev-parse --show-toplevel) +ifeq ($(APP_DIR),) +MSG := "[ERROR] You should be inside a git repo (you can use 'git init')" +ifneq ($(ENABLE_SDK_WERROR),0) +$(error $(MSG)) +else +$(warning $(MSG)) +endif +endif + +# Extract BOLOS_SDK source files added by the App Makefile +APP_SRC_FROM_SDK = $(filter $(BOLOS_SDK)/%, $(APP_SOURCE_FILES)) +# Extract generated and glyphs source files added by the App Makefile +APP_SRC_GEN = $(filter $(GEN_SRC_DIR)/%, $(APP_SOURCE_FILES)) +# Extract proto source files added by the App Makefile +APP_SRC_PROTOC = $(filter %.pb.c, $(APP_SOURCE_FILES) $(SOURCE_FILES)) $(shell find $(APP_SOURCE_PATH) -name '*.pb.c') +# Filter remaining real source files from App (proto filtered globally hereafter) +APP_SRC_FILTER = $(filter-out $(APP_SRC_FROM_SDK) $(APP_SRC_GEN), $(APP_SOURCE_FILES)) + +# Separate SDK and APP and GEN sources +SOURCES_SDK += $(foreach libdir, src $(SDK_SOURCE_PATH), $(shell find $(BOLOS_SDK)/$(libdir) -name '*.[csS]')) $(APP_SRC_FROM_SDK) +SOURCES_APP += $(filter-out %.pb.c, $(abspath $(SOURCE_FILES) $(foreach libdir, $(SOURCE_PATH) $(APP_SOURCE_PATH), $(shell find $(libdir) -name '*.[csS]')) $(APP_SRC_FILTER))) +SOURCES_GEN += $(GLYPH_DESTC) $(APP_SRC_GEN) +VPATH += $(call uniq, $(dir $(SOURCES_SDK) $(SOURCES_APP) $(GLYPH_DESTC))) + +# Retrieve APP header filenames +INCLUDES_APP += $(shell find $(APP_SOURCE_PATH) -name '*.h') +# Warn if a same header filename is found in both APP and SDK +$(call check_duplicate, $(INCLUDES_APP), $(BOLOS_SDK)) +# Compute header directories list +INCLUDES_PATH += $(call uniq, $(dir $(foreach libdir, $(SDK_SOURCE_PATH), $(dir $(shell find $(BOLOS_SDK)/$(libdir) -name '*.h')))) include $(BOLOS_SDK)/include $(BOLOS_SDK)/include/arm $(dir $(INCLUDES_APP)) $(GLYPH_SRC_DIR)) + +# Separate object files from SDK and APP to avoid name conflicts +OBJECTS_SDK += $(sort $(subst $(BOLOS_SDK), $(OBJ_DIR)/sdk, $(addsuffix .o, $(basename $(SOURCES_SDK))))) +OBJECTS_APP += $(sort $(addprefix $(OBJ_DIR)/app, $(addsuffix .o, $(basename $(foreach f, $(SOURCES_APP), $(shell echo $(f) | sed "s|$(APP_DIR)||" 2>/dev/null)))))) +OBJECTS_GEN += $(sort $(SOURCES_GEN:%c=%o)) +OBJECTS_PROTOC += $(sort $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(basename $(APP_SRC_PROTOC))))) +OBJECT_FILES = $(OBJECTS_GEN) $(OBJECTS_PROTOC) $(OBJECTS_APP) $(OBJECTS_SDK) +OBJECTS_DIR += $(sort $(dir $(OBJECT_FILES))) -VPATH += $(dir $(SOURCE_FILES)) -OBJECT_FILES += $(sort $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(basename $(notdir $(SOURCE_FILES)))))) -DEPEND_FILES += $(sort $(addprefix $(DEP_DIR)/, $(addsuffix .d, $(basename $(notdir $(SOURCE_FILES)))))) +# Separate dependency files from SDK and APP to avoid name conflicts +DEPEND_FILES = $(subst $(OBJ_DIR), $(DEP_DIR), $(addsuffix .d, $(basename $(OBJECT_FILES)))) +DEPEND_DIR += $(sort $(dir $(DEPEND_FILES))) include $(BOLOS_SDK)/Makefile.rules_generic diff --git a/Makefile.rules_generic b/Makefile.rules_generic index 443c3881..6f647751 100644 --- a/Makefile.rules_generic +++ b/Makefile.rules_generic @@ -72,7 +72,7 @@ BUILD_DEPENDENCIES += $(APP_CUSTOM_BUILD_DEPENDENCIES) prepare: $(L)echo Prepare directories - @mkdir -p $(BIN_DIR) $(OBJ_DIR) $(DBG_DIR) $(DEP_DIR) $(GEN_SRC_DIR) bin debug + @mkdir -p $(BIN_DIR) $(OBJ_DIR) $(OBJECTS_DIR) $(DBG_DIR) $(DEP_DIR) $(DEPEND_DIR) $(GEN_SRC_DIR) bin debug $(BUILD_DEPENDENCIES): prepare @@ -81,6 +81,38 @@ DBG_TARGETS := debug/app.map debug/app.asm default: $(BIN_TARGETS) $(DBG_TARGETS) +# Glyphs target +$(GEN_SRC_DIR)/%.o: $(GEN_SRC_DIR)/%.c $(BUILD_DEPENDENCIES) prepare + @echo "[CC] $@" + $(L)$(call cc_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@) + +# App files targets +$(OBJ_DIR)/app/%.o: $(APP_DIR)/%.c $(BUILD_DEPENDENCIES) prepare + @echo "[CC] $@" + $(L)$(call cc_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@) + +$(OBJ_DIR)/app/%.o: $(APP_DIR)/%.s $(BUILD_DEPENDENCIES) prepare + @echo "[AS] $@" + $(L)$(call as_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@) + +$(OBJ_DIR)/app/%.o: $(APP_DIR)/%.S $(BUILD_DEPENDENCIES) prepare + @echo "[AS] $@" + $(L)$(call as_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@) + +# SDK files targets +$(OBJ_DIR)/sdk/%.o: $(BOLOS_SDK)/%.c $(BUILD_DEPENDENCIES) prepare + @echo "[CC] $@" + $(L)$(call cc_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@) + +$(OBJ_DIR)/sdk/%.o: $(BOLOS_SDK)/%.s $(BUILD_DEPENDENCIES) prepare + @echo "[AS] $@" + $(L)$(call as_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@) + +$(OBJ_DIR)/sdk/%.o: $(BOLOS_SDK)/%.S $(BUILD_DEPENDENCIES) prepare + @echo "[AS] $@" + $(L)$(call as_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@) + +# Generic targets $(OBJ_DIR)/%.o: %.c $(BUILD_DEPENDENCIES) prepare @echo "[CC] $@" $(L)$(call cc_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@) @@ -163,7 +195,7 @@ endif # cc_cmdline(include,defines,src,dest) Macro that is used to format arguments for the compiler # dependency files are generated along the object file -cc_cmdline = $(CC) -c $(CFLAGS) -MMD -MT $(OBJ_DIR)/$(basename $(notdir $(4))).o -MF $(DEP_DIR)/$(basename $(notdir $(4))).d $(addprefix -D,$(2)) $(addprefix -I,$(1)) -o $(4) $(3) +cc_cmdline = $(CC) -c $(CFLAGS) -MMD -MT $(4) -MF $(subst $(OBJ_DIR), $(DEP_DIR), $(addsuffix .d, $(basename $(4)))) $(addprefix -D,$(2)) $(addprefix -I,$(1)) -o $(4) $(3) as_cmdline = $(AS) -c $(AFLAGS) $(addprefix -D,$(2)) $(addprefix -I,$(1)) -o $(4) $(3) diff --git a/include/cx_errors.h b/include/cx_errors.h index cff97d52..92be6fb4 100644 --- a/include/cx_errors.h +++ b/include/cx_errors.h @@ -6,6 +6,7 @@ #pragma once #include +#include "ledger_assert.h" /** * Check the error code of a function. @@ -32,6 +33,16 @@ } \ } while (0) +/** + * Checks the error code of a function and assert in case of error. + */ +#define CX_ASSERT(call) \ + do { \ + cx_err_t _assert_err = call; \ + LEDGER_ASSERT(!_assert_err, "err 0x%X <%s>", _assert_err, #call); \ + } while (0) + + /** Success. */ #define CX_OK 0x00000000 diff --git a/include/ledger_assert.h b/include/ledger_assert.h index 15387e5c..c3b714a6 100644 --- a/include/ledger_assert.h +++ b/include/ledger_assert.h @@ -1,156 +1,95 @@ #pragma once -#include - -#ifdef LEDGER_ASSERT_CONFIG_FILE_INFO -#define LEDGER_ASSERT_CONFIG_MESSAGE_INFO 1 -#define LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO 1 -#endif - -#ifdef LEDGER_ASSERT_CONFIG_MESSAGE_INFO -#define LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO 1 -#endif - -#if defined(LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO) && defined(HAVE_LEDGER_ASSERT_DISPLAY) -#define LR_AND_PC_SIZE 30 -void assert_display_lr_and_pc(int lr, int pc); -#define ASSERT_DISPLAY_LR_AND_PC(lr, pc) assert_display_lr_and_pc(lr, pc) -#else -#define LR_AND_PC_SIZE 0 -#define ASSERT_DISPLAY_LR_AND_PC(lr, pc) \ - do { \ - } while (0) -#endif - -#if defined(LEDGER_ASSERT_CONFIG_MESSAGE_INFO) && defined(HAVE_LEDGER_ASSERT_DISPLAY) -#define MESSAGE_SIZE 20 -void assert_display_message(const char *message); -#define ASSERT_DISPLAY_MESSAGE(message) assert_display_message(message) -#else -#define MESSAGE_SIZE 0 -#define ASSERT_DISPLAY_MESSAGE(message) \ - do { \ - } while (0) -#endif - -#if defined(LEDGER_ASSERT_CONFIG_FILE_INFO) && defined(HAVE_LEDGER_ASSERT_DISPLAY) -#define FILE_SIZE 50 -void assert_display_file_info(const char *file, unsigned int line); -#define ASSERT_DISPLAY_FILE_INFO(file, line) assert_display_file_info(file, line) -#else -#define FILE_SIZE 0 -#define ASSERT_DISPLAY_FILE_INFO(file, line) \ - do { \ - } while (0) -#endif - -#ifdef HAVE_LEDGER_ASSERT_DISPLAY -#define ASSERT_BUFFER_LEN LR_AND_PC_SIZE + MESSAGE_SIZE + FILE_SIZE -void __attribute__((noreturn)) assert_display_exit(void); - -#define LEDGER_ASSERT_EXIT() assert_display_exit() -#else -void assert_exit(bool confirm); -#define LEDGER_ASSERT_EXIT() assert_exit(true) -#endif - -#if defined(LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO) && defined(HAVE_PRINTF) -void assert_print_lr_and_pc(int lr, int pc); -#define ASSERT_PRINT_LR_AND_PC(lr, pc) assert_print_lr_and_pc(lr, pc) -#else -#define ASSERT_PRINT_LR_AND_PC(lr, pc) \ - do { \ - } while (0) -#endif - -#if defined(LEDGER_ASSERT_CONFIG_MESSAGE_INFO) && defined(HAVE_PRINTF) -void assert_print_message(const char *message); -#define ASSERT_PRINT_MESSAGE(message) assert_print_message(message) -#else -#define ASSERT_PRINT_MESSAGE(message) \ - do { \ - } while (0) -#endif - -#if defined(LEDGER_ASSERT_CONFIG_FILE_INFO) && defined(HAVE_PRINTF) -void assert_print_file_info(const char *file, int line); -#define ASSERT_PRINT_FILE_INFO(file, line) assert_print_file_info(file, line) -#else -#define ASSERT_PRINT_FILE_INFO(file, line) \ - do { \ - } while (0) -#endif - -#ifdef LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO -#define LEDGER_ASSERT_LR_AND_PC() \ - do { \ - int _lr_address = 0; \ - int _pc_address = 0; \ - \ - __asm volatile("mov %0, lr" : "=r"(_lr_address)); \ - __asm volatile("mov %0, pc" : "=r"(_pc_address)); \ - ASSERT_PRINT_LR_AND_PC(_lr_address, _pc_address); \ - ASSERT_DISPLAY_LR_AND_PC(_lr_address, _pc_address); \ - } while (0) -#elif defined(HAVE_PRINTF) -#define LEDGER_ASSERT_LR_AND_PC() PRINTF("LEDGER_ASSERT FAILED\n") -#else -#define LEDGER_ASSERT_LR_AND_PC() \ - do { \ - } while (0) -#endif - -#ifdef LEDGER_ASSERT_CONFIG_MESSAGE_INFO -#define LEDGER_ASSERT_MESSAGE(message) \ - do { \ - ASSERT_PRINT_MESSAGE(message); \ - ASSERT_DISPLAY_MESSAGE(message); \ - } while (0) -#else -#define LEDGER_ASSERT_MESSAGE(message) \ - do { \ - } while (0) -#endif - -#ifdef LEDGER_ASSERT_CONFIG_FILE_INFO -#define LEDGER_ASSERT_FILE_INFO() \ - do { \ - ASSERT_PRINT_FILE_INFO(__FILE__, __LINE__); \ - ASSERT_DISPLAY_FILE_INFO(__FILE__, __LINE__); \ - } while (0) -#else -#define LEDGER_ASSERT_FILE_INFO() \ - do { \ - } while (0) -#endif - -#define LEDGER_ASSERT(test, message) \ - do { \ - if (!(test)) { \ - LEDGER_ASSERT_LR_AND_PC(); \ - LEDGER_ASSERT_MESSAGE(message); \ - LEDGER_ASSERT_FILE_INFO(); \ - LEDGER_ASSERT_EXIT(); \ - } \ - } while (0) - -#if defined(HAVE_DEBUG_THROWS) && defined(HAVE_PRINTF) -void throw_print_lr(int e, int lr); -#define THROW_PRINT_LR(e, lr_val) throw_print_lr(e, lr_val) -#else -#define THROW_PRINT_LR(e, lr_val) \ - do { \ - } while (0) -#endif - -#if defined(HAVE_DEBUG_THROWS) -void __attribute__((noreturn)) assert_display_exit(void); -void throw_display_lr(int e, int lr); -#define DEBUG_THROW(e) \ - do { \ - unsigned int lr_val; \ - __asm volatile("mov %0, lr" : "=r"(lr_val)); \ - throw_display_lr(e, lr_val); \ - THROW_PRINT_LR(e, lr_val); \ +#include "ledger_assert_internals.h" + +/***************** + * LEDGER_ASSERT * + ****************/ + +/** + * LEDGER_ASSERT - exit the app if assertion is false. + * + * Description: + * This is a C macro that can be used similarly of the libc `assert` macro. + * Therefore, it can help programmers find bugs in their programs, or handle + * exceptional cases via a crash that will produce limited debugging output. + * + * + * Important note: + * Note that contrary to the libc `assert`, the `LEDGER_ASSERT` macro will + * still end the app execution even if build with DEBUG=0 or NDEBUG. + * However, there are configurations explained below that shall be used to + * reduce the code size impact of the `LEDGER_ASSERT` macro to the bare minimum. + * + * + * Examples of usage: + * + * 1/ Simple example always raising with simple message: + * - `LEDGER_ASSERT(false, "Always assert");` + * + * 2/ More complex examples: + * - `LEDGER_ASSERT(len <= sizeof(buf), "Len too long");` + * - `LEDGER_ASSERT(check_value(value) == 0, "check_value failed");` + * + * 3/ Examples showcasing advance message format: + * - `LEDGER_ASSERT(len <= sizeof(buf), "Len too long %d <= %d", len, sizeof(buf));` + * - `int err = check_value(value); LEDGER_ASSERT(err == 0, "check_value failed (%d)", err);` + * + * + * Configuration: + * + * I/ Type of info to expose in PRINTF and screen if enabled. + * + * There are 4 types of information that can be displayed: + * + * 1/ A simple info displaying "LEDGER_ASSERT FAILED" + * => This is always enabled + * + * 2/ An info containing the PC and LR of the instruction that failed. + * This can be used to locate the failing code and flow using the following + * command: `arm-none-eabi-addr2line --exe bin/app.elf -pf 0xC0DE586B` + * => This is enabled when `LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO` is defined. + * + * 3/ An info displaying the `LEDGER_ASSERT` message passed as parameter. + * => This is enabled when `LEDGER_ASSERT_CONFIG_MESSAGE_INFO` is defined. + * + * 4/ An info displaying the file and line position of the failing + * `LEDGER_ASSERT`. + * => This is enabled when `LEDGER_ASSERT_CONFIG_FILE_INFO` is defined. + * + * By default, when an info level X is enabled, all info level below are enabled. + * + * When using `Makefile.standard_app` and building with `DEBUG=1` all info are + * enabled. + * + * Note that enabling these info increase the app code size and is only + * recommended to ease the debugging. + * + * + * II/ Display info on device screen. + * + * Control whether or not a specific screen displaying assert info is shown + * to the app user before exiting the app due to an assert failure. + * + * To enable it, add `DEFINES+=HAVE_LEDGER_ASSERT_DISPLAY` in your app Makefile. + * + * This is enabled by default when using `Makefile.standard_app` and building + * with `DEBUG=1`. It can still be disabled with using + * `DISABLE_DEBUG_LEDGER_ASSERT=1`. + * + * Note that this is increasing the app code size and exposes a non-user + * friendly screen in case of assert. therefore this should not be enabled in + * app release build but only kept for debug purposes. + * + */ +#define LEDGER_ASSERT(test, format, ...) \ + do { \ + if (!(test)) { \ + LEDGER_ASSERT_LR_AND_PC_PREAMBLE(); \ + PRINTF("LEDGER_ASSERT FAILED\n"); \ + LEDGER_ASSERT_MESSAGE(format, ##__VA_ARGS__); \ + LEDGER_ASSERT_FILE_INFO(); \ + LEDGER_ASSERT_LR_AND_PC(); \ + LEDGER_ASSERT_EXIT(); \ + } \ } while (0) -#endif diff --git a/include/ledger_assert_internals.h b/include/ledger_assert_internals.h new file mode 100644 index 00000000..ddf8e2eb --- /dev/null +++ b/include/ledger_assert_internals.h @@ -0,0 +1,226 @@ +#pragma once + +#include +#include +#include +#include "os_print.h" + +/******************************* + * Default configuration level * + ******************************/ +#ifdef LEDGER_ASSERT_CONFIG_FILE_INFO +#define LEDGER_ASSERT_CONFIG_MESSAGE_INFO 1 +#define LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO 1 +#endif + +#ifdef LEDGER_ASSERT_CONFIG_MESSAGE_INFO +#define LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO 1 +#endif + +/********************************************************************* + * Compute needed buffer length to display the assert info on screen * + ********************************************************************/ +#ifdef HAVE_LEDGER_ASSERT_DISPLAY + +#ifdef LEDGER_ASSERT_CONFIG_MESSAGE_INFO +#if defined(TARGET_NANOS) +// Spare RAM on NANOS +#define MESSAGE_SIZE 20 +#else +#define MESSAGE_SIZE 50 +#endif +#else +#define MESSAGE_SIZE 0 +#endif + +#ifdef LEDGER_ASSERT_CONFIG_FILE_INFO +#define FILE_SIZE 50 +#else +#define FILE_SIZE 0 +#endif + +#ifdef LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO +#define LR_AND_PC_SIZE 30 +#else +#define LR_AND_PC_SIZE 0 +#endif + +#define ASSERT_BUFFER_LEN LR_AND_PC_SIZE + MESSAGE_SIZE + FILE_SIZE +extern char assert_buffer[ASSERT_BUFFER_LEN]; + +#endif // HAVE_LEDGER_ASSERT_DISPLAY + +/************************************************************ + * Define behavior when LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO * + ***********************************************************/ +#ifdef LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO + +#ifdef HAVE_PRINTF +void assert_print_lr_and_pc(int lr, int pc); +#define ASSERT_PRINT_LR_AND_PC(lr, pc) assert_print_lr_and_pc(lr, pc) +#else +#define ASSERT_PRINT_LR_AND_PC(lr, pc) \ + do { \ + } while (0) +#endif + +#ifdef HAVE_LEDGER_ASSERT_DISPLAY +void assert_display_lr_and_pc(int lr, int pc); +#define ASSERT_DISPLAY_LR_AND_PC(lr, pc) assert_display_lr_and_pc(lr, pc) +#else +#define ASSERT_DISPLAY_LR_AND_PC(lr, pc) \ + do { \ + } while (0) +#endif + +#define LEDGER_ASSERT_LR_AND_PC_PREAMBLE() \ + int _lr_address = 0; \ + int _pc_address = 0; \ + \ + __asm volatile("mov %0, lr" : "=r"(_lr_address)); \ + __asm volatile("mov %0, pc" : "=r"(_pc_address)) + +#define LEDGER_ASSERT_LR_AND_PC() \ + do { \ + ASSERT_PRINT_LR_AND_PC(_lr_address, _pc_address); \ + ASSERT_DISPLAY_LR_AND_PC(_lr_address, _pc_address); \ + } while (0) + +#else // LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO + +#define LEDGER_ASSERT_LR_AND_PC_PREAMBLE() \ + do { \ + } while (0) + +#define LEDGER_ASSERT_LR_AND_PC() \ + do { \ + } while (0) + +#endif // LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO + +/********************************************************** + * Define behavior when LEDGER_ASSERT_CONFIG_MESSAGE_INFO * + *********************************************************/ +#ifdef LEDGER_ASSERT_CONFIG_MESSAGE_INFO + +#ifdef HAVE_PRINTF +#define ASSERT_PRINT_MESSAGE(format, ...) \ + do { \ + PRINTF(format, ##__VA_ARGS__); \ + PRINTF("\n"); \ + } while (0) +#else +#define ASSERT_PRINT_MESSAGE(...) \ + do { \ + } while (0) +#endif + +#ifdef HAVE_LEDGER_ASSERT_DISPLAY +// Immediately call snprintf here (no function wrapping it cleanly in ledger_assert.c). +// This is because we don't have an vsnprintf implementation which would be needed if +// we were to pass the va_args to an intermediate function. +// See https://stackoverflow.com/a/150578 +#define ASSERT_DISPLAY_MESSAGE(format, ...) \ + do { \ + snprintf(assert_buffer, MESSAGE_SIZE, format, ##__VA_ARGS__); \ + strncat(assert_buffer, "\n", MESSAGE_SIZE); \ + } while (0) +#else +#define ASSERT_DISPLAY_MESSAGE(format, ...) \ + do { \ + } while (0) +#endif + +#define LEDGER_ASSERT_MESSAGE(format, ...) \ + do { \ + if (format != NULL) { \ + ASSERT_PRINT_MESSAGE(format, ##__VA_ARGS__); \ + ASSERT_DISPLAY_MESSAGE(format, ##__VA_ARGS__); \ + } \ + } while (0) + +#else // LEDGER_ASSERT_CONFIG_MESSAGE_INFO + +#define LEDGER_ASSERT_MESSAGE(...) \ + do { \ + } while (0) + +#endif // LEDGER_ASSERT_CONFIG_MESSAGE_INFO + +/******************************************************* + * Define behavior when LEDGER_ASSERT_CONFIG_FILE_INFO * + ******************************************************/ +#ifdef LEDGER_ASSERT_CONFIG_FILE_INFO + +#ifdef HAVE_PRINTF +void assert_print_file_info(const char *file, int line); +#define ASSERT_PRINT_FILE_INFO(file, line) assert_print_file_info(file, line) +#else +#define ASSERT_PRINT_FILE_INFO(file, line) \ + do { \ + } while (0) +#endif + +#ifdef HAVE_LEDGER_ASSERT_DISPLAY +void assert_display_file_info(const char *file, unsigned int line); +#define ASSERT_DISPLAY_FILE_INFO(file, line) assert_display_file_info(file, line) +#else +#define ASSERT_DISPLAY_FILE_INFO(file, line) \ + do { \ + } while (0) +#endif + +#define LEDGER_ASSERT_FILE_INFO() \ + do { \ + ASSERT_PRINT_FILE_INFO(__FILE__, __LINE__); \ + ASSERT_DISPLAY_FILE_INFO(__FILE__, __LINE__); \ + } while (0) + +#else // LEDGER_ASSERT_CONFIG_FILE_INFO + +#define LEDGER_ASSERT_FILE_INFO() \ + do { \ + } while (0) + +#endif // LEDGER_ASSERT_CONFIG_FILE_INFO + +/******************************************************** + * Define exit behavior when HAVE_LEDGER_ASSERT_DISPLAY * + *******************************************************/ +#ifdef HAVE_LEDGER_ASSERT_DISPLAY +void __attribute__((noreturn)) assert_display_exit(void); +#define LEDGER_ASSERT_EXIT() assert_display_exit() + +#else // HAVE_LEDGER_ASSERT_DISPLAY + +void assert_exit(bool confirm); +#define LEDGER_ASSERT_EXIT() assert_exit(true) + +#endif // HAVE_LEDGER_ASSERT_DISPLAY + +/************************************* + * Specific mechanism to debug THROW * + ************************************/ +#ifdef HAVE_DEBUG_THROWS + +#ifdef HAVE_PRINTF +void throw_print_lr(int e, int lr); +#define THROW_PRINT_LR(e, lr_val) throw_print_lr(e, lr_val) +#else +#define THROW_PRINT_LR(e, lr_val) \ + do { \ + } while (0) +#endif + +void __attribute__((noreturn)) assert_display_exit(void); +void throw_display_lr(int e, int lr); + +#define DEBUG_THROW(e) \ + do { \ + unsigned int lr_val; \ + __asm volatile("mov %0, lr" : "=r"(lr_val)); \ + throw_display_lr(e, lr_val); \ + THROW_PRINT_LR(e, lr_val); \ + } while (0) + +#endif // HAVE_DEBUG_THROWS diff --git a/include/os.h b/include/os.h index b3cb8b28..58bcdbfa 100644 --- a/include/os.h +++ b/include/os.h @@ -119,13 +119,6 @@ os is not an application (it calls ux upon user inputs) /* ----------------------------------------------------------------------- */ /* - DEBUG FUNCTIONS - */ /* ----------------------------------------------------------------------- */ -#ifdef HAVE_PRINTF -void screen_printf(const char *format, ...); -void mcu_usb_printf(const char *format, ...); -#else // !HAVE_PRINTF -#define PRINTF(...) -#endif // !HAVE_PRINTF - // redefined if string.h not included #ifdef HAVE_SPRINTF int snprintf(char *str, size_t str_size, const char *format, ...); diff --git a/include/os_print.h b/include/os_print.h index 1480becf..9e0d293c 100644 --- a/include/os_print.h +++ b/include/os_print.h @@ -4,3 +4,10 @@ // avoid typing the size each time #define SPRINTF(strbuf, ...) snprintf(strbuf, sizeof(strbuf), __VA_ARGS__) + +#ifdef HAVE_PRINTF +void screen_printf(const char *format, ...); +void mcu_usb_printf(const char *format, ...); +#else // !HAVE_PRINTF +#define PRINTF(...) +#endif // !HAVE_PRINTF diff --git a/lib_cxng/include/lcx_aes.h b/lib_cxng/include/lcx_aes.h index 8530da61..45b0822c 100644 --- a/lib_cxng/include/lcx_aes.h +++ b/lib_cxng/include/lcx_aes.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,18 +28,18 @@ * for more details. */ -#ifdef HAVE_AES - #ifndef LCX_AES_H #define LCX_AES_H +#ifdef HAVE_AES + #include "cx_errors.h" #include "lcx_wrappers.h" #include "lcx_common.h" #include "ox_aes.h" /** - * @brief Initialize an AES Key. + * @brief Initializes an AES Key. * * @details Once initialized, the key can be stored in non-volatile memory * and directly used for any AES processing. @@ -48,13 +48,15 @@ * * @param[in] key_len Length of the key: 16, 24 or 32 octets. * - * @param[out] key Pointer to the key. + * @param[out] key Pointer to the key structure. This must not be NULL. * * @return Error code: * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_aes_init_key_no_throw(const uint8_t *rawkey, size_t key_len, cx_aes_key_t *key); +WARN_UNUSED_RESULT cx_err_t cx_aes_init_key_no_throw(const uint8_t *rawkey, + size_t key_len, + cx_aes_key_t *key); /** * @deprecated @@ -69,7 +71,7 @@ DEPRECATED static inline int cx_aes_init_key(const unsigned char *rawkey, } /** - * @brief Encrypt, Decrypt, Sign or Verify data with AES algorithm. + * @brief Encrypts, decrypts, signs or verifies data with AES algorithm. * * @param[in] key Pointer to the key initialized with #cx_aes_init_key_no_throw. * @@ -87,6 +89,9 @@ DEPRECATED static inline int cx_aes_init_key(const unsigned char *rawkey, * - CX_CHAIN_CBC * - CX_CHAIN_CTR * + * When using the CTR mode with AES, CX_ENCRYPT must be used for encryption + * and decryption. + * * @param[in] iv Initialization vector. * * @param[in] iv_len Length of the initialization vector. @@ -109,14 +114,14 @@ DEPRECATED static inline int cx_aes_init_key(const unsigned char *rawkey, * - CX_INVALID_PARAMETER * - INVALID_PARAMETER */ -cx_err_t cx_aes_iv_no_throw(const cx_aes_key_t *key, - uint32_t mode, - const uint8_t *iv, - size_t iv_len, - const uint8_t *in, - size_t in_len, - uint8_t *out, - size_t *out_len); +WARN_UNUSED_RESULT cx_err_t cx_aes_iv_no_throw(const cx_aes_key_t *key, + uint32_t mode, + const uint8_t *iv, + size_t iv_len, + const uint8_t *in, + size_t in_len, + uint8_t *out, + size_t *out_len); /** * @deprecated @@ -137,7 +142,7 @@ DEPRECATED static inline int cx_aes_iv(const cx_aes_key_t *key, } /** - * @brief Encrypt, Decrypt, Sign or Verify data with AES algorithm. + * @brief Encrypts, decrypts, signs or verifies data with AES algorithm. * * @details Same as #cx_aes_iv_no_throw with initial IV assumed to be sixteen zeros. * @@ -176,12 +181,12 @@ DEPRECATED static inline int cx_aes_iv(const cx_aes_key_t *key, * - CX_INVALID_PARAMETER * - INVALID_PARAMETER */ -cx_err_t cx_aes_no_throw(const cx_aes_key_t *key, - uint32_t mode, - const uint8_t *in, - size_t in_len, - uint8_t *out, - size_t *out_len); +WARN_UNUSED_RESULT cx_err_t cx_aes_no_throw(const cx_aes_key_t *key, + uint32_t mode, + const uint8_t *in, + size_t in_len, + uint8_t *out, + size_t *out_len); /** * @deprecated @@ -200,7 +205,7 @@ DEPRECATED static inline int cx_aes(const cx_aes_key_t *key, } /** - * @brief Encrypt a 16-byte block using AES algorithm. + * @brief Encrypts a 16-byte block using AES algorithm. * * @param[in] key Pointer to the AES key. * @@ -213,10 +218,12 @@ DEPRECATED static inline int cx_aes(const cx_aes_key_t *key, * - CX_INVALID_PARAMETER * - INVALID_PARAMETER */ -cx_err_t cx_aes_enc_block(const cx_aes_key_t *key, const uint8_t *inblock, uint8_t *outblock); +WARN_UNUSED_RESULT cx_err_t cx_aes_enc_block(const cx_aes_key_t *key, + const uint8_t *inblock, + uint8_t *outblock); /** - * @brief Decrypt a 16-byte block using AES algorithm. + * @brief Decrypts a 16-byte block using AES algorithm. * * @param[in] key Pointer to the AES key. * @@ -229,8 +236,10 @@ cx_err_t cx_aes_enc_block(const cx_aes_key_t *key, const uint8_t *inblock, uint8 * - CX_INVALID_PARAMETER * - INVALID_PARAMETER */ -cx_err_t cx_aes_dec_block(const cx_aes_key_t *key, const uint8_t *inblock, uint8_t *outblock); - -#endif +WARN_UNUSED_RESULT cx_err_t cx_aes_dec_block(const cx_aes_key_t *key, + const uint8_t *inblock, + uint8_t *outblock); #endif // HAVE_AES + +#endif // LCX_AES_H diff --git a/lib_cxng/include/lcx_blake2.h b/lib_cxng/include/lcx_blake2.h index 003699f1..3acd3e6e 100644 --- a/lib_cxng/include/lcx_blake2.h +++ b/lib_cxng/include/lcx_blake2.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,10 +24,11 @@ * produces digests of any size between 1 and 64 bytes. It is specified at https://blake2.net. */ -#ifdef HAVE_BLAKE2 #ifndef LCX_BLAKE2_H #define LCX_BLAKE2_H +#ifdef HAVE_BLAKE2 + #include "lcx_wrappers.h" #include "lcx_hash.h" #include @@ -67,7 +68,7 @@ struct cx_blake2b_s { typedef struct cx_blake2b_s cx_blake2b_t; /** - * @brief Initialize BLAKE2b message digest context. + * @brief Initializes BLAKE2b message digest context. * * @param[out] hash Pointer to the BLAKE2b context to initialize. * The context shall be in RAM. @@ -78,7 +79,7 @@ typedef struct cx_blake2b_s cx_blake2b_t; * - CX_OK * - CX_INVALID_PARAMETER */ -cx_err_t cx_blake2b_init_no_throw(cx_blake2b_t *hash, size_t out_len); +WARN_UNUSED_RESULT cx_err_t cx_blake2b_init_no_throw(cx_blake2b_t *hash, size_t out_len); /** * @deprecated @@ -91,7 +92,7 @@ DEPRECATED static inline int cx_blake2b_init(cx_blake2b_t *hash, unsigned int ou } /** - * @brief Initialize BLAKE2b message digest context with + * @brief Initializes BLAKE2b message digest context with * salt and personnalization string. * * @param[out] hash Pointer to the BLAKE2b context to initialize. @@ -111,12 +112,12 @@ DEPRECATED static inline int cx_blake2b_init(cx_blake2b_t *hash, unsigned int ou * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_blake2b_init2_no_throw(cx_blake2b_t *hash, - size_t out_len, - uint8_t *salt, - size_t salt_len, - uint8_t *perso, - size_t perso_len); +WARN_UNUSED_RESULT cx_err_t cx_blake2b_init2_no_throw(cx_blake2b_t *hash, + size_t out_len, + uint8_t *salt, + size_t salt_len, + uint8_t *perso, + size_t perso_len); /** * @deprecated @@ -133,6 +134,6 @@ DEPRECATED static inline int cx_blake2b_init2(cx_blake2b_t *hash, return CX_BLAKE2B; } -#endif - #endif // HAVE_BLAKE2 + +#endif // LCX_BLAKE2_H diff --git a/lib_cxng/include/lcx_common.h b/lib_cxng/include/lcx_common.h index dcc95623..59c95422 100644 --- a/lib_cxng/include/lcx_common.h +++ b/lib_cxng/include/lcx_common.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,7 +34,7 @@ #define ARCH_BIG_ENDIAN #endif -#ifdef __UINT64_TYPE__ +#if defined(__UINT64_TYPE__) && !defined(NATIVE_64BITS) #define NATIVE_64BITS #endif @@ -95,7 +95,7 @@ typedef uint64_t uint64bits_t; * | 2:1 | 0000000000000100 | CX_ENCRYPT | Encryption | AES/DES | * | 2:1 | 0000000000000010 | CX_VERIFY | Signature verification | AES/DES | * | 2:1 | 0000000000000000 | CX_DECRYPT | Decryption | AES/DES | - * | 0 | 0000000000000000 | CX_LAST | Last block | | + * | 0 | 0000000000000001 | CX_LAST | Last block | | */ // clang-format on #define CX_FLAG diff --git a/lib_cxng/include/lcx_crc.h b/lib_cxng/include/lcx_crc.h index 03ab781e..98fb545f 100644 --- a/lib_cxng/include/lcx_crc.h +++ b/lib_cxng/include/lcx_crc.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,11 +23,11 @@ * CRC-16 is a variant of CRC, an error-detecting code, with a 16-bit long check value. */ -#ifdef HAVE_CRC - #ifndef LCX_CRC_H #define LCX_CRC_H +#ifdef HAVE_CRC + #include #include @@ -35,7 +35,7 @@ #define CX_CRC16_INIT 0xFFFF /** - * @brief Compute a 16-bit checksum value. + * @brief Computes a 16-bit checksum value. * * @details The 16-bit value is computed according to the CRC16 CCITT definition. * @@ -48,7 +48,7 @@ uint16_t cx_crc16(const void *buffer, size_t len); /** - * @brief Accumulate more data to CRC. + * @brief Accumulates more data to CRC. * * @param[in] crc CRC value to be updated. * @@ -60,6 +60,6 @@ uint16_t cx_crc16(const void *buffer, size_t len); */ uint16_t cx_crc16_update(uint16_t crc, const void *buffer, size_t len); -#endif - #endif // HAVE_CRC + +#endif // LCX_CRC_H diff --git a/lib_cxng/include/lcx_des.h b/lib_cxng/include/lcx_des.h index c7b5dfce..17d114a8 100644 --- a/lib_cxng/include/lcx_des.h +++ b/lib_cxng/include/lcx_des.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,9 +21,10 @@ * @brief DES (Data Encryption Standard). * * DES is an encryption algorithm designed to encipher and decipher blocks of - * 64 bits under control of a 64-bit key. + * 64 bits under control of a 56-bit key. However, the key is represented with 64 bits. * - * Triple DES variant supports either a 128-bit or 192-bit key. + * Triple DES variant supports either a 128-bit (two 64-bit keys) or 192-bit key + * (three 64-bit keys). */ #ifdef HAVE_DES @@ -37,8 +38,17 @@ #include #include +/** Simple DES key length in bits */ +#define CX_DES_KEY_LENGTH 64 + +/** Key length in bits of a triple DES with 2 keys */ +#define CX_3DES_2_KEY_LENGTH 128 + +/** Key length in bits of a triple DES with 3 keys */ +#define CX_3DES_3_KEY_LENGTH 192 + /** - * @brief Initialize a DES key. + * @brief Initializes a DES key. * * @details Once initialized, the key can be stored in non-volatile memory * and directly used for any DES processing. @@ -47,7 +57,7 @@ * * @param[in] key_len Length of the key: 8, 16 or 24 octets. * - * @param[out] key Pointer to the key. + * @param[out] key Pointer to the key structure. This must not be NULL. * * @return Error code: * - CX_OK on success @@ -68,7 +78,7 @@ DEPRECATED static inline int cx_des_init_key(const unsigned char *rawkey, } /** - * @brief Encrypt, Decrypt, Sign or Verify data with DES algorithm. + * @brief Encrypts, decrypts, signs or verifies data with DES algorithm. * * @param[in] key Pointer to the key initialized with * #cx_des_init_key_no_throw. @@ -137,7 +147,7 @@ DEPRECATED static inline int cx_des_iv(const cx_des_key_t *key, } /** - * @brief Encrypt, Decrypt, Sign or Verify data with DES algorithm. + * @brief Encrypts, decrypts, signs or verifies data with DES algorithm. * * @param[in] key Pointer to the key initialized with * #cx_des_init_key_no_throw. @@ -198,7 +208,7 @@ DEPRECATED static inline int cx_des(const cx_des_key_t *key, } /** - * @brief Encrypt a 8-byte block using DES/3-DES algorithm. + * @brief Encrypts a 8-byte block using DES/3-DES algorithm. * * @param[in] key Pointer to the DES key. * @@ -214,7 +224,7 @@ DEPRECATED static inline int cx_des(const cx_des_key_t *key, void cx_des_enc_block(const cx_des_key_t *key, const uint8_t *inblock, uint8_t *outblock); /** - * @brief Decrypt a 8-byte block using DES/3-DES algorithm. + * @brief Decrypts a 8-byte block using DES/3-DES algorithm. * * @param[in] key Pointer to the DES key. * diff --git a/lib_cxng/include/lcx_ecdh.h b/lib_cxng/include/lcx_ecdh.h index 23286d46..dbf5e730 100644 --- a/lib_cxng/include/lcx_ecdh.h +++ b/lib_cxng/include/lcx_ecdh.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,11 +25,11 @@ * are elements of a chosen elliptic curve. */ -#ifdef HAVE_ECDH - #ifndef LCX_ECDH_H #define LCX_ECDH_H +#ifdef HAVE_ECDH + #if defined(HAVE_ECDH) || defined(HAVE_X25519) || defined(HAVE_X448) #include "lcx_wrappers.h" @@ -38,7 +38,7 @@ #if defined(HAVE_ECDH) /** - * @brief Compute an ECDH shared secret. + * @brief Computes an ECDH shared secret. * * @details Depending on the mode, the shared secret is either the full point or * only the *x* coordinate. @@ -72,12 +72,12 @@ * - CX_INVALID_PARAMETER_SIZE * - CX_EC_INFINITE_POINT */ -cx_err_t cx_ecdh_no_throw(const cx_ecfp_private_key_t *pvkey, - uint32_t mode, - const uint8_t *P, - size_t P_len, - uint8_t *secret, - size_t secret_len); +WARN_UNUSED_RESULT cx_err_t cx_ecdh_no_throw(const cx_ecfp_private_key_t *pvkey, + uint32_t mode, + const uint8_t *P, + size_t P_len, + uint8_t *secret, + size_t secret_len); /** * @deprecated @@ -107,7 +107,8 @@ DEPRECATED static inline int cx_ecdh(const cx_ecfp_private_key_t *pvkey, #if defined(HAVE_X25519) /** - * @brief Perform a scalar multiplication on Curve25519 with u-coordinate only. + * @brief Performs a scalar multiplication + * on Curve25519 with u-coordinate only. * * @details The notation (u, v) is used for Montgomery curves while (x, y) * is used for the birational equivalents (Edwards curves). @@ -131,12 +132,13 @@ DEPRECATED static inline int cx_ecdh(const cx_ecfp_private_key_t *pvkey, * - CX_EC_INFINITE_POINT * - CX_INVALID_PARAMETER_VALUE */ -cx_err_t cx_x25519(uint8_t *u, const uint8_t *k, size_t k_len); +WARN_UNUSED_RESULT cx_err_t cx_x25519(uint8_t *u, const uint8_t *k, size_t k_len); #endif // HAVE_X25519 #if defined(HAVE_X448) /** - * @brief Perform a scalar multiplication on Curve448 with u-coordinate only. + * @brief Performs a scalar multiplication + * on Curve448 with u-coordinate only. * * @details The notation (u, v) is used for Montgomery curves while (x, y) * is used for the birational equivalents (Edwards curves). @@ -160,7 +162,7 @@ cx_err_t cx_x25519(uint8_t *u, const uint8_t *k, size_t k_len); * - CX_EC_INFINITE_POINT * - CX_INVALID_PARAMETER_VALUE */ -cx_err_t cx_x448(uint8_t *u, const uint8_t *k, size_t k_len); +WARN_UNUSED_RESULT cx_err_t cx_x448(uint8_t *u, const uint8_t *k, size_t k_len); #endif // HAVE_X448 #endif // HAVE_ECDH || HAVE_X25519 || HAVE_X448 diff --git a/lib_cxng/include/lcx_ecdsa.h b/lib_cxng/include/lcx_ecdsa.h index 8b46ba32..d4e1dff6 100644 --- a/lib_cxng/include/lcx_ecdsa.h +++ b/lib_cxng/include/lcx_ecdsa.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,11 +25,11 @@ * RFC6979 for more details. */ -#ifdef HAVE_ECDSA - #ifndef LCX_ECDSA_H #define LCX_ECDSA_H +#ifdef HAVE_ECDSA + #include "lcx_wrappers.h" #include "lcx_ecfp.h" @@ -39,7 +39,7 @@ #define cx_ecdsa_init_private_key cx_ecfp_init_private_key_no_throw /** - * @brief Sign a message digest according to ECDSA specification + * @brief Signs a message digest according to ECDSA specification * * @param[in] pvkey Private key. * Shall be initialized with #cx_ecfp_init_private_key_no_throw. @@ -53,7 +53,8 @@ * This parameter is mandatory with the flag CX_RND_RFC6979. * * @param[in] hash Digest of the message to be signed. - * The length of *hash* must be shorter than the curve domain size. + * The length of *hash* must be shorter than the group order size. + * Otherwise it is truncated. * * @param[in] hash_len Length of the digest in octets. * @@ -79,14 +80,14 @@ * - CX_EC_INFINITE_POINT * - CX_INVALID_PARAMETER_VALUE */ -cx_err_t cx_ecdsa_sign_no_throw(const cx_ecfp_private_key_t *pvkey, - uint32_t mode, - cx_md_t hashID, - const uint8_t *hash, - size_t hash_len, - uint8_t *sig, - size_t *sig_len, - uint32_t *info); +WARN_UNUSED_RESULT cx_err_t cx_ecdsa_sign_no_throw(const cx_ecfp_private_key_t *pvkey, + uint32_t mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len, + uint32_t *info); /** * @deprecated @@ -151,18 +152,18 @@ DEPRECATED static inline int cx_ecdsa_sign(const cx_ecfp_private_key_t *pvkey, * - CX_EC_INFINITE_POINT * - CX_INVALID_PARAMETER_VALUE */ -cx_err_t cx_ecdsa_sign_rs_no_throw(const cx_ecfp_private_key_t *key, - uint32_t mode, - cx_md_t hashID, - const uint8_t *hash, - size_t hash_len, - size_t rs_len, - uint8_t *sig_r, - uint8_t *sig_s, - uint32_t *info); +WARN_UNUSED_RESULT cx_err_t cx_ecdsa_sign_rs_no_throw(const cx_ecfp_private_key_t *key, + uint32_t mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + size_t rs_len, + uint8_t *sig_r, + uint8_t *sig_s, + uint32_t *info); /** - * @brief Verify an ECDSA signature according to ECDSA specification. + * @brief Verifies an ECDSA signature according to ECDSA specification. * * @param[in] pukey Public key initialized with #cx_ecfp_init_public_key_no_throw. * @@ -179,15 +180,15 @@ cx_err_t cx_ecdsa_sign_rs_no_throw(const cx_ecfp_private_key_t *key, * * @return 1 if the signature is verified, 0 otherwise. */ -bool cx_ecdsa_verify_no_throw(const cx_ecfp_public_key_t *pukey, - const uint8_t *hash, - size_t hash_len, - const uint8_t *sig, - size_t sig_len); +WARN_UNUSED_RESULT bool cx_ecdsa_verify_no_throw(const cx_ecfp_public_key_t *pukey, + const uint8_t *hash, + size_t hash_len, + const uint8_t *sig, + size_t sig_len); /** * @deprecated - * See #cx_ecdsa_sign_no_throw + * See #cx_ecdsa_verify_no_throw */ DEPRECATED static inline bool cx_ecdsa_verify(const cx_ecfp_public_key_t *pukey, int mode, @@ -202,6 +203,6 @@ DEPRECATED static inline bool cx_ecdsa_verify(const cx_ecfp_public_key_t *pukey, return cx_ecdsa_verify_no_throw(pukey, hash, hash_len, sig, sig_len); } -#endif - #endif // HAVE_ECDSA + +#endif // LCX_ECDSA_H diff --git a/lib_cxng/include/lcx_ecfp.h b/lib_cxng/include/lcx_ecfp.h index 5c6bdc74..bca0b37a 100644 --- a/lib_cxng/include/lcx_ecfp.h +++ b/lib_cxng/include/lcx_ecfp.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,10 +23,11 @@ * Private and public keys initialization and key pair generation based on elliptic curves. */ -#ifdef HAVE_ECC #ifndef LCX_ECFP_H #define LCX_ECFP_H +#ifdef HAVE_ECC + #include "lcx_wrappers.h" #include "lcx_hash.h" #include "ox_ec.h" @@ -36,33 +37,33 @@ struct cx_ecfp_public_key_s { cx_curve_t curve; ///< Curve identifier size_t W_len; ///< Public key length in bytes - uint8_t W[1]; ///< Public key value starting at offset 0 + uint8_t W[1]; ///< Public key value }; /** Elliptic Curve private key */ struct cx_ecfp_private_key_s { cx_curve_t curve; ///< Curve identifier size_t d_len; ///< Private key length in bytes - uint8_t d[1]; ///< Private key value starting at offset 0 + uint8_t d[1]; ///< Private key value }; /** Up to 256-bit Elliptic Curve public key */ struct cx_ecfp_256_public_key_s { cx_curve_t curve; ///< Curve identifier size_t W_len; ///< Public key length in bytes - uint8_t W[65]; ///< Public key value starting at offset 0 + uint8_t W[65]; ///< Public key value }; /** Up to 256-bit Elliptic Curve private key */ struct cx_ecfp_256_private_key_s { cx_curve_t curve; ///< Curve identifier size_t d_len; ///< Private key length in bytes - uint8_t d[32]; ///< Private key value starting at offset 0 + uint8_t d[32]; ///< Private key value }; /** Up to 256-bit Elliptic Curve extended private key */ struct cx_ecfp_256_extended_private_key_s { cx_curve_t curve; ///< Curve identifier size_t d_len; ///< Public key length in bytes - uint8_t d[64]; ///< Public key value starting at offset 0 + uint8_t d[64]; ///< Public key value }; /** Convenience type. See #cx_ecfp_256_public_key_s. */ typedef struct cx_ecfp_256_public_key_s cx_ecfp_256_public_key_t; @@ -79,13 +80,13 @@ typedef struct cx_ecfp_256_private_key_s cx_ecfp_private_key_t; struct cx_ecfp_384_public_key_s { cx_curve_t curve; ///< Curve identifier size_t W_len; ///< Public key length in bytes - uint8_t W[97]; ///< Public key value starting at offset 0 + uint8_t W[97]; ///< Public key value }; /** Up to 384-bit Elliptic Curve private key */ struct cx_ecfp_384_private_key_s { cx_curve_t curve; ///< Curve identifier size_t d_len; ///< Private key length in bytes - uint8_t d[48]; ///< Private key value starting at offset 0 + uint8_t d[48]; ///< Private key value }; /** Convenience type. See #cx_ecfp_384_public_key_s. */ typedef struct cx_ecfp_384_private_key_s cx_ecfp_384_private_key_t; @@ -96,19 +97,19 @@ typedef struct cx_ecfp_384_public_key_s cx_ecfp_384_public_key_t; struct cx_ecfp_512_public_key_s { cx_curve_t curve; ///< Curve identifier size_t W_len; ///< Public key length in bytes - uint8_t W[129]; ///< Public key value starting at offset 0 + uint8_t W[129]; ///< Public key value }; /** Up to 512-bit Elliptic Curve private key */ struct cx_ecfp_512_private_key_s { cx_curve_t curve; ///< Curve identifier size_t d_len; ///< Private key length in bytes - uint8_t d[64]; ///< Private key value starting at offset 0 + uint8_t d[64]; ///< Private key value }; /** Up to 512-bit Elliptic Curve extended private key */ struct cx_ecfp_512_extented_private_key_s { cx_curve_t curve; ///< Curve identifier size_t d_len; ///< Private key length in bytes - uint8_t d[128]; ///< Private key value starting at offset 0 + uint8_t d[128]; ///< Private key value }; /** Convenience type. See #cx_ecfp_512_public_key_s. */ typedef struct cx_ecfp_512_public_key_s cx_ecfp_512_public_key_t; @@ -121,13 +122,13 @@ typedef struct cx_ecfp_512_extented_private_key_s cx_ecfp_512_extented_private_k struct cx_ecfp_640_public_key_s { cx_curve_t curve; ///< Curve identifier size_t W_len; ///< Public key length in bytes - uint8_t W[161]; ///< Public key value starting at offset 0 + uint8_t W[161]; ///< Public key value }; /** Up to 640-bit Elliptic Curve private key */ struct cx_ecfp_640_private_key_s { cx_curve_t curve; ///< Curve identifier size_t d_len; ///< Private key length in bytes - uint8_t d[80]; ///< Private key value starting at offset 0 + uint8_t d[80]; ///< Private key value }; /** Convenience type. See #cx_ecfp_640_public_key_s. */ typedef struct cx_ecfp_640_public_key_s cx_ecfp_640_public_key_t; @@ -135,7 +136,7 @@ typedef struct cx_ecfp_640_public_key_s cx_ecfp_640_public_key_t; typedef struct cx_ecfp_640_private_key_s cx_ecfp_640_private_key_t; /** - * @brief Add two points of an elliptic curve. + * @brief Adds two points of an elliptic curve. * * @param[in] curve Curve identifier. * @@ -159,10 +160,10 @@ typedef struct cx_ecfp_640_private_key_s cx_ecfp_640_private_key_t; * - CX_EC_INVALID_POINT * - CX_EC_INFINITE_POINT */ -cx_err_t cx_ecfp_add_point_no_throw(cx_curve_t curve, - uint8_t *R, - const uint8_t *P, - const uint8_t *Q); +WARN_UNUSED_RESULT cx_err_t cx_ecfp_add_point_no_throw(cx_curve_t curve, + uint8_t *R, + const uint8_t *P, + const uint8_t *Q); /** * @deprecated @@ -185,7 +186,7 @@ DEPRECATED static inline int cx_ecfp_add_point(cx_curve_t curve, } /** - * @brief Perform a scalar multiplication over an elliptic curve. + * @brief Performs a scalar multiplication over an elliptic curve. * * @param[in] curve Curve identifier. * @@ -209,7 +210,10 @@ DEPRECATED static inline int cx_ecfp_add_point(cx_curve_t curve, * - CX_INVALID_PARAMETER * - CX_EC_INFINITE_POINT */ -cx_err_t cx_ecfp_scalar_mult_no_throw(cx_curve_t curve, uint8_t *P, const uint8_t *k, size_t k_len); +WARN_UNUSED_RESULT cx_err_t cx_ecfp_scalar_mult_no_throw(cx_curve_t curve, + uint8_t *P, + const uint8_t *k, + size_t k_len); /** * @deprecated @@ -232,7 +236,7 @@ DEPRECATED static inline int cx_ecfp_scalar_mult(cx_curve_t curve, } /** - * @brief Initialize a public key. + * @brief Initializes a public key. * * @param[in] curve Curve identifier. * @@ -254,10 +258,10 @@ DEPRECATED static inline int cx_ecfp_scalar_mult(cx_curve_t curve, * - CX_EC_INVALID_CURVE * - INVALID_PARAMETER */ -cx_err_t cx_ecfp_init_public_key_no_throw(cx_curve_t curve, - const uint8_t *rawkey, - size_t key_len, - cx_ecfp_public_key_t *key); +WARN_UNUSED_RESULT cx_err_t cx_ecfp_init_public_key_no_throw(cx_curve_t curve, + const uint8_t *rawkey, + size_t key_len, + cx_ecfp_public_key_t *key); /** * @deprecated @@ -273,7 +277,7 @@ DEPRECATED static inline int cx_ecfp_init_public_key(cx_curve_t curve } /** - * @brief Initialize a private key. + * @brief Initializes a private key. * * @details The key can be stored in non-volatile memory and * used for ECDSA or ECDH processing. @@ -292,10 +296,10 @@ DEPRECATED static inline int cx_ecfp_init_public_key(cx_curve_t curve * - CX_EC_INVALID_CURVE * - CX_INVALID_PARAMETER */ -cx_err_t cx_ecfp_init_private_key_no_throw(cx_curve_t curve, - const uint8_t *rawkey, - size_t key_len, - cx_ecfp_private_key_t *pvkey); +WARN_UNUSED_RESULT cx_err_t cx_ecfp_init_private_key_no_throw(cx_curve_t curve, + const uint8_t *rawkey, + size_t key_len, + cx_ecfp_private_key_t *pvkey); /** * @deprecated @@ -311,7 +315,7 @@ DEPRECATED static inline int cx_ecfp_init_private_key(cx_curve_t cur } /** - * @brief Generate a key pair with SHA-512 hash function. + * @brief Generates a key pair with SHA-512 hash function. * * @param[in] curve Curve identifier. * @@ -335,10 +339,10 @@ DEPRECATED static inline int cx_ecfp_init_private_key(cx_curve_t cur * - CX_EC_INVALID_POINT * - CX_EC_INFINITE_POINT */ -cx_err_t cx_ecfp_generate_pair_no_throw(cx_curve_t curve, - cx_ecfp_public_key_t *pubkey, - cx_ecfp_private_key_t *privkey, - bool keepprivate); +WARN_UNUSED_RESULT cx_err_t cx_ecfp_generate_pair_no_throw(cx_curve_t curve, + cx_ecfp_public_key_t *pubkey, + cx_ecfp_private_key_t *privkey, + bool keepprivate); /** * @deprecated @@ -354,7 +358,7 @@ DEPRECATED static inline int cx_ecfp_generate_pair(cx_curve_t curve, } /** - * @brief Generate a key pair. + * @brief Generates a key pair. * * @param[in] curve Curve identifier. * @@ -380,11 +384,11 @@ DEPRECATED static inline int cx_ecfp_generate_pair(cx_curve_t curve, * - CX_EC_INVALID_POINT * - CX_EC_INFINITE_POINT */ -cx_err_t cx_ecfp_generate_pair2_no_throw(cx_curve_t curve, - cx_ecfp_public_key_t *pubkey, - cx_ecfp_private_key_t *privkey, - bool keepprivate, - cx_md_t hashID); +WARN_UNUSED_RESULT cx_err_t cx_ecfp_generate_pair2_no_throw(cx_curve_t curve, + cx_ecfp_public_key_t *pubkey, + cx_ecfp_private_key_t *privkey, + bool keepprivate, + cx_md_t hashID); /** * @deprecated @@ -403,10 +407,10 @@ DEPRECATED static inline int cx_ecfp_generate_pair2(cx_curve_t curve #ifdef HAVE_ECC_TWISTED_EDWARDS /** - * @brief Retrieve an EDDSA public key. + * @brief Retrieves an EDDSA public key. * - * @details Retrieve (a,h) = (Kr, Kl), such that (Kr, Kl) = Hash(pv_key) - * as specified in RFC8032 . + * @details Retrieves (a,h) = (Kr, Kl), such that (Kr, Kl) = Hash(pv_key) + * as specified at RFC8032 . * * @param[in] pvkey A private key fully initialized with #cx_ecfp_init_private_key_no_throw. * @@ -436,13 +440,13 @@ DEPRECATED static inline int cx_ecfp_generate_pair2(cx_curve_t curve * - CX_INTERNAL_ERROR * */ -cx_err_t cx_eddsa_get_public_key_no_throw(const cx_ecfp_private_key_t *pvkey, - cx_md_t hashID, - cx_ecfp_public_key_t *pukey, - uint8_t *a, - size_t a_len, - uint8_t *h, - size_t h_len); +WARN_UNUSED_RESULT cx_err_t cx_eddsa_get_public_key_no_throw(const cx_ecfp_private_key_t *pvkey, + cx_md_t hashID, + cx_ecfp_public_key_t *pukey, + uint8_t *a, + size_t a_len, + uint8_t *h, + size_t h_len); /** * @deprecated @@ -460,8 +464,8 @@ DEPRECATED static inline void cx_eddsa_get_public_key(const cx_ecfp_private_key_ } /** - * @brief Compress a point according to RFC8032 - * . + * @brief Compresses a point according to + * RFC8032 . * * @param[in] curve Curve identifier. The curve must be * a Twisted Edwards curve. @@ -481,7 +485,9 @@ DEPRECATED static inline void cx_eddsa_get_public_key(const cx_ecfp_private_key_ * - CX_INVALID_PARAMETER * - CX_EC_INFINITE_POINT */ -cx_err_t cx_edwards_compress_point_no_throw(cx_curve_t curve, uint8_t *p, size_t p_len); +WARN_UNUSED_RESULT cx_err_t cx_edwards_compress_point_no_throw(cx_curve_t curve, + uint8_t *p, + size_t p_len); /** * @deprecated @@ -493,8 +499,8 @@ DEPRECATED static inline void cx_edwards_compress_point(cx_curve_t curve, uint8_ } /** - * @brief Decompress a point according to RFC8032 - * . + * @brief Decompresses a point according to + * RFC8032 . * * @param[in] curve Curve identifier. The curve must be * a Twisted Edwards curve. @@ -516,7 +522,9 @@ DEPRECATED static inline void cx_edwards_compress_point(cx_curve_t curve, uint8_ * - CX_NO_RESIDUE * - INVALID_PARAMETER */ -cx_err_t cx_edwards_decompress_point_no_throw(cx_curve_t curve, uint8_t *p, size_t p_len); +WARN_UNUSED_RESULT cx_err_t cx_edwards_decompress_point_no_throw(cx_curve_t curve, + uint8_t *p, + size_t p_len); /** * @deprecated @@ -549,6 +557,6 @@ DEPRECATED static inline void cx_edward_decompress_point(cx_curve_t curve, uint8 #endif // HAVE_ECC_TWISTED_EDWARDS -#endif - #endif // HAVE_ECC + +#endif // LCX_ECFP_H diff --git a/lib_cxng/include/lcx_ecschnorr.h b/lib_cxng/include/lcx_ecschnorr.h index 9a169d19..09cf2fd3 100644 --- a/lib_cxng/include/lcx_ecschnorr.h +++ b/lib_cxng/include/lcx_ecschnorr.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +32,7 @@ #define LCX_ECSCHNORR_H /** - * @brief Sign a digest message according to the given mode. + * @brief Signs a digest message according to the given mode. * * @param[in] pvkey Pointer to the private key initialized with * #cx_ecfp_init_private_key_no_throw beforehand. @@ -43,6 +43,7 @@ * - CX_ECSCHNORR_BSI03111 * - CX_ECSCHNORR_LIBSECP * - CX_ECSCHNORR_Z + * - CX_ECSCHNORR_BIP0340 * * @param[in] hashID Message digest algorithm identifier. * This parameter is mandatory when @@ -54,8 +55,7 @@ * @param[in] msg_len Length of input data. * * @param[out] sig ECSchnorr signature encoded in TLV: **30 || L || 02 || Lr || r || 02 || Ls || - * s**. - * + * s**. This parameter holds the auxiliary random data when CX_ECSCHNORR_BIP0340 is used. * * @param[in] sig_len Length of the signature. * @@ -71,13 +71,13 @@ * - CX_EC_INFINITE_POINT * - CX_INVALID_PARAMETER_VALUE */ -cx_err_t cx_ecschnorr_sign_no_throw(const cx_ecfp_private_key_t *pvkey, - uint32_t mode, - cx_md_t hashID, - const uint8_t *msg, - size_t msg_len, - uint8_t *sig, - size_t *sig_len); +WARN_UNUSED_RESULT cx_err_t cx_ecschnorr_sign_no_throw(const cx_ecfp_private_key_t *pvkey, + uint32_t mode, + cx_md_t hashID, + const uint8_t *msg, + size_t msg_len, + uint8_t *sig, + size_t *sig_len); /** * @deprecated @@ -98,7 +98,7 @@ DEPRECATED static inline int cx_ecschnorr_sign(const cx_ecfp_private_key_t *pvke } /** - * @brief Verify a hash message signature according to the given mode. + * @brief Verifies a digest message signature according to the given mode. * * @param[in] pukey Pointer to the public key initialized with * #cx_ecfp_init_private_key_no_throw beforehand. @@ -128,13 +128,13 @@ DEPRECATED static inline int cx_ecschnorr_sign(const cx_ecfp_private_key_t *pvke * * @return 1 if signature is verified, 0 otherwise. */ -bool cx_ecschnorr_verify(const cx_ecfp_public_key_t *pukey, - uint32_t mode, - cx_md_t hashID, - const uint8_t *msg, - size_t msg_len, - const uint8_t *sig, - size_t sig_len); +WARN_UNUSED_RESULT bool cx_ecschnorr_verify(const cx_ecfp_public_key_t *pukey, + uint32_t mode, + cx_md_t hashID, + const uint8_t *msg, + size_t msg_len, + const uint8_t *sig, + size_t sig_len); #endif diff --git a/lib_cxng/include/lcx_eddsa.h b/lib_cxng/include/lcx_eddsa.h index 1632ce83..383d7e6e 100644 --- a/lib_cxng/include/lcx_eddsa.h +++ b/lib_cxng/include/lcx_eddsa.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,18 +25,18 @@ * for more details. */ -#ifdef HAVE_EDDSA +#ifndef LCX_EDDSA_H +#define LCX_EDDSA_H #include "lcx_ecfp.h" #include "lcx_wrappers.h" -#ifndef LCX_EDDSA_H -#define LCX_EDDSA_H +#ifdef HAVE_EDDSA /** - * @brief Sign a message digest. + * @brief Signs a message digest. * - * @details Sign a message digest according to the EDDSA specification + * @details The signature is done according to the EDDSA specification * RFC8032 . * * @param[in] pvkey Private key. @@ -71,12 +71,12 @@ * - CX_INTERNAL_ERROR * - CX_INVALID_PARAMETER_VALUE */ -cx_err_t cx_eddsa_sign_no_throw(const cx_ecfp_private_key_t *pvkey, - cx_md_t hashID, - const uint8_t *hash, - size_t hash_len, - uint8_t *sig, - size_t sig_len); +WARN_UNUSED_RESULT cx_err_t cx_eddsa_sign_no_throw(const cx_ecfp_private_key_t *pvkey, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t sig_len); /** * @deprecated @@ -107,9 +107,9 @@ DEPRECATED static inline int cx_eddsa_sign(const cx_ecfp_private_key_t *pvkey, } /** - * @brief Verify a signature. + * @brief Verifies a signature. * - * @details Verify a signature according to the specification + * @details The verification is done according to the specification * RFC8032 . * * @param[in] pukey Public key. @@ -131,17 +131,17 @@ DEPRECATED static inline int cx_eddsa_sign(const cx_ecfp_private_key_t *pvkey, * * @return 1 if the signature is verified, otherwise 0. */ -bool cx_eddsa_verify_no_throw(const cx_ecfp_public_key_t *pukey, - cx_md_t hashID, - const uint8_t *hash, - size_t hash_len, - const uint8_t *sig, - size_t sig_len); +WARN_UNUSED_RESULT bool cx_eddsa_verify_no_throw(const cx_ecfp_public_key_t *pukey, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + const uint8_t *sig, + size_t sig_len); /** - * @brief Verify a signature. + * @brief Verifies a signature. * - * @details Verify a signature according to the specification + * @details The verification is done according to the specification * RFC8032 . * This function throws an exception if the computation doesn't * succeed. @@ -189,28 +189,28 @@ static inline int cx_eddsa_verify(const cx_ecfp_public_key_t *pukey, } /** - * @brief Encode the curve point coordinates. + * @brief Encodes the curve point coordinates. * - * @param[in] coord A pointer to the point coordinates in the form x|y. + * @param[in, out] coord A pointer to the point coordinates in the form x|y. * - * @param[in] len Length of the coordinates. + * @param[in] len Length of the coordinates. * - * @param[in] sign Sign of the x-coordinate. + * @param[in] sign Sign of the x-coordinate. * */ void cx_encode_coord(uint8_t *coord, int len, int sign); /** - * @brief Decode the curve point coordinates. + * @brief Decodes the curve point coordinates. * - * @param[in] coord A pointer to the point encoded coordinates. + * @param[in, out] coord A pointer to the point encoded coordinates. * - * @param[in] len Length of the encoded coordinates. + * @param[in] len Length of the encoded coordinates. * - * @return Sign of the x-coordinate. + * @return Sign of the x-coordinate. */ int cx_decode_coord(uint8_t *coord, int len); -#endif - #endif // HAVE_EDDSA + +#endif // LCX_EDDSA_H diff --git a/lib_cxng/include/lcx_groestl.h b/lib_cxng/include/lcx_groestl.h index 4ae7b993..f22e7bd4 100644 --- a/lib_cxng/include/lcx_groestl.h +++ b/lib_cxng/include/lcx_groestl.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -62,9 +62,9 @@ struct cx_groestl_s { typedef struct cx_groestl_s cx_groestl_t; /** - * @brief Initialize a GROESTL224 context. + * @brief Initializes a GROESTL context. * - * @param[out] hash Pointer to the context to init. + * @param[out] hash Pointer to the context to initialize. * * @param[in] size Length of the digest. * @@ -72,7 +72,7 @@ typedef struct cx_groestl_s cx_groestl_t; * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_groestl_init_no_throw(cx_groestl_t *hash, size_t size); +WARN_UNUSED_RESULT cx_err_t cx_groestl_init_no_throw(cx_groestl_t *hash, size_t size); /** * @deprecated diff --git a/lib_cxng/include/lcx_hash.h b/lib_cxng/include/lcx_hash.h index afcc51a8..f241999b 100644 --- a/lib_cxng/include/lcx_hash.h +++ b/lib_cxng/include/lcx_hash.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,11 +37,11 @@ * - SHA512 */ -#ifdef HAVE_HASH - #ifndef LCX_HASH_H #define LCX_HASH_H +#ifdef HAVE_HASH + #include "cx_errors.h" #include "lcx_wrappers.h" #include "lcx_common.h" @@ -116,7 +116,7 @@ struct cx_hash_header_s { size_t cx_hash_get_size(const cx_hash_t *ctx); /** - * @brief Hash data according to the specified algorithm. + * @brief Hashes data according to the specified algorithm. * * @param[in] hash Pointer to the hash context. * Shall be in RAM. @@ -136,19 +136,19 @@ size_t cx_hash_get_size(const cx_hash_t *ctx); * - message digest if CX_LAST is set * * @param[out] out_len The size of the output buffer or 0 if out is NULL. - * If buffer is too small to store the hash a exception is returned. + * If buffer is too small to store the hash an error is returned. * * @return Error code: * - CX_OK on success * - INVALID_PARAMETER * - CX_INVALID_PARAMETER */ -cx_err_t cx_hash_no_throw(cx_hash_t *hash, - uint32_t mode, - const uint8_t *in, - size_t len, - uint8_t *out, - size_t out_len); +WARN_UNUSED_RESULT cx_err_t cx_hash_no_throw(cx_hash_t *hash, + uint32_t mode, + const uint8_t *in, + size_t len, + uint8_t *out, + size_t out_len); /** * @deprecated @@ -166,7 +166,7 @@ DEPRECATED static inline int cx_hash(cx_hash_t *hash, } /** - * @brief Initialize a hash context. + * @brief Initializes a hash context. * * @param[out] hash Pointer to the context to be initialized. * The context shall be in RAM. @@ -177,12 +177,12 @@ DEPRECATED static inline int cx_hash(cx_hash_t *hash, * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_hash_init(cx_hash_t *hash, cx_md_t hash_id); +WARN_UNUSED_RESULT cx_err_t cx_hash_init(cx_hash_t *hash, cx_md_t hash_id); /** - * @brief Initialize a hash context. + * @brief Initializes a hash context. * - * @details Initialize a hash context with a chosen output length + * @details It initializes a hash context with a chosen output length * (typically for eXtendable Output Functions (XOF)). * * @param[out] hash Pointer to the context to be initialized. @@ -200,10 +200,10 @@ cx_err_t cx_hash_init(cx_hash_t *hash, cx_md_t hash_id); * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_hash_init_ex(cx_hash_t *hash, cx_md_t hash_id, size_t output_size); +WARN_UNUSED_RESULT cx_err_t cx_hash_init_ex(cx_hash_t *hash, cx_md_t hash_id, size_t output_size); /** - * @brief Add more data to hash. + * @brief Adds more data to hash. * * @details A call to this function is equivalent to: * *cx_hash_no_throw(hash, 0, in, in_len, NULL, 0)*. @@ -219,10 +219,10 @@ cx_err_t cx_hash_init_ex(cx_hash_t *hash, cx_md_t hash_id, size_t output_size); * - CX_INVALID_PARAMETER * - INVALID_PARAMETER */ -cx_err_t cx_hash_update(cx_hash_t *hash, const uint8_t *in, size_t in_len); +WARN_UNUSED_RESULT cx_err_t cx_hash_update(cx_hash_t *hash, const uint8_t *in, size_t in_len); /** - * @brief Finalize the hash. + * @brief Finalizes the hash. * * @details A call to this function is equivalent to: * *cx_hash_no_throw(hash, CX_LAST, NULL, 0, out, out_len)*. @@ -234,8 +234,8 @@ cx_err_t cx_hash_update(cx_hash_t *hash, const uint8_t *in, size_t in_len); * @return Error code: * - CX_OK on success */ -cx_err_t cx_hash_final(cx_hash_t *hash, uint8_t *digest); - -#endif +WARN_UNUSED_RESULT cx_err_t cx_hash_final(cx_hash_t *hash, uint8_t *digest); #endif // HAVE_HASH + +#endif // LCX_HASH_H diff --git a/lib_cxng/include/lcx_hmac.h b/lib_cxng/include/lcx_hmac.h index 10e56518..e5823755 100644 --- a/lib_cxng/include/lcx_hmac.h +++ b/lib_cxng/include/lcx_hmac.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,11 +24,12 @@ * which involves a hash function and a secret key. It enables * the verification of the integrity and the authenticity of a message. */ -#ifdef HAVE_HMAC #ifndef LCX_HMAC_H #define LCX_HMAC_H +#ifdef HAVE_HMAC + #include "lcx_wrappers.h" #include "lcx_hash.h" #include "lcx_ripemd160.h" @@ -56,14 +57,14 @@ typedef struct { } cx_hmac_ripemd160_t; /** - * @brief Initialize a HMAC-RIPEMD160 context. + * @brief Initializes a HMAC-RIPEMD160 context. * * @param[out] hmac Pointer to the HMAC context. * The context shall be in RAM. * * @param[in] key Pointer to the HMAC key value. * If a key has been set, passing - * NULL pointeur will reinitialize + * NULL pointer will reinitialize * the context with the previously set key. * * @param [in] key_len Length of the key. @@ -73,9 +74,9 @@ typedef struct { * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_hmac_ripemd160_init_no_throw(cx_hmac_ripemd160_t *hmac, - const uint8_t *key, - size_t key_len); +WARN_UNUSED_RESULT cx_err_t cx_hmac_ripemd160_init_no_throw(cx_hmac_ripemd160_t *hmac, + const uint8_t *key, + size_t key_len); /** * @deprecated @@ -103,14 +104,14 @@ typedef struct { #ifdef HAVE_SHA224 /** - * @brief Initialize a HMAC-SHA224 context. + * @brief Initializes a HMAC-SHA224 context. * * @param[out] hmac Pointer to the HMAC context. * The context shall be in RAM. * * @param[in] key Pointer to the HMAC key value. * If a key has been set, passing - * NULL pointeur will reinitialize + * NULL pointer will reinitialize * the context with the previously set key. * * @param [in] key_len Length of the key. @@ -120,20 +121,22 @@ typedef struct { * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_hmac_sha224_init(cx_hmac_sha256_t *hmac, const uint8_t *key, unsigned int key_len); +WARN_UNUSED_RESULT cx_err_t cx_hmac_sha224_init(cx_hmac_sha256_t *hmac, + const uint8_t *key, + unsigned int key_len); #endif #ifdef HAVE_SHA256 /** - * @brief Initialize a HMAC-SHA256 context. + * @brief Initializes a HMAC-SHA256 context. * * @param[out] hmac Pointer to the HMAC context. * The context shall be in RAM. * * @param[in] key Pointer to the HMAC key value. * If a key has been set, passing - * NULL pointeur will reinitialize + * NULL pointer will reinitialize * the context with the previously set key. * * @param [in] key_len Length of the key. @@ -143,7 +146,9 @@ cx_err_t cx_hmac_sha224_init(cx_hmac_sha256_t *hmac, const uint8_t *key, unsigne * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_hmac_sha256_init_no_throw(cx_hmac_sha256_t *hmac, const uint8_t *key, size_t key_len); +WARN_UNUSED_RESULT cx_err_t cx_hmac_sha256_init_no_throw(cx_hmac_sha256_t *hmac, + const uint8_t *key, + size_t key_len); /** * @deprecated @@ -158,7 +163,7 @@ DEPRECATED static inline int cx_hmac_sha256_init(cx_hmac_sha256_t *hmac, } /** - * @brief Compute a HMAC value using SHA256. + * @brief Computes a HMAC value using SHA256. * * @param[in] key HMAC key value. * @@ -198,14 +203,14 @@ typedef struct { #ifdef HAVE_SHA384 /** - * @brief Initialize a HMAC-SHA384 context. + * @brief Initializes a HMAC-SHA384 context. * * @param[out] hmac Pointer to the context. * The context shall be in RAM. * * @param[in] key Pointer to the HMAC key value. * If a key has been set, passing - * NULL pointeur will reinitialize + * NULL pointer will reinitialize * the context with the previously set key. * * @param[in] key_len Length of the key. @@ -215,20 +220,22 @@ typedef struct { * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_hmac_sha384_init(cx_hmac_sha512_t *hmac, const uint8_t *key, unsigned int key_len); +WARN_UNUSED_RESULT cx_err_t cx_hmac_sha384_init(cx_hmac_sha512_t *hmac, + const uint8_t *key, + unsigned int key_len); #endif #ifdef HAVE_SHA512 /** - * @brief Initialize a HMAC-SHA512 context. + * @brief Initializes a HMAC-SHA512 context. * * @param[out] hmac Pointer to the context. * The context shall be in RAM. * * @param[in] key Pointer to the HMAC key value. * If a key has been set, passing - * NULL pointeur will reinitialize + * NULL pointer will reinitialize * the context with the previously set key. * * @param[in] key_len Length of the key. @@ -238,7 +245,9 @@ cx_err_t cx_hmac_sha384_init(cx_hmac_sha512_t *hmac, const uint8_t *key, unsigne * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_hmac_sha512_init_no_throw(cx_hmac_sha512_t *hmac, const uint8_t *key, size_t key_len); +WARN_UNUSED_RESULT cx_err_t cx_hmac_sha512_init_no_throw(cx_hmac_sha512_t *hmac, + const uint8_t *key, + size_t key_len); /** * @deprecated @@ -253,7 +262,7 @@ DEPRECATED static inline int cx_hmac_sha512_init(cx_hmac_sha512_t *hmac, } /** - * @brief Compute a HMAC value using SHA512. + * @brief Computes a HMAC value using SHA512. * * @param[in] key HMAC key value. * @@ -281,7 +290,7 @@ size_t cx_hmac_sha512(const uint8_t *key, #endif /** - * @brief Compute a HMAC value according to the specified + * @brief Computes a HMAC value according to the specified * hash function. * * @param[in] hmac Pointer to the HMAC context. @@ -311,12 +320,12 @@ size_t cx_hmac_sha512(const uint8_t *key, * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_hmac_no_throw(cx_hmac_t *hmac, - uint32_t mode, - const uint8_t *in, - size_t len, - uint8_t *mac, - size_t mac_len); +WARN_UNUSED_RESULT cx_err_t cx_hmac_no_throw(cx_hmac_t *hmac, + uint32_t mode, + const uint8_t *in, + size_t len, + uint8_t *mac, + size_t mac_len); /** * @deprecated @@ -359,16 +368,16 @@ DEPRECATED static inline int cx_hmac(cx_hmac_t *hmac, } /** - * @brief Initialize a HMAC context. + * @brief Initializes a HMAC context. * * @param[out] hmac Pointer to the context. * The context shall be in RAM. * - * @param[in] hash_id The message digest algorithm identifier + * @param[in] hash_id The message digest algorithm identifier. * * @param[in] key Pointer to the HMAC key value. * If a key has been set, passing - * NULL pointeur will reinitialize + * NULL pointer will reinitialize * the context with the previously set key. * * @param[in] key_len Length of the key. @@ -378,10 +387,13 @@ DEPRECATED static inline int cx_hmac(cx_hmac_t *hmac, * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_hmac_init(cx_hmac_t *hmac, cx_md_t hash_id, const uint8_t *key, size_t key_len); +WARN_UNUSED_RESULT cx_err_t cx_hmac_init(cx_hmac_t *hmac, + cx_md_t hash_id, + const uint8_t *key, + size_t key_len); /** - * @brief Add more data to compute the HMAC. + * @brief Adds more data to compute the HMAC. * * @details A call to this function is equivalent to: * *cx_hmac_no_throw(hmac, 0, in, in_len, NULL, 0)*. @@ -397,15 +409,16 @@ cx_err_t cx_hmac_init(cx_hmac_t *hmac, cx_md_t hash_id, const uint8_t *key, size * - CX_INVALID_PARAMETER * - INVALID_PARAMETER */ -cx_err_t cx_hmac_update(cx_hmac_t *hmac, const uint8_t *in, size_t in_len); +WARN_UNUSED_RESULT cx_err_t cx_hmac_update(cx_hmac_t *hmac, const uint8_t *in, size_t in_len); /** - * @brief Finalize the HMAC algorithm. + * @brief Finalizes the HMAC algorithm. * * @details A call to this function is * equivalent to *cx_hmac_no_throw(hash, CX_LAST, NULL, 0, out, out_len)*. * * @param[in] ctx Pointer to the HMAC context. + * * @param[out] out Computed HMAC value is CX_LAST is set. * * @param[in] out_len Length of the output (the most significant bytes). @@ -413,8 +426,8 @@ cx_err_t cx_hmac_update(cx_hmac_t *hmac, const uint8_t *in, size_t in_len); * @return Error code: * - CX_OK on success */ -cx_err_t cx_hmac_final(cx_hmac_t *ctx, uint8_t *out, size_t *out_len); - -#endif +WARN_UNUSED_RESULT cx_err_t cx_hmac_final(cx_hmac_t *ctx, uint8_t *out, size_t *out_len); #endif // HAVE_HMAC + +#endif // LCX_HMAC_H diff --git a/lib_cxng/include/lcx_math.h b/lib_cxng/include/lcx_math.h index 5761afb4..40b9a90d 100644 --- a/lib_cxng/include/lcx_math.h +++ b/lib_cxng/include/lcx_math.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,16 +21,16 @@ * @brief Basic arithmetic. */ -#ifdef HAVE_MATH - #ifndef LCX_MATH_H #define LCX_MATH_H +#ifdef HAVE_MATH + #include "lcx_wrappers.h" #include "ox_bn.h" /** - * @brief Compare two integers represented as byte arrays. + * @brief Compares two integers represented as byte arrays. * * @param[in] a Pointer to the first integer. * @@ -51,7 +51,10 @@ * - CX_MEMORY_FULL * - CX_INVALID_PARAMETER */ -cx_err_t cx_math_cmp_no_throw(const uint8_t *a, const uint8_t *b, size_t length, int *diff); +WARN_UNUSED_RESULT cx_err_t cx_math_cmp_no_throw(const uint8_t *a, + const uint8_t *b, + size_t length, + int *diff); /** * @deprecated @@ -65,7 +68,7 @@ DEPRECATED static inline int32_t cx_math_cmp(const uint8_t *a, const uint8_t *b, } /** - * @brief Add two integers represented as byte arrays. + * @brief Adds two integers represented as byte arrays. * * @param[out] r Buffer for the result. * @@ -83,14 +86,20 @@ DEPRECATED static inline int32_t cx_math_cmp(const uint8_t *a, const uint8_t *b, * - CX_MEMORY_FULL * - CX_INVALID_PARAMETER */ -cx_err_t cx_math_add_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len); +WARN_UNUSED_RESULT cx_err_t cx_math_add_no_throw(uint8_t *r, + const uint8_t *a, + const uint8_t *b, + size_t len); /** - * @brief Add two integers represented as byte arrays. + * @brief Adds two integers represented as byte arrays. * * @details This function throws an exception if the computation * doesn't succeed. * + * @warning It is recommended to use #cx_math_add_no_throw rather + * than this function. + * * @param[out] r Buffer for the result. * * @param[in] a Pointer to the first integer. @@ -117,7 +126,7 @@ static inline uint32_t cx_math_add(uint8_t *r, const uint8_t *a, const uint8_t * } /** - * @brief Subtract two integers represented as byte arrays. + * @brief Subtracts two integers represented as byte arrays. * * @param[out] r Buffer for the result. * @@ -135,14 +144,20 @@ static inline uint32_t cx_math_add(uint8_t *r, const uint8_t *a, const uint8_t * * - CX_MEMORY_FULL * - CX_INVALID_PARAMETER */ -cx_err_t cx_math_sub_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len); +WARN_UNUSED_RESULT cx_err_t cx_math_sub_no_throw(uint8_t *r, + const uint8_t *a, + const uint8_t *b, + size_t len); /** - * @brief Subtract two integers represented as byte arrays. + * @brief Subtracts two integers represented as byte arrays. * * @details This function throws an exception if the computation * doesn't succeed. * + * @warning It is recommended to use #cx_math_sub_no_throw rather + * than this function. + * * @param[out] r Buffer for the result. * * @param[in] a Pointer to the first integer. @@ -169,7 +184,7 @@ static inline uint32_t cx_math_sub(uint8_t *r, const uint8_t *a, const uint8_t * } /** - * @brief Multiply two integers represented as byte arrays. + * @brief Multiplies two integers represented as byte arrays. * * @param[out] r Buffer for the result. * @@ -187,7 +202,10 @@ static inline uint32_t cx_math_sub(uint8_t *r, const uint8_t *a, const uint8_t * * - CX_MEMORY_FULL * - CX_INVALID_PARAMETER */ -cx_err_t cx_math_mult_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len); +WARN_UNUSED_RESULT cx_err_t cx_math_mult_no_throw(uint8_t *r, + const uint8_t *a, + const uint8_t *b, + size_t len); /** * @deprecated @@ -202,7 +220,8 @@ DEPRECATED static inline void cx_math_mult(uint8_t *r, } /** - * @brief Modular addition of two integers represented as byte arrays. + * @brief Performs a modular addition + * of two integers represented as byte arrays. * * @param[out] r Buffer for the result. * @@ -224,11 +243,8 @@ DEPRECATED static inline void cx_math_mult(uint8_t *r, * - CX_MEMORY_FULL * - CX_INVALID_PARAMETER */ -cx_err_t cx_math_addm_no_throw(uint8_t *r, - const uint8_t *a, - const uint8_t *b, - const uint8_t *m, - size_t len); +WARN_UNUSED_RESULT cx_err_t +cx_math_addm_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, const uint8_t *m, size_t len); /** * @deprecated @@ -244,7 +260,8 @@ DEPRECATED static inline void cx_math_addm(uint8_t *r, } /** - * @brief Modular subtraction of two integers represented as byte arrays. + * @brief Performs a modular subtraction of + * two integers represented as byte arrays. * * @param[out] r Buffer for the result. * @@ -266,11 +283,8 @@ DEPRECATED static inline void cx_math_addm(uint8_t *r, * - CX_MEMORY_FULL * - CX_INVALID_PARAMETER */ -cx_err_t cx_math_subm_no_throw(uint8_t *r, - const uint8_t *a, - const uint8_t *b, - const uint8_t *m, - size_t len); +WARN_UNUSED_RESULT cx_err_t +cx_math_subm_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *b, const uint8_t *m, size_t len); /** * @deprecated @@ -286,7 +300,8 @@ DEPRECATED static inline void cx_math_subm(uint8_t *r, } /** - * @brief Modular multiplication of two integers represented as byte arrays. + * @brief Performs a modular multiplication of + * two integers represented as byte arrays. * * @param[out] r Buffer for the result. * @@ -308,11 +323,11 @@ DEPRECATED static inline void cx_math_subm(uint8_t *r, * - CX_INVALID_PARAMETER * - CX_INVALID_PARAMETER_VALUE */ -cx_err_t cx_math_multm_no_throw(uint8_t *r, - const uint8_t *a, - const uint8_t *b, - const uint8_t *m, - size_t len); +WARN_UNUSED_RESULT cx_err_t cx_math_multm_no_throw(uint8_t *r, + const uint8_t *a, + const uint8_t *b, + const uint8_t *m, + size_t len); /** * @deprecated @@ -328,9 +343,9 @@ DEPRECATED static inline void cx_math_multm(uint8_t *r, } /** - * @brief Modulo operation. + * @brief Performs a modular reduction. * - * @details Compute the remainder of the division of v by m. Store the result in v. + * @details Computes the remainder of the division of v by m. Store the result in v. * * @param[in,out] v Pointer to the dividend and buffer for the result. * @@ -348,7 +363,10 @@ DEPRECATED static inline void cx_math_multm(uint8_t *r, * - CX_MEMORY_FULL * - CX_INVALID_PARAMETER */ -cx_err_t cx_math_modm_no_throw(uint8_t *v, size_t len_v, const uint8_t *m, size_t len_m); +WARN_UNUSED_RESULT cx_err_t cx_math_modm_no_throw(uint8_t *v, + size_t len_v, + const uint8_t *m, + size_t len_m); /** * @deprecated @@ -360,9 +378,9 @@ DEPRECATED static inline void cx_math_modm(uint8_t *v, size_t len_v, const uint8 } /** - * @brief Modular exponentiation. + * @brief Performs a modular exponentiation. * - * @details Compute the result of **a^e mod m**. + * @details Computes the result of **a^e mod m**. * * @param[out] r Buffer for the result. * @@ -384,12 +402,12 @@ DEPRECATED static inline void cx_math_modm(uint8_t *v, size_t len_v, const uint8 * - CX_MEMORY_FULL * - CX_INVALID_PARAMETER */ -cx_err_t cx_math_powm_no_throw(uint8_t *r, - const uint8_t *a, - const uint8_t *e, - size_t len_e, - const uint8_t *m, - size_t len); +WARN_UNUSED_RESULT cx_err_t cx_math_powm_no_throw(uint8_t *r, + const uint8_t *a, + const uint8_t *e, + size_t len_e, + const uint8_t *m, + size_t len); /** * @deprecated @@ -406,9 +424,9 @@ DEPRECATED static inline void cx_math_powm(uint8_t *r, } /** - * @brief Modular inverse with a prime modulus. + * @brief Computes the modular inverse with a prime modulus. * - * @details Compute the result of **a^(-1) mod m**, for a prime *m*. + * @details It computes the result of **a^(-1) mod m**, for a prime *m*. * * @param[out] r Buffer for the result. * @@ -426,7 +444,10 @@ DEPRECATED static inline void cx_math_powm(uint8_t *r, * - CX_MEMORY_FULL * - CX_INVALID_PARAMETER */ -cx_err_t cx_math_invprimem_no_throw(uint8_t *r, const uint8_t *a, const uint8_t *m, size_t len); +WARN_UNUSED_RESULT cx_err_t cx_math_invprimem_no_throw(uint8_t *r, + const uint8_t *a, + const uint8_t *m, + size_t len); /** * @deprecated @@ -441,10 +462,10 @@ DEPRECATED static inline void cx_math_invprimem(uint8_t *r, } /** - * @brief Modular inverse. + * @brief Computes the modular inverse. * - * @details Compute the result of **a^(-1) mod m**. *a* must be invertible modulo *m*, - * i.e. the greatest common divisor of *a* and *n* is 1. + * @details It computes the result of **a^(-1) mod m**. *a* must be invertible modulo *m*, + * i.e. the greatest common divisor of *a* and *m* is 1. * * @param[out] r Buffer for the result. * @@ -462,7 +483,10 @@ DEPRECATED static inline void cx_math_invprimem(uint8_t *r, * - CX_MEMORY_FULL * - CX_INVALID_PARAMETER */ -cx_err_t cx_math_invintm_no_throw(uint8_t *r, uint32_t a, const uint8_t *m, size_t len); +WARN_UNUSED_RESULT cx_err_t cx_math_invintm_no_throw(uint8_t *r, + uint32_t a, + const uint8_t *m, + size_t len); /** * @deprecated @@ -474,7 +498,7 @@ DEPRECATED static inline void cx_math_invintm(uint8_t *r, uint32_t a, const uint } /** - * @brief Check whether a number is probable prime. + * @brief Checks whether a number is probably prime. * * @param[in] r Pointer to an integer. * @@ -492,7 +516,7 @@ DEPRECATED static inline void cx_math_invintm(uint8_t *r, uint32_t a, const uint * - CX_MEMORY_FULL * - CX_INVALID_PARAMETER */ -cx_err_t cx_math_is_prime_no_throw(const uint8_t *r, size_t len, bool *prime); +WARN_UNUSED_RESULT cx_err_t cx_math_is_prime_no_throw(const uint8_t *r, size_t len, bool *prime); /** * @deprecated @@ -506,23 +530,23 @@ DEPRECATED static inline bool cx_math_is_prime(const uint8_t *r, size_t len) } /** - * @brief Compute the next prime after a given number. + * @brief Computes the next prime after a given number. * - * @param[in] r Pointer to the integer and buffer for the result. + * @param[in, out] r Pointer to the integer and buffer for the result. * - * @param[in] len Number of bytes of the integer. + * @param[in] len Number of bytes of the integer. * - * @return Error code: - * - CX_OK on success - * - CX_NOT_UNLOCKED - * - CX_INVALID_PARAMETER_SIZE - * - CX_MEMORY_FULL - * - CX_NOT_LOCKED - * - CX_INVALID_PARAMETER - * - CX_INTERNAL_ERROR - * - CX_OVERFLOW + * @return Error code: + * - CX_OK on success + * - CX_NOT_UNLOCKED + * - CX_INVALID_PARAMETER_SIZE + * - CX_MEMORY_FULL + * - CX_NOT_LOCKED + * - CX_INVALID_PARAMETER + * - CX_INTERNAL_ERROR + * - CX_OVERFLOW */ -cx_err_t cx_math_next_prime_no_throw(uint8_t *r, uint32_t len); +WARN_UNUSED_RESULT cx_err_t cx_math_next_prime_no_throw(uint8_t *r, uint32_t len); /** * @deprecated @@ -534,7 +558,7 @@ DEPRECATED static inline void cx_math_next_prime(uint8_t *r, uint32_t len) } /** - * @brief Compare if the byte array of an integer is all zero. + * @brief Checks whether the byte array of an integer is all zero. * * @param[in] a Pointer to an integer. * @@ -553,6 +577,6 @@ static inline bool cx_math_is_zero(const uint8_t *a, size_t len) return 1; } -#endif // LCX_MATH_H - #endif // HAVE_MATH + +#endif // LCX_MATH_H diff --git a/lib_cxng/include/lcx_pbkdf2.h b/lib_cxng/include/lcx_pbkdf2.h index 98b86ec9..f4f1ef1d 100644 --- a/lib_cxng/include/lcx_pbkdf2.h +++ b/lib_cxng/include/lcx_pbkdf2.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,18 +26,18 @@ * It consists in iteratively deriving HMAC. */ -#ifdef HAVE_PBKDF2 - #ifndef LCX_PBKDF2_H #define LCX_PBKDF2_H +#ifdef HAVE_PBKDF2 + #include "lcx_wrappers.h" #include "lcx_hash.h" /** - * @brief Compute PBKDF2 bytes sequence. + * @brief Computes a PBKDF2 bytes sequence. * - * @details Compute PBKDF2 bytes sequence according to + * @details It computes the bytes sequence according to * RFC 2898 . * * @param[in] md_type Message digest algorithm identifier. @@ -62,6 +62,7 @@ * - CX_OK * - CX_INVALID_PARAMETER */ +// No need to add WARN_UNUSED_RESULT, return value is never checked! cx_err_t cx_pbkdf2_no_throw(cx_md_t md_type, const uint8_t *password, size_t passwordlen, @@ -89,9 +90,9 @@ DEPRECATED static inline void cx_pbkdf2(cx_md_t md_type, } /** - * @brief Compute PBKDF2 bytes sequence with SHA512. + * @brief Computes a PBKDF2 bytes sequence with SHA512. * - * @details Compute PBKDF2 bytes sequence according to + * @details It computes the bytes sequence according to * RFC 2898 * with SHA512 as the underlying hash function. * @@ -118,6 +119,6 @@ DEPRECATED static inline void cx_pbkdf2(cx_md_t md_type, #define cx_pbkdf2_sha512(password, password_len, salt, salt_len, iterations, out, out_len) \ cx_pbkdf2_no_throw(CX_SHA512, password, password_len, salt, salt_len, iterations, out, out_len) -#endif // LCX_PBKDF2_H - #endif // HAVE_PBKDF2 + +#endif // LCX_PBKDF2_H diff --git a/lib_cxng/include/lcx_ripemd160.h b/lib_cxng/include/lcx_ripemd160.h index 832700fb..730c42f7 100644 --- a/lib_cxng/include/lcx_ripemd160.h +++ b/lib_cxng/include/lcx_ripemd160.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,11 +24,11 @@ * "https://homes.esat.kuleuven.be/~bosselae/ripemd160.html"> RIPEMD-160 for more details. */ -#ifdef HAVE_RIPEMD160 - #ifndef LCX_RIPEMD160_H #define LCX_RIPEMD160_H +#ifdef HAVE_RIPEMD160 + #include "lcx_wrappers.h" #include "lcx_hash.h" @@ -51,7 +51,7 @@ struct cx_ripemd160_s { typedef struct cx_ripemd160_s cx_ripemd160_t; /** - * @brief Initialize a RIPEMD-160 context. + * @brief Initializes a RIPEMD-160 context. * * @param[out] hash Pointer to the context. * The context shall be in RAM. @@ -59,10 +59,10 @@ typedef struct cx_ripemd160_s cx_ripemd160_t; * @return Error code: * - CX_OK on success */ -cx_err_t cx_ripemd160_init_no_throw(cx_ripemd160_t *hash); +WARN_UNUSED_RESULT cx_err_t cx_ripemd160_init_no_throw(cx_ripemd160_t *hash); /** - * @brief Initialize a RIPEMD-160 context. + * @brief Initializes a RIPEMD-160 context. * * @param[out] hash Pointer to the context. * The context shall be in RAM. @@ -71,10 +71,13 @@ cx_err_t cx_ripemd160_init_no_throw(cx_ripemd160_t *hash); */ static inline int cx_ripemd160_init(cx_ripemd160_t *hash) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-result" cx_ripemd160_init_no_throw(hash); +#pragma GCC diagnostic pop return CX_RIPEMD160; } -#endif - #endif // HAVE_RIPEMD160 + +#endif // LCX_RIPEMD160_H diff --git a/lib_cxng/include/lcx_rng.h b/lib_cxng/include/lcx_rng.h index 1f8ef715..c76973db 100644 --- a/lib_cxng/include/lcx_rng.h +++ b/lib_cxng/include/lcx_rng.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,16 +25,17 @@ * random bytes. The random number can also be generated within a specific range. */ -#ifdef HAVE_RNG - #ifndef LCX_RNG_H #define LCX_RNG_H +#ifdef HAVE_RNG + #include "lcx_wrappers.h" #include "lcx_hash.h" /** - * @brief Generate a random buffer such that each byte is between 0 and 255. + * @brief Generates a random buffer such that + * each byte is between 0 and 255. * * @param[out] buffer Buffer to hold the random data. * @@ -44,7 +45,8 @@ void cx_rng_no_throw(uint8_t *buffer, size_t len); /** - * @brief Generate a random buffer such that each byte is between 0 and 255. + * @brief Generates a random buffer such that + * each byte is between 0 and 255. * * @param[out] buffer Buffer to hold the random data. * @@ -60,7 +62,7 @@ static inline unsigned char *cx_rng(uint8_t *buffer, size_t len) } /** - * @brief Output 32 random bits. + * @brief Returns 32 random bits. * * @return A 32-bit random number. */ @@ -72,7 +74,7 @@ static inline uint32_t cx_rng_u32(void) } /** - * @brief Output 8 random bits. + * @brief Returns 8 random bits. * * @return A 8-bit random number. */ @@ -86,7 +88,7 @@ static inline uint8_t cx_rng_u8(void) typedef uint32_t (*cx_rng_u32_range_randfunc_t)(void); /** - * @brief Generate a random 32-bit unsigned integer + * @brief Generates a random 32-bit unsigned integer * with a specified function. * * @details The generated number is taken in the range [a;b[ @@ -103,7 +105,7 @@ typedef uint32_t (*cx_rng_u32_range_randfunc_t)(void); uint32_t cx_rng_u32_range_func(uint32_t a, uint32_t b, cx_rng_u32_range_randfunc_t randfunc); /** - * @brief Generate a random 32-bit unsigned integer. + * @brief Generates a random 32-bit unsigned integer. * * @details The generated number is taken in the range [a;b[ * with uniform distribution. @@ -120,7 +122,7 @@ static inline uint32_t cx_rng_u32_range(uint32_t a, uint32_t b) } /** - * @brief Generate a random buffer according to + * @brief Generates a random buffer according to * RFC6979 . * * @param[in] hash_id Message digest algorithm identifier. @@ -145,16 +147,16 @@ static inline uint32_t cx_rng_u32_range(uint32_t a, uint32_t b) * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_rng_rfc6979(cx_md_t hash_id, - const uint8_t *x, - size_t x_len, - const uint8_t *h1, - size_t h1_len, - const uint8_t *q, - size_t q_len, - uint8_t *out, - size_t out_len); - -#endif // LCX_RNG_H +WARN_UNUSED_RESULT cx_err_t cx_rng_rfc6979(cx_md_t hash_id, + const uint8_t *x, + size_t x_len, + const uint8_t *h1, + size_t h1_len, + const uint8_t *q, + size_t q_len, + uint8_t *out, + size_t out_len); #endif // HAVE_RNG + +#endif // LCX_RNG_H diff --git a/lib_cxng/include/lcx_rsa.h b/lib_cxng/include/lcx_rsa.h index d738315d..a267c833 100644 --- a/lib_cxng/include/lcx_rsa.h +++ b/lib_cxng/include/lcx_rsa.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,7 +40,7 @@ * * @details This type shall not be instantiate, * it is only defined to allow unified API - * for RSA operations. + * for RSA operations. */ struct cx_rsa_public_key_s { size_t size; ///< Key size in bytes @@ -130,13 +130,13 @@ typedef struct cx_rsa_4096_public_key_s cx_rsa_4096_public_key_t; typedef struct cx_rsa_4096_private_key_s cx_rsa_4096_private_key_t; /** - * @brief Initialize a RSA public key. + * @brief Initializes a RSA public key. * * @details Once initialized, the key may be stored in non-volatile memory * and used for any RSA processing. * * Passing NULL as raw key initializes the key without any value. - * The key can not be used. + * The key cannot be used. * * @param[in] exponent Public exponent: pointer to a raw key value (4 bytes) or NULL. * @@ -152,11 +152,11 @@ typedef struct cx_rsa_4096_private_key_s cx_rsa_4096_private_key_t; * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_rsa_init_public_key_no_throw(const uint8_t *exponent, - size_t exponent_len, - const uint8_t *modulus, - size_t modulus_len, - cx_rsa_public_key_t *key); +WARN_UNUSED_RESULT cx_err_t cx_rsa_init_public_key_no_throw(const uint8_t *exponent, + size_t exponent_len, + const uint8_t *modulus, + size_t modulus_len, + cx_rsa_public_key_t *key); /** * @deprecated @@ -173,7 +173,7 @@ DEPRECATED static inline int cx_rsa_init_public_key(const unsigned char *exponen } /** - * @brief Initialize a RSA private key. + * @brief Initializes a RSA private key. * * @details Once initialized, the key may be stored in non-volatile memory * and used for any RSA processing. @@ -181,7 +181,7 @@ DEPRECATED static inline int cx_rsa_init_public_key(const unsigned char *exponen * Passing NULL as raw key initializes the key without any value. * The key cannot be used. * - * @param[in] exponent Private exponent: pointer to a raw key value (4 bytes) or NULL. + * @param[in] exponent Private exponent: pointer to a raw key value or NULL. * * @param[in] exponent_len Length of the exponent. * @@ -195,11 +195,11 @@ DEPRECATED static inline int cx_rsa_init_public_key(const unsigned char *exponen * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_rsa_init_private_key_no_throw(const uint8_t *exponent, - size_t exponent_len, - const uint8_t *modulus, - size_t modulus_len, - cx_rsa_private_key_t *key); +WARN_UNUSED_RESULT cx_err_t cx_rsa_init_private_key_no_throw(const uint8_t *exponent, + size_t exponent_len, + const uint8_t *modulus, + size_t modulus_len, + cx_rsa_private_key_t *key); /** * @deprecated @@ -216,7 +216,7 @@ DEPRECATED static inline int cx_rsa_init_private_key(const unsigned char *expon } /** - * @brief Generate a RSA key pair. + * @brief Generates a RSA key pair. * * @param[in] modulus_len Size of the modulus in bytes. Expected sizes: * - 256 @@ -249,12 +249,12 @@ DEPRECATED static inline int cx_rsa_init_private_key(const unsigned char *expon * - CX_INTERNAL_ERROR * - CX_OVERFLOW */ -cx_err_t cx_rsa_generate_pair_no_throw(size_t modulus_len, - cx_rsa_public_key_t *public_key, - cx_rsa_private_key_t *private_key, - const uint8_t *pub_exponent, - size_t exponent_len, - const uint8_t *externalPQ); +WARN_UNUSED_RESULT cx_err_t cx_rsa_generate_pair_no_throw(size_t modulus_len, + cx_rsa_public_key_t *public_key, + cx_rsa_private_key_t *private_key, + const uint8_t *pub_exponent, + size_t exponent_len, + const uint8_t *externalPQ); /** * @deprecated @@ -273,7 +273,7 @@ DEPRECATED static inline int cx_rsa_generate_pair(unsigned int modulus_ } /** - * @brief Compute a message digest signature according to RSA specification. + * @brief Computes a message digest signature according to RSA specification. * * @details When using PSS padding, the salt length is fixed to the hash output length. * The MGF1 function is the one descrided in PKCS1 v2.0 specification, @@ -311,17 +311,17 @@ DEPRECATED static inline int cx_rsa_generate_pair(unsigned int modulus_ * - CX_MEMORY_FULL * - CX_NOT_LOCKED */ -cx_err_t cx_rsa_sign_with_salt_len(const cx_rsa_private_key_t *key, - uint32_t mode, - cx_md_t hashID, - const uint8_t *hash, - size_t hash_len, - uint8_t *sig, - size_t sig_len, - size_t salt_len); +WARN_UNUSED_RESULT cx_err_t cx_rsa_sign_with_salt_len(const cx_rsa_private_key_t *key, + uint32_t mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t sig_len, + size_t salt_len); /** - * @brief Compute a message digest signature according to RSA specification. + * @brief Computes a message digest signature according to RSA specification. * * @details When using PSS padding, the salt length is fixed to the hash output length. * If another salt length is used, call #cx_rsa_sign_with_salt_len instead. @@ -358,13 +358,13 @@ cx_err_t cx_rsa_sign_with_salt_len(const cx_rsa_private_key_t *key, * - CX_MEMORY_FULL * - CX_NOT_LOCKED */ -cx_err_t cx_rsa_sign_no_throw(const cx_rsa_private_key_t *key, - uint32_t mode, - cx_md_t hashID, - const uint8_t *hash, - size_t hash_len, - uint8_t *sig, - size_t sig_len); +WARN_UNUSED_RESULT cx_err_t cx_rsa_sign_no_throw(const cx_rsa_private_key_t *key, + uint32_t mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t sig_len); /** * @deprecated @@ -383,9 +383,9 @@ DEPRECATED static inline int cx_rsa_sign(const cx_rsa_private_key_t *key, } /** - * @brief Verify a message digest signature. + * @brief Verifies a message digest signature. * - * @details Verify a message digest signature according to RSA specification + * @details It verifies a message digest signature according to RSA specification * with a specified salt length. * * @param[in] key RSA public key initialized with #cx_rsa_init_public_key_no_throw. @@ -425,9 +425,9 @@ bool cx_rsa_verify_with_salt_len(const cx_rsa_public_key_t *key, size_t salt_len); /** - * @brief Verify a message digest signature. + * @brief Verifies a message digest signature. * - * @details Verify a message digest signature according to RSA specification. + * @details It verifies a message digest signature according to RSA specification. * Please note that if the mode is set to CX_PAD_PKCS1_PSS, then * the underlying salt length is by convention equal to the hash length. * If another salt length is used, please call #cx_rsa_verify_with_salt_len @@ -447,9 +447,9 @@ bool cx_rsa_verify_with_salt_len(const cx_rsa_public_key_t *key, * - CX_SHA3_256 (for CX_PAD_PKCS1_1o5 mode only) * - CX_SHA3_512 (for CX_PAD_PKCS1_1o5 mode only) * - * @param[in] hash Input data to be signed. + * @param[in] hash Message digest corresponding to the signature. * - * @param[in] hash_len Length of the input data. + * @param[in] hash_len Length of the message digest. * * @param[in] sig RSA signature encoded as raw bytes. * This is used as a temporary buffer. @@ -468,7 +468,7 @@ bool cx_rsa_verify(const cx_rsa_public_key_t *key, size_t sig_len); /** - * @brief Encrypt a message according to RSA specification. + * @brief Encrypts a message according to RSA specification. * * @param[in] key RSA public key initialized with #cx_rsa_init_public_key_no_throw. * @@ -499,13 +499,13 @@ bool cx_rsa_verify(const cx_rsa_public_key_t *key, * - CX_MEMORY_FULL * - CX_NOT_LOCKED */ -cx_err_t cx_rsa_encrypt_no_throw(const cx_rsa_public_key_t *key, - uint32_t mode, - cx_md_t hashID, - const uint8_t *mesg, - size_t mesg_len, - uint8_t *enc, - size_t enc_len); +WARN_UNUSED_RESULT cx_err_t cx_rsa_encrypt_no_throw(const cx_rsa_public_key_t *key, + uint32_t mode, + cx_md_t hashID, + const uint8_t *mesg, + size_t mesg_len, + uint8_t *enc, + size_t enc_len); /** * @deprecated @@ -524,7 +524,7 @@ DEPRECATED static inline int cx_rsa_encrypt(const cx_rsa_public_key_t *key, } /** - * @brief Decrypt a message according to RSA specification. + * @brief Decrypts a message according to RSA specification. * * @param[in] key RSA private key initialized with #cx_rsa_init_private_key_no_throw. * @@ -555,13 +555,13 @@ DEPRECATED static inline int cx_rsa_encrypt(const cx_rsa_public_key_t *key, * - CX_MEMORY_FULL * - CX_NOT_LOCKED */ -cx_err_t cx_rsa_decrypt_no_throw(const cx_rsa_private_key_t *key, - uint32_t mode, - cx_md_t hashID, - const uint8_t *mesg, - size_t mesg_len, - uint8_t *dec, - size_t *dec_len); +WARN_UNUSED_RESULT cx_err_t cx_rsa_decrypt_no_throw(const cx_rsa_private_key_t *key, + uint32_t mode, + cx_md_t hashID, + const uint8_t *mesg, + size_t mesg_len, + uint8_t *dec, + size_t *dec_len); /** * @deprecated diff --git a/lib_cxng/include/lcx_sha256.h b/lib_cxng/include/lcx_sha256.h index e6d07ab7..8c4c83e9 100644 --- a/lib_cxng/include/lcx_sha256.h +++ b/lib_cxng/include/lcx_sha256.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,11 +27,11 @@ * for more details. */ -#if defined(HAVE_SHA256) || defined(HAVE_SHA224) - #ifndef LCX_SHA256_H #define LCX_SHA256_H +#if defined(HAVE_SHA256) || defined(HAVE_SHA224) + #include "lcx_wrappers.h" #include "lcx_hash.h" #include @@ -59,7 +59,7 @@ typedef struct cx_sha256_s cx_sha256_t; #if defined(HAVE_SHA224) /** - * @brief Initialize a SHA-224 context. + * @brief Initializes a SHA-224 context. * * @param[out] hash Pointer to the context. * The context shall be in RAM. @@ -67,8 +67,17 @@ typedef struct cx_sha256_s cx_sha256_t; * @return Error code: * - CX_OK on success */ +// No need to add WARN_UNUSED_RESULT to cx_sha224_init_no_throw(), it always returns CX_OK cx_err_t cx_sha224_init_no_throw(cx_sha256_t *hash); +/** + * @brief Initializes a SHA-224 context. + * + * @param[out] hash Pointer to the context. + * The context shall be in RAM. + * + * @return SHA224 identifier. + */ static inline int cx_sha224_init(cx_sha256_t *hash) { cx_sha224_init_no_throw(hash); @@ -77,7 +86,7 @@ static inline int cx_sha224_init(cx_sha256_t *hash) #endif /** - * @brief Initialize a SHA-256 context. + * @brief Initializes a SHA-256 context. * * @param[out] hash Pointer to the context. * The context shall be in RAM. @@ -85,10 +94,11 @@ static inline int cx_sha224_init(cx_sha256_t *hash) * @return Error code: * - CX_OK on success */ +// No need to add WARN_UNUSED_RESULT to cx_sha256_init_no_throw(), it always returns CX_OK cx_err_t cx_sha256_init_no_throw(cx_sha256_t *hash); /** - * @brief Initialize a SHA-256 context. + * @brief Initializes a SHA-256 context. * * @param[out] hash Pointer to the context. * The context shall be in RAM. @@ -102,7 +112,7 @@ static inline int cx_sha256_init(cx_sha256_t *hash) } /** - * @brief Compute a one shot SHA-256 digest. + * @brief Computes a one shot SHA-256 digest. * * @param[in] in Input data. * @@ -116,6 +126,6 @@ static inline int cx_sha256_init(cx_sha256_t *hash) */ size_t cx_hash_sha256(const uint8_t *in, size_t len, uint8_t *out, size_t out_len); -#endif - #endif // defined(HAVE_SHA256) || defined(HAVE_SHA224) + +#endif // LCX_SHA256_H diff --git a/lib_cxng/include/lcx_sha3.h b/lib_cxng/include/lcx_sha3.h index a38b0c4f..0c8874c1 100644 --- a/lib_cxng/include/lcx_sha3.h +++ b/lib_cxng/include/lcx_sha3.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,11 +26,11 @@ * for more details. */ -#ifdef HAVE_SHA3 - #ifndef LCX_SHA3_H #define LCX_SHA3_H +#ifdef HAVE_SHA3 + #include "lcx_common.h" #include "lcx_hash.h" #include @@ -50,7 +50,7 @@ struct cx_sha3_s { typedef struct cx_sha3_s cx_sha3_t; /** - * @brief Initialize a SHA3 context. + * @brief Initializes a SHA3 context. * * @details Supported output sizes in bits: * - 224 @@ -67,7 +67,7 @@ typedef struct cx_sha3_s cx_sha3_t; * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_sha3_init_no_throw(cx_sha3_t *hash, size_t size); +WARN_UNUSED_RESULT cx_err_t cx_sha3_init_no_throw(cx_sha3_t *hash, size_t size); /** * @deprecated @@ -80,7 +80,7 @@ DEPRECATED static inline int cx_sha3_init(cx_sha3_t *hash, size_t size) } /** - * @brief Initialize a KECCAK context. + * @brief Initializes a KECCAK context. * * @details Supported output sizes in bits: * - 224 @@ -98,7 +98,7 @@ DEPRECATED static inline int cx_sha3_init(cx_sha3_t *hash, size_t size) * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_keccak_init_no_throw(cx_sha3_t *hash, size_t size); +WARN_UNUSED_RESULT cx_err_t cx_keccak_init_no_throw(cx_sha3_t *hash, size_t size); /** * @deprecated @@ -111,7 +111,7 @@ DEPRECATED static inline int cx_keccak_init(cx_sha3_t *hash, size_t size) } /** - * @brief Initialize a SHA3-XOF context. + * @brief Initializes a SHA3-XOF context. * * @details SHAKE128 is a SHA3-XOF (Extendable Output Function * based on SHA3) with a 128-bit security. @@ -128,7 +128,7 @@ DEPRECATED static inline int cx_keccak_init(cx_sha3_t *hash, size_t size) * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_shake128_init_no_throw(cx_sha3_t *hash, size_t out_size); +WARN_UNUSED_RESULT cx_err_t cx_shake128_init_no_throw(cx_sha3_t *hash, size_t out_size); /** * @deprecated @@ -141,7 +141,7 @@ DEPRECATED static inline int cx_shake128_init(cx_sha3_t *hash, unsigned int out_ } /** - * @brief Initialize a SHA3-XOF context. + * @brief Initializes a SHA3-XOF context. * * @details SHAKE256 is a SHA3-XOF (Extendable Output Function * based on SHA3) with a 256-bit security. @@ -158,7 +158,7 @@ DEPRECATED static inline int cx_shake128_init(cx_sha3_t *hash, unsigned int out_ * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_shake256_init_no_throw(cx_sha3_t *hash, size_t out_size); +WARN_UNUSED_RESULT cx_err_t cx_shake256_init_no_throw(cx_sha3_t *hash, size_t out_size); /** * @deprecated @@ -171,7 +171,7 @@ DEPRECATED static inline int cx_shake256_init(cx_sha3_t *hash, unsigned int out_ } /** - * @brief Initialize a SHA3-XOF context. + * @brief Initializes a SHA3-XOF context. * * @details This can be used to initialize either SHAKE128 * or SHAKE256. @@ -190,7 +190,9 @@ DEPRECATED static inline int cx_shake256_init(cx_sha3_t *hash, unsigned int out_ * - CX_OK on success * - CX_INVALID_PARAMETER */ -cx_err_t cx_sha3_xof_init_no_throw(cx_sha3_t *hash, size_t size, size_t out_length); +WARN_UNUSED_RESULT cx_err_t cx_sha3_xof_init_no_throw(cx_sha3_t *hash, + size_t size, + size_t out_length); /** * @deprecated @@ -210,6 +212,6 @@ DEPRECATED static inline int cx_sha3_xof_init(cx_sha3_t *hash, } } -#endif - #endif // HAVE_SHA3 + +#endif // LCX_SHA3_H diff --git a/lib_cxng/include/lcx_sha512.h b/lib_cxng/include/lcx_sha512.h index 6f6b1228..9f039366 100644 --- a/lib_cxng/include/lcx_sha512.h +++ b/lib_cxng/include/lcx_sha512.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,11 +27,11 @@ * for more details. */ -#if defined(HAVE_SHA384) || defined(HAVE_SHA512) - #ifndef LCX_SHA512_H #define LCX_SHA512_H +#if defined(HAVE_SHA384) || defined(HAVE_SHA512) + /** SHA-384 message digest size */ #define CX_SHA384_SIZE 48 /** SHA-512 message digest size */ @@ -50,7 +50,7 @@ struct cx_sha512_s { typedef struct cx_sha512_s cx_sha512_t; /** - * @brief Initialize a SHA-384 context. + * @brief Initializes a SHA-384 context. * * @param[out] hash Pointer to the context. * The context shall be in RAM. @@ -58,10 +58,11 @@ typedef struct cx_sha512_s cx_sha512_t; * @return Error code: * - CX_OK on success */ +// No need to add WARN_UNUSED_RESULT to cx_sha384_init_no_throw(), it always returns CX_OK cx_err_t cx_sha384_init_no_throw(cx_sha512_t *hash); /** - * @brief Initialize a SHA-384 context. + * @brief Initializes a SHA-384 context. * * @param[out] hash Pointer to the context. * The context shall be in RAM. @@ -75,7 +76,7 @@ static inline int cx_sha384_init(cx_sha512_t *hash) } /** - * @brief Initialize a SHA-512 context. + * @brief Initializes a SHA-512 context. * * @param[out] hash Pointer to the context. * The context shall be in RAM. @@ -83,10 +84,11 @@ static inline int cx_sha384_init(cx_sha512_t *hash) * @return Error code: * - CX_OK on success */ +// No need to add WARN_UNUSED_RESULT to cx_sha512_init_no_throw(), it always returns CX_OK cx_err_t cx_sha512_init_no_throw(cx_sha512_t *hash); /** - * @brief Initialize a SHA-512 context. + * @brief Initializes a SHA-512 context. * * @param[out] hash Pointer to the context. * The context shall be in RAM. @@ -100,7 +102,7 @@ static inline int cx_sha512_init(cx_sha512_t *hash) } /** - * @brief Compute a one shot SHA-512 digest. + * @brief Computes a one shot SHA-512 digest. * * @param[in] in Input data. * @@ -113,6 +115,6 @@ static inline int cx_sha512_init(cx_sha512_t *hash) */ size_t cx_hash_sha512(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len); -#endif - #endif // defined(HAVE_SHA384) || defined(HAVE_SHA512) + +#endif // LCX_SHA512_H diff --git a/lib_cxng/include/libcxng.h b/lib_cxng/include/libcxng.h index d562106e..b5574735 100644 --- a/lib_cxng/include/libcxng.h +++ b/lib_cxng/include/libcxng.h @@ -1,7 +1,7 @@ /******************************************************************************* * Ledger Nano S - Secure firmware - * (c) 2021 Ledger + * (c) 2022 Ledger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/lib_cxng/src/cx_blake2.h b/lib_cxng/src/cx_blake2.h index d5e95741..c2a4f9bc 100644 --- a/lib_cxng/src/cx_blake2.h +++ b/lib_cxng/src/cx_blake2.h @@ -12,11 +12,12 @@ More information about the BLAKE2 hash function can be found at https://blake2.net. */ -#ifdef HAVE_BLAKE2 #ifndef CX_BLAKE2_H #define CX_BLAKE2_H +#ifdef HAVE_BLAKE2 + #include "lcx_blake2.h" #include #include @@ -213,6 +214,6 @@ int blake2(void *out, size_t outlen, const void *in, size_t inlen, const void *k } #endif -#endif - #endif // HAVE_BLAKE2 + +#endif // CX_BLAKE2_H diff --git a/lib_cxng/src/cx_blake2b.h b/lib_cxng/src/cx_blake2b.h index 8a0a80c7..dada8897 100644 --- a/lib_cxng/src/cx_blake2b.h +++ b/lib_cxng/src/cx_blake2b.h @@ -16,11 +16,11 @@ * limitations under the License. ********************************************************************************/ -#ifdef HAVE_BLAKE2 - #ifndef CX_BLAKE2B_H #define CX_BLAKE2B_H +#ifdef HAVE_BLAKE2 + #include "lcx_wrappers.h" #include "lcx_blake2.h" #include @@ -28,7 +28,8 @@ extern const cx_hash_info_t cx_blake2b_info; -cx_err_t cx_blake2b_update(cx_blake2b_t *ctx, const uint8_t *data, size_t len); +WARN_UNUSED_RESULT cx_err_t cx_blake2b_update(cx_blake2b_t *ctx, const uint8_t *data, size_t len); +// No need to add WARN_UNUSED_RESULT to cx_blake2b_final(), it always returns CX_OK cx_err_t cx_blake2b_final(cx_blake2b_t *ctx, uint8_t *digest); size_t cx_blake2b_get_output_size(const cx_blake2b_t *ctx); @@ -41,6 +42,6 @@ struct cx_xblake_s { }; typedef struct cx_xblake_s cx_xblake_t; -#endif // CX_BLAKE2B_H - #endif // HAVE_BLAKE2 + +#endif // CX_BLAKE2B_H diff --git a/lib_cxng/src/cx_crc.h b/lib_cxng/src/cx_crc.h index 6ceb3bf0..0698874c 100644 --- a/lib_cxng/src/cx_crc.h +++ b/lib_cxng/src/cx_crc.h @@ -16,16 +16,16 @@ * limitations under the License. ********************************************************************************/ -#ifdef HAVE_CRC - #ifndef CX_CRC_H #define CX_CRC_H +#ifdef HAVE_CRC + #include #include uint32_t cx_crc32(const void *buf, size_t len); -#endif +#endif // HAVE_CRC -#endif +#endif // CX_CRC_H diff --git a/lib_cxng/src/cx_ecfp.h b/lib_cxng/src/cx_ecfp.h index 7413e00c..c03e883c 100644 --- a/lib_cxng/src/cx_ecfp.h +++ b/lib_cxng/src/cx_ecfp.h @@ -16,11 +16,11 @@ * limitations under the License. ********************************************************************************/ -#ifdef HAVE_ECC - #ifndef CX_ECFP_H #define CX_ECFP_H +#ifdef HAVE_ECC + #include #include #include "lcx_ecfp.h" @@ -49,6 +49,6 @@ int cx_ecfp_decode_sig_der(const uint8_t *sig, const uint8_t **s, size_t *s_len); -#endif // CX_ECFP_H - #endif // HAVE_ECC + +#endif // CX_ECFP_H diff --git a/lib_cxng/src/cx_eddsa.h b/lib_cxng/src/cx_eddsa.h index 92fb7fc4..aee70f1d 100644 --- a/lib_cxng/src/cx_eddsa.h +++ b/lib_cxng/src/cx_eddsa.h @@ -16,20 +16,20 @@ * limitations under the License. ********************************************************************************/ -#ifdef HAVE_EDDSA - #ifndef CX_EDDSA_H #define CX_EDDSA_H -cx_err_t cx_eddsa_get_public_key_internal(const cx_ecfp_private_key_t *pv_key, - cx_md_t hashID, - cx_ecfp_public_key_t *pu_key, - uint8_t *a, - size_t a_len, - uint8_t *h, - size_t h_len, - uint8_t *scal /*temp uint8[114]*/); +#ifdef HAVE_EDDSA + +WARN_UNUSED_RESULT cx_err_t cx_eddsa_get_public_key_internal(const cx_ecfp_private_key_t *pv_key, + cx_md_t hashID, + cx_ecfp_public_key_t *pu_key, + uint8_t *a, + size_t a_len, + uint8_t *h, + size_t h_len, + uint8_t *scal /*temp uint8[114]*/); -#endif +#endif // HAVE_EDDSA -#endif +#endif // CX_EDDSA_H diff --git a/lib_cxng/src/cx_hash.h b/lib_cxng/src/cx_hash.h index e1d04673..16a201ad 100644 --- a/lib_cxng/src/cx_hash.h +++ b/lib_cxng/src/cx_hash.h @@ -16,11 +16,11 @@ * limitations under the License. ********************************************************************************/ -#ifdef HAVE_HASH - #ifndef CX_HASH_H #define CX_HASH_H +#ifdef HAVE_HASH + #include "lcx_hash.h" #include @@ -37,25 +37,25 @@ #define MAX_HASH_BLOCK_SIZE 128 #ifdef HAVE_GROESTL -cx_err_t cx_groestl(cx_hash_t *hash, - uint32_t mode, - const uint8_t *in, - size_t in_len, - uint8_t *out, - size_t out_len); +WARN_UNUSED_RESULT cx_err_t cx_groestl(cx_hash_t *hash, + uint32_t mode, + const uint8_t *in, + size_t in_len, + uint8_t *out, + size_t out_len); #endif #ifdef HAVE_BLAKE2 -cx_err_t cx_blake2b(cx_hash_t *hash, - uint32_t mode, - const uint8_t *in, - size_t in_len, - uint8_t *out, - size_t out_len); +WARN_UNUSED_RESULT cx_err_t cx_blake2b(cx_hash_t *hash, + uint32_t mode, + const uint8_t *in, + size_t in_len, + uint8_t *out, + size_t out_len); #endif const cx_hash_info_t *cx_hash_get_info(cx_md_t md_type); -#endif - #endif // HAVE_HASH + +#endif // CX_HASH_H diff --git a/lib_cxng/src/cx_pbkdf2.h b/lib_cxng/src/cx_pbkdf2.h index c84ea51a..ea0d30fd 100644 --- a/lib_cxng/src/cx_pbkdf2.h +++ b/lib_cxng/src/cx_pbkdf2.h @@ -16,11 +16,11 @@ * limitations under the License. ********************************************************************************/ -#ifdef HAVE_PBKDF2 - #ifndef CX_PBKDF2_H #define CX_PBKDF2_H +#ifdef HAVE_PBKDF2 + #include "lcx_hmac.h" #include @@ -54,14 +54,15 @@ struct cx_pbkdf2_s { }; typedef struct cx_pbkdf2_s cx_pbkdf2_t; -cx_err_t cx_pbkdf2_hmac(cx_md_t md_type, - const uint8_t *password, - size_t password_len, - const uint8_t *salt, - size_t salt_len, - uint32_t iterations, - uint8_t *key, - size_t key_len); +WARN_UNUSED_RESULT cx_err_t cx_pbkdf2_hmac(cx_md_t md_type, + const uint8_t *password, + size_t password_len, + const uint8_t *salt, + size_t salt_len, + uint32_t iterations, + uint8_t *key, + size_t key_len); -#endif // CX_PBKDF2_H #endif // HAVE_PBKDF2 + +#endif // CX_PBKDF2_H diff --git a/lib_cxng/src/cx_pkcs1.c b/lib_cxng/src/cx_pkcs1.c index e2785488..0c8ade48 100644 --- a/lib_cxng/src/cx_pkcs1.c +++ b/lib_cxng/src/cx_pkcs1.c @@ -244,10 +244,13 @@ static cx_err_t cx_pkcs1_MGF1(cx_md_t hID, while (out_len) { round_len = (out_len < hLen) ? out_len : hLen; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-result" cx_hash_init_ex(hash_ctx, hID, hLen); cx_hash_update(hash_ctx, seed, seed_len); cx_hash_update(hash_ctx, counter, 4); cx_hash_final(hash_ctx, G_cx.pkcs1.digest); +#pragma GCC diagnostic pop memcpy(out, G_cx.pkcs1.digest, round_len); out_len -= round_len; @@ -380,11 +383,14 @@ cx_err_t cx_pkcs1_emsa_pss_encode_with_salt_len(cx_md_t hID, cx_rng_no_throw(salt, mSaltLen); #endif +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-result" cx_hash_init_ex(hash_ctx, hID, hLen); cx_hash_update(hash_ctx, C_cx_pss_zeros, 8); cx_hash_update(hash_ctx, mHash, mHashLen); cx_hash_update(hash_ctx, salt, mSaltLen); cx_hash_final(hash_ctx, em + mDBlen); +#pragma GCC diagnostic pop em[emLen - 1] = 0xbc; CX_CHECK(cx_pkcs1_MGF1(hID, em + mDBlen, hLen, em, mDBlen)); @@ -459,11 +465,14 @@ bool cx_pkcs1_emsa_pss_verify_with_salt_len(cx_md_t hID, return false; } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-result" cx_hash_init_ex(hash_ctx, hID, hLen); cx_hash_update(hash_ctx, C_cx_pss_zeros, 8); cx_hash_update(hash_ctx, mHash, mHashLen); cx_hash_update(hash_ctx, em + PSLen + 1, mSaltLen); cx_hash_final(hash_ctx, G_cx.pkcs1.digest); +#pragma GCC diagnostic pop return memcmp(G_cx.pkcs1.digest, em + mDBlen, hLen) == 0; } diff --git a/lib_cxng/src/cx_ripemd160.h b/lib_cxng/src/cx_ripemd160.h index 96621601..463c86fb 100644 --- a/lib_cxng/src/cx_ripemd160.h +++ b/lib_cxng/src/cx_ripemd160.h @@ -1,16 +1,36 @@ -#ifdef HAVE_RIPEMD160 + +/******************************************************************************* + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifndef CX_RIPEMD160_H #define CX_RIPEMD160_H +#ifdef HAVE_RIPEMD160 + #include "lcx_ripemd160.h" #include #include extern const cx_hash_info_t cx_ripemd160_info; -cx_err_t cx_ripemd160_update(cx_ripemd160_t *ctx, const uint8_t *data, size_t len); -cx_err_t cx_ripemd160_final(cx_ripemd160_t *ctx, uint8_t *digest); +WARN_UNUSED_RESULT cx_err_t cx_ripemd160_update(cx_ripemd160_t *ctx, + const uint8_t *data, + size_t len); +WARN_UNUSED_RESULT cx_err_t cx_ripemd160_final(cx_ripemd160_t *ctx, uint8_t *digest); #endif // HAVE_RIPEMD160 diff --git a/lib_cxng/src/cx_rng.h b/lib_cxng/src/cx_rng.h index 0f15ec21..8d89ba3c 100644 --- a/lib_cxng/src/cx_rng.h +++ b/lib_cxng/src/cx_rng.h @@ -15,11 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. ********************************************************************************/ -#ifdef HAVE_RNG #ifndef CX_RNG_H #define CX_RNG_H +#ifdef HAVE_RNG + #include void cx_rng_init(void); @@ -31,6 +32,6 @@ uint32_t cx_trng_u32(void); void cx_trng_lengthtest(void); #endif -#endif - #endif // HAVE_RNG + +#endif // CX_RNG_G diff --git a/lib_cxng/src/cx_rng_rfc6979.h b/lib_cxng/src/cx_rng_rfc6979.h index 8738a1aa..5d934532 100644 --- a/lib_cxng/src/cx_rng_rfc6979.h +++ b/lib_cxng/src/cx_rng_rfc6979.h @@ -16,11 +16,11 @@ * limitations under the License. ********************************************************************************/ -#ifdef HAVE_RNG_RFC6979 - #ifndef CX_RNG_RFC6979_H #define CX_RNG_RFC6979_H +#ifdef HAVE_RNG_RFC6979 + #include "libcxng.h" #include "cx_hash.h" #include @@ -41,17 +41,18 @@ typedef struct { cx_hmac_t hmac; } cx_rnd_rfc6979_ctx_t; -cx_err_t cx_rng_rfc6979_init(cx_rnd_rfc6979_ctx_t *rfc_ctx, - cx_md_t hash_id, - const uint8_t *x, - size_t x_len, - const uint8_t *h1, - size_t h1_len, - const uint8_t *q, - size_t q_len - /*const uint8_t *additional_input, size_t additional_input_len*/); +WARN_UNUSED_RESULT cx_err_t cx_rng_rfc6979_init(cx_rnd_rfc6979_ctx_t *rfc_ctx, + cx_md_t hash_id, + const uint8_t *x, + size_t x_len, + const uint8_t *h1, + size_t h1_len, + const uint8_t *q, + size_t q_len + /*const uint8_t *additional_input, size_t additional_input_len*/); -cx_err_t cx_rng_rfc6979_next(cx_rnd_rfc6979_ctx_t *rfc_ctx, uint8_t *out, size_t out_len); -#endif // CX_HMAC_DRBG_H +WARN_UNUSED_RESULT cx_err_t cx_rng_rfc6979_next(cx_rnd_rfc6979_ctx_t *rfc_ctx, uint8_t *out, size_t out_len); #endif // HAVE_RNG_RFC6979 + +#endif // CX_RNG_RFC6979_H diff --git a/lib_cxng/src/cx_rsa.c b/lib_cxng/src/cx_rsa.c index 9e20166b..d3e1f56e 100644 --- a/lib_cxng/src/cx_rsa.c +++ b/lib_cxng/src/cx_rsa.c @@ -265,8 +265,8 @@ cx_err_t cx_rsa_generate_pair_no_throw(size_t modulus_len, CX_CHECK(cx_bn_destroy(&bn_q)); // - d = inv(e) mod n CX_CHECK(cx_bn_alloc(&bn_p, modulus_len)); - cx_bn_mod_u32_invert( - bn_p, (pu_e[0] << 24) | (pu_e[1] << 16) | (pu_e[2] << 8) | (pu_e[3] << 0), bn_n); + CX_CHECK(cx_bn_mod_u32_invert( + bn_p, (pu_e[0] << 24) | (pu_e[1] << 16) | (pu_e[2] << 8) | (pu_e[3] << 0), bn_n)); CX_CHECK(cx_bn_export(bn_p, pv_d, modulus_len)); memmove(pv_n, pu_n, modulus_len); diff --git a/lib_cxng/src/cx_rsa.h b/lib_cxng/src/cx_rsa.h index 30d81690..7db0ee2e 100644 --- a/lib_cxng/src/cx_rsa.h +++ b/lib_cxng/src/cx_rsa.h @@ -40,11 +40,11 @@ size_t cx_pkcs1_get_hash_len(cx_md_t hID); * * @return em_len, if encoded 0 else */ -cx_err_t cx_pkcs1_emsa_v1o5_encode(cx_md_t hID, - uint8_t *em, - size_t em_len, - const uint8_t *mHash, - size_t mHashLen); +WARN_UNUSED_RESULT cx_err_t cx_pkcs1_emsa_v1o5_encode(cx_md_t hID, + uint8_t *em, + size_t em_len, + const uint8_t *mHash, + size_t mHashLen); /* * @param [in] hID underlaid hash (ignored, sha256 forced) * @param [in] em encoded message to verify @@ -73,12 +73,12 @@ bool cx_pkcs1_emsa_v1o5_verify(cx_md_t hID, * * @return em_len, if encoded 0 else */ -cx_err_t cx_pkcs1_emsa_pss_encode(cx_md_t hID, - uint8_t *em, - size_t em_len, - const uint8_t *mHash, - size_t mHashLen, - size_t *size); +WARN_UNUSED_RESULT cx_err_t cx_pkcs1_emsa_pss_encode(cx_md_t hID, + uint8_t *em, + size_t em_len, + const uint8_t *mHash, + size_t mHashLen, + size_t *size); /* * @param [in] hID underlaid hash (ignored, sha256 forced) @@ -90,13 +90,13 @@ cx_err_t cx_pkcs1_emsa_pss_encode(cx_md_t hID, * * @return em_len, if encoded 0 else */ -cx_err_t cx_pkcs1_emsa_pss_encode_with_salt_len(cx_md_t hID, - uint8_t *em, - size_t em_len, - const uint8_t *mHash, - size_t mHashLen, - size_t mSaltLen, - size_t *size); +WARN_UNUSED_RESULT cx_err_t cx_pkcs1_emsa_pss_encode_with_salt_len(cx_md_t hID, + uint8_t *em, + size_t em_len, + const uint8_t *mHash, + size_t mHashLen, + size_t mSaltLen, + size_t *size); /* The salt length is equal to the mHashLen value. * If another salt length is to be used, the @@ -142,11 +142,11 @@ bool cx_pkcs1_emsa_pss_verify_with_salt_len(cx_md_t hID, * * @return em_len, if encoded 0 else */ -cx_err_t cx_pkcs1_eme_v1o5_encode(cx_md_t hID, - uint8_t *em, - size_t em_len, - const uint8_t *mHash, - size_t mHashLen); +WARN_UNUSED_RESULT cx_err_t cx_pkcs1_eme_v1o5_encode(cx_md_t hID, + uint8_t *em, + size_t em_len, + const uint8_t *mHash, + size_t mHashLen); /* * @param [in] hID underlaid hash (ignored, sha256 forced) * @param [in] em encoded message @@ -171,11 +171,8 @@ size_t cx_pkcs1_eme_v1o5_decode(cx_md_t hID, * * @return em_len, if encoded 0 else */ -cx_err_t cx_pkcs1_eme_oaep_encode(cx_md_t hID, - uint8_t *em, - size_t em_len, - const uint8_t *m, - size_t mLen); +WARN_UNUSED_RESULT cx_err_t +cx_pkcs1_eme_oaep_encode(cx_md_t hID, uint8_t *em, size_t em_len, const uint8_t *m, size_t mLen); /* * @param [in] hID underlaid hash (ignored, sha256 forced) * @param [in] em encoded message @@ -185,11 +182,8 @@ cx_err_t cx_pkcs1_eme_oaep_encode(cx_md_t hID, * * @return decoded message length, -1 if decoding fail */ -cx_err_t cx_pkcs1_eme_oaep_decode(cx_md_t hID, - uint8_t *em, - size_t em_len, - uint8_t *m, - size_t *mLen); +WARN_UNUSED_RESULT cx_err_t +cx_pkcs1_eme_oaep_decode(cx_md_t hID, uint8_t *em, size_t em_len, uint8_t *m, size_t *mLen); // For PKCS1.5 #define PKCS1_DIGEST_BUFFER_LENGTH 64 @@ -238,10 +232,15 @@ extern uint8_t const C_cx_oid_sha3_256[CX_OID_SHA3_256_LENGTH]; extern uint8_t const C_cx_oid_sha3_512[CX_OID_SHA3_512_LENGTH]; #endif // HAVE_SHA3 -cx_err_t cx_rsa_get_public_components(const cx_rsa_public_key_t *key, uint8_t **e, uint8_t **n); -cx_err_t cx_rsa_get_private_components(const cx_rsa_private_key_t *key, uint8_t **d, uint8_t **n); +WARN_UNUSED_RESULT cx_err_t cx_rsa_get_public_components(const cx_rsa_public_key_t *key, + uint8_t **e, + uint8_t **n); +WARN_UNUSED_RESULT cx_err_t cx_rsa_get_private_components(const cx_rsa_private_key_t *key, + uint8_t **d, + uint8_t **n); -cx_err_t cx_rsa_private_key_ctx_size(const cx_rsa_private_key_t *key, size_t *size); +WARN_UNUSED_RESULT cx_err_t cx_rsa_private_key_ctx_size(const cx_rsa_private_key_t *key, + size_t *size); #endif // CX_RSA_H #endif // HAVE_RSA diff --git a/lib_cxng/src/cx_sha256.h b/lib_cxng/src/cx_sha256.h index a89a5cdf..53fa2ecd 100644 --- a/lib_cxng/src/cx_sha256.h +++ b/lib_cxng/src/cx_sha256.h @@ -1,8 +1,26 @@ -#if defined(HAVE_SHA256) || defined(HAVE_SHA224) + +/******************************************************************************* + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifndef CX_SHA256_H #define CX_SHA256_H +#if defined(HAVE_SHA256) || defined(HAVE_SHA224) + #include "lcx_sha256.h" #include #include @@ -16,8 +34,10 @@ extern const cx_hash_info_t cx_sha224_info; extern const cx_hash_info_t cx_sha256_info; #endif // HAVE_SHA256 -cx_err_t cx_sha256_update(cx_sha256_t *ctx, const uint8_t *data, size_t len); +WARN_UNUSED_RESULT cx_err_t cx_sha256_update(cx_sha256_t *ctx, const uint8_t *data, size_t len); +// No need to add WARN_UNUSED_RESULT to cx_sha256_final(), it always returns CX_OK cx_err_t cx_sha256_final(cx_sha256_t *ctx, uint8_t *digest); -#endif // CX_SHA256_H #endif // HAVE_SHA256 + +#endif // CX_SHA256_H diff --git a/lib_cxng/src/cx_sha3.h b/lib_cxng/src/cx_sha3.h index 96bab3f4..7534a81f 100644 --- a/lib_cxng/src/cx_sha3.h +++ b/lib_cxng/src/cx_sha3.h @@ -1,8 +1,26 @@ -#ifdef HAVE_SHA3 + +/******************************************************************************* + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifndef CX_SHA3_H #define CX_SHA3_H +#ifdef HAVE_SHA3 + #include "lcx_sha3.h" extern const cx_hash_info_t cx_sha3_info; @@ -10,10 +28,11 @@ extern const cx_hash_info_t cx_keccak_info; extern const cx_hash_info_t cx_shake128_info; extern const cx_hash_info_t cx_shake256_info; -cx_err_t cx_sha3_update(cx_sha3_t *ctx, const uint8_t *data, size_t len); +WARN_UNUSED_RESULT cx_err_t cx_sha3_update(cx_sha3_t *ctx, const uint8_t *data, size_t len); +// No need to add WARN_UNUSED_RESULT to cx_sha3_final(), it always returns CX_OK cx_err_t cx_sha3_final(cx_sha3_t *ctx, uint8_t *digest); size_t cx_sha3_get_output_size(const cx_sha3_t *ctx); -#endif // CX_SHA3_H - #endif // HAVE_SHA3 + +#endif // CX_SHA3_H diff --git a/lib_cxng/src/cx_sha512.h b/lib_cxng/src/cx_sha512.h index ee2c2e28..11f42f00 100644 --- a/lib_cxng/src/cx_sha512.h +++ b/lib_cxng/src/cx_sha512.h @@ -1,8 +1,26 @@ -#if defined(HAVE_SHA512) || defined(HAVE_SHA384) + +/******************************************************************************* + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #ifndef CX_SHA512_H #define CX_SHA512_H +#if defined(HAVE_SHA512) || defined(HAVE_SHA384) + #include #include #include "lcx_sha512.h" @@ -15,9 +33,10 @@ extern const cx_hash_info_t cx_sha384_info; extern const cx_hash_info_t cx_sha512_info; #endif // HAVE_SHA512 -cx_err_t cx_sha512_update(cx_sha512_t *ctx, const uint8_t *data, size_t len); +WARN_UNUSED_RESULT cx_err_t cx_sha512_update(cx_sha512_t *ctx, const uint8_t *data, size_t len); +// No need to add WARN_UNUSED_RESULT to cx_sha512_final(), it always returns CX_OK cx_err_t cx_sha512_final(cx_sha512_t *ctx, uint8_t *digest); -#endif // CX_SHA512_H - #endif // defined(HAVE_SHA512) || defined(HAVE_SHA384) + +#endif // CX_SHA512_H diff --git a/lib_cxng/src/cx_utils.h b/lib_cxng/src/cx_utils.h index b401f588..1a117f61 100644 --- a/lib_cxng/src/cx_utils.h +++ b/lib_cxng/src/cx_utils.h @@ -89,4 +89,4 @@ void cx_swap_buffer64(uint64bits_t *v, int len); void cx_memxor(uint8_t *buf1, const uint8_t *buf2, size_t len); -#endif +#endif // CX_UTILS_H diff --git a/lib_stusb/STM32_USB_Device_Library/Class/CCID/inc/sc_itf.h b/lib_stusb/STM32_USB_Device_Library/Class/CCID/inc/sc_itf.h index dfac8d60..8babdec3 100644 --- a/lib_stusb/STM32_USB_Device_Library/Class/CCID/inc/sc_itf.h +++ b/lib_stusb/STM32_USB_Device_Library/Class/CCID/inc/sc_itf.h @@ -64,7 +64,7 @@ uint8_t SC_ExecuteEscape (uint8_t* escapePtr, uint32_t escapeLen, uint8_t* responseBuff, uint16_t* responseLen); uint8_t SC_SetClock (uint8_t bClockCommand); -uint8_t SC_XferBlock (uint8_t* ptrBlock, uint32_t blockLen, uint16_t* expectedLen); +uint8_t SC_XferBlock (uint8_t* ptrBlock, uint32_t blockLen); uint8_t SC_Request_GetClockFrequencies(uint8_t* pbuf, uint16_t* len); uint8_t SC_Request_GetDataRates(uint8_t* pbuf, uint16_t* len); uint8_t SC_T0Apdu(uint8_t bmChanges, uint8_t bClassGetResponse, @@ -72,8 +72,7 @@ uint8_t SC_T0Apdu(uint8_t bmChanges, uint8_t bClassGetResponse, uint8_t SC_Mechanical(uint8_t bFunction); uint8_t SC_SetDataRateAndClockFrequency(uint32_t dwClockFrequency, uint32_t dwDataRate); -uint8_t SC_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter, - uint8_t* pbuf, uint32_t* returnLen ); +uint8_t SC_Secure(uint8_t* pbuf, uint32_t* returnLen); #endif // HAVE_USB_CLASS_CCID diff --git a/lib_stusb/STM32_USB_Device_Library/Class/CCID/inc/usbd_ccid_if.h b/lib_stusb/STM32_USB_Device_Library/Class/CCID/inc/usbd_ccid_if.h index 9326da8f..1e077a7c 100644 --- a/lib_stusb/STM32_USB_Device_Library/Class/CCID/inc/usbd_ccid_if.h +++ b/lib_stusb/STM32_USB_Device_Library/Class/CCID/inc/usbd_ccid_if.h @@ -58,6 +58,14 @@ #define VOLTAGE_SELECTION_5V 0x01 #define VOLTAGE_SELECTION_1V8 0x03 +/* PC_to_RDR_Secure PIN operations */ +#define PIN_OPR_VERIFICATION 0x00 +#define PIN_OPR_MODIFICATION 0x01 +#define PIN_OPR_TRANSFER 0x02 +#define PIN_OPR_WAIT_ICC_RESP 0x03 +#define PIN_OPR_CANCEL 0x04 +#define PIN_OPR_APDU_CLA 0xEF + #define PC_TO_RDR_ICCPOWERON 0x62 #define PC_TO_RDR_ICCPOWEROFF 0x63 #define PC_TO_RDR_GETSLOTSTATUS 0x65 @@ -223,6 +231,8 @@ void Set_CSW (uint8_t CSW_Status, uint8_t Send_Permission); void io_usb_ccid_set_card_inserted(unsigned int inserted); +void io_usb_ccid_configure_pinpad(uint8_t enabled); + #endif // HAVE_USB_CLASS_CCID #endif /* __USBD_CCID_IF_H */ diff --git a/lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_cmd.c b/lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_cmd.c index 31e4759a..2c1b0a7d 100644 --- a/lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_cmd.c +++ b/lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_cmd.c @@ -230,29 +230,26 @@ uint8_t PC_to_RDR_XfrBlock(void) CHK_ACTIVE_STATE ); if (error != 0) return error; - - if (G_io_ccid.bulk_header.bulkout.dwLength > IO_CCID_DATA_BUFFER_SIZE) - { /* Check amount of Data Sent by Host is > than memory allocated ? */ - - return SLOTERROR_BAD_DWLENGTH; - } + if (G_io_ccid.bulk_header.bulkout.dwLength > IO_CCID_DATA_BUFFER_SIZE) + { /* Check amount of Data Sent by Host is > than memory allocated ? */ - /* wLevelParameter = Size of expected data to be returned by the - bulk-IN endpoint */ - expectedLength = (G_io_ccid.bulk_header.bulkout.bSpecific_2 << 8) | - G_io_ccid.bulk_header.bulkout.bSpecific_1; + return SLOTERROR_BAD_DWLENGTH; + } - reqlen = G_io_ccid.bulk_header.bulkout.dwLength; - - G_io_ccid.bulk_header.bulkin.dwLength = (uint16_t)expectedLength; + /* wLevelParameter = Size of expected data to be returned by the + bulk-IN endpoint */ + expectedLength = (G_io_ccid.bulk_header.bulkout.bSpecific_2 << 8) | + G_io_ccid.bulk_header.bulkout.bSpecific_1; - error = SC_XferBlock(&G_io_ccid_data_buffer[0], - reqlen, - &expectedLength); + reqlen = G_io_ccid.bulk_header.bulkout.dwLength; - if (error != SLOT_NO_ERROR) + G_io_ccid.bulk_header.bulkin.dwLength = (uint16_t)expectedLength; + + error = SC_XferBlock(&G_io_ccid_data_buffer[0], reqlen); + + if (error != SLOT_NO_ERROR) { CCID_UpdateCommandStatus(BM_COMMAND_STATUS_FAILED, BM_ICC_PRESENT_ACTIVE); } @@ -639,7 +636,6 @@ uint8_t PC_TO_RDR_SetDataRateAndClockFrequency(void) uint8_t error; uint32_t clockFrequency; uint32_t dataRate; - uint32_t temp =0; error = CCID_CheckCommandParams(CHK_PARAM_SLOT |\ CHK_PARAM_CARD_PRESENT |\ @@ -694,7 +690,6 @@ uint8_t PC_TO_RDR_SetDataRateAndClockFrequency(void) uint8_t PC_TO_RDR_Secure(void) { uint8_t error; - uint8_t bBWI; uint16_t wLevelParameter; uint32_t responseLen; @@ -708,14 +703,13 @@ uint8_t PC_TO_RDR_Secure(void) return error; } - bBWI = G_io_ccid.bulk_header.bulkout.bSpecific_0; wLevelParameter = (G_io_ccid.bulk_header.bulkout.bSpecific_1 + ((uint16_t)G_io_ccid.bulk_header.bulkout.bSpecific_2<<8)); if ((EXCHANGE_LEVEL_FEATURE == TPDU_EXCHANGE) || (EXCHANGE_LEVEL_FEATURE == SHORT_APDU_EXCHANGE)) { /* TPDU level & short APDU level, wLevelParameter is RFU, = 0000h */ - if (wLevelParameter != 0 ) + if (wLevelParameter != 0) { G_io_ccid.bulk_header.bulkin.dwLength = 0; CCID_UpdateCommandStatus(BM_COMMAND_STATUS_FAILED, BM_ICC_PRESENT_ACTIVE); @@ -724,8 +718,7 @@ uint8_t PC_TO_RDR_Secure(void) } } - error = SC_Secure(G_io_ccid.bulk_header.bulkout.dwLength - CCID_HEADER_SIZE, bBWI, wLevelParameter, - &G_io_ccid_data_buffer[0], &responseLen); + error = SC_Secure(&G_io_ccid_data_buffer[0], &responseLen); G_io_ccid.bulk_header.bulkin.dwLength = responseLen; diff --git a/lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_if.c b/lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_if.c index ef030261..fc05b946 100644 --- a/lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_if.c +++ b/lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_if.c @@ -206,6 +206,7 @@ void CCID_BulkMessage_Out (USBD_HandleTypeDef *pdev, G_io_ccid.Ccid_BulkState = CCID_STATE_IDLE; // no break is intentional + __attribute__((fallthrough)); case CCID_STATE_IDLE: // prepare to receive another packet later on (to avoid troubles with timeout due to other hid command timeouting the ccid endpoint reply) USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE); @@ -525,35 +526,39 @@ uint8_t SC_SetDataRateAndClockFrequency(uint32_t dwClockFrequency, UNUSED(dwDataRate); return SLOT_NO_ERROR; } -uint8_t SC_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter, - uint8_t* pbuf, uint32_t* returnLen ) { - UNUSED(bBWI); - UNUSED(wLevelParameter); - UNUSED(returnLen); - // return SLOTERROR_CMD_NOT_SUPPORTED; - uint16_t ret_len,off; +uint8_t SC_Secure(uint8_t* pbuf, uint32_t* returnLen) { + // Extract the APDU to send to the App switch(pbuf[0]) { - case 0: // verify pin - ret_len = dwLength - 15; - memmove(G_io_apdu_buffer, pbuf+15, dwLength-15); + case PIN_OPR_VERIFICATION: + // CCID Spec: APDU starts at offset 25, after the 10-Byte header + pbuf += 15; break; - case 1: // modify pin + case PIN_OPR_MODIFICATION: + // CCID Spec: APDU starts at offset 28, 29 or 30 + // depending on the nb of messages to display switch(pbuf[11]) { - case 3: - off = 20; + case 0: + // CCID Spec: No message to display + // APDU starts at offset 28, after the 10-Byte header + pbuf += 18; break; - case 2: case 1: - off = 19; + case 2: + // CCID Spec: 1 or 2 message(s) to display + // APDU starts at offset 29, after the 10-Byte header + pbuf += 19; break; - // 0 and 4-0xFF - default: - off = 18; + case 3: + // CCID Spec: 3 messages to display + // APDU starts at offset 30, after the 10-Byte header + pbuf += 20; break; + default: // unsupported + G_io_ccid.bulk_header.bulkin.dwLength = 0; + RDR_to_PC_DataBlock(SLOTERROR_CMD_NOT_SUPPORTED); + CCID_Send_Reply(&USBD_Device); + return SLOTERROR_CMD_NOT_SUPPORTED; } - ret_len = dwLength-off; - // provide with the complete apdu - memmove(G_io_apdu_buffer, pbuf+off, dwLength-off); break; default: // unsupported G_io_ccid.bulk_header.bulkin.dwLength = 0; @@ -561,13 +566,15 @@ uint8_t SC_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter, CCID_Send_Reply(&USBD_Device); return SLOTERROR_CMD_NOT_SUPPORTED; } - return SC_XferBlock(G_io_apdu_buffer, ret_len, &ret_len); + // Change APDU CLA to be interpreted by the CCID compatible App (like OpenPGP) + pbuf[0] = PIN_OPR_APDU_CLA; + // The APDU has no data, only the header (size 5) + *returnLen = 5; + return SC_XferBlock(pbuf, *returnLen); } // prepare the apdu to be processed by the application -uint8_t SC_XferBlock (uint8_t* ptrBlock, uint32_t blockLen, uint16_t* expectedLen) { - UNUSED(expectedLen); - +uint8_t SC_XferBlock (uint8_t* ptrBlock, uint32_t blockLen) { // check for overflow if (blockLen > IO_APDU_BUFFER_SIZE) { return SLOTERROR_BAD_LENTGH; @@ -614,11 +621,10 @@ void io_usb_ccid_set_card_inserted(unsigned int inserted) { #endif // HAVE_CCID_INTERRUPT } - - - - - +void io_usb_ccid_configure_pinpad(uint8_t enabled) { + const volatile uint8_t *cfgDesc = USBD_GetPinPadOffset(); + nvm_write((void *)cfgDesc, &enabled, 1); +} #endif // HAVE_USB_CLASS_CCID diff --git a/lib_stusb/usbd_conf.h b/lib_stusb/usbd_conf.h index 745ee53a..3489645c 100644 --- a/lib_stusb/usbd_conf.h +++ b/lib_stusb/usbd_conf.h @@ -164,6 +164,7 @@ typedef unsigned short uint16_t; void *USBD_static_malloc(uint32_t size); void USBD_static_free(void *p); +const volatile uint8_t *USBD_GetPinPadOffset(void); void USB_power(unsigned char enabled); diff --git a/lib_stusb_impl/u2f_impl.c b/lib_stusb_impl/u2f_impl.c index 65e71c11..a77b15f8 100644 --- a/lib_stusb_impl/u2f_impl.c +++ b/lib_stusb_impl/u2f_impl.c @@ -38,6 +38,17 @@ #define INIT_CAPABILITIES 0x00 #endif +#define OFFSET_CLA 0 +#define OFFSET_INS 1 +#define OFFSET_P1 2 +#define OFFSET_P2 3 +#define OFFSET_DATA 7 + +#define APDU_MIN_HEADER 4 +#define LC_FIRST_BYTE_OFFSET 4 +#define LONG_ENC_LC_SIZE 3 +#define LONG_ENC_LE_SIZE 2 // considering only scenarios where Lc is present + #define FIDO_CLA 0x00 #define FIDO_INS_ENROLL 0x01 #define FIDO_INS_SIGN 0x02 @@ -52,6 +63,12 @@ #define SIGN_USER_PRESENCE_MASK 0x01 +#ifndef U2F_PROXY_MAGIC + +static const uint8_t SW_WRONG_LENGTH[] = {0x67, 0x00}; + +#else // U2F_PROXY_MAGIC + static const uint8_t SW_BUSY[] = {0x90, 0x01}; static const uint8_t SW_PROOF_OF_PRESENCE_REQUIRED[] = {0x69, 0x85}; static const uint8_t SW_BAD_KEY_HANDLE[] = {0x6A, 0x80}; @@ -61,8 +78,6 @@ static const uint8_t SW_UNKNOWN_CLASS[] = {0x6e, 0x00}; static const uint8_t SW_WRONG_LENGTH[] = {0x67, 0x00}; static const uint8_t SW_INTERNAL[] = {0x6F, 0x00}; -#ifdef U2F_PROXY_MAGIC - static const uint8_t U2F_VERSION[] = {'U', '2', 'F', '_', 'V', '2', 0x90, 0x00}; // take into account max header (u2f usb) @@ -240,28 +255,85 @@ void u2f_handle_cmd_ping(u2f_service_t *service, uint8_t *buffer, uint16_t lengt u2f_message_reply(service, U2F_CMD_PING, buffer, length); } -void u2f_handle_cmd_msg(u2f_service_t *service, uint8_t *buffer, uint16_t length) +int u2f_get_cmd_msg_data_length(const uint8_t *buffer, uint16_t length) { - // screen_printf("U2F msg\n"); - uint8_t cla = buffer[0]; - uint8_t ins = buffer[1]; - uint8_t p1 = buffer[2]; - uint8_t p2 = buffer[3]; - // in extended length buffer[4] must be 0 - uint32_t dataLength = /*(buffer[4] << 16) |*/ (buffer[5] << 8) | (buffer[6]); - if (dataLength == (uint16_t) (length - 9) || dataLength == (uint16_t) (length - 7)) { - // Le is optional - // nominal case from the specification + /* Parse buffer to retrieve the data length. + Only Extended encoding is supported */ + + if (length < APDU_MIN_HEADER) { + return -1; } - // circumvent google chrome extended length encoding done on the last byte only (module 256) but - // all data being transferred - else if (dataLength == (uint16_t) (length - 9) % 256) { - dataLength = length - 9; + + if (length == APDU_MIN_HEADER) { + // Either short or extended encoding with Lc and Le omitted + return 0; } - else if (dataLength == (uint16_t) (length - 7) % 256) { - dataLength = length - 7; + + if (length == APDU_MIN_HEADER + 1) { + // Short encoding, with next byte either Le or Lc with the other one omitted + // There is no way to tell so no way to check the value + // but anyway the data length is 0 + + // Support this particular short encoding APDU as Fido Conformance Tool v1.7.0 + // is using it even though spec requires that short encoding should not be used + // over HID. + return 0; } - else { + + if (length < APDU_MIN_HEADER + 3) { + // Short encoding or bad length + // We don't support short encoding + return -1; + } + + if (length == APDU_MIN_HEADER + 3) { + if (buffer[4] != 0) { + // Short encoding or bad length + // We don't support short encoding + return -1; + } + // Can't be short encoding as Lc = 0x00 would lead to invalid length + // so extended encoding and either: + // - Lc = 0x00 0x00 0x00 and Le is omitted + // - Lc omitted and Le = 0x00 0xyy 0xzz + // so no way to check the value + // but anyway the data length is 0 + return 0; + } + + if (buffer[LC_FIRST_BYTE_OFFSET] != 0) { + // Short encoding or bad length + // We don't support short encoding + return -1; + } + + // Can't be short encoding as Lc = 0 would lead to invalid length + // so extended encoding with Lc field present, optionally Le (2B) is present too + uint32_t dataLength + = (buffer[LC_FIRST_BYTE_OFFSET + 1] << 8) | (buffer[LC_FIRST_BYTE_OFFSET + 2]); + + // Ensure that Lc value is consistent + if ((APDU_MIN_HEADER + LONG_ENC_LC_SIZE + dataLength != length) + && (APDU_MIN_HEADER + LONG_ENC_LC_SIZE + dataLength + LONG_ENC_LE_SIZE != length)) { + return -1; + } + + return dataLength; +} + +void u2f_handle_cmd_msg(u2f_service_t *service, uint8_t *buffer, uint16_t length) +{ + // screen_printf("U2F msg\n"); + +#ifdef U2F_PROXY_MAGIC + uint8_t cla = buffer[OFFSET_CLA]; + uint8_t ins = buffer[OFFSET_INS]; + uint8_t p1 = buffer[OFFSET_P1]; + uint8_t p2 = buffer[OFFSET_P2]; +#endif // U2F_PROXY_MAGIC + + uint32_t dataLength = u2f_get_cmd_msg_data_length(buffer, length); + if (dataLength < 0) { // invalid size u2f_message_reply( service, U2F_CMD_MSG, (uint8_t *) SW_WRONG_LENGTH, sizeof(SW_WRONG_LENGTH)); @@ -286,20 +358,20 @@ void u2f_handle_cmd_msg(u2f_service_t *service, uint8_t *buffer, uint16_t length switch (ins) { case FIDO_INS_ENROLL: // screen_printf("enroll\n"); - u2f_apdu_enroll(service, p1, p2, buffer + 7, dataLength); + u2f_apdu_enroll(service, p1, p2, buffer + OFFSET_DATA, dataLength); break; case FIDO_INS_SIGN: // screen_printf("sign\n"); - u2f_apdu_sign(service, p1, p2, buffer + 7, dataLength); + u2f_apdu_sign(service, p1, p2, buffer + OFFSET_DATA, dataLength); break; case FIDO_INS_GET_VERSION: // screen_printf("version\n"); - u2f_apdu_get_version(service, p1, p2, buffer + 7, dataLength); + u2f_apdu_get_version(service, p1, p2, buffer + OFFSET_DATA, dataLength); break; // only support by case FIDO_INS_PROP_GET_INFO: - u2f_apdu_get_info(service, p1, p2, buffer + 7, dataLength); + u2f_apdu_get_info(service, p1, p2, buffer + OFFSET_DATA, dataLength); break; default: diff --git a/lib_stusb_impl/u2f_impl.h b/lib_stusb_impl/u2f_impl.h index 71b5863a..233e2314 100644 --- a/lib_stusb_impl/u2f_impl.h +++ b/lib_stusb_impl/u2f_impl.h @@ -17,3 +17,10 @@ ********************************************************************************/ #include "usbd_hid_impl.h" + +/** + * Parse the cmd msg header to retrieve the data length. + * Return -1 in case of parsing error. + * Else return the data length. + */ +int u2f_get_cmd_msg_data_length(const uint8_t *buffer, uint16_t length); diff --git a/lib_stusb_impl/usbd_impl.c b/lib_stusb_impl/usbd_impl.c index ee37bbc9..0d64fd0f 100644 --- a/lib_stusb_impl/usbd_impl.c +++ b/lib_stusb_impl/usbd_impl.c @@ -304,21 +304,34 @@ static uint8_t const HID_ReportDesc_fido[] = { #define ARRAY_U2LE(l) (l)&0xFF, (l)>>8 +#define CFG_HDR_LEN (0x9) +#define CFG_HIDGEN_LEN (0x9+0x9+0x7+0x7) +#define CFG_IO_U2F_LEN (0x9+0x9+0x7+0x7) +#define CFG_USB_CCID_LEN (0x9+0x36+0x7+0x7) +#define CFG_WEBUSB_LEN (0x9+0x7+0x7) + /* USB HID device Configuration Descriptor */ +#ifdef HAVE_USB_CLASS_CCID +// Note: keeping const qualifier to ensure the good section is used by the linker. +// This table is mapped in NVRAM section and therefore it is correctly initialized, +// normal Read is possible and Write can be done through nvm_write() calls. +static __ALIGN_BEGIN uint8_t const N_USBD_CfgDesc[] __ALIGN_END = +#else static __ALIGN_BEGIN uint8_t const USBD_CfgDesc[] __ALIGN_END = +#endif // HAVE_USB_CLASS_CCID { 0x09, /* bLength: Configuration Descriptor size */ USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ - ARRAY_U2LE(0x9 /* wTotalLength: Bytes returned */ - +0x9+0x9+0x7+0x7 + ARRAY_U2LE(CFG_HDR_LEN /* wTotalLength: Bytes returned */ + +CFG_HIDGEN_LEN #ifdef HAVE_IO_U2F - +0x9+0x9+0x7+0x7 + +CFG_IO_U2F_LEN #endif // HAVE_IO_U2F #ifdef HAVE_USB_CLASS_CCID - +0x9+0x36+0x7+0x7 + +CFG_USB_CCID_LEN #endif // HAVE_USB_CLASS_CCID #ifdef HAVE_WEBUSB - +0x9+0x7+0x7 + +CFG_WEBUSB_LEN #endif // HAVE_WEBUSB ), 1 @@ -821,8 +834,13 @@ static uint8_t *USBD_GetDeviceQualifierDesc_impl(uint16_t *length) */ static uint8_t *USBD_GetCfgDesc_impl(uint16_t *length) { +#ifdef HAVE_USB_CLASS_CCID + *length = sizeof(N_USBD_CfgDesc); + return (uint8_t *) N_USBD_CfgDesc; +#else *length = sizeof(USBD_CfgDesc); return (uint8_t *) USBD_CfgDesc; +#endif } uint8_t *USBD_HID_GetHidDescriptor_impl(uint16_t *len) @@ -878,6 +896,34 @@ uint8_t *USBD_HID_GetReportDescriptor_impl(uint16_t *len) return 0; } +#ifdef HAVE_USB_CLASS_CCID +/** + * @brief Returns the pinpad value offset in the descriptor. + * @retval Offset + */ +const volatile uint8_t *USBD_GetPinPadOffset(void) +{ + unsigned short length = 0; + uint8_t *cfgDesc = NULL; + unsigned short offset = 0; + + cfgDesc = USBD_GetCfgDesc_impl(&length); + + offset = CFG_HDR_LEN + CFG_HIDGEN_LEN; +#ifdef HAVE_IO_U2F + offset += CFG_IO_U2F_LEN; +#endif // HAVE_IO_U2F + // Offset of the parameter 'bPINSupport' inside the CCID interface structure in N_USBD_CfgDesc + offset += 61; + + // Returns a const volatile pointer allowing callers to do + // - write operations through nvram_write + // - read operation without potential compilation optimization issue thanks to the volatile + // qualifier. + return (const volatile uint8_t *) (cfgDesc + offset); +} +#endif // HAVE_USB_CLASS_CCID + /** * @} */ diff --git a/src/cx_stubs.S b/src/cx_stubs.S index abb5e35d..a3b20b21 100644 --- a/src/cx_stubs.S +++ b/src/cx_stubs.S @@ -29,7 +29,9 @@ CX_TRAMPOLINE _NR_cx_blake2b_init_no_throw cx_blake2b_init_no_th CX_TRAMPOLINE _NR_cx_blake2b_update cx_blake2b_update CX_TRAMPOLINE _NR_cx_crc16 cx_crc16 CX_TRAMPOLINE _NR_cx_crc16_update cx_crc16_update -CX_TRAMPOLINE _NR_cx_crc32 cx_crc32 +// Disable lib CX CRC32 until it get fixed in the OS. +// Meanwhile, it's implemented in cx_wrappers.c +//CX_TRAMPOLINE _NR_cx_crc32 cx_crc32 CX_TRAMPOLINE _NR_cx_decode_coord cx_decode_coord CX_TRAMPOLINE _NR_cx_des_dec_block cx_des_dec_block CX_TRAMPOLINE _NR_cx_des_enc_block cx_des_enc_block diff --git a/src/cx_wrappers.c b/src/cx_wrappers.c index f1db2af9..579846f6 100644 --- a/src/cx_wrappers.c +++ b/src/cx_wrappers.c @@ -60,3 +60,56 @@ cx_err_t cx_ecdsa_sign_rs_no_throw(const cx_ecfp_private_key_t *key, } return error; } + +#define CX_CRC32_INIT 0xFFFFFFFF + +static unsigned int cx_ccitt32[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; + +uint32_t cx_crc32_update(uint32_t crc, const void *buf, size_t len) +{ +#define buffer ((const uint8_t *) buf) + uint32_t i; + + for (i = 0; i < len; i++) { + crc = cx_ccitt32[(crc ^ buffer[i]) & 0xff] ^ (crc >> 8u); + } + + return crc ^ CX_CRC32_INIT; +} + +uint32_t cx_crc32(const void *buf, size_t len) +{ + return cx_crc32_update(CX_CRC32_INIT, buf, len); +} diff --git a/src/ledger_assert.c b/src/ledger_assert.c index d39b7681..3ba6619c 100644 --- a/src/ledger_assert.c +++ b/src/ledger_assert.c @@ -27,15 +27,19 @@ #include "nbgl_use_case.h" #endif +#if defined(HAVE_LEDGER_ASSERT_DISPLAY) || defined(HAVE_DEBUG_THROWS) #ifndef ASSERT_BUFFER_LEN #define ASSERT_BUFFER_LEN 24 #endif -#if defined(HAVE_LEDGER_ASSERT_DISPLAY) || defined(HAVE_DEBUG_THROWS) -static char assert_buffer[ASSERT_BUFFER_LEN]; +char assert_buffer[ASSERT_BUFFER_LEN]; #endif -#if defined(HAVE_LEDGER_ASSERT_DISPLAY) && defined(LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO) +/************************************************************ + * Define behavior when LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO * + ***********************************************************/ +#ifdef LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO +#ifdef HAVE_LEDGER_ASSERT_DISPLAY void assert_display_lr_and_pc(int lr, int pc) { char buff[LR_AND_PC_SIZE]; @@ -47,17 +51,22 @@ void assert_display_lr_and_pc(int lr, int pc) } #endif -#if defined(HAVE_LEDGER_ASSERT_DISPLAY) && defined(LEDGER_ASSERT_CONFIG_MESSAGE_INFO) -void assert_display_message(const char *message) +#ifdef HAVE_PRINTF +void assert_print_lr_and_pc(int lr, int pc) { - char buff[MESSAGE_SIZE]; - - snprintf(buff, MESSAGE_SIZE, "%s\n", message); - strncat(assert_buffer, buff, MESSAGE_SIZE); + lr = compute_address_location(lr); + pc = compute_address_location(pc); + PRINTF("=> LR: 0x%08X \n", lr); + PRINTF("=> PC: 0x%08X \n", pc); } #endif +#endif // LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO -#if defined(HAVE_LEDGER_ASSERT_DISPLAY) && defined(LEDGER_ASSERT_CONFIG_FILE_INFO) +/******************************************************* + * Define behavior when LEDGER_ASSERT_CONFIG_FILE_INFO * + ******************************************************/ +#ifdef LEDGER_ASSERT_CONFIG_FILE_INFO +#ifdef HAVE_LEDGER_ASSERT_DISPLAY void assert_display_file_info(const char *file, unsigned int line) { char buff[FILE_SIZE]; @@ -67,55 +76,45 @@ void assert_display_file_info(const char *file, unsigned int line) } #endif -#if defined(HAVE_PRINTF) && defined(LEDGER_ASSERT_CONFIG_LR_AND_PC_INFO) -void assert_print_lr_and_pc(int lr, int pc) -{ - lr = compute_address_location(lr); - pc = compute_address_location(pc); - PRINTF("LEDGER_ASSERT FAILED\n"); - PRINTF("=> LR: 0x%08X \n", lr); - PRINTF("=> PC: 0x%08X \n", pc); -} -#endif - -#if defined(HAVE_PRINTF) && defined(LEDGER_ASSERT_CONFIG_FILE_INFO) +#ifdef HAVE_PRINTF void assert_print_file_info(const char *file, int line) { PRINTF("%s::%d \n", file, line); } #endif +#endif // LEDGER_ASSERT_CONFIG_FILE_INFO -#if defined(HAVE_PRINTF) && defined(LEDGER_ASSERT_CONFIG_MESSAGE_INFO) -void assert_print_message(const char *message) -{ - if (message) { - PRINTF("%s\n", message); - } -} -#endif - -#if defined(HAVE_DEBUG_THROWS) +/************************************* + * Specific mechanism to debug THROW * + ************************************/ +#ifdef HAVE_DEBUG_THROWS void throw_display_lr(int e, int lr) { lr = compute_address_location(lr); snprintf(assert_buffer, ASSERT_BUFFER_LEN, "e=0x%04X\n LR=0x%08X\n", e, lr); } -#endif -#if defined(HAVE_PRINTF) && defined(HAVE_DEBUG_THROWS) +#ifdef HAVE_PRINTF void throw_print_lr(int e, int lr) { lr = compute_address_location(lr); PRINTF("exception[0x%04X]: LR=0x%08X\n", e, lr); } #endif +#endif // HAVE_DEBUG_THROWS +/******************* + * Common app exit * + ******************/ void assert_exit(bool confirm) { UNUSED(confirm); os_sched_exit(-1); } +/************************************ + * Display info on screen mechanism * + ***********************************/ #if defined(HAVE_LEDGER_ASSERT_DISPLAY) || defined(HAVE_DEBUG_THROWS) #ifdef HAVE_BAGL UX_STEP_CB(ux_error,