Using files from the SDK/lib_standard_app
What changed, and why it matters
This commit is a large refactoring that replaces many locally-implemented utility files (for parsing APDUs, buffers, base58, BIP32, varints, read/write helpers, etc.) with equivalent files from Ledger's official SDK library (lib_standard_app). It also renames some local files (e.g., io.c -> io_ext.c, buffer.c -> buffer_ext.c) to hold only app-specific extensions. The change itself is not a security patch; it is a code-maintenance / deduplication move. However, any large-scale dependency switch can introduce subtle behavioral differences or regressions, so it warrants careful review rather than alarm.
Treat this as a high-touch refactoring commit. Verify that the SDK versions of base58, bip32, buffer, format, parser, read, varint, write, and crypto_helpers are functionally equivalent to the removed local versions, especially around edge cases in buffer bounds, varint parsing, and BIP32 path validation. Run the existing unit and integration tests, and consider a diff between the removed local files and the SDK files they replace to catch any semantic drift.
Security signals we found
Large-scale source-file replacement and include-path migration
Removal of local crypto/encoding utility implementations in favor of SDK equivalents
Renaming of local modules to *_ext to avoid symbol collisions with SDK
No explicit security bug fix or bounds-check change visible in the diff
Evidence from the diff
The diff removes local implementations of standard Ledger app helpers under src/common and src/boilerplate, and instead compiles the corresponding sources from $(BOLOS_SDK)/lib_standard_app (base58, bip32, buffer, format, parser, read, varint, write, plus crypto_helpers). Local files that remain are renamed to *_ext and now only contain app-specific additions (e.g., buffer_ext adds peek/read/write helpers not in the SDK buffer, io_ext keeps the app’s event/timeout/response logic). Include paths are updated throughout the tree. There is no direct evidence in the diff of a vulnerability fix; the motivation appears to be unification with the SDK’s standard app library.
Changed components
Makefile build configurationsrc/boilerplate/apdu_parser (removed, now SDK)src/boilerplate/io (renamed io_ext)src/common/base58, bip32, buffer, format, parser, read, varint, write (removed, now SDK)src/common/buffer_ext, parser_ext, io_ext (new local extensions)All handlers and crypto code that include the above headersInspect captured patch +1514 / −2893
diff --git a/Makefile b/Makefile
index 229d39e..cbe63d0 100644
--- a/Makefile
+++ b/Makefile
@@ -175,9 +175,18 @@ endif
# Needed to be able to include the definition of G_cx
INCLUDES_PATH += $(BOLOS_SDK)/lib_cxng/src
+INCLUDES_PATH += $(BOLOS_SDK)/lib_standard_app
# Application source files
APP_SOURCE_PATH += src
+APP_SOURCE_FILES += ${BOLOS_SDK}/lib_standard_app/base58.c
+APP_SOURCE_FILES += ${BOLOS_SDK}/lib_standard_app/bip32.c
+APP_SOURCE_FILES += ${BOLOS_SDK}/lib_standard_app/buffer.c
+APP_SOURCE_FILES += ${BOLOS_SDK}/lib_standard_app/format.c
+APP_SOURCE_FILES += ${BOLOS_SDK}/lib_standard_app/parser.c
+APP_SOURCE_FILES += ${BOLOS_SDK}/lib_standard_app/read.c
+APP_SOURCE_FILES += ${BOLOS_SDK}/lib_standard_app/varint.c
+APP_SOURCE_FILES += ${BOLOS_SDK}/lib_standard_app/write.c
# Allow usage of function from lib_standard_app/crypto_helpers.c
APP_SOURCE_FILES += ${BOLOS_SDK}/lib_standard_app/crypto_helpers.c
diff --git a/src/boilerplate/apdu_parser.c b/src/boilerplate/apdu_parser.c
deleted file mode 100644
index 2ad3869..0000000
--- a/src/boilerplate/apdu_parser.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*****************************************************************************
- * Ledger App Bitcoin.
- * (c) 2025 Ledger SAS.
- *
- * 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.
- *****************************************************************************/
-
-#include <stddef.h> // size_t
-#include <stdint.h> // uint*_t
-#include <stdbool.h> // bool
-
-#include "apdu_parser.h"
-#include "offsets.h"
-
-bool apdu_parser(command_t *cmd, uint8_t *buf, size_t buf_len) {
- // Check minimum length and Lc field of APDU command
- if (buf_len < OFFSET_CDATA || buf_len - OFFSET_CDATA != buf[OFFSET_LC]) {
- return false;
- }
-
- cmd->cla = buf[OFFSET_CLA];
- cmd->ins = buf[OFFSET_INS];
- cmd->p1 = buf[OFFSET_P1];
- cmd->p2 = buf[OFFSET_P2];
- cmd->lc = buf[OFFSET_LC];
- cmd->data = (buf[OFFSET_LC] > 0) ? buf + OFFSET_CDATA : NULL;
-
- return true;
-}
diff --git a/src/boilerplate/apdu_parser.h b/src/boilerplate/apdu_parser.h
deleted file mode 100644
index 4d002dd..0000000
--- a/src/boilerplate/apdu_parser.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#pragma once
-
-#include <stddef.h> // size_t
-#include <stdint.h> // uint*_t
-#include <stdbool.h> // bool
-
-/**
- * Structure with fields of APDU command.
- */
-typedef struct {
- uint8_t cla; /// Instruction class
- uint8_t ins; /// Instruction code
- uint8_t p1; /// Instruction parameter 1
- uint8_t p2; /// Instruction parameter 2
- uint8_t lc; /// Length of command data
- uint8_t *data; /// Command data
-} command_t;
-
-/**
- * Parse APDU command from byte buffer.
- *
- * @param[out] cmd
- * Structured APDU command (CLA, INS, P1, P2, Lc, Command data).
- * @param[in] buf
- * Byte buffer with raw APDU command.
- * @param[in] buf_len
- * Length of byte buffer.
- *
- * @return true if success, false otherwise.
- *
- */
-bool apdu_parser(command_t *cmd, uint8_t *buf, size_t buf_len);
diff --git a/src/boilerplate/constants.h b/src/boilerplate/constants.h
deleted file mode 100644
index e9c390f..0000000
--- a/src/boilerplate/constants.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-/**
- * APDU instruction class for command defined by the framework.
- */
-#define CLA_FRAMEWORK 0xF8
-
-/**
- * Framework instruction to continue execution after an interruption.
- */
-#define INS_CONTINUE 0x01
diff --git a/src/boilerplate/dispatcher.c b/src/boilerplate/dispatcher.c
index b307d75..405e863 100644
--- a/src/boilerplate/dispatcher.c
+++ b/src/boilerplate/dispatcher.c
@@ -15,17 +15,21 @@
* limitations under the License.
*****************************************************************************/
-#include <stdint.h>
#include <stdbool.h>
+#include <stdint.h>
#include "dispatcher.h"
+
+/* SDK headers */
+#include "buffer.h"
+
+/* Local headers */
+#include "buffer_ext.h"
#include "constants.h"
#include "globals.h"
-#include "io.h"
+#include "io_ext.h"
#include "sw.h"
-#include "common/buffer.h"
-
extern dispatcher_context_t G_dispatcher_context;
extern bool G_was_processing_screen_shown;
diff --git a/src/boilerplate/dispatcher.h b/src/boilerplate/dispatcher.h
index 8a36dfe..b30a44c 100644
--- a/src/boilerplate/dispatcher.h
+++ b/src/boilerplate/dispatcher.h
@@ -1,10 +1,11 @@
#pragma once
+/* SDK headers */
+#include "buffer.h"
#include "os.h"
-#include "apdu_parser.h"
-
-#include "common/buffer.h"
+/* Local headers */
+#include "parser.h"
// Forward declaration
struct dispatcher_context_s;
diff --git a/src/boilerplate/io.c b/src/boilerplate/io.c
deleted file mode 100644
index f671e1b..0000000
--- a/src/boilerplate/io.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/*****************************************************************************
- * Ledger App Bitcoin.
- * (c) 2025 Ledger SAS.
- *
- * 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.
- *****************************************************************************/
-
-#include <stdint.h>
-#include <string.h>
-
-#include "os.h"
-#include "ux.h"
-#include "nbgl_touch.h"
-#include "nbgl_use_case.h"
-
-#include "io.h"
-#include "globals.h"
-#include "sw.h"
-#include "common/buffer.h"
-#include "common/write.h"
-
-#include "dispatcher.h"
-#include "../swap/swap_globals.h"
-#include "../ui/display.h"
-
-uint16_t G_output_len = 0;
-
-// Counter incremented at every tick
-// The initial value does not matter, as only the difference between timeframes is used.
-uint16_t G_ticks;
-
-struct {
- bool interruption : 1;
- bool processing : 1;
-} G_is_timeout_active;
-
-// set to true when the "Processing..." screen is shown, in order for the dispatcher to know if the
-// UX is not in idle state at the end of a command handler.
-bool G_was_processing_screen_shown;
-
-uint16_t G_interruption_timeout_start_tick;
-uint16_t G_processing_timeout_start_tick;
-
-void io_start_interruption_timeout() {
- G_interruption_timeout_start_tick = G_ticks;
- G_is_timeout_active.interruption = true;
-}
-
-void io_clear_interruption_timeout() {
- G_is_timeout_active.interruption = false;
-}
-
-void io_start_processing_timeout() {
- G_processing_timeout_start_tick = G_ticks;
- G_is_timeout_active.processing = true;
-}
-
-void io_clear_processing_timeout() {
- G_is_timeout_active.processing = false;
-}
-
-void io_reset_timeouts() {
- io_clear_interruption_timeout();
- io_clear_processing_timeout();
- G_was_processing_screen_shown = false;
-}
-
-void io_show_processing_screen() {
- if (!G_was_processing_screen_shown) {
- G_was_processing_screen_shown = true;
- if (!G_swap_state.called_from_swap) {
- nbgl_useCaseSpinner(ui_get_processing_screen_text());
- }
- }
-}
-
-uint8_t io_event(uint8_t channel) {
- UNUSED(channel);
-
- switch (G_io_seproxyhal_spi_buffer[0]) {
- case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT:
- UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer);
- break;
- case SEPROXYHAL_TAG_STATUS_EVENT:
- if (G_io_apdu_media == IO_APDU_MEDIA_USB_HID && //
- !(U4BE(G_io_seproxyhal_spi_buffer, 3) & //
- SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_POWERED)) {
- THROW(EXCEPTION_IO_RESET);
- }
- __attribute__((fallthrough));
- case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT:
- UX_DEFAULT_EVENT();
- break;
-#ifdef SCREEN_SIZE_WALLET
- case SEPROXYHAL_TAG_FINGER_EVENT:
- UX_FINGER_EVENT(G_io_seproxyhal_spi_buffer);
- break;
-#endif // SCREEN_SIZE_WALLET
- case SEPROXYHAL_TAG_TICKER_EVENT:
- ++G_ticks;
-
- if (G_is_timeout_active.processing &&
- G_ticks - G_processing_timeout_start_tick >= PROCESSING_TIMEOUT_TICKS) {
- io_clear_processing_timeout();
-
- io_show_processing_screen();
- }
-
- if (G_is_timeout_active.interruption &&
- G_ticks - G_interruption_timeout_start_tick >= INTERRUPTION_TIMEOUT_TICKS) {
- io_clear_interruption_timeout();
-
- // TODO: It would be better to have the dispatcher be notified somehow.
- // This would require some tampering with the io_exchange in
- // process_interruption.
- THROW(EXCEPTION_IO_RESET);
- }
-
- UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, {});
- break;
- default:
- UX_DEFAULT_EVENT();
- break;
- }
-
- if (!io_seproxyhal_spi_is_status_sent()) {
- io_seproxyhal_general_status();
- }
-
- return 1;
-}
-
-uint16_t io_exchange_al(uint8_t channel, uint16_t tx_len) {
- switch (channel & ~(IO_FLAGS)) {
- case CHANNEL_KEYBOARD:
- break;
- case CHANNEL_SPI:
- if (tx_len) {
- io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len);
-
- if (channel & IO_RESET_AFTER_REPLIED) {
- halt();
- }
-
- return 0;
- } else {
- return io_seproxyhal_spi_recv(G_io_apdu_buffer, sizeof(G_io_apdu_buffer), 0);
- }
- default:
- THROW(INVALID_PARAMETER);
- }
-
- return 0;
-}
-
-void io_add_to_response(const void *rdata, size_t rdata_len) {
- if (G_output_len >= IO_APDU_BUFFER_SIZE - 2) {
- G_output_len = IO_APDU_BUFFER_SIZE;
- write_u16_be(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, SW_WRONG_RESPONSE_LENGTH);
- } else if (G_output_len + rdata_len > IO_APDU_BUFFER_SIZE - 2) {
- io_add_to_response(rdata, IO_APDU_BUFFER_SIZE - 2 - rdata_len);
- io_finalize_response(SW_WRONG_RESPONSE_LENGTH);
- } else {
- memmove(G_io_apdu_buffer + G_output_len, rdata, rdata_len);
- G_output_len += rdata_len;
- }
-}
-
-void io_finalize_response(uint16_t sw) {
- if (G_output_len >= IO_APDU_BUFFER_SIZE - 2) {
- G_output_len = IO_APDU_BUFFER_SIZE;
- write_u16_be(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, SW_WRONG_RESPONSE_LENGTH);
- } else {
- write_u16_be(G_io_apdu_buffer, G_output_len, sw);
- G_output_len += 2;
- }
-}
-
-void io_reset_response() {
- G_output_len = 0;
-}
-
-void io_set_response(const void *rdata, size_t rdata_len, uint16_t sw) {
- io_reset_response();
- if (rdata != NULL) {
- io_add_to_response(rdata, rdata_len);
- }
- io_finalize_response(sw);
-}
-
-int io_confirm_response() {
- int ret;
-
- ret = io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, G_output_len);
- G_output_len = 0;
-
- return ret;
-}
-
-int io_send_response(void *rdata, size_t rdata_len, uint16_t sw) {
- io_set_response(rdata, rdata_len, sw);
- return io_confirm_response();
-}
-
-int io_send_sw(uint16_t sw) {
- return io_send_response(NULL, 0, sw);
-}
diff --git a/src/boilerplate/io.h b/src/boilerplate/io.h
deleted file mode 100644
index e2ba520..0000000
--- a/src/boilerplate/io.h
+++ /dev/null
@@ -1,103 +0,0 @@
-#pragma once
-
-#include <stdint.h>
-
-#include "ux.h"
-#include "os_io_seproxyhal.h"
-
-#include "common/buffer.h"
-
-/**
- * IO callback called when an interrupt based channel has received
- * data to be processed.
- *
- * @return 1 if success, 0 otherwise.
- *
- */
-uint8_t io_event(uint8_t channel);
-
-uint16_t io_exchange_al(uint8_t channel, uint16_t tx_len);
-
-#define INTERRUPTION_TIMEOUT_TICKS 50
-#define PROCESSING_TIMEOUT_TICKS 10
-
-/**
- * Instructs io_event to reset the app if INTERRUPTION_TIMEOUT_TICKS tick events are received before
- * io_clear_interruption_timeout is called. Used to cause an app reset if the client stop responding
- * while an APDU is being processed.
- */
-void io_start_interruption_timeout();
-
-/**
- * Removes the timeout started from io_start_interruption_timeout.
- */
-void io_clear_interruption_timeout();
-
-/**
- * Instructs io_event to show the "Processing..." screen if PROCESSING_TIMEOUT_TICKS tick events are
- * received before io_clear_interruption_timeout is called.
- */
-void io_start_processing_timeout();
-
-/**
- * Removes the timeout started from io_start_processing_timeout.
- */
-void io_clear_processing_timeout();
-
-/**
- * Clears both the interruption and processing timeouts, and sets G_was_processing_screen_shown to
- * false.
- */
-void io_reset_timeouts();
-
-/**
- * Shows the "Processing..." screen.
- */
-void io_show_processing_screen();
-
-/**
- * TODO: docs
- */
-void io_reset_response();
-
-/**
- * TODO: docs
- */
-void io_add_to_response(const void *rdata, size_t rdata_len);
-
-/**
- * TODO: docs
- */
-void io_finalize_response(uint16_t sw);
-
-/* TODO: docs */
-void io_set_response(const void *rdata, size_t rdata_len, uint16_t sw);
-
-/* TODO: docs */
-int io_confirm_response(void);
-
-/**
- * Send APDU response (response data + status word) by filling G_io_apdu_buffer.
- *
- * @param[in] rdata
- * Pointer to the response.
- * @param[in] rdata_len
- * Length of response.
- * @param[in] sw
- * Status word of APDU response.
- *
- * @return zero or positive integer if success, -1 otherwise.
- *
- */
-int io_send_response(void *rdata, size_t rdata_len, uint16_t sw);
-
-/**
- * Send APDU response (only status word) by filling G_io_apdu_buffer.
- *
- * @param[in] sw
- * Status word of APDU response.
- *
- * @return zero or positive integer if success, -1 otherwise.
- *
- */
-int io_send_sw(uint16_t sw);
diff --git a/src/boilerplate/io_ext.c b/src/boilerplate/io_ext.c
new file mode 100644
index 0000000..1f14db4
--- /dev/null
+++ b/src/boilerplate/io_ext.c
@@ -0,0 +1,219 @@
+/*****************************************************************************
+ * Ledger App Bitcoin.
+ * (c) 2025 Ledger SAS.
+ *
+ * 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.
+ *****************************************************************************/
+
+#include <stdint.h>
+#include <string.h>
+
+#include "io_ext.h"
+
+/* SDK headers */
+#include "buffer.h"
+#include "nbgl_touch.h"
+#include "nbgl_use_case.h"
+#include "os.h"
+#include "ux.h"
+#include "write.h"
+
+/* Local headers */
+#include "dispatcher.h"
+#include "display.h"
+#include "globals.h"
+#include "sw.h"
+#include "swap_globals.h"
+
+uint16_t G_output_len = 0;
+
+// Counter incremented at every tick
+// The initial value does not matter, as only the difference between timeframes is used.
+uint16_t G_ticks;
+
+struct {
+ bool interruption : 1;
+ bool processing : 1;
+} G_is_timeout_active;
+
+// set to true when the "Processing..." screen is shown, in order for the dispatcher to know if the
+// UX is not in idle state at the end of a command handler.
+bool G_was_processing_screen_shown;
+
+uint16_t G_interruption_timeout_start_tick;
+uint16_t G_processing_timeout_start_tick;
+
+void io_start_interruption_timeout() {
+ G_interruption_timeout_start_tick = G_ticks;
+ G_is_timeout_active.interruption = true;
+}
+
+void io_clear_interruption_timeout() {
+ G_is_timeout_active.interruption = false;
+}
+
+void io_start_processing_timeout() {
+ G_processing_timeout_start_tick = G_ticks;
+ G_is_timeout_active.processing = true;
+}
+
+void io_clear_processing_timeout() {
+ G_is_timeout_active.processing = false;
+}
+
+void io_reset_timeouts() {
+ io_clear_interruption_timeout();
+ io_clear_processing_timeout();
+ G_was_processing_screen_shown = false;
+}
+
+void io_show_processing_screen() {
+ if (!G_was_processing_screen_shown) {
+ G_was_processing_screen_shown = true;
+ if (!G_swap_state.called_from_swap) {
+ nbgl_useCaseSpinner(ui_get_processing_screen_text());
+ }
+ }
+}
+
+uint8_t io_event(uint8_t channel) {
+ UNUSED(channel);
+
+ switch (G_io_seproxyhal_spi_buffer[0]) {
+ case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT:
+ UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer);
+ break;
+ case SEPROXYHAL_TAG_STATUS_EVENT:
+ if (G_io_apdu_media == IO_APDU_MEDIA_USB_HID && //
+ !(U4BE(G_io_seproxyhal_spi_buffer, 3) & //
+ SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_POWERED)) {
+ THROW(EXCEPTION_IO_RESET);
+ }
+ __attribute__((fallthrough));
+ case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT:
+ UX_DEFAULT_EVENT();
+ break;
+#ifdef SCREEN_SIZE_WALLET
+ case SEPROXYHAL_TAG_FINGER_EVENT:
+ UX_FINGER_EVENT(G_io_seproxyhal_spi_buffer);
+ break;
+#endif // SCREEN_SIZE_WALLET
+ case SEPROXYHAL_TAG_TICKER_EVENT:
+ ++G_ticks;
+
+ if (G_is_timeout_active.processing &&
+ G_ticks - G_processing_timeout_start_tick >= PROCESSING_TIMEOUT_TICKS) {
+ io_clear_processing_timeout();
+
+ io_show_processing_screen();
+ }
+
+ if (G_is_timeout_active.interruption &&
+ G_ticks - G_interruption_timeout_start_tick >= INTERRUPTION_TIMEOUT_TICKS) {
+ io_clear_interruption_timeout();
+
+ // TODO: It would be better to have the dispatcher be notified somehow.
+ // This would require some tampering with the io_exchange in
+ // process_interruption.
+ THROW(EXCEPTION_IO_RESET);
+ }
+
+ UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, {});
+ break;
+ default:
+ UX_DEFAULT_EVENT();
+ break;
+ }
+
+ if (!io_seproxyhal_spi_is_status_sent()) {
+ io_seproxyhal_general_status();
+ }
+
+ return 1;
+}
+
+uint16_t io_exchange_al(uint8_t channel, uint16_t tx_len) {
+ switch (channel & ~(IO_FLAGS)) {
+ case CHANNEL_KEYBOARD:
+ break;
+ case CHANNEL_SPI:
+ if (tx_len) {
+ io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len);
+
+ if (channel & IO_RESET_AFTER_REPLIED) {
+ halt();
+ }
+
+ return 0;
+ } else {
+ return io_seproxyhal_spi_recv(G_io_apdu_buffer, sizeof(G_io_apdu_buffer), 0);
+ }
+ default:
+ THROW(INVALID_PARAMETER);
+ }
+
+ return 0;
+}
+
+void io_add_to_response(const void *rdata, size_t rdata_len) {
+ if (G_output_len >= IO_APDU_BUFFER_SIZE - 2) {
+ G_output_len = IO_APDU_BUFFER_SIZE;
+ write_u16_be(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, SW_WRONG_RESPONSE_LENGTH);
+ } else if (G_output_len + rdata_len > IO_APDU_BUFFER_SIZE - 2) {
+ io_add_to_response(rdata, IO_APDU_BUFFER_SIZE - 2 - rdata_len);
+ io_finalize_response(SW_WRONG_RESPONSE_LENGTH);
+ } else {
+ memmove(G_io_apdu_buffer + G_output_len, rdata, rdata_len);
+ G_output_len += rdata_len;
+ }
+}
+
+void io_finalize_response(uint16_t sw) {
+ if (G_output_len >= IO_APDU_BUFFER_SIZE - 2) {
+ G_output_len = IO_APDU_BUFFER_SIZE;
+ write_u16_be(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 2, SW_WRONG_RESPONSE_LENGTH);
+ } else {
+ write_u16_be(G_io_apdu_buffer, G_output_len, sw);
+ G_output_len += 2;
+ }
+}
+
+void io_reset_response() {
+ G_output_len = 0;
+}
+
+void io_set_response(const void *rdata, size_t rdata_len, uint16_t sw) {
+ io_reset_response();
+ if (rdata != NULL) {
+ io_add_to_response(rdata, rdata_len);
+ }
+ io_finalize_response(sw);
+}
+
+int io_confirm_response() {
+ int ret;
+
+ ret = io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, G_output_len);
+ G_output_len = 0;
+
+ return ret;
+}
+
+int io_send_response(void *rdata, size_t rdata_len, uint16_t sw) {
+ io_set_response(rdata, rdata_len, sw);
+ return io_confirm_response();
+}
+
+int io_send_sw(uint16_t sw) {
+ return io_send_response(NULL, 0, sw);
+}
diff --git a/src/boilerplate/io_ext.h b/src/boilerplate/io_ext.h
new file mode 100644
index 0000000..d4ab46b
--- /dev/null
+++ b/src/boilerplate/io_ext.h
@@ -0,0 +1,105 @@
+#pragma once
+
+#include <stdint.h>
+
+/* SDK headers */
+#include "buffer.h"
+#include "ux.h"
+
+/* Local headers */
+#include "os_io_seproxyhal.h"
+
+/**
+ * IO callback called when an interrupt based channel has received
+ * data to be processed.
+ *
+ * @return 1 if success, 0 otherwise.
+ *
+ */
+uint8_t io_event(uint8_t channel);
+
+uint16_t io_exchange_al(uint8_t channel, uint16_t tx_len);
+
+#define INTERRUPTION_TIMEOUT_TICKS 50
+#define PROCESSING_TIMEOUT_TICKS 10
+
+/**
+ * Instructs io_event to reset the app if INTERRUPTION_TIMEOUT_TICKS tick events are received before
+ * io_clear_interruption_timeout is called. Used to cause an app reset if the client stop responding
+ * while an APDU is being processed.
+ */
+void io_start_interruption_timeout();
+
+/**
+ * Removes the timeout started from io_start_interruption_timeout.
+ */
+void io_clear_interruption_timeout();
+
+/**
+ * Instructs io_event to show the "Processing..." screen if PROCESSING_TIMEOUT_TICKS tick events are
+ * received before io_clear_interruption_timeout is called.
+ */
+void io_start_processing_timeout();
+
+/**
+ * Removes the timeout started from io_start_processing_timeout.
+ */
+void io_clear_processing_timeout();
+
+/**
+ * Clears both the interruption and processing timeouts, and sets G_was_processing_screen_shown to
+ * false.
+ */
+void io_reset_timeouts();
+
+/**
+ * Shows the "Processing..." screen.
+ */
+void io_show_processing_screen();
+
+/**
+ * TODO: docs
+ */
+void io_reset_response();
+
+/**
+ * TODO: docs
+ */
+void io_add_to_response(const void *rdata, size_t rdata_len);
+
+/**
+ * TODO: docs
+ */
+void io_finalize_response(uint16_t sw);
+
+/* TODO: docs */
+void io_set_response(const void *rdata, size_t rdata_len, uint16_t sw);
+
+/* TODO: docs */
+int io_confirm_response(void);
+
+/**
+ * Send APDU response (response data + status word) by filling G_io_apdu_buffer.
+ *
+ * @param[in] rdata
+ * Pointer to the response.
+ * @param[in] rdata_len
+ * Length of response.
+ * @param[in] sw
+ * Status word of APDU response.
+ *
+ * @return zero or positive integer if success, -1 otherwise.
+ *
+ */
+int io_send_response(void *rdata, size_t rdata_len, uint16_t sw);
+
+/**
+ * Send APDU response (only status word) by filling G_io_apdu_buffer.
+ *
+ * @param[in] sw
+ * Status word of APDU response.
+ *
+ * @return zero or positive integer if success, -1 otherwise.
+ *
+ */
+int io_send_sw(uint16_t sw);
diff --git a/src/boilerplate/offsets.h b/src/boilerplate/offsets.h
deleted file mode 100644
index 3db4bc1..0000000
--- a/src/boilerplate/offsets.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma once
-
-/**
- * Offset of instruction class.
- */
-#define OFFSET_CLA 0
-/**
- * Offset of instruction code.
- */
-#define OFFSET_INS 1
-/**
- * Offset of instruction parameter 1.
- */
-#define OFFSET_P1 2
-/**
- * Offset of instruction parameter 2.
- */
-#define OFFSET_P2 3
-/**
- * Offset of command data length.
- */
-#define OFFSET_LC 4
-/**
- * Offset of command data.
- */
-#define OFFSET_CDATA 5
diff --git a/src/common/base58.c b/src/common/base58.c
deleted file mode 100644
index 5db60c3..0000000
--- a/src/common/base58.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*****************************************************************************
- * (c) 2025 Ledger SAS.
- *
- * 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.
- *****************************************************************************/
-
-#include <stddef.h> // size_t
-#include <stdint.h> // uint*_t
-#include <string.h> // memmove, memset
-#include <stdbool.h> // bool
-
-#include "base58.h"
-
-uint8_t const BASE58_TABLE[] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
- 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xFF, 0xFF, //
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, //
- 0x10, 0xFF, 0x11, 0x12, 0x13, 0x14, 0x15, 0xFF, 0x16, 0x17, 0x18, 0x19, //
- 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
- 0xFF, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, //
- 0xFF, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, //
- 0x37, 0x38, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF //
-};
-
-char const BASE58_ALPHABET[] = {
- '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', //
- 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', //
- 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', //
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' //
-};
-
-int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len) {
- uint8_t tmp[MAX_DEC_INPUT_SIZE] = {0};
- uint8_t buffer[MAX_DEC_INPUT_SIZE] = {0};
-
- memset(tmp, 0, MAX_DEC_INPUT_SIZE);
- memset(buffer, 0, MAX_DEC_INPUT_SIZE);
-
- uint8_t j;
- uint8_t start_at;
- uint8_t zero_count = 0;
-
- if (in_len > MAX_DEC_INPUT_SIZE || in_len < 2) {
- return -1;
- }
-
- memmove(tmp, in, in_len);
-
- for (uint8_t i = 0; i < in_len; i++) {
- if (in[i] >= sizeof(BASE58_TABLE)) {
- return -1;
- }
-
- tmp[i] = BASE58_TABLE[(int) in[i]];
-
- if (tmp[i] == 0xFF) {
- return -1;
- }
- }
-
- while ((zero_count < in_len) && (tmp[zero_count] == 0)) {
- ++zero_count;
- }
-
- j = in_len;
- start_at = zero_count;
- while (start_at < in_len) {
- uint16_t remainder = 0;
- for (uint8_t div_loop = start_at; div_loop < in_len; div_loop++) {
- uint16_t digit256 = (uint16_t) (tmp[div_loop] & 0xFF);
- uint16_t tmp_div = remainder * 58 + digit256;
- tmp[div_loop] = (uint8_t) (tmp_div / 256);
- remainder = tmp_div % 256;
- }
-
- if (tmp[start_at] == 0) {
- ++start_at;
- }
-
- buffer[--j] = (uint8_t) remainder;
- }
-
- while ((j < in_len) && (buffer[j] == 0)) {
- ++j;
- }
-
- int length = in_len - (j - zero_count);
-
- if ((int) out_len < length) {
- return -1;
- }
-
- memmove(out, buffer + j - zero_count, length);
-
- return length;
-}
-
-int base58_encode(const uint8_t *in, size_t in_len, char *out, size_t out_len) {
- uint8_t buffer[MAX_ENC_INPUT_SIZE * 138 / 100 + 1] = {0};
- size_t i, j;
- size_t stop_at;
- size_t zero_count = 0;
- size_t output_size;
-
- if (in_len > MAX_ENC_INPUT_SIZE) {
- return -1;
- }
-
- while ((zero_count < in_len) && (in[zero_count] == 0)) {
- ++zero_count;
- }
-
- output_size = (in_len - zero_count) * 138 / 100 + 1;
- stop_at = output_size - 1;
- for (size_t start_at = zero_count; start_at < in_len; start_at++) {
- unsigned int carry = in[start_at];
- for (j = output_size - 1; (int) j >= 0; j--) {
- carry += 256 * buffer[j];
- buffer[j] = carry % 58;
- carry /= 58;
-
- if (j <= stop_at - 1 && carry == 0) {
- break;
- }
- }
- stop_at = j;
- }
-
- j = 0;
- while (j < output_size && buffer[j] == 0) {
- j += 1;
- }
-
- if (out_len < zero_count + output_size - j) {
- return -1;
- }
-
- memset(out, BASE58_ALPHABET[0], zero_count);
-
- i = zero_count;
- while (j < output_size) {
- out[i++] = BASE58_ALPHABET[buffer[j++]];
- }
-
- return i;
-}
diff --git a/src/common/base58.h b/src/common/base58.h
deleted file mode 100644
index f214afd..0000000
--- a/src/common/base58.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#pragma once
-
-#include <stddef.h> // size_t
-#include <stdint.h> // uint*_t
-#include <stdbool.h> // bool
-
-/**
- * Maximum length of input when decoding in base 58.
- */
-#define MAX_DEC_INPUT_SIZE 164
-/**
- * Maximum length of input when encoding in base 58.
- */
-#define MAX_ENC_INPUT_SIZE 120
-
-/**
- * Decode input string in base 58.
- *
- * @see https://tools.ietf.org/html/draft-msporny-base58-02
- *
- * @param[in] in
- * Pointer to input string buffer.
- * @param[in] in_len
- * Length of the input string buffer.
- * @param[out] out
- * Pointer to output byte buffer.
- * @param[in] out_len
- * Maximum length to write in output byte buffer.
- *
- * @return number of bytes decoded, -1 otherwise.
- *
- */
-int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len);
-
-/**
- * Encode input bytes in base 58.
- *
- * @see https://tools.ietf.org/html/draft-msporny-base58-02
- *
- * @param[in] in
- * Pointer to input byte buffer.
- * @param[in] in_len
- * Length of the input byte buffer.
- * @param[out] out
- * Pointer to output string buffer.
- * @param[in] out_len
- * Maximum length to write in output byte buffer.
- *
- * @return number of bytes encoded, -1 otherwise.
- *
- */
-int base58_encode(const uint8_t *in, size_t in_len, char *out, size_t out_len);
diff --git a/src/common/bip32.c b/src/common/bip32.c
deleted file mode 100644
index 8cec65f..0000000
--- a/src/common/bip32.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*****************************************************************************
- * (c) 2025 Ledger SAS.
- *
- * 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.
- *****************************************************************************/
-
-#include <stdio.h> // snprintf
-#include <string.h> // memset, strlen
-#include <stddef.h> // size_t
-#include <stdint.h> // uint*_t
-#include <stdbool.h> // bool
-
-#include "bip32.h"
-#include "base58.h"
-#include "read.h"
-#include "write.h"
-
-// shortcut for convenience
-#define H BIP32_FIRST_HARDENED_CHILD
-
-bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out_len) {
- if (out_len > MAX_BIP32_PATH_STEPS) {
- return false;
- }
-
- size_t offset = 0;
-
- for (size_t i = 0; i < out_len; i++) {
- if (offset > in_len) {
- return false;
- }
- out[i] = read_u32_be(in, offset);
- offset += 4;
- }
-
- return true;
-}
-
-bool bip32_path_format(const uint32_t *bip32_path,
- size_t bip32_path_len,
- char *out,
- size_t out_len) {
- if (bip32_path_len > MAX_BIP32_PATH_STEPS || out_len < 1) {
- return false;
- }
- if (bip32_path_len == 0) {
- out[0] = '\0';
- }
-
- size_t offset = 0;
-
- for (uint16_t i = 0; i < bip32_path_len; i++) {
- size_t written;
-
- snprintf(out + offset, out_len - offset, "%d", bip32_path[i] & 0x7FFFFFFFu);
- written = strlen(out + offset);
- if (written == 0 || written >= out_len - offset) {
- memset(out, 0, out_len);
- return false;
- }
- offset += written;
-
- if ((bip32_path[i] & H) != 0) {
- snprintf(out + offset, out_len - offset, "'");
- written = strlen(out + offset);
- if (written == 0 || written >= out_len - offset) {
- memset(out, 0, out_len);
- return false;
- }
- offset += written;
- }
-
- if (i != bip32_path_len - 1) {
- snprintf(out + offset, out_len - offset, "/");
- written = strlen(out + offset);
- if (written == 0 || written >= out_len - offset) {
- memset(out, 0, out_len);
- return false;
- }
- offset += written;
- }
- }
-
- return true;
-}
-
-bool is_pubkey_path_standard(const uint32_t *bip32_path,
- size_t bip32_path_len,
- uint32_t expected_purpose,
- const uint32_t expected_coin_types[],
- size_t expected_coin_types_len) {
- // if exporting the pubkey, should specify _at least_ until the coin type,
- // and not deeper than the account (therefore 2 or 3 steps)
- if (bip32_path_len < 2 || bip32_path_len > 3) {
- return false;
- }
-
- uint32_t purpose = bip32_path[BIP44_PURPOSE_OFFSET];
- if (purpose != (expected_purpose ^ H)) { // the purpose should be hardened
- return false;
- }
-
- uint32_t coin_type = bip32_path[BIP44_COIN_TYPE_OFFSET];
- if (coin_type < H) {
- return false; // the coin_type should be hardened
- }
-
- if (expected_coin_types_len > 0) {
- // make sure that the coin_type is in the given list
- bool is_coin_type_valid = false;
- for (unsigned int i = 0; i < expected_coin_types_len; i++) {
- if (coin_type == (expected_coin_types[i] ^ H)) {
- is_coin_type_valid = true;
- break;
- }
- }
- if (!is_coin_type_valid) {
- return false;
- }
- }
-
- if (bip32_path_len == 2) {
- return true; // nothing else to check
- }
-
- uint32_t account_number = bip32_path[BIP44_ACCOUNT_OFFSET];
- if ((account_number ^ H) >
- MAX_BIP44_ACCOUNT_RECOMMENDED) { // should be hardened, and not too large
- return false;
- }
-
- return true;
-}
diff --git a/src/common/bip32.h b/src/common/bip32.h
deleted file mode 100644
index cd6707e..0000000
--- a/src/common/bip32.h
+++ /dev/null
@@ -1,116 +0,0 @@
-#pragma once
-
-#include <stddef.h> // size_t
-#include <stdint.h> // uint*_t
-#include <stdbool.h> // bool
-
-/**
- * Maximum length of BIP32 path supported.
- * Note: BIP32 allows up to 256 derivation steps - but only 5 or 6 are used in most cases.
- */
-#define MAX_BIP32_PATH_STEPS 8
-
-/**
- * Maximum length of a string representing a BIP32 derivation path.
- * Each step is up to 11 characters (10 decimal digits, plus the "hardened" symbol),
- * and there is 1 separator before each step.
- */
-#define MAX_SERIALIZED_BIP32_PATH_LENGTH (12 * MAX_BIP32_PATH_STEPS)
-
-/**
- * Index of first hardened child according to BIP32; it can also be used as the bitmask for hardened
- * children.
- */
-#define BIP32_FIRST_HARDENED_CHILD 0x80000000
-
-#define BIP44_PURPOSE_OFFSET 0
-#define BIP44_COIN_TYPE_OFFSET 1
-#define BIP44_ACCOUNT_OFFSET 2
-#define BIP44_CHANGE_OFFSET 3
-#define BIP44_ADDRESS_INDEX_OFFSET 4
-#define MAX_BIP44_ACCOUNT_RECOMMENDED 100
-#define MAX_BIP44_ADDRESS_INDEX_RECOMMENDED 50000
-
-// Address types
-// Legacy address. P2PKH for single sig, P2SH for scripts.
-#define ADDRESS_TYPE_LEGACY 1
-// Native segwit. P2WPKH for single sig, P2WPSH for scripts.
-#define ADDRESS_TYPE_WIT 2
-// Nested segwit. P2SH-P2WPKH for single sig, P2SH-P2WPSH for scripts.
-#define ADDRESS_TYPE_SH_WIT 3
-// Taproot P2TR
-#define ADDRESS_TYPE_TR 4
-
-/**
- * Read BIP32 path from byte buffer.
- *
- * @param[in] in
- * Pointer to input byte buffer.
- * @param[in] in_len
- * Length of input byte buffer.
- * @param[out] out
- * Pointer to output 32-bit integer buffer.
- * @param[in] out_len
- * Number of BIP32 paths read in the output buffer.
- *
- * @return true if success, false otherwise.
- *
- */
-bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out_len);
-
-/**
- * Format BIP32 path as string.
- *
- * @param[in] bip32_path
- * Pointer to 32-bit integer input buffer.
- * @param[in] bip32_path_len
- * Maximum number of BIP32 paths in the input buffer.
- * @param[out] out string
- * Pointer to output string.
- * @param[in] out_len
- * Length of the output string.
- *
- * @return true if success, false otherwise.
- *
- */
-bool bip32_path_format(const uint32_t *bip32_path,
- size_t bip32_path_len,
- char *out,
- size_t out_len);
-
-/**
- * Verifies if a given path is standard according to BIP44 or derived standards, and it is
- * reasonable to export its pubkey. Should not export paths that are too short to specify the coin
- * type (it would expose other coins' keys), but also not deeper than the standard account number
- * (third level of derivation), since no standard currently defines deeper hardened derivations.
- *
- * Returns false if any of the following conditions is not satisfied by the given bip32_path:
- * - the bip32_path has 2 or 3 steps;
- * - purpose, coin_type and account_number (if given) are hardened;
- * - purpose is not hardened, or it does not match expected_purpose;
- * - coin_type is in the expected_coin_types array (if given);
- * - account_number (if given) at most MAX_BIP44_ACCOUNT_RECOMMENDED.
- *
- * @param[in] bip32_path
- * Pointer to 32-bit integer input buffer.
- * @param[in] bip32_path_len
- * Maximum number of BIP32 paths in the input buffer.
- * @param[in] expected_purpose
- * The purpose that should be in the derivation (e.g. 44 for BIP44).
- * @param[in] expected_coin_types
- * Pointer to an array with the coin types that are considered acceptable. The
- * elements of the array should be given as simple numbers (not their hardened version);
- * for example, the coin type for Bitcoin is 0.
- * Ignored if expected_coin_types_len is 0; in that case, it is only checked
- * that the coin_type is hardened, as expected in the standard.
- * @param[in] expected_coin_types_len
- * The length of expected_coin_types.
- *
- * @return true if the given address is standard, false otherwise.
- *
- */
-bool is_pubkey_path_standard(const uint32_t *bip32_path,
- size_t bip32_path_len,
- uint32_t expected_purpose,
- const uint32_t expected_coin_types[],
- size_t expected_coin_types_len);
diff --git a/src/common/bitvector.h b/src/common/bitvector.h
index 4be97c0..037fb78 100644
--- a/src/common/bitvector.h
+++ b/src/common/bitvector.h
@@ -1,7 +1,7 @@
#pragma once
-#include <stdint.h>
#include <stdbool.h>
+#include <stdint.h>
/**
* Returns the size in bytes of a bitvector that can contain n bits.
diff --git a/src/common/buffer.c b/src/common/buffer.c
deleted file mode 100644
index b5ce2ff..0000000
--- a/src/common/buffer.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*****************************************************************************
- * (c) 2025 Ledger SAS.
- *
- * 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.
- *****************************************************************************/
-
-#include <stdint.h> // uint*_t
-#include <stddef.h> // size_t
-#include <stdbool.h> // bool
-#include <string.h> // memmove
-
-#include "buffer.h"
-#include "read.h"
-#include "write.h"
-#include "varint.h"
-#include "bip32.h"
-
-bool buffer_can_read(const buffer_t *buffer, size_t n) {
- return buffer->size - buffer->offset >= n;
-}
-
-bool buffer_seek_set(buffer_t *buffer, size_t offset) {
- if (offset > buffer->size) {
- return false;
- }
-
- buffer->offset = offset;
-
- return true;
-}
-
-bool buffer_seek_cur(buffer_t *buffer, size_t offset) {
- if (buffer->offset + offset < buffer->offset || // overflow
- buffer->offset + offset > buffer->size) { // exceed buffer size
- return false;
- }
-
- buffer->offset += offset;
-
- return true;
-}
-
-bool buffer_seek_end(buffer_t *buffer, size_t offset) {
- if (offset > buffer->size) {
- return false;
- }
-
- buffer->offset = buffer->size - offset;
-
- return true;
-}
-
-bool buffer_read_u8(buffer_t *buffer, uint8_t *value) {
- if (!buffer_can_read(buffer, 1)) {
- *value = 0;
-
- return false;
- }
-
- *value = buffer->ptr[buffer->offset];
- buffer_seek_cur(buffer, 1);
-
- return true;
-}
-
-bool buffer_peek(const buffer_t *buffer, uint8_t *value) {
- return buffer_peek_n(buffer, 0, value);
-}
-
-bool buffer_peek_n(const buffer_t *buffer, size_t n, uint8_t *value) {
- if (!buffer_can_read(buffer, n + 1)) {
- return false;
- }
-
- *value = buffer->ptr[buffer->offset + n];
-
- return true;
-}
-
-bool buffer_read_u16(buffer_t *buffer, uint16_t *value, endianness_t endianness) {
- if (!buffer_can_read(buffer, 2)) {
- *value = 0;
-
- return false;
- }
-
- *value = ((endianness == BE) ? read_u16_be(buffer->ptr, buffer->offset)
- : read_u16_le(buffer->ptr, buffer->offset));
-
- buffer_seek_cur(buffer, 2);
-
- return true;
-}
-
-bool buffer_read_u32(buffer_t *buffer, uint32_t *value, endianness_t endianness) {
- if (!buffer_can_read(buffer, 4)) {
- *value = 0;
-
- return false;
- }
-
- *value = ((endianness == BE) ? read_u32_be(buffer->ptr, buffer->offset)
- : read_u32_le(buffer->ptr, buffer->offset));
-
- buffer_seek_cur(buffer, 4);
-
- return true;
-}
-
-bool buffer_read_u64(buffer_t *buffer, uint64_t *value, endianness_t endianness) {
- if (!buffer_can_read(buffer, 8)) {
- *value = 0;
-
- return false;
- }
-
- *value = ((endianness == BE) ? read_u64_be(buffer->ptr, buffer->offset)
- : read_u64_le(buffer->ptr, buffer->offset));
-
- buffer_seek_cur(buffer, 8);
-
- return true;
-}
-
-bool buffer_read_varint(buffer_t *buffer, uint64_t *value) {
- int length = varint_read(buffer->ptr + buffer->offset, buffer->size - buffer->offset, value);
-
- if (length < 0) {
- *value = 0;
-
- return false;
- }
-
- buffer_seek_cur(buffer, (size_t) length);
-
- return true;
-}
-
-bool buffer_read_bip32_path(buffer_t *buffer, uint32_t *out, size_t out_len) {
- if (!bip32_path_read(buffer->ptr + buffer->offset,
- buffer->size - buffer->offset,
- out,
- out_len)) {
- return false;
- }
-
- buffer_seek_cur(buffer, sizeof(*out) * out_len);
-
- return true;
-}
-
-bool buffer_read_bytes(buffer_t *buffer, uint8_t *out, size_t n) {
- if (buffer->size - buffer->offset < n) {
- return false;
- }
-
- memmove(out, buffer->ptr + buffer->offset, n);
- buffer_seek_cur(buffer, n);
-
- return true;
-}
-
-bool buffer_write_u8(buffer_t *buffer, uint8_t value) {
- if (!buffer_can_read(buffer, 1)) {
- return false;
- }
-
- buffer->ptr[buffer->offset] = value;
- buffer_seek_cur(buffer, 1);
-
- return true;
-}
-
-bool buffer_write_u16(buffer_t *buffer, uint16_t value, endianness_t endianness) {
- if (!buffer_can_read(buffer, 2)) {
- return false;
- }
-
- if (endianness == BE) {
- write_u16_be(buffer->ptr, buffer->offset, value);
- } else {
- write_u16_le(buffer->ptr, buffer->offset, value);
- }
- buffer_seek_cur(buffer, 2);
-
- return true;
-}
-
-bool buffer_write_u32(buffer_t *buffer, uint32_t value, endianness_t endianness) {
- if (!buffer_can_read(buffer, 4)) {
- return false;
- }
-
- if (endianness == BE) {
- write_u32_be(buffer->ptr, buffer->offset, value);
- } else {
- write_u32_le(buffer->ptr, buffer->offset, value);
- }
- buffer_seek_cur(buffer, 4);
-
- return true;
-}
-
-bool buffer_write_u64(buffer_t *buffer, uint64_t value, endianness_t endianness) {
- if (!buffer_can_read(buffer, 8)) {
- return false;
- }
-
- if (endianness == BE) {
- write_u64_be(buffer->ptr, buffer->offset, value);
- } else {
- write_u64_le(buffer->ptr, buffer->offset, value);
- }
-
- buffer_seek_cur(buffer, 8);
-
- return true;
-}
-
-bool buffer_write_bytes(buffer_t *buffer, const uint8_t *data, size_t n) {
- if (!buffer_can_read(buffer, n)) {
- return false;
- }
-
- memmove(buffer->ptr + buffer->offset, data, n);
- buffer_seek_cur(buffer, n);
- return true;
-}
-
-void *buffer_alloc(buffer_t *buffer, size_t size, bool aligned) {
- size_t padding_size = 0;
-
- if (aligned) {
- uint32_t d = (uint32_t) (buffer->ptr + buffer->offset) % 4;
- if (d != 0) {
- padding_size = 4 - d;
- }
- }
-
- if (!buffer_can_read(buffer, padding_size + size)) {
- return NULL;
- }
-
- void *result = buffer->ptr + buffer->offset + padding_size;
- buffer_seek_cur(buffer, padding_size + size);
- return result;
-}
diff --git a/src/common/buffer.h b/src/common/buffer.h
deleted file mode 100644
index 3f3539f..0000000
--- a/src/common/buffer.h
+++ /dev/null
@@ -1,358 +0,0 @@
-#pragma once
-
-#include <stdint.h> // uint*_t
-#include <stddef.h> // size_t
-#include <stdbool.h> // bool
-
-/**
- * Enumeration for endianness.
- */
-typedef enum {
- BE, /// Big Endian
- LE /// Little Endian
-} endianness_t;
-
-typedef size_t buffer_snapshot_t;
-
-/**
- * Struct for buffer with size and offset.
- */
-typedef struct {
- uint8_t *ptr; /// Pointer to byte buffer
- size_t size; /// Size of byte buffer
- size_t offset; /// Offset in byte buffer
-} buffer_t;
-
-/**
- * Tell whether buffer can read bytes or not.
- *
- * @param[in] buffer
- * Pointer to input buffer struct.
- * @param[in] n
- * Number of bytes to read in buffer.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_can_read(const buffer_t *buffer, size_t n);
-
-/**
- * Seek the buffer to specific offset.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[in] offset
- * Specific offset to seek.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_seek_set(buffer_t *buffer, size_t offset);
-
-/**
- * Seek buffer relatively to current offset.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[in] offset
- * Offset to seek relatively to `buffer->offset`.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_seek_cur(buffer_t *buffer, size_t offset);
-
-/**
- * Seek the buffer relatively to the end.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[in] offset
- * Offset to seek relatively to `buffer->size`.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_seek_end(buffer_t *buffer, size_t offset);
-
-/**
- * Returns the pointer to byte in the current position of the buffer.
- *
- * @param[in] buffer
- * Pointer to input buffer struct.
- *
- * @return the pointer to the current position.
- *
- */
-static inline uint8_t *buffer_get_cur(const buffer_t *buffer) {
- return buffer->ptr + buffer->offset;
-}
-
-/**
- * Read 1 byte from buffer into uint8_t.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[out] value
- * Pointer to 8-bit unsigned integer read from buffer.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_read_u8(buffer_t *buffer, uint8_t *value);
-
-/**
- * Read 1 byte from buffer into uint8_t without advancing the current position in the buffer.
- * Returns `true` on success, `false` if the buffer was empty; `value` is not changed in case of
- * failure.
- *
- * @param[in] buffer
- * Pointer to input buffer struct.
- * @param[out] value
- * Pointer to 8-bit unsigned integer read from buffer.
- *
- * @return true if success, false otherwise.
- */
-bool buffer_peek(const buffer_t *buffer, uint8_t *value);
-
-/**
- * Read 1 byte at position `n` from buffer into uint8_t without advancing the current position in
- * the buffer. Returns `true` on success, `false` if the buffer is not large enough; `value` is not
- * changed in case of failure.
- *
- * @param[in] buffer
- * Pointer to input buffer struct.
- * @param[out] n
- * Index of the byte to read, where the immediate next byte has index 0.
- * @param[out] value
- * Pointer to 8-bit unsigned integer read from buffer.
- *
- * @return true if success, false otherwise.
- */
-bool buffer_peek_n(const buffer_t *buffer, size_t n, uint8_t *value);
-
-/**
- * Read 2 bytes from buffer into uint16_t.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[out] value
- * Pointer to 16-bit unsigned integer read from buffer.
- * @param[in] endianness
- * Either BE (Big Endian) or LE (Little Endian).
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_read_u16(buffer_t *buffer, uint16_t *value, endianness_t endianness);
-
-/**
- * Read 4 bytes from buffer into uint32_t.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[out] value
- * Pointer to 32-bit unsigned integer read from buffer.
- * @param[in] endianness
- * Either BE (Big Endian) or LE (Little Endian).
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_read_u32(buffer_t *buffer, uint32_t *value, endianness_t endianness);
-
-/**
- * Read 8 bytes from buffer into uint64_t.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[out] value
- * Pointer to 64-bit unsigned integer read from buffer.
- * @param[in] endianness
- * Either BE (Big Endian) or LE (Little Endian).
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_read_u64(buffer_t *buffer, uint64_t *value, endianness_t endianness);
-
-/**
- * Read Bitcoin-like varint from buffer into uint64_t.
- *
- * @see https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[out] value
- * Pointer to 64-bit unsigned integer read from buffer.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_read_varint(buffer_t *buffer, uint64_t *value);
-
-/**
- * Read BIP32 path from buffer.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[out] out
- * Pointer to output 32-bit integer buffer.
- * @param[in] out_len
- * Number of BIP32 paths read in the output buffer.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_read_bip32_path(buffer_t *buffer, uint32_t *out, size_t out_len);
-
-/**
- * Read n bytes from buffer, and stores them in out.
- *
- * @param[in,out] buffer
- * Pointer to input buffer struct.
- * @param[out] out
- * Pointer to output buffer. It is the responsibility of the caller to make sure that the output
- * buffer is at least n bytes long.
- * @param[in] n
- * Number of bytes to read from buffer.
- *
- * @return true if success, false otherwise.
- *
- */
-bool buffer_read_bytes(buffer_t *buffer, uint8_t *out, size_t n);
-
-/**
- * Write a uint8_t into a buffer.
- *
- * @param[in,out] buffer
- * Pointer to output buffer struct.
- * @param[out] value
- * Value to be written.
- *
- * @return true if success, false if not enough space left in the buffer.
- *
- */
-bool buffer_write_u8(buffer_t *buffer, uint8_t value);
-
-/**
- * Write a uint16_t into the buffer as 2 bytes, with the given endianness.
- *
- * @param[in,out] buffer
- * Pointer to output buffer struct.
- * @param[out] value
- * Value to be written.
- * @param[in] endianness
- * Either BE (Big Endian) or LE (Little Endian).
- *
- * @return true if success, false if not enough space left in the buffer.
- *
- */
-bool buffer_write_u16(buffer_t *buffer, uint16_t value, endianness_t endianness);
-
-/**
- * Write a uint32_t into the buffer as 4 bytes, with the given endianness.
- *
- * @param[in,out] buffer
- * Pointer to output buffer struct.
- * @param[out] value
- * Value to be written.
- * @param[in] endianness
- * Either BE (Big Endian) or LE (Little Endian).
- *
- * @return true if success, false if not enough space left in the buffer.
- *
- */
-bool buffer_write_u32(buffer_t *buffer, uint32_t value, endianness_t endianness);
-
-/**
- * Write a uint64_t into the buffer as 8 bytes, with the given endianness.
- *
- * @param[in,out] buffer
- * Pointer to output buffer struct.
- * @param[out] value
- * Value to be written.
- * @param[in] endianness
- * Either BE (Big Endian) or LE (Little Endian).
- *
- * @return true if success, false if not enough space left in the buffer.
- *
- */
-bool buffer_write_u64(buffer_t *buffer, uint64_t value, endianness_t endianness);
-
-/**
- * Write a number of bytes to a buffer.
- *
- * @param[in,out] buffer
- * Pointer to output buffer struct.
- * @param[in] data
- * Pointer to bytes to be written.
- * @param[in] n
- * Size of bytes to be written.
- *
- * @return true if success, false if not enough space left in the buffer.
- *
- */
-bool buffer_write_bytes(buffer_t *buffer, const uint8_t *data, size_t n);
-
-/**
- * Creates a buffer pointing at ptr and with the given size; the initial offset is 0.
- *
- * @param[in,out] ptr
- * Pointer to the buffer's data.
- * @param[in] size
- * Size of the buffer.
- *
- * @return the new buffer with the given pointer and size.
- *
- */
-static inline buffer_t buffer_create(void *ptr, size_t size) {
- return (buffer_t){.ptr = ptr, .size = size, .offset = 0};
-}
-
-/**
- * Returns a pointer to the current position in the buffer if at least `size` bytes are available in
- * the buffer (possibly after skipping some bytes to guarantee alignment), or NULL otherwise. On
- * success, the buffer is advanced by `size` bytes. If `aligned == true`, the returned pointer is
- * 32-bit aligned (adding up to three padding bytes if necessary). The buffer is not advanced in
- * case of failure.
- *
- * @param[in,out] buffer The buffer in which the memory is to be allocated.
- * @param[in] size The number of bytes allocated within `buffer`.
- * @param[in] aligned If `true`, makes sure that the returned pointer is 32-bit aligned.
- *
- * @return a pointer to the allocated memory within the buffer.
- */
-void *buffer_alloc(buffer_t *buffer, size_t size, bool aligned);
-
-/**
- * Checks if the current position in the buffer is aligned in memory to a 4-byte boundary.
- *
- * @param[in] buffer Pointer to a buffer struct.
- *
- * @return `true` if the current position in the buffer is aligned, `false` otherwise.
- */
-static inline bool buffer_is_cur_aligned(const buffer_t *buffer) {
- return (size_t) (buffer->ptr + buffer->offset) % 4 == 0;
-}
-
-/**
- * Saves a snapshot of the current position within the buffer.
- *
- * @param[in] buffer The buffer whose position is saved.
- *
- * @return a snapshot that can be restored with `buffer_restore`.
- */
-static inline buffer_snapshot_t buffer_snapshot(const buffer_t *buffer) {
- return buffer->offset;
-}
-
-/**
- * Restores a previously taken snapshot of the buffer.
- *
- * @param[in,out] snapshot The snapshot previously returned by a call to `buffer_snapshot` on the
- * same buffer. The behavior is undefined if any other value is passed as `snapshot`.
- */
-static inline void buffer_restore(buffer_t *buffer, buffer_snapshot_t snapshot) {
- buffer->offset = snapshot;
-}
diff --git a/src/common/buffer_ext.c b/src/common/buffer_ext.c
new file mode 100644
index 0000000..05211f7
--- /dev/null
+++ b/src/common/buffer_ext.c
@@ -0,0 +1,140 @@
+/*****************************************************************************
+ * (c) 2026 Ledger SAS.
+ *
+ * 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.
+ *****************************************************************************/
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "buffer_ext.h"
+
+/* SDK headers */
+#include "bip32.h"
+#include "buffer.h"
+#include "read.h"
+#include "varint.h"
+#include "write.h"
+
+bool buffer_peek(const buffer_t *buffer, uint8_t *value) {
+ return buffer_peek_n(buffer, 0, value);
+}
+
+bool buffer_peek_n(const buffer_t *buffer, size_t n, uint8_t *value) {
+ if (!buffer_can_read(buffer, n + 1)) {
+ return false;
+ }
+
+ *value = buffer->ptr[buffer->offset + n];
+
+ return true;
+}
+
+bool buffer_read_bytes(buffer_t *buffer, uint8_t *out, size_t n) {
+ if (buffer->size - buffer->offset < n) {
+ return false;
+ }
+
+ memmove(out, buffer->ptr + buffer->offset, n);
+ buffer_seek_cur(buffer, n);
+
+ return true;
+}
+
+bool buffer_write_u8(buffer_t *buffer, uint8_t value) {
+ if (!buffer_can_read(buffer, 1)) {
+ return false;
+ }
+
+ ((uint8_t *) buffer->ptr)[buffer->offset] = value;
+ buffer_seek_cur(buffer, 1);
+
+ return true;
+}
+
+bool buffer_write_u16(buffer_t *buffer, uint16_t value, endianness_t endianness) {
+ if (!buffer_can_read(buffer, 2)) {
+ return false;
+ }
+
+ if (endianness == BE) {
+ write_u16_be((uint8_t *) buffer->ptr, buffer->offset, value);
+ } else {
+ write_u16_le((uint8_t *) buffer->ptr, buffer->offset, value);
+ }
+ buffer_seek_cur(buffer, 2);
+
+ return true;
+}
+
+bool buffer_write_u32(buffer_t *buffer, uint32_t value, endianness_t endianness) {
+ if (!buffer_can_read(buffer, 4)) {
+ return false;
+ }
+
+ if (endianness == BE) {
+ write_u32_be((uint8_t *) buffer->ptr, buffer->offset, value);
+ } else {
+ write_u32_le((uint8_t *) buffer->ptr, buffer->offset, value);
+ }
+ buffer_seek_cur(buffer, 4);
+
+ return true;
+}
+
+bool buffer_write_u64(buffer_t *buffer, uint64_t value, endianness_t endianness) {
+ if (!buffer_can_read(buffer, 8)) {
+ return false;
+ }
+
+ if (endianness == BE) {
+ write_u64_be((uint8_t *) buffer->ptr, buffer->offset, value);
+ } else {
+ write_u64_le((uint8_t *) buffer->ptr, buffer->offset, value);
+ }
+
+ buffer_seek_cur(buffer, 8);
+
+ return true;
+}
+
+bool buffer_write_bytes(buffer_t *buffer, const uint8_t *data, size_t n) {
+ if (!buffer_can_read(buffer, n)) {
+ return false;
+ }
+
+ memmove((uint8_t *) (buffer->ptr + buffer->offset), data, n);
+ buffer_seek_cur(buffer, n);
+ return true;
+}
+
+void *buffer_alloc(buffer_t *buffer, size_t size, bool aligned) {
+ size_t padding_size = 0;
+
+ if (aligned) {
+ uint32_t d = (uint32_t) (buffer->ptr + buffer->offset) % 4;
+ if (d != 0) {
+ padding_size = 4 - d;
+ }
+ }
+
+ if (!buffer_can_read(buffer, padding_size + size)) {
+ return NULL;
+ }
+
+ void *result = (uint8_t *) (buffer->ptr + buffer->offset) + padding_size;
+ buffer_seek_cur(buffer, padding_size + size);
+ return result;
+}
diff --git a/src/common/buffer_ext.h b/src/common/buffer_ext.h
new file mode 100644
index 0000000..19ccf66
--- /dev/null
+++ b/src/common/buffer_ext.h
@@ -0,0 +1,217 @@
+#pragma once
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/* SDK headers */
+#include "buffer.h"
+
+typedef size_t buffer_snapshot_t;
+
+/**
+ * Returns the pointer to byte in the current position of the buffer.
+ *
+ * @param[in] buffer
+ * Pointer to input buffer struct.
+ *
+ * @return the pointer to the current position.
+ *
+ */
+static inline uint8_t *buffer_get_cur(const buffer_t *buffer) {
+ return (uint8_t *) (buffer->ptr + buffer->offset);
+}
+
+/**
+ * Read 1 byte from buffer into uint8_t.
+ *
+ * @param[in,out] buffer
+ * Pointer to input buffer struct.
+ * @param[out] value
+ * Pointer to 8-bit unsigned integer read from buffer.
+ *
+ * @return true if success, false otherwise.
+ *
+ */
+bool buffer_read_u8(buffer_t *buffer, uint8_t *value);
+
+/**
+ * Read 1 byte from buffer into uint8_t without advancing the current position in the buffer.
+ * Returns `true` on success, `false` if the buffer was empty; `value` is not changed in case of
+ * failure.
+ *
+ * @param[in] buffer
+ * Pointer to input buffer struct.
+ * @param[out] value
+ * Pointer to 8-bit unsigned integer read from buffer.
+ *
+ * @return true if success, false otherwise.
+ */
+bool buffer_peek(const buffer_t *buffer, uint8_t *value);
+
+/**
+ * Read 1 byte at position `n` from buffer into uint8_t without advancing the current position in
+ * the buffer. Returns `true` on success, `false` if the buffer is not large enough; `value` is not
+ * changed in case of failure.
+ *
+ * @param[in] buffer
+ * Pointer to input buffer struct.
+ * @param[out] n
+ * Index of the byte to read, where the immediate next byte has index 0.
+ * @param[out] value
+ * Pointer to 8-bit unsigned integer read from buffer.
+ *
+ * @return true if success, false otherwise.
+ */
+bool buffer_peek_n(const buffer_t *buffer, size_t n, uint8_t *value);
+
+/**
+ * Read n bytes from buffer, and stores them in out.
+ *
+ * @param[in,out] buffer
+ * Pointer to input buffer struct.
+ * @param[out] out
+ * Pointer to output buffer. It is the responsibility of the caller to make sure that the output
+ * buffer is at least n bytes long.
+ * @param[in] n
+ * Number of bytes to read from buffer.
+ *
+ * @return true if success, false otherwise.
+ *
+ */
+bool buffer_read_bytes(buffer_t *buffer, uint8_t *out, size_t n);
+
+/**
+ * Write a uint8_t into a buffer.
+ *
+ * @param[in,out] buffer
+ * Pointer to output buffer struct.
+ * @param[out] value
+ * Value to be written.
+ *
+ * @return true if success, false if not enough space left in the buffer.
+ *
+ */
+bool buffer_write_u8(buffer_t *buffer, uint8_t value);
+
+/**
+ * Write a uint16_t into the buffer as 2 bytes, with the given endianness.
+ *
+ * @param[in,out] buffer
+ * Pointer to output buffer struct.
+ * @param[out] value
+ * Value to be written.
+ * @param[in] endianness
+ * Either BE (Big Endian) or LE (Little Endian).
+ *
+ * @return true if success, false if not enough space left in the buffer.
+ *
+ */
+bool buffer_write_u16(buffer_t *buffer, uint16_t value, endianness_t endianness);
+
+/**
+ * Write a uint32_t into the buffer as 4 bytes, with the given endianness.
+ *
+ * @param[in,out] buffer
+ * Pointer to output buffer struct.
+ * @param[out] value
+ * Value to be written.
+ * @param[in] endianness
+ * Either BE (Big Endian) or LE (Little Endian).
+ *
+ * @return true if success, false if not enough space left in the buffer.
+ *
+ */
+bool buffer_write_u32(buffer_t *buffer, uint32_t value, endianness_t endianness);
+
+/**
+ * Write a uint64_t into the buffer as 8 bytes, with the given endianness.
+ *
+ * @param[in,out] buffer
+ * Pointer to output buffer struct.
+ * @param[out] value
+ * Value to be written.
+ * @param[in] endianness
+ * Either BE (Big Endian) or LE (Little Endian).
+ *
+ * @return true if success, false if not enough space left in the buffer.
+ *
+ */
+bool buffer_write_u64(buffer_t *buffer, uint64_t value, endianness_t endianness);
+
+/**
+ * Write a number of bytes to a buffer.
+ *
+ * @param[in,out] buffer
+ * Pointer to output buffer struct.
+ * @param[in] data
+ * Pointer to bytes to be written.
+ * @param[in] n
+ * Size of bytes to be written.
+ *
+ * @return true if success, false if not enough space left in the buffer.
+ *
+ */
+bool buffer_write_bytes(buffer_t *buffer, const uint8_t *data, size_t n);
+
+/**
+ * Creates a buffer pointing at ptr and with the given size; the initial offset is 0.
+ *
+ * @param[in,out] ptr
+ * Pointer to the buffer's data.
+ * @param[in] size
+ * Size of the buffer.
+ *
+ * @return the new buffer with the given pointer and size.
+ *
+ */
+static inline buffer_t buffer_create(void *ptr, size_t size) {
+ return (buffer_t){.ptr = ptr, .size = size, .offset = 0};
+}
+
+/**
+ * Returns a pointer to the current position in the buffer if at least `size` bytes are available in
+ * the buffer (possibly after skipping some bytes to guarantee alignment), or NULL otherwise. On
+ * success, the buffer is advanced by `size` bytes. If `aligned == true`, the returned pointer is
+ * 32-bit aligned (adding up to three padding bytes if necessary). The buffer is not advanced in
+ * case of failure.
+ *
+ * @param[in,out] buffer The buffer in which the memory is to be allocated.
+ * @param[in] size The number of bytes allocated within `buffer`.
+ * @param[in] aligned If `true`, makes sure that the returned pointer is 32-bit aligned.
+ *
+ * @return a pointer to the allocated memory within the buffer.
+ */
+void *buffer_alloc(buffer_t *buffer, size_t size, bool aligned);
+
+/**
+ * Checks if the current position in the buffer is aligned in memory to a 4-byte boundary.
+ *
+ * @param[in] buffer Pointer to a buffer struct.
+ *
+ * @return `true` if the current position in the buffer is aligned, `false` otherwise.
+ */
+static inline bool buffer_is_cur_aligned(const buffer_t *buffer) {
+ return (size_t) (buffer->ptr + buffer->offset) % 4 == 0;
+}
+
+/**
+ * Saves a snapshot of the current position within the buffer.
+ *
+ * @param[in] buffer The buffer whose position is saved.
+ *
+ * @return a snapshot that can be restored with `buffer_restore`.
+ */
+static inline buffer_snapshot_t buffer_snapshot(const buffer_t *buffer) {
+ return buffer->offset;
+}
+
+/**
+ * Restores a previously taken snapshot of the buffer.
+ *
+ * @param[in,out] snapshot The snapshot previously returned by a call to `buffer_snapshot` on the
+ * same buffer. The behavior is undefined if any other value is passed as `snapshot`.
+ */
+static inline void buffer_restore(buffer_t *buffer, buffer_snapshot_t snapshot) {
+ buffer->offset = snapshot;
+}
diff --git a/src/common/format.c b/src/common/format.c
deleted file mode 100644
index 8433806..0000000
--- a/src/common/format.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*****************************************************************************
- * (c) 2025 Ledger SAS.
- *
- * 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.
- *****************************************************************************/
-
-#include <stddef.h> // size_t
-#include <stdint.h> // int*_t, uint*_t
-#include <string.h> // strncpy, memmove
-#include <stdbool.h> // bool
-
-#include "format.h"
-
-bool format_i64(char *dst, size_t dst_len, const int64_t value) {
- char temp[] = "-9223372036854775808";
-
- char *ptr = temp;
- int64_t num = value;
- int sign = 1;
-
- if (value < 0) {
- sign = -1;
- }
-
- while (num != 0) {
- *ptr++ = '0' + (num % 10) * sign;
- num /= 10;
- }
-
- if (value < 0) {
- *ptr++ = '-';
- } else if (value == 0) {
- *ptr++ = '0';
- }
-
- int distance = (ptr - temp) + 1;
-
- if ((int) dst_len < distance) {
- return false;
- }
-
- size_t index = 0;
-
- while (--ptr >= temp) {
- dst[index++] = *ptr;
- }
-
- dst[index] = '\0';
-
- return true;
-}
-
-bool format_u64(char *out, size_t outLen, uint64_t in) {
- uint8_t i = 0;
-
- if (outLen == 0) {
- return false;
- }
- outLen--;
-
- while (in > 9) {
- out[i] = in % 10 + '0';
- in /= 10;
- i++;
- if (i + 1 > outLen) {
- return false;
- }
- }
- out[i] = in + '0';
- out[i + 1] = '\0';
-
- uint8_t j = 0;
- char tmp;
-
- // revert the string
- while (j < i) {
- // swap out[j] and out[i]
- tmp = out[j];
- out[j] = out[i];
- out[i] = tmp;
-
- i--;
- j++;
- }
- return true;
-}
-
-bool format_fpu64(char *dst, size_t dst_len, const uint64_t value, uint8_t decimals) {
- char buffer[21] = {0};
-
- if (!format_u64(buffer, sizeof(buffer), value)) {
- return false;
- }
-
- size_t digits = strlen(buffer);
-
- if (digits <= decimals) {
- if (dst_len <= 2 + decimals - digits) {
- return false;
- }
- *dst++ = '0';
- *dst++ = '.';
- for (uint16_t i = 0; i < decimals - digits; i++, dst++) {
- *dst = '0';
- }
- dst_len -= 2 + decimals - digits;
- strncpy(dst, buffer, dst_len);
- } else {
- if (dst_len <= digits + 1 + decimals) {
- return false;
- }
-
- const size_t shift = digits - decimals;
- memmove(dst, buffer, shift);
- dst[shift] = '.';
- strncpy(dst + shift + 1, buffer + shift, decimals);
- }
-
- return true;
-}
-
-int format_hex(const uint8_t *in, size_t in_len, char *out, size_t out_len) {
- if (out_len < 2 * in_len + 1) {
- return -1;
- }
-
- const char hex[] = "0123456789abcdef";
- size_t i = 0;
- int written = 0;
-
- while (i < in_len && (i * 2 + (2 + 1)) <= out_len) {
- uint8_t high_nibble = (in[i] & 0xF0) >> 4;
- *out = hex[high_nibble];
- out++;
-
- uint8_t low_nibble = in[i] & 0x0F;
- *out = hex[low_nibble];
- out++;
-
- i++;
- written += 2;
- }
-
- *out = '\0';
-
- return written + 1;
-}
diff --git a/src/common/format.h b/src/common/format.h
deleted file mode 100644
index f145748..0000000
--- a/src/common/format.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#pragma once
-
-#include <stddef.h> // size_t
-#include <stdint.h> // int*_t, uint*_t
-#include <stdbool.h> // bool
-
-/**
- * Format 64-bit signed integer as string.
- *
- * @param[out] dst
- * Pointer to output string.
- * @param[in] dst_len
- * Length of output string.
- * @param[in] value
- * 64-bit signed integer to format.
- *
- * @return true if success, false otherwise.
- *
- */
-bool format_i64(char *dst, size_t dst_len, const int64_t value);
-
-/**
- * Format 64-bit unsigned integer as string.
- *
- * @param[out] dst
- * Pointer to output string.
- * @param[in] dst_len
- * Length of output string.
- * @param[in] value
- * 64-bit unsigned integer to format.
- *
- * @return true if success, false otherwise.
- *
- */
-bool format_u64(char *dst, size_t dst_len, uint64_t value);
-
-/**
- * Format 64-bit unsigned integer as string with decimals.
- *
- * @param[out] dst
- * Pointer to output string.
- * @param[in] dst_len
- * Length of output string.
- * @param[in] value
- * 64-bit unsigned integer to format.
- * @param[in] decimals
- * Number of digits after decimal separator.
- *
- * @return true if success, false otherwise.
- *
- */
-bool format_fpu64(char *dst, size_t dst_len, const uint64_t value, uint8_t decimals);
-
-/**
- * Format byte buffer to uppercase hexadecimal string.
- *
- * @param[in] in
- * Pointer to input byte buffer.
- * @param[in] in_len
- * Length of input byte buffer.
- * @param[out] out
- * Pointer to output string.
- * @param[in] out_len
- * Length of output string.
- *
- * @return number of bytes written if success, -1 otherwise.
- *
- */
-int format_hex(const uint8_t *in, size_t in_len, char *out, size_t out_len);
diff --git a/src/common/merkle.c b/src/common/merkle.c
index fa6c507..20a8770 100644
--- a/src/common/merkle.c
+++ b/src/common/merkle.c
@@ -15,19 +15,20 @@
* limitations under the License.
*****************************************************************************/
-#include <stdint.h> // uint*_t
-#include <string.h> // memset, explicit_bzero
-#include <stdbool.h> // bool
-
-#include "buffer.h"
-#include "../crypto.h"
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
#include "merkle.h"
-#include "../debug-helpers/debug.h"
-
+/* SDK headers */
+#include "buffer.h"
#include "ledger_assert.h"
+/* Local headers */
+#include "crypto.h"
+#include "debug.h"
+
void merkle_compute_element_hash(const uint8_t *in,
size_t in_len,
uint8_t out[static CX_SHA256_SIZE]) {
diff --git a/src/common/parser.c b/src/common/parser.c
deleted file mode 100644
index 02913a7..0000000
--- a/src/common/parser.c
+++ /dev/null
@@ -1,144 +0,0 @@
-#include <stdio.h>
-
-#include "parser.h"
-
-#include "read.h"
-
-size_t dbuffer_get_length(buffer_t *buffers[2]) {
- return (buffers[0]->size - buffers[0]->offset) + (buffers[1]->size - buffers[1]->offset);
-}
-
-bool dbuffer_can_read(buffer_t *buffers[2], size_t n) {
- return dbuffer_get_length(buffers) >= n;
-}
-
-bool dbuffer_read_bytes(buffer_t *buffers[2], uint8_t *out, size_t n) {
- size_t length0 = buffers[0]->size - buffers[0]->offset;
- size_t length1 = buffers[1]->size - buffers[1]->offset;
- if (n > length0 + length1) {
- return false;
- }
-
- size_t n0 = (length0 >= n) ? n : length0; // bytes to read from first buffer
- size_t n1 = n - n0; // bytes to read from second buffer
-
- if (n0 > 0) {
- buffer_read_bytes(buffers[0], out, n0);
- }
- if (n1 > 0) {
- buffer_read_bytes(buffers[1], out + n0, n1);
- }
- return true;
-}
-
-bool dbuffer_read_u8(buffer_t *buffers[2], uint8_t *out) {
- return dbuffer_read_bytes(buffers, out, 1);
-}
-
-bool dbuffer_read_u16(buffer_t *buffers[2], uint16_t *out, endianness_t endianness) {
- if (!dbuffer_can_read(buffers, 2)) {
- return false;
- }
-
- uint8_t tmp[2];
- dbuffer_read_bytes(buffers, tmp, 2);
- if (endianness == BE)
- *out = read_u16_be(tmp, 0);
- else
- *out = read_u16_le(tmp, 0);
- return true;
-}
-
-bool dbuffer_read_u32(buffer_t *buffers[2], uint32_t *out, endianness_t endianness) {
- if (!dbuffer_can_read(buffers, 4)) {
- return false;
- }
-
- uint8_t tmp[4];
- dbuffer_read_bytes(buffers, tmp, 4);
- if (endianness == BE)
- *out = read_u32_be(tmp, 0);
- else
- *out = read_u32_le(tmp, 0);
- return true;
-}
-
-bool dbuffer_read_varint(buffer_t *buffers[2], uint64_t *out) {
- if (!dbuffer_can_read(buffers, 1)) {
- return false;
- }
-
- // peek the first byte without changing the offsets
- uint8_t first_byte = buffer_can_read(buffers[0], 1) ? buffers[0]->ptr[buffers[0]->offset]
- : buffers[1]->ptr[buffers[1]->offset];
- uint8_t len; // length excluding the prefix
- switch (first_byte) {
- case 0xfd:
- len = 2;
- break;
- case 0xfe:
- len = 4;
- break;
- case 0xff:
- len = 8;
- break;
- default:
- len = 0;
- break;
- }
-
- if (!dbuffer_can_read(buffers, 1 + len)) {
- return false;
- }
-
- dbuffer_read_u8(buffers, &first_byte); // redundant, just to skip 1 byte
-
- if (first_byte <= 0xfc) {
- *out = first_byte;
- return true;
- }
-
- uint8_t data[8] = {0};
- dbuffer_read_bytes(buffers, data, len);
-
- // Since data was zeroed, parsing the entire array as a little-endian works for any size
- *out = read_u64_le(data, 0);
- return true;
-}
-
-bool parser_consolidate_buffers(buffer_t *buffers[2], size_t max_size) {
- size_t length0 = buffers[0]->size - buffers[0]->offset;
- size_t length1 = buffers[1]->size - buffers[1]->offset;
- if (length0 + length1 > max_size) {
- return false;
- }
-
- memmove(buffers[0]->ptr, buffers[0]->ptr + buffers[0]->offset, length0);
- memmove(buffers[0]->ptr + length0, buffers[1]->ptr + buffers[1]->offset, length1);
- buffers[0]->offset = 0;
- buffers[0]->size = length0 + length1;
- return true;
-}
-
-int parser_run(const parsing_step_t *parsing_steps,
- size_t n_steps,
- parser_context_t *parser_context,
- buffer_t *buffers[2],
- void *(*pic_fn)(void *) ) {
- while (parser_context->cur_step < n_steps) {
- parsing_step_t step_fn =
- pic_fn != NULL ? (parsing_step_t) pic_fn(parsing_steps[parser_context->cur_step])
- : parsing_steps[parser_context->cur_step];
-
- int step_result = step_fn(parser_context->state, buffers);
-
- if (step_result <= 0) {
- // Either error, or parsing incomplete and more data is needed
- return step_result;
- } else {
- // continue with the next step
- ++parser_context->cur_step;
- }
- }
- return 1;
-}
diff --git a/src/common/parser.h b/src/common/parser.h
deleted file mode 100644
index f6aebea..0000000
--- a/src/common/parser.h
+++ /dev/null
@@ -1,86 +0,0 @@
-#pragma once
-
-#include <stdint.h>
-#include <string.h>
-#include "buffer.h"
-
-typedef struct {
- size_t cur_step;
- void *state; // subtyped for each specific parser
-} parser_context_t;
-
-/**
- * A parsing step gets a pointer to the parser's state, and an array of two pointers to buffers. The
- * concatenation o the two buffer is the (possibly incomplete) data to be parsed. The parsing step
- * returns -1 in case of parsing error (e.g.: invalid value was parsed); 1 if the parsing step is
- * completed successfully, 0 if more data is expected.
- * Any remaining data in the concatenation of the two buffers' remaining content must be passed in
- * the next call to the parser, that will continue from the same parsing step.
- */
-typedef int (*parsing_step_t)(void *, buffer_t *[2]);
-
-// Convenience functions to handle reading from the concatenation of two buffers.
-// All these functions are analogous to the corresponding buffer_read_X functions, but they exhaust
-// the first buffer before reading from the second buffer.
-
-/**
- * Get the total remaining length readable from this pair of buffers.
- * TODO: finish docs
- */
-size_t dbuffer_get_length(buffer_t *buffers[2]);
-
-/**
- * TODO: docs.
- */
-bool dbuffer_can_read(buffer_t *buffers[2], size_t n);
-
-/**
- * TODO: docs.
- */
-bool dbuffer_read_bytes(buffer_t *buffers[2], uint8_t *out, size_t n);
-
-/**
- * TODO: docs.
- */
-bool dbuffer_read_u8(buffer_t *buffers[2], uint8_t *out);
-
-/**
- * TODO: docs.
- */
-bool dbuffer_read_u16(buffer_t *buffers[2], uint16_t *out, endianness_t endianness);
-
-/**
- * TODO: docs.
- */
-bool dbuffer_read_u32(buffer_t *buffers[2], uint32_t *out, endianness_t endianness);
-
-/**
- * TODO: docs.
- */
-bool dbuffer_read_varint(buffer_t *buffers[2], uint64_t *out);
-
-/**
- * TODO: docs.
- */
-static inline void parser_init_context(parser_context_t *parser_context, void *state) {
- parser_context->cur_step = 0;
- parser_context->state = state;
-}
-
-/**
- * Moves the concatenation of all the remaining bytes in the two buffers into the memory pointed by
- * the first buffer, as long as the number of remaining bytes is at most max_byte. The offset of the
- * first buffer is set to 0, and the new size reflects the total size
- *
- * Returns true on success; false if the total number of remaining bytes is larger than max_size.
- */
-bool parser_consolidate_buffers(buffer_t *buffers[2], size_t max_size);
-
-/**
- * TODO: docs
- */
-int parser_run(const parsing_step_t *parsing_steps,
- size_t n_steps,
- parser_context_t *parser_context,
- buffer_t *buffers[2],
- void *(*pic_fn)(void *) );
diff --git a/src/common/parser_ext.c b/src/common/parser_ext.c
new file mode 100644
index 0000000..0f54bab
--- /dev/null
+++ b/src/common/parser_ext.c
@@ -0,0 +1,148 @@
+#include <stdio.h>
+
+#include "parser_ext.h"
+
+/* SDK headers */
+#include "read.h"
+
+/* Local headers */
+#include "buffer_ext.h"
+
+size_t dbuffer_get_length(buffer_t *buffers[2]) {
+ return (buffers[0]->size - buffers[0]->offset) + (buffers[1]->size - buffers[1]->offset);
+}
+
+bool dbuffer_can_read(buffer_t *buffers[2], size_t n) {
+ return dbuffer_get_length(buffers) >= n;
+}
+
+bool dbuffer_read_bytes(buffer_t *buffers[2], uint8_t *out, size_t n) {
+ size_t length0 = buffers[0]->size - buffers[0]->offset;
+ size_t length1 = buffers[1]->size - buffers[1]->offset;
+ if (n > length0 + length1) {
+ return false;
+ }
+
+ size_t n0 = (length0 >= n) ? n : length0; // bytes to read from first buffer
+ size_t n1 = n - n0; // bytes to read from second buffer
+
+ if (n0 > 0) {
+ buffer_read_bytes(buffers[0], out, n0);
+ }
+ if (n1 > 0) {
+ buffer_read_bytes(buffers[1], out + n0, n1);
+ }
+ return true;
+}
+
+bool dbuffer_read_u8(buffer_t *buffers[2], uint8_t *out) {
+ return dbuffer_read_bytes(buffers, out, 1);
+}
+
+bool dbuffer_read_u16(buffer_t *buffers[2], uint16_t *out, endianness_t endianness) {
+ if (!dbuffer_can_read(buffers, 2)) {
+ return false;
+ }
+
+ uint8_t tmp[2];
+ dbuffer_read_bytes(buffers, tmp, 2);
+ if (endianness == BE)
+ *out = read_u16_be(tmp, 0);
+ else
+ *out = read_u16_le(tmp, 0);
+ return true;
+}
+
+bool dbuffer_read_u32(buffer_t *buffers[2], uint32_t *out, endianness_t endianness) {
+ if (!dbuffer_can_read(buffers, 4)) {
+ return false;
+ }
+
+ uint8_t tmp[4];
+ dbuffer_read_bytes(buffers, tmp, 4);
+ if (endianness == BE)
+ *out = read_u32_be(tmp, 0);
+ else
+ *out = read_u32_le(tmp, 0);
+ return true;
+}
+
+bool dbuffer_read_varint(buffer_t *buffers[2], uint64_t *out) {
+ if (!dbuffer_can_read(buffers, 1)) {
+ return false;
+ }
+
+ // peek the first byte without changing the offsets
+ uint8_t first_byte = buffer_can_read(buffers[0], 1) ? buffers[0]->ptr[buffers[0]->offset]
+ : buffers[1]->ptr[buffers[1]->offset];
+ uint8_t len; // length excluding the prefix
+ switch (first_byte) {
+ case 0xfd:
+ len = 2;
+ break;
+ case 0xfe:
+ len = 4;
+ break;
+ case 0xff:
+ len = 8;
+ break;
+ default:
+ len = 0;
+ break;
+ }
+
+ if (!dbuffer_can_read(buffers, 1 + len)) {
+ return false;
+ }
+
+ dbuffer_read_u8(buffers, &first_byte); // redundant, just to skip 1 byte
+
+ if (first_byte <= 0xfc) {
+ *out = first_byte;
+ return true;
+ }
+
+ uint8_t data[8] = {0};
+ dbuffer_read_bytes(buffers, data, len);
+
+ // Since data was zeroed, parsing the entire array as a little-endian works for any size
+ *out = read_u64_le(data, 0);
+ return true;
+}
+
+bool parser_consolidate_buffers(buffer_t *buffers[2], size_t max_size) {
+ size_t length0 = buffers[0]->size - buffers[0]->offset;
+ size_t length1 = buffers[1]->size - buffers[1]->offset;
+ if (length0 + length1 > max_size) {
+ return false;
+ }
+
+ memmove((uint8_t *) buffers[0]->ptr, buffers[0]->ptr + buffers[0]->offset, length0);
+ memmove((uint8_t *) buffers[0]->ptr + length0, buffers[1]->ptr + buffers[1]->offset, length1);
+ buffers[0]->offset = 0;
+ buffers[0]->size = length0 + length1;
+ return true;
+}
+
+int parser_run(const parsing_step_t *parsing_steps,
+ size_t n_steps,
+ parser_context_t *parser_context,
+ buffer_t *buffers[2],
+ void *(*pic_fn)(void *) ) {
+ while (parser_context->cur_step < n_steps) {
+ parsing_step_t step_fn =
+ pic_fn != NULL ? (parsing_step_t) pic_fn(parsing_steps[parser_context->cur_step])
+ : parsing_steps[parser_context->cur_step];
+
+ int step_result = step_fn(parser_context->state, buffers);
+
+ if (step_result <= 0) {
+ // Either error, or parsing incomplete and more data is needed
+ return step_result;
+ } else {
+ // continue with the next step
+ ++parser_context->cur_step;
+ }
+ }
+ return 1;
+}
diff --git a/src/common/parser_ext.h b/src/common/parser_ext.h
new file mode 100644
index 0000000..d7f6b94
--- /dev/null
+++ b/src/common/parser_ext.h
@@ -0,0 +1,88 @@
+#pragma once
+
+#include <stdint.h>
+#include <string.h>
+
+/* SDK headers */
+#include "buffer.h"
+
+typedef struct {
+ size_t cur_step;
+ void *state; // subtyped for each specific parser
+} parser_context_t;
+
+/**
+ * A parsing step gets a pointer to the parser's state, and an array of two pointers to buffers. The
+ * concatenation o the two buffer is the (possibly incomplete) data to be parsed. The parsing step
+ * returns -1 in case of parsing error (e.g.: invalid value was parsed); 1 if the parsing step is
+ * completed successfully, 0 if more data is expected.
+ * Any remaining data in the concatenation of the two buffers' remaining content must be passed in
+ * the next call to the parser, that will continue from the same parsing step.
+ */
+typedef int (*parsing_step_t)(void *, buffer_t *[2]);
+
+// Convenience functions to handle reading from the concatenation of two buffers.
+// All these functions are analogous to the corresponding buffer_read_X functions, but they exhaust
+// the first buffer before reading from the second buffer.
+
+/**
+ * Get the total remaining length readable from this pair of buffers.
+ * TODO: finish docs
+ */
+size_t dbuffer_get_length(buffer_t *buffers[2]);
+
+/**
+ * TODO: docs.
+ */
+bool dbuffer_can_read(buffer_t *buffers[2], size_t n);
+
+/**
+ * TODO: docs.
+ */
+bool dbuffer_read_bytes(buffer_t *buffers[2], uint8_t *out, size_t n);
+
+/**
+ * TODO: docs.
+ */
+bool dbuffer_read_u8(buffer_t *buffers[2], uint8_t *out);
+
+/**
+ * TODO: docs.
+ */
+bool dbuffer_read_u16(buffer_t *buffers[2], uint16_t *out, endianness_t endianness);
+
+/**
+ * TODO: docs.
+ */
+bool dbuffer_read_u32(buffer_t *buffers[2], uint32_t *out, endianness_t endianness);
+
+/**
+ * TODO: docs.
+ */
+bool dbuffer_read_varint(buffer_t *buffers[2], uint64_t *out);
+
+/**
+ * TODO: docs.
+ */
+static inline void parser_init_context(parser_context_t *parser_context, void *state) {
+ parser_context->cur_step = 0;
+ parser_context->state = state;
+}
+
+/**
+ * Moves the concatenation of all the remaining bytes in the two buffers into the memory pointed by
+ * the first buffer, as long as the number of remaining bytes is at most max_byte. The offset of the
+ * first buffer is set to 0, and the new size reflects the total size
+ *
+ * Returns true on success; false if the total number of remaining bytes is larger than max_size.
+ */
+bool parser_consolidate_buffers(buffer_t *buffers[2], size_t max_size);
+
+/**
+ * TODO: docs
+ */
+int parser_run(const parsing_step_t *parsing_steps,
+ size_t n_steps,
+ parser_context_t *parser_context,
+ buffer_t *buffers[2],
+ void *(*pic_fn)(void *) );
diff --git a/src/common/read.c b/src/common/read.c
deleted file mode 100644
index d170f37..0000000
--- a/src/common/read.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*****************************************************************************
- * (c) 2025 Ledger SAS.
- *
- * 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.
- *****************************************************************************/
-
-#include <stdint.h> // uint*_t
-#include <stddef.h> // size_t
-
-uint16_t read_u16_be(const uint8_t *ptr, size_t offset) {
- return (uint16_t) ptr[offset + 0] << 8 | //
- (uint16_t) ptr[offset + 1] << 0;
-}
-
-uint32_t read_u32_be(const uint8_t *ptr, size_t offset) {
- return (uint32_t) ptr[offset + 0] << 24 | //
- (uint32_t) ptr[offset + 1] << 16 | //
- (uint32_t) ptr[offset + 2] << 8 | //
- (uint32_t) ptr[offset + 3] << 0;
-}
-
-uint64_t read_u64_be(const uint8_t *ptr, size_t offset) {
- return (uint64_t) ptr[offset + 0] << 56 | //
- (uint64_t) ptr[offset + 1] << 48 | //
- (uint64_t) ptr[offset + 2] << 40 | //
- (uint64_t) ptr[offset + 3] << 32 | //
- (uint64_t) ptr[offset + 4] << 24 | //
- (uint64_t) ptr[offset + 5] << 16 | //
- (uint64_t) ptr[offset + 6] << 8 | //
- (uint64_t) ptr[offset + 7] << 0;
-}
-
-uint16_t read_u16_le(const uint8_t *ptr, size_t offset) {
- return (uint16_t) ptr[offset + 0] << 0 | //
- (uint16_t) ptr[offset + 1] << 8;
-}
-
-uint32_t read_u32_le(const uint8_t *ptr, size_t offset) {
- return (uint32_t) ptr[offset + 0] << 0 | //
- (uint32_t) ptr[offset + 1] << 8 | //
- (uint32_t) ptr[offset + 2] << 16 | //
- (uint32_t) ptr[offset + 3] << 24;
-}
-
-uint64_t read_u64_le(const uint8_t *ptr, size_t offset) {
- return (uint64_t) ptr[offset + 0] << 0 | //
- (uint64_t) ptr[offset + 1] << 8 | //
- (uint64_t) ptr[offset + 2] << 16 | //
- (uint64_t) ptr[offset + 3] << 24 | //
- (uint64_t) ptr[offset + 4] << 32 | //
- (uint64_t) ptr[offset + 5] << 40 | //
- (uint64_t) ptr[offset + 6] << 48 | //
- (uint64_t) ptr[offset + 7] << 56;
-}
diff --git a/src/common/read.h b/src/common/read.h
deleted file mode 100644
index 61cfa8c..0000000
--- a/src/common/read.h
+++ /dev/null
@@ -1,82 +0,0 @@
-#pragma once
-
-#include <stdint.h> // uint*_t
-#include <stddef.h> // size_t
-
-/**
- * Read 2 bytes as Big Endian from byte buffer.
- *
- * @param[in] ptr
- * Pointer to byte buffer.
- * @param[in] offset
- * Offset in the byte buffer.
- *
- * @return 2 bytes value read from buffer.
- *
- */
-uint16_t read_u16_be(const uint8_t *ptr, size_t offset);
-
-/**
- * Read 4 bytes as Big Endian from byte buffer.
- *
- * @param[in] ptr
- * Pointer to byte buffer.
- * @param[in] offset
- * Offset in the byte buffer.
- *
- * @return 4 bytes value read from buffer.
- *
- */
-uint32_t read_u32_be(const uint8_t *ptr, size_t offset);
-
-/**
- * Read 8 bytes as Big Endian from byte buffer.
- *
- * @param[in] ptr
- * Pointer to byte buffer.
- * @param[in] offset
- * Offset in the byte buffer.
- *
- * @return 8 bytes value read from buffer.
- *
- */
-uint64_t read_u64_be(const uint8_t *ptr, size_t offset);
-
-/**
- * Read 2 bytes as Little Endian from byte buffer.
- *
- * @param[in] ptr
- * Pointer to byte buffer.
- * @param[in] offset
- * Offset in the byte buffer.
- *
- * @return 2 bytes value read from buffer.
- *
- */
-uint16_t read_u16_le(const uint8_t *ptr, size_t offset);
-
-/**
- * Read 4 bytes as Little Endian from byte buffer.
- *
- * @param[in] ptr
- * Pointer to byte buffer.
- * @param[in] offset
- * Offset in the byte buffer.
- *
- * @return 4 bytes value read from buffer.
- *
- */
-uint32_t read_u32_le(const uint8_t *ptr, size_t offset);
-
-/**
- * Read 8 bytes as Little Endian from byte buffer.
- *
- * @param[in] ptr
- * Pointer to byte buffer.
- * @param[in] offset
- * Offset in the byte buffer.
- *
- * @return 8 bytes value read from buffer.
- *
- */
-uint64_t read_u64_le(const uint8_t *ptr, size_t offset);
diff --git a/src/common/script.c b/src/common/script.c
index ffcc8f1..cdac1c1 100644
--- a/src/common/script.c
+++ b/src/common/script.c
@@ -1,13 +1,17 @@
+#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
-#include <limits.h>
-#include "../common/bip32.h"
-#include "../common/buffer.h"
-#include "../common/read.h"
-#include "../common/script.h"
-#include "../common/segwit_addr.h"
+#include "script.h"
+
+/* SDK headers */
+#include "bip32.h"
+#include "buffer.h"
+#include "read.h"
+
+/* Local headers */
+#include "segwit_addr.h"
#ifndef SKIP_FOR_CMOCKA
#include "../crypto.h"
@@ -239,4 +243,4 @@ bool format_script(const uint8_t script[],
return true;
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/common/script.h b/src/common/script.h
index 793a942..0360098 100644
--- a/src/common/script.h
+++ b/src/common/script.h
@@ -1,8 +1,12 @@
#pragma once
+#include <stdbool.h>
+
+/* SDK headers */
#include "os.h"
-#include "../constants.h"
+/* Local headers */
+#include "constants.h"
/** Script opcodes */
// from bitcoin-core
@@ -255,4 +259,4 @@ int format_opscript_script(const uint8_t script[],
*/
bool format_script(const uint8_t script[],
size_t script_len,
- char out[static MAX_OUTPUT_SCRIPT_DESC_SIZE]);
\ No newline at end of file
+ char out[static MAX_OUTPUT_SCRIPT_DESC_SIZE]);
diff --git a/src/common/segwit_addr.c b/src/common/segwit_addr.c
index d54f59e..35ac18f 100644
--- a/src/common/segwit_addr.c
+++ b/src/common/segwit_addr.c
@@ -21,8 +21,8 @@
* THE SOFTWARE.
*/
#include <assert.h>
-#include <stdlib.h>
#include <stdint.h>
+#include <stdlib.h>
#include <string.h>
#include "segwit_addr.h"
diff --git a/src/common/varint.c b/src/common/varint.c
deleted file mode 100644
index 7087fb0..0000000
--- a/src/common/varint.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*****************************************************************************
- * (c) 2025 Ledger SAS.
- *
- * 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.
- *****************************************************************************/
-
-#include <stdint.h> // uint*_t
-#include <stddef.h> // size_t
-#include <stdbool.h> // bool
-
-#include "varint.h"
-#include "write.h"
-#include "read.h"
-
-uint8_t varint_size(uint64_t value) {
- if (value <= 0xFC) {
- return 1;
- }
-
- if (value <= UINT16_MAX) {
- return 3;
- }
-
- if (value <= UINT32_MAX) {
- return 5;
- }
-
- return 9; // <= UINT64_MAX
-}
-
-int varint_read(const uint8_t *in, size_t in_len, uint64_t *value) {
- if (in_len < 1) {
- return -1;
- }
-
- uint8_t prefix = in[0];
-
- if (prefix == 0xFD) {
- if (in_len < 3) {
- return -1;
- }
- *value = (uint64_t) read_u16_le(in, 1);
- return 3;
- }
-
- if (prefix == 0xFE) {
- if (in_len < 5) {
- return -1;
- }
- *value = (uint64_t) read_u32_le(in, 1);
- return 5;
- }
-
- if (prefix == 0xFF) {
- if (in_len < 9) {
- return -1;
- }
- *value = (uint64_t) read_u64_le(in, 1);
- return 9;
- }
-
- *value = (uint64_t) prefix; // prefix <= 0xFC
-
- return 1;
-}
-
-int varint_write(uint8_t *out, size_t offset, uint64_t value) {
- uint8_t varint_len = varint_size(value);
-
- switch (varint_len) {
- case 1:
- out[offset] = (uint8_t) value;
- break;
- case 3:
- out[offset++] = 0xFD;
- write_u16_le(out, offset, (uint16_t) value);
- break;
- case 5:
- out[offset++] = 0xFE;
- write_u32_le(out, offset, (uint32_t) value);
- break;
- case 9:
- out[offset++] = 0xFF;
- write_u64_le(out, offset, (uint64_t) value);
- break;
- default:
- return -1;
- }
-
- return varint_len;
-}
diff --git a/src/common/varint.h b/src/common/varint.h
deleted file mode 100644
index 6cb263d..0000000
--- a/src/common/varint.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#pragma once
-
-#include <stdint.h> // uint*_t
-#include <stddef.h> // size_t
-#include <stdbool.h> // bool
-
-// TODO: write unit tests
-
-/**
- * Size of value represented as Bitcoin-like varint.
- *
- * @see https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer
- *
- * @param[in] value
- * 64-bit unsigned integer to compute varint size.
- *
- * @return number of bytes to write value as varint (1, 3, 5 or 9 bytes).
- *
- */
-uint8_t varint_size(uint64_t value);
-
-/**
- * Read Bitcoin-like varint from byte buffer.
- *
- * @see https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer
- *
- * @param[in] in
- * Pointer to input byte buffer.
- * @param[in] in_len
- * Length of the input byte buffer.
- * @param[out] value
- * Pointer to 64-bit unsigned integer to output varint.
- *
- * @return number of bytes read (1, 3, 5 or 9 bytes), -1 otherwise.
- *
- */
-int varint_read(const uint8_t *in, size_t in_len, uint64_t *value);
-
-/**
- * Write Bitcoin-like varint to byte buffer.
- *
- * @see https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer
- *
- * @param[out] out
- * Pointer to output byte buffer.
- * @param[in] offset
- * Offset in the output byte buffer.
- * @param[in] value
- * 64-bit unsigned integer to write as varint.
- *
- * @return number of bytes written (1, 3, 5 or 9 bytes), -1 otherwise.
- *
- */
-int varint_write(uint8_t *out, size_t offset, uint64_t value);
diff --git a/src/common/wallet.c b/src/common/wallet.c
index 1f9434d..56a9f63 100644
--- a/src/common/wallet.c
+++ b/src/common/wallet.c
@@ -1,17 +1,20 @@
+#include <limits.h>
#include <stdint.h>
#include <string.h>
-#include <limits.h>
-#include "../common/base58.h"
-#include "../common/bip32.h"
-#include "../common/buffer.h"
-#include "../common/script.h"
-#include "../common/segwit_addr.h"
-#include "../common/wallet.h"
+#include "wallet.h"
-#include "../boilerplate/sw.h"
+/* SDK headers */
+#include "base58.h"
+#include "bip32.h"
+#include "buffer.h"
-#include "../debug-helpers/debug.h"
+/* Local headers */
+#include "buffer_ext.h"
+#include "debug.h"
+#include "script.h"
+#include "segwit_addr.h"
+#include "sw.h"
#ifndef SKIP_FOR_CMOCKA
#include "../crypto.h"
diff --git a/src/common/wallet.h b/src/common/wallet.h
index 77b389f..605bcd0 100644
--- a/src/common/wallet.h
+++ b/src/common/wallet.h
@@ -1,14 +1,16 @@
#pragma once
-#include <stdint.h>
#include <assert.h>
+#include <stdint.h>
+/* SDK headers */
+#include "bip32.h"
+#include "buffer.h"
#include "ledger_assert.h"
-#include "common/bip32.h"
-#include "common/buffer.h"
-#include "../constants.h"
-#include "../crypto.h"
+/* Local headers */
+#include "constants.h"
+#include "crypto.h"
#ifndef SKIP_FOR_CMOCKA
#include "os.h"
diff --git a/src/common/write.c b/src/common/write.c
deleted file mode 100644
index 3ab47d8..0000000
--- a/src/common/write.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*****************************************************************************
- * (c) 2025 Ledger SAS.
- *
- * 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.
- *****************************************************************************/
-
-#include <stdint.h> // uint*_t
-#include <stddef.h> // size_t
-
-void write_u16_be(uint8_t *ptr, size_t offset, uint16_t value) {
- ptr[offset + 0] = (uint8_t) (value >> 8);
- ptr[offset + 1] = (uint8_t) (value >> 0);
-}
-
-void write_u32_be(uint8_t *ptr, size_t offset, uint32_t value) {
- ptr[offset + 0] = (uint8_t) (value >> 24);
- ptr[offset + 1] = (uint8_t) (value >> 16);
- ptr[offset + 2] = (uint8_t) (value >> 8);
- ptr[offset + 3] = (uint8_t) (value >> 0);
-}
-
-void write_u64_be(uint8_t *ptr, size_t offset, uint64_t value) {
- ptr[offset + 0] = (uint8_t) (value >> 56);
- ptr[offset + 1] = (uint8_t) (value >> 48);
- ptr[offset + 2] = (uint8_t) (value >> 40);
- ptr[offset + 3] = (uint8_t) (value >> 32);
- ptr[offset + 4] = (uint8_t) (value >> 24);
- ptr[offset + 5] = (uint8_t) (value >> 16);
- ptr[offset + 6] = (uint8_t) (value >> 8);
- ptr[offset + 7] = (uint8_t) (value >> 0);
-}
-
-void write_u16_le(uint8_t *ptr, size_t offset, uint16_t value) {
- ptr[offset + 0] = (uint8_t) (value >> 0);
- ptr[offset + 1] = (uint8_t) (value >> 8);
-}
-
-void write_u32_le(uint8_t *ptr, size_t offset, uint32_t value) {
- ptr[offset + 0] = (uint8_t) (value >> 0);
- ptr[offset + 1] = (uint8_t) (value >> 8);
- ptr[offset + 2] = (uint8_t) (value >> 16);
- ptr[offset + 3] = (uint8_t) (value >> 24);
-}
-
-void write_u64_le(uint8_t *ptr, size_t offset, uint64_t value) {
- ptr[offset + 0] = (uint8_t) (value >> 0);
- ptr[offset + 1] = (uint8_t) (value >> 8);
- ptr[offset + 2] = (uint8_t) (value >> 16);
- ptr[offset + 3] = (uint8_t) (value >> 24);
- ptr[offset + 4] = (uint8_t) (value >> 32);
- ptr[offset + 5] = (uint8_t) (value >> 40);
- ptr[offset + 6] = (uint8_t) (value >> 48);
- ptr[offset + 7] = (uint8_t) (value >> 56);
-}
diff --git a/src/common/write.h b/src/common/write.h
deleted file mode 100644
index 0418f5c..0000000
--- a/src/common/write.h
+++ /dev/null
@@ -1,82 +0,0 @@
-#pragma once
-
-#include <stdint.h> // uint*_t
-#include <stddef.h> // size_t
-
-/**
- * Write 16-bit unsigned integer value as Big Endian.
- *
- * @param[out] ptr
- * Pointer to output byte buffer.
- * @param[in] offset
- * Offset in the output byte buffer.
- * @param[in] value
- * 16-bit unsigned integer to write in output byte buffer as Big Endian.
- *
- */
-void write_u16_be(const uint8_t *ptr, size_t offset, uint16_t value);
-
-/**
- * Write 32-bit unsigned integer value as Big Endian.
- *
- * @param[out] ptr
- * Pointer to output byte buffer.
- * @param[in] offset
- * Offset in the output byte buffer.
- * @param[in] value
- * 32-bit unsigned integer to write in output byte buffer as Big Endian.
- *
- */
-void write_u32_be(uint8_t *ptr, size_t offset, uint32_t value);
-
-/**
- * Write 64-bit unsigned integer value as Big Endian.
- *
- * @param[out] ptr
- * Pointer to output byte buffer.
- * @param[in] offset
- * Offset in the output byte buffer.
- * @param[in] value
- * 64-bit unsigned integer to write in output byte buffer as Big Endian.
- *
- */
-void write_u64_be(uint8_t *ptr, size_t offset, uint64_t value);
-
-/**
- * Write 16-bit unsigned integer value as Little Endian.
- *
- * @param[out] ptr
- * Pointer to output byte buffer.
- * @param[in] offset
- * Offset in the output byte buffer.
- * @param[in] value
- * 16-bit unsigned integer to write in output byte buffer as Little Endian.
- *
- */
-void write_u16_le(uint8_t *ptr, size_t offset, uint16_t value);
-
-/**
- * Write 32-bit unsigned integer value as Little Endian.
- *
- * @param[out] ptr
- * Pointer to output byte buffer.
- * @param[in] offset
- * Offset in the output byte buffer.
- * @param[in] value
- * 32-bit unsigned integer to write in output byte buffer as Little Endian.
- *
- */
-void write_u32_le(uint8_t *ptr, size_t offset, uint32_t value);
-
-/**
- * Write 64-bit unsigned integer value as Little Endian.
- *
- * @param[out] ptr
- * Pointer to output byte buffer.
- * @param[in] offset
- * Offset in the output byte buffer.
- * @param[in] value
- * 64-bit unsigned integer to write in output byte buffer as Little Endian.
- *
- */
-void write_u64_le(uint8_t *ptr, size_t offset, uint64_t value);
diff --git a/src/constants.h b/src/constants.h
index ad9aa0a..352be68 100644
--- a/src/constants.h
+++ b/src/constants.h
@@ -1,10 +1,23 @@
#pragma once
+/* SDK headers */
+#include "bip32.h"
+
/**
* Instruction class of the Bitcoin application.
*/
#define CLA_APP 0xE1
+/**
+ * APDU instruction class for command defined by the framework.
+ */
+#define CLA_FRAMEWORK 0xF8
+
+/**
+ * Framework instruction to continue execution after an interruption.
+ */
+#define INS_CONTINUE 0x01
+
/**
* Encodes the protocol version, which is passed in the p2 field of APDUs.
*/
@@ -81,3 +94,30 @@
#define MAX_STANDARD_P2WSH_STACK_ITEMS 100U
#define MAX_STANDARD_P2WSH_SCRIPT_SIZE 3600U
#define MAX_OPS_PER_SCRIPT 201U
+
+
+/* BIP-32, BIP-44 and BIP-388 constants */
+/**
+ * Maximum length of BIP32 path supported.
+ * Note: BIP32 allows up to 256 derivation steps - but only 5 or 6 are used in most cases.
+ */
+#define MAX_BIP32_PATH_STEPS MAX_BIP32_PATH
+//#define MAX_BIP388_XPUB_DERIVATION_STEPS 8
+//#define MAX_BIP32_PATH_STEPS (MAX_BIP388_XPUB_DERIVATION_STEPS + 2)
+
+
+/**
+ * Maximum length of a string representing a BIP32 derivation path.
+ * Each step is up to 11 characters (10 decimal digits, plus the "hardened" symbol),
+ * and there is 1 separator before each step.
+ */
+#define MAX_SERIALIZED_BIP32_PATH_LENGTH (12 * MAX_BIP32_PATH_STEPS)
+
+/**
+ * Index of first hardened child according to BIP32; it can also be used as the bitmask for hardened
+ * children.
+ */
+#define BIP32_FIRST_HARDENED_CHILD 0x80000000
+
+#define MAX_BIP44_ACCOUNT_RECOMMENDED 100
+#define MAX_BIP44_ADDRESS_INDEX_RECOMMENDED 50000
diff --git a/src/crypto.c b/src/crypto.c
index fcca770..22b7b11 100644
--- a/src/crypto.c
+++ b/src/crypto.c
@@ -15,32 +15,33 @@
* limitations under the License.
*****************************************************************************/
-#include <stdint.h> // uint*_t
-#include <string.h> // memset, explicit_bzero
-#include <stdbool.h> // bool
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
-#include "os.h"
+#include "crypto.h"
+
+/* SDK headers */
+#include "base58.h"
+#include "bip32.h"
+#include "crypto_helpers.h"
#include "cx.h"
-#include "cx_stubs.h"
#include "cx_ecfp.h"
-#include "ox_ec.h"
#include "cx_ram.h"
-#include "lcx_ripemd160.h"
#include "cx_ripemd160.h"
-#include "lib_standard_app/crypto_helpers.h"
-
-#include "common/base58.h"
-#include "common/bip32.h"
-#include "common/format.h"
-#include "common/read.h"
-#include "common/write.h"
-
-#include "../boilerplate/sw.h"
-#include "../debug-helpers/debug.h"
-
-#include "crypto.h"
+#include "cx_stubs.h"
+#include "format.h"
+#include "lcx_ripemd160.h"
+#include "os.h"
+#include "ox_ec.h"
+#include "read.h"
+#include "write.h"
+/* Local headers */
+#include "constants.h"
+#include "debug.h"
#include "secp256k1.h"
+#include "sw.h"
/* BIP0341 tags for computing the tagged hashes when tweaking public keys */
const uint8_t BIP0341_taptweak_tag[] = {'T', 'a', 'p', 'T', 'w', 'e', 'a', 'k'};
diff --git a/src/crypto.h b/src/crypto.h
index 9e24aee..4c41df0 100644
--- a/src/crypto.h
+++ b/src/crypto.h
@@ -4,13 +4,15 @@
#include <stdint.h>
#include <string.h>
-#include "os.h"
+/* SDK headers */
+#include "bip32.h"
#include "cx.h"
-#include "constants.h"
+#include "os.h"
+#include "varint.h"
+#include "write.h"
-#include "./common/bip32.h"
-#include "./common/varint.h"
-#include "./common/write.h"
+/* Local headers */
+#include "constants.h"
/**
* A serialized extended pubkey according to BIP32 specifications.
diff --git a/src/debug-helpers/debug.c b/src/debug-helpers/debug.c
index d01f243..95db14d 100644
--- a/src/debug-helpers/debug.c
+++ b/src/debug-helpers/debug.c
@@ -1,5 +1,8 @@
-#include <stdio.h>
#include <stdarg.h>
+#include <stdio.h>
+
+
+/* Local headers */
#include "printf.h"
#pragma GCC diagnostic ignored "-Wunused-function"
diff --git a/src/debug-helpers/debug.h b/src/debug-helpers/debug.h
index 9966fbe..f327ee5 100644
--- a/src/debug-helpers/debug.h
+++ b/src/debug-helpers/debug.h
@@ -1,5 +1,6 @@
#pragma once
+/* SDK headers */
#include "os.h"
void debug_write(const char *buf);
diff --git a/src/globals.h b/src/globals.h
index ede4e83..34e1b79 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -2,11 +2,13 @@
#include <stdint.h>
+/* SDK headers */
#include "ux.h"
-#include "boilerplate/io.h"
+/* Local headers */
#include "commands.h"
#include "constants.h"
+#include "io_ext.h"
/**
* Global buffer for interactions between SE and MCU.
diff --git a/src/handler/get_extended_pubkey.c b/src/handler/get_extended_pubkey.c
index 143ce98..9025cea 100644
--- a/src/handler/get_extended_pubkey.c
+++ b/src/handler/get_extended_pubkey.c
@@ -17,16 +17,19 @@
#include <stdint.h>
-#include "boilerplate/io.h"
-#include "boilerplate/dispatcher.h"
-#include "boilerplate/sw.h"
-#include "../common/base58.h"
-#include "../common/bip32.h"
-#include "../commands.h"
-#include "../constants.h"
-#include "../crypto.h"
-#include "../ui/display.h"
-#include "../ui/menu.h"
+/* SDK headers */
+#include "base58.h"
+#include "bip32.h"
+
+/* Local headers */
+#include "commands.h"
+#include "constants.h"
+#include "crypto.h"
+#include "dispatcher.h"
+#include "display.h"
+#include "io_ext.h"
+#include "menu.h"
+#include "sw.h"
#define H 0x80000000ul
@@ -124,9 +127,11 @@ void handler_get_extended_pubkey(dispatcher_context_t *dc, uint8_t protocol_vers
}
uint32_t bip32_path[MAX_BIP32_PATH_STEPS];
- if (!buffer_read_bip32_path(&dc->read_buffer, bip32_path, bip32_path_len)) {
- SEND_SW(dc, SW_WRONG_DATA_LENGTH);
- return;
+ if (bip32_path_len > 0) {
+ if (!buffer_read_bip32_path(&dc->read_buffer, bip32_path, bip32_path_len)) {
+ SEND_SW(dc, SW_WRONG_DATA_LENGTH);
+ return;
+ }
}
bool is_safe = is_path_safe_for_pubkey_export(bip32_path, bip32_path_len);
diff --git a/src/handler/get_master_fingerprint.c b/src/handler/get_master_fingerprint.c
index 1a32842..2e18acc 100644
--- a/src/handler/get_master_fingerprint.c
+++ b/src/handler/get_master_fingerprint.c
@@ -17,14 +17,14 @@
#include <stdint.h>
-#include "os_seed.h"
-
-#include "boilerplate/dispatcher.h"
-#include "boilerplate/sw.h"
-#include "../commands.h"
-#include "../crypto.h"
+/* Local headers */
+#include "commands.h"
+#include "crypto.h"
+#include "dispatcher.h"
#include "handlers.h"
+#include "os_seed.h"
+#include "sw.h"
void handler_get_master_fingerprint(dispatcher_context_t *dc, uint8_t protocol_version) {
(void) protocol_version;
diff --git a/src/handler/get_wallet_address.c b/src/handler/get_wallet_address.c
index 7f7bb55..a9aeb65 100644
--- a/src/handler/get_wallet_address.c
+++ b/src/handler/get_wallet_address.c
@@ -17,32 +17,33 @@
#include <stdint.h>
-#include "boilerplate/io.h"
-#include "boilerplate/sw.h"
-#include "../common/base58.h"
-#include "../common/bip32.h"
-#include "../common/buffer.h"
-#include "../common/merkle.h"
-#include "../common/read.h"
-#include "../common/script.h"
-#include "../common/segwit_addr.h"
-#include "../common/wallet.h"
-#include "../commands.h"
-#include "../constants.h"
-#include "../crypto.h"
-#include "../error_codes.h"
-#include "../ui/display.h"
-#include "../ui/menu.h"
-
-#include "../swap/swap_globals.h"
-#include "../swap/handle_swap_sign_transaction.h"
-
-#include "lib/policy.h"
-#include "lib/get_preimage.h"
-#include "lib/get_merkle_leaf_element.h"
-
-#include "handlers.h"
+/* SDK headers */
+#include "base58.h"
+#include "bip32.h"
+#include "buffer.h"
+#include "read.h"
+
+/* Local headers */
+#include "buffer_ext.h"
#include "client_commands.h"
+#include "commands.h"
+#include "constants.h"
+#include "crypto.h"
+#include "display.h"
+#include "error_codes.h"
+#include "get_merkle_leaf_element.h"
+#include "get_preimage.h"
+#include "handle_swap_sign_transaction.h"
+#include "handlers.h"
+#include "io_ext.h"
+#include "menu.h"
+#include "merkle.h"
+#include "policy.h"
+#include "script.h"
+#include "segwit_addr.h"
+#include "sw.h"
+#include "swap_globals.h"
+#include "wallet.h"
void handler_get_wallet_address(dispatcher_context_t *dc, uint8_t protocol_version) {
UNUSED(protocol_version);
diff --git a/src/handler/handlers.h b/src/handler/handlers.h
index ad3d28d..5dbb536 100644
--- a/src/handler/handlers.h
+++ b/src/handler/handlers.h
@@ -1,6 +1,8 @@
#pragma once
-#include "../boilerplate/dispatcher.h"
+
+/* Local headers */
+#include "dispatcher.h"
void handler_get_extended_pubkey(dispatcher_context_t *dispatcher_context, uint8_t p2);
void handler_get_master_fingerprint(dispatcher_context_t *dispatcher_context, uint8_t p2);
diff --git a/src/handler/lib/check_merkle_tree_sorted.c b/src/handler/lib/check_merkle_tree_sorted.c
index 3c1f16f..550dcb4 100644
--- a/src/handler/lib/check_merkle_tree_sorted.c
+++ b/src/handler/lib/check_merkle_tree_sorted.c
@@ -1,9 +1,11 @@
#include <string.h>
#include "check_merkle_tree_sorted.h"
-#include "get_merkle_leaf_element.h"
-#include "../../common/merkle.h"
+/* Local headers */
+#include "buffer_ext.h"
+#include "get_merkle_leaf_element.h"
+#include "merkle.h"
static int compare_byte_arrays(const uint8_t array1[],
size_t array1_len,
@@ -76,4 +78,4 @@ static int compare_byte_arrays(const uint8_t array1[],
}
return memcmp_result;
-}
\ No newline at end of file
+}
diff --git a/src/handler/lib/check_merkle_tree_sorted.h b/src/handler/lib/check_merkle_tree_sorted.h
index 23f28d5..38a79ca 100644
--- a/src/handler/lib/check_merkle_tree_sorted.h
+++ b/src/handler/lib/check_merkle_tree_sorted.h
@@ -1,8 +1,10 @@
#pragma once
-#include "../../boilerplate/dispatcher.h"
-#include "../../common/merkle.h"
-#include "../../common/wallet.h"
+
+/* Local headers */
+#include "dispatcher.h"
+#include "merkle.h"
+#include "wallet.h"
// this flow aborts if any element is larger than this size
// TODO: we might remove this limitation altogether with a more careful implementation.
diff --git a/src/handler/lib/get_merkle_leaf_element.c b/src/handler/lib/get_merkle_leaf_element.c
index 5ab4b04..f29dcb5 100644
--- a/src/handler/lib/get_merkle_leaf_element.c
+++ b/src/handler/lib/get_merkle_leaf_element.c
@@ -1,5 +1,6 @@
#include "get_merkle_leaf_element.h"
+/* Local headers */
#include "get_merkle_leaf_hash.h"
#include "get_merkle_preimage.h"
diff --git a/src/handler/lib/get_merkle_leaf_element.h b/src/handler/lib/get_merkle_leaf_element.h
index f11429a..4979e7e 100644
--- a/src/handler/lib/get_merkle_leaf_element.h
+++ b/src/handler/lib/get_merkle_leaf_element.h
@@ -1,6 +1,8 @@
#pragma once
-#include "../../boilerplate/dispatcher.h"
+
+/* Local headers */
+#include "dispatcher.h"
/**
* TODO: docs
diff --git a/src/handler/lib/get_merkle_leaf_hash.c b/src/handler/lib/get_merkle_leaf_hash.c
index ca7acfd..183e14d 100644
--- a/src/handler/lib/get_merkle_leaf_hash.c
+++ b/src/handler/lib/get_merkle_leaf_hash.c
@@ -2,14 +2,17 @@
#include "get_merkle_leaf_hash.h"
-#include "../../common/buffer.h"
-#include "../../common/write.h"
-#include "../../common/merkle.h"
-#include "../../common/varint.h"
-#include "../../boilerplate/sw.h"
-#include "../client_commands.h"
-
-#include "../../debug-helpers/debug.h"
+/* SDK headers */
+#include "buffer.h"
+#include "varint.h"
+#include "write.h"
+
+/* Local headers */
+#include "buffer_ext.h"
+#include "client_commands.h"
+#include "debug.h"
+#include "merkle.h"
+#include "sw.h"
// Reads the inputs and sends the GET_MERKLE_LEAF_PROOF request.
int call_get_merkle_leaf_hash(dispatcher_context_t *dc,
diff --git a/src/handler/lib/get_merkle_leaf_hash.h b/src/handler/lib/get_merkle_leaf_hash.h
index 9a92e86..f6f6962 100644
--- a/src/handler/lib/get_merkle_leaf_hash.h
+++ b/src/handler/lib/get_merkle_leaf_hash.h
@@ -1,6 +1,8 @@
#pragma once
-#include "../../boilerplate/dispatcher.h"
+
+/* Local headers */
+#include "dispatcher.h"
/**
* TODO: docs
diff --git a/src/handler/lib/get_merkle_leaf_index.c b/src/handler/lib/get_merkle_leaf_index.c
index 6689778..c9086e9 100644
--- a/src/handler/lib/get_merkle_leaf_index.c
+++ b/src/handler/lib/get_merkle_leaf_index.c
@@ -1,9 +1,10 @@
#include <string.h>
-#include "../../boilerplate/sw.h"
-#include "get_merkle_leaf_hash.h"
-#include "../client_commands.h"
+/* Local headers */
+#include "client_commands.h"
+#include "get_merkle_leaf_hash.h"
+#include "sw.h"
int call_get_merkle_leaf_index(dispatcher_context_t *dispatcher_context,
size_t size,
diff --git a/src/handler/lib/get_merkle_leaf_index.h b/src/handler/lib/get_merkle_leaf_index.h
index 64fa329..808e228 100644
--- a/src/handler/lib/get_merkle_leaf_index.h
+++ b/src/handler/lib/get_merkle_leaf_index.h
@@ -1,6 +1,8 @@
#pragma once
-#include "../../boilerplate/dispatcher.h"
+
+/* Local headers */
+#include "dispatcher.h"
/**
* TODO: docs
diff --git a/src/handler/lib/get_merkle_preimage.c b/src/handler/lib/get_merkle_preimage.c
index 6795208..2f03645 100644
--- a/src/handler/lib/get_merkle_preimage.c
+++ b/src/handler/lib/get_merkle_preimage.c
@@ -2,12 +2,15 @@
#include "get_merkle_preimage.h"
-#include "../../boilerplate/sw.h"
-#include "../../common/buffer.h"
-#include "../../crypto.h"
-#include "../client_commands.h"
+/* SDK headers */
+#include "buffer.h"
-#include "../../debug-helpers/debug.h"
+/* Local headers */
+#include "buffer_ext.h"
+#include "client_commands.h"
+#include "crypto.h"
+#include "debug.h"
+#include "sw.h"
// TODO: refactor common code with stream_preimage.c
@@ -56,7 +59,7 @@ int call_get_merkle_preimage(dispatcher_context_t *dispatcher_context,
}
uint8_t *data_ptr =
- dispatcher_context->read_buffer.ptr + dispatcher_context->read_buffer.offset;
+ (uint8_t *) (dispatcher_context->read_buffer.ptr + dispatcher_context->read_buffer.offset);
cx_sha256_t hash_context;
@@ -97,7 +100,8 @@ int call_get_merkle_preimage(dispatcher_context_t *dispatcher_context,
return -9;
}
- data_ptr = dispatcher_context->read_buffer.ptr + dispatcher_context->read_buffer.offset;
+ data_ptr = (uint8_t *) dispatcher_context->read_buffer.ptr +
+ dispatcher_context->read_buffer.offset;
// update hash
crypto_hash_update(&hash_context.header, data_ptr, n_bytes);
@@ -118,4 +122,4 @@ int call_get_merkle_preimage(dispatcher_context_t *dispatcher_context,
}
return (int) (preimage_len - 1);
-}
\ No newline at end of file
+}
diff --git a/src/handler/lib/get_merkle_preimage.h b/src/handler/lib/get_merkle_preimage.h
index 0ba7ea2..c1d3519 100644
--- a/src/handler/lib/get_merkle_preimage.h
+++ b/src/handler/lib/get_merkle_preimage.h
@@ -1,6 +1,8 @@
#pragma once
-#include "../../boilerplate/dispatcher.h"
+
+/* Local headers */
+#include "dispatcher.h"
/**
* In this flow, the HWW sends a CCMD_GET_PREIMAGE command with a SHA256 hash.
diff --git a/src/handler/lib/get_merkleized_map.c b/src/handler/lib/get_merkleized_map.c
index 1e6e7a9..f11ae5b 100644
--- a/src/handler/lib/get_merkleized_map.c
+++ b/src/handler/lib/get_merkleized_map.c
@@ -2,10 +2,13 @@
#include "get_merkleized_map.h"
-#include "get_merkle_leaf_element.h"
-#include "check_merkle_tree_sorted.h"
+/* SDK headers */
+#include "buffer.h"
-#include "../../common/buffer.h"
+/* Local headers */
+#include "buffer_ext.h"
+#include "check_merkle_tree_sorted.h"
+#include "get_merkle_leaf_element.h"
int call_get_merkleized_map_with_callback(dispatcher_context_t *dispatcher_context,
void *callback_state,
@@ -42,4 +45,4 @@ int call_get_merkleized_map_with_callback(dispatcher_context_t *dispatcher_conte
out_ptr->size,
callback,
out_ptr);
-}
\ No newline at end of file
+}
diff --git a/src/handler/lib/get_merkleized_map.h b/src/handler/lib/get_merkleized_map.h
index c3ed69e..6e4119f 100644
--- a/src/handler/lib/get_merkleized_map.h
+++ b/src/handler/lib/get_merkleized_map.h
@@ -1,9 +1,10 @@
#pragma once
-#include "../../boilerplate/dispatcher.h"
-#include "../../common/merkle.h"
+/* Local headers */
#include "check_merkle_tree_sorted.h"
+#include "dispatcher.h"
+#include "merkle.h"
/**
* TODO: docs
diff --git a/src/handler/lib/get_merkleized_map_value.c b/src/handler/lib/get_merkleized_map_value.c
index f9baf2f..039c2e5 100644
--- a/src/handler/lib/get_merkleized_map_value.c
+++ b/src/handler/lib/get_merkleized_map_value.c
@@ -2,8 +2,9 @@
#include "get_merkleized_map_value.h"
-#include "get_merkle_leaf_index.h"
+/* Local headers */
#include "get_merkle_leaf_element.h"
+#include "get_merkle_leaf_index.h"
int call_get_merkleized_map_value(dispatcher_context_t *dispatcher_context,
const merkleized_map_commitment_t *map,
diff --git a/src/handler/lib/get_merkleized_map_value.h b/src/handler/lib/get_merkleized_map_value.h
index b7a6aa0..68d5dd4 100644
--- a/src/handler/lib/get_merkleized_map_value.h
+++ b/src/handler/lib/get_merkleized_map_value.h
@@ -1,8 +1,11 @@
#pragma once
-#include "../../boilerplate/dispatcher.h"
-#include "../../common/merkle.h"
-#include "../../common/read.h"
+/* SDK headers */
+#include "read.h"
+
+/* Local headers */
+#include "dispatcher.h"
+#include "merkle.h"
/**
* Given a commitment to a merkleized key-value map, this flow finds out the index of the element
@@ -42,4 +45,4 @@ static inline int call_get_merkleized_map_value_u32_le(dispatcher_context_t *dis
*out = read_u32_le(result_raw, 0);
return 4;
-}
\ No newline at end of file
+}
diff --git a/src/handler/lib/get_merkleized_map_value_hash.c b/src/handler/lib/get_merkleized_map_value_hash.c
index 29ee4b0..ea1881f 100644
--- a/src/handler/lib/get_merkleized_map_value_hash.c
+++ b/src/handler/lib/get_merkleized_map_value_hash.c
@@ -2,6 +2,7 @@
#include "get_merkleized_map_value_hash.h"
+/* Local headers */
#include "get_merkle_leaf_hash.h"
#include "get_merkle_leaf_index.h"
diff --git a/src/handler/lib/get_merkleized_map_value_hash.h b/src/handler/lib/get_merkleized_map_value_hash.h
index db1ca4c..3213413 100644
--- a/src/handler/lib/get_merkleized_map_value_hash.h
+++ b/src/handler/lib/get_merkleized_map_value_hash.h
@@ -1,7 +1,9 @@
#pragma once
-#include "../../boilerplate/dispatcher.h"
-#include "../../common/merkle.h"
+
+/* Local headers */
+#include "dispatcher.h"
+#include "merkle.h"
/**
* Given a commitment to a merkleized key-value map, this flow finds out the index of the element
diff --git a/src/handler/lib/get_preimage.c b/src/handler/lib/get_preimage.c
index b5f5f5c..733a7ae 100644
--- a/src/handler/lib/get_preimage.c
+++ b/src/handler/lib/get_preimage.c
@@ -1,10 +1,12 @@
#include <string.h>
-#include "../../boilerplate/sw.h"
-#include "stream_preimage.h"
-#include "../../crypto.h"
-#include "../client_commands.h"
+/* Local headers */
+#include "buffer_ext.h"
+#include "client_commands.h"
+#include "crypto.h"
+#include "stream_preimage.h"
+#include "sw.h"
int call_get_preimage(dispatcher_context_t *dispatcher_context,
const uint8_t hash[static 32],
@@ -46,7 +48,7 @@ int call_get_preimage(dispatcher_context_t *dispatcher_context,
buffer_t buffer_out = buffer_create(out, out_len);
uint8_t *data_ptr =
- dispatcher_context->read_buffer.ptr + dispatcher_context->read_buffer.offset;
+ (uint8_t *) (dispatcher_context->read_buffer.ptr + dispatcher_context->read_buffer.offset);
cx_sha256_t hash_context;
cx_sha256_init(&hash_context);
@@ -86,7 +88,8 @@ int call_get_preimage(dispatcher_context_t *dispatcher_context,
return -8;
}
- data_ptr = dispatcher_context->read_buffer.ptr + dispatcher_context->read_buffer.offset;
+ data_ptr = (uint8_t *) (dispatcher_context->read_buffer.ptr +
+ dispatcher_context->read_buffer.offset);
// update hash
crypto_hash_update(&hash_context.header, data_ptr, n_bytes);
diff --git a/src/handler/lib/get_preimage.h b/src/handler/lib/get_preimage.h
index f748c1c..627a5b4 100644
--- a/src/handler/lib/get_preimage.h
+++ b/src/handler/lib/get_preimage.h
@@ -1,6 +1,8 @@
#pragma once
-#include "../../boilerplate/dispatcher.h"
+
+/* Local headers */
+#include "dispatcher.h"
/**
* Given a sha256 hash, requests the corresponding pre-image to the host.
diff --git a/src/handler/lib/policy.c b/src/handler/lib/policy.c
index cc93be6..5e3eaac 100644
--- a/src/handler/lib/policy.c
+++ b/src/handler/lib/policy.c
@@ -2,20 +2,22 @@
#include "policy.h"
-#include "../lib/get_merkle_leaf_element.h"
-#include "../lib/get_preimage.h"
-#include "../../crypto.h"
-#include "../../musig/musig.h"
-#include "../../common/base58.h"
-#include "../../common/bitvector.h"
-#include "../../common/read.h"
-#include "../../common/script.h"
-#include "../../common/segwit_addr.h"
-#include "../../common/wallet.h"
-
-#include "../../debug-helpers/debug.h"
-
+/* SDK headers */
+#include "base58.h"
#include "ledger_assert.h"
+#include "read.h"
+
+/* Local headers */
+#include "bitvector.h"
+#include "buffer_ext.h"
+#include "crypto.h"
+#include "debug.h"
+#include "get_merkle_leaf_element.h"
+#include "get_preimage.h"
+#include "musig.h"
+#include "script.h"
+#include "segwit_addr.h"
+#include "wallet.h"
#define MAX_POLICY_DEPTH 10
diff --git a/src/handler/lib/policy.h b/src/handler/lib/policy.h
index e5cd241..b1c5a22 100644
--- a/src/handler/lib/policy.h
+++ b/src/handler/lib/policy.h
@@ -1,8 +1,10 @@
#pragma once
-#include "../../boilerplate/dispatcher.h"
-#include "../../common/wallet.h"
-#include "../../handler/sign_psbt/sign_psbt_cache.h"
+
+/* Local headers */
+#include "dispatcher.h"
+#include "sign_psbt_cache.h"
+#include "wallet.h"
/**
* Parses a serialized wallet policy, saving the wallet header, the policy map descriptor and the
diff --git a/src/handler/lib/psbt_parse_rawtx.c b/src/handler/lib/psbt_parse_rawtx.c
index d0c0ee4..05808eb 100644
--- a/src/handler/lib/psbt_parse_rawtx.c
+++ b/src/handler/lib/psbt_parse_rawtx.c
@@ -1,21 +1,22 @@
#include <stdlib.h>
#include <string.h>
-#include "cx.h"
-
#include "psbt_parse_rawtx.h"
+/* SDK headers */
+#include "buffer.h"
+#include "cx.h"
+#include "read.h"
+#include "varint.h"
+
+/* Local headers */
+#include "buffer_ext.h"
+#include "crypto.h"
+#include "dispatcher.h"
#include "get_merkleized_map_value_hash.h"
+#include "parser_ext.h"
#include "stream_preimage.h"
-
-#include "../../boilerplate/dispatcher.h"
-#include "../../boilerplate/sw.h"
-
-#include "../../common/buffer.h"
-#include "../../common/parser.h"
-#include "../../common/read.h"
-#include "../../common/varint.h"
-#include "../../crypto.h"
+#include "sw.h"
struct parse_rawtx_state_s; // forward declaration
diff --git a/src/handler/lib/psbt_parse_rawtx.h b/src/handler/lib/psbt_parse_rawtx.h
index 21082ae..daeb92f 100644
--- a/src/handler/lib/psbt_parse_rawtx.h
+++ b/src/handler/lib/psbt_parse_rawtx.h
@@ -1,8 +1,10 @@
#pragma once
-#include "../../boilerplate/dispatcher.h"
-#include "../../common/merkle.h"
-#include "../../constants.h"
+
+/* Local headers */
+#include "constants.h"
+#include "dispatcher.h"
+#include "merkle.h"
typedef struct {
uint64_t vout_value; // will contain the value of the requested output
diff --git a/src/handler/lib/stream_merkle_leaf_element.c b/src/handler/lib/stream_merkle_leaf_element.c
index 751e0b0..ce21ced 100644
--- a/src/handler/lib/stream_merkle_leaf_element.c
+++ b/src/handler/lib/stream_merkle_leaf_element.c
@@ -1,6 +1,7 @@
#include "stream_merkle_leaf_element.h"
+/* Local headers */
#include "get_merkle_leaf_hash.h"
#include "stream_preimage.h"
diff --git a/src/handler/lib/stream_merkle_leaf_element.h b/src/handler/lib/stream_merkle_leaf_element.h
index 638650e..ba2872a 100644
--- a/src/handler/lib/stream_merkle_leaf_element.h
+++ b/src/handler/lib/stream_merkle_leaf_element.h
@@ -1,7 +1,9 @@
#pragma once
-#include "../../boilerplate/dispatcher.h"
-#include "../../common/merkle.h"
+
+/* Local headers */
+#include "dispatcher.h"
+#include "merkle.h"
/**
* This flow obtains and streams to the callback the preimage of a leaf of a Merkle tree, specified
diff --git a/src/handler/lib/stream_merkleized_map_value.c b/src/handler/lib/stream_merkleized_map_value.c
index 0c7c44a..f5d79b5 100644
--- a/src/handler/lib/stream_merkleized_map_value.c
+++ b/src/handler/lib/stream_merkleized_map_value.c
@@ -1,4 +1,6 @@
#include "stream_merkleized_map_value.h"
+
+/* Local headers */
#include "get_merkle_leaf_index.h"
#include "stream_merkle_leaf_element.h"
diff --git a/src/handler/lib/stream_merkleized_map_value.h b/src/handler/lib/stream_merkleized_map_value.h
index b1f6f6f..4c77954 100644
--- a/src/handler/lib/stream_merkleized_map_value.h
+++ b/src/handler/lib/stream_merkleized_map_value.h
@@ -1,7 +1,9 @@
#pragma once
-#include "../../boilerplate/dispatcher.h"
-#include "../../common/merkle.h"
+
+/* Local headers */
+#include "dispatcher.h"
+#include "merkle.h"
/**
* Given a commitment to a merkleized key-value map, this flow find out the index of the
diff --git a/src/handler/lib/stream_preimage.c b/src/handler/lib/stream_preimage.c
index cd6a0c7..09f8990 100644
--- a/src/handler/lib/stream_preimage.c
+++ b/src/handler/lib/stream_preimage.c
@@ -1,10 +1,12 @@
#include <string.h>
-#include "../../boilerplate/sw.h"
#include "stream_preimage.h"
-#include "../../crypto.h"
-#include "../client_commands.h"
+/* Local headers */
+#include "buffer_ext.h"
+#include "client_commands.h"
+#include "crypto.h"
+#include "sw.h"
int call_stream_preimage(dispatcher_context_t *dispatcher_context,
const uint8_t hash[static 32],
@@ -49,7 +51,7 @@ int call_stream_preimage(dispatcher_context_t *dispatcher_context,
}
uint8_t *data_ptr =
- dispatcher_context->read_buffer.ptr + dispatcher_context->read_buffer.offset;
+ (uint8_t *) (dispatcher_context->read_buffer.ptr + dispatcher_context->read_buffer.offset);
cx_sha256_t hash_context;
cx_sha256_init(&hash_context);
@@ -90,7 +92,8 @@ int call_stream_preimage(dispatcher_context_t *dispatcher_context,
return -8;
}
- data_ptr = dispatcher_context->read_buffer.ptr + dispatcher_context->read_buffer.offset;
+ data_ptr = (uint8_t *) dispatcher_context->read_buffer.ptr +
+ dispatcher_context->read_buffer.offset;
// update hash
crypto_hash_update(&hash_context.header, data_ptr, n_bytes);
diff --git a/src/handler/lib/stream_preimage.h b/src/handler/lib/stream_preimage.h
index 8f57115..fb9b28f 100644
--- a/src/handler/lib/stream_preimage.h
+++ b/src/handler/lib/stream_preimage.h
@@ -1,6 +1,8 @@
#pragma once
-#include "../../boilerplate/dispatcher.h"
+
+/* Local headers */
+#include "dispatcher.h"
/**
* Given the hash of a leaf of a Merkle tree, requests the corresponding pre-image to the host. The
diff --git a/src/handler/register_wallet.c b/src/handler/register_wallet.c
index 3339fc4..5a7b5d1 100644
--- a/src/handler/register_wallet.c
+++ b/src/handler/register_wallet.c
@@ -18,31 +18,30 @@
#include <stdint.h>
#include <string.h>
-#include "os.h"
+/* SDK headers */
+#include "bip32.h"
#include "cx.h"
+#include "os.h"
+#include "read.h"
+#include "write.h"
-#include "../boilerplate/dispatcher.h"
-#include "../boilerplate/sw.h"
-#include "../common/bip32.h"
-#include "../common/merkle.h"
-#include "../common/read.h"
-#include "../common/wallet.h"
-#include "../common/write.h"
-
-#include "../commands.h"
-#include "../constants.h"
-#include "../crypto.h"
-#include "../error_codes.h"
-#include "../ui/display.h"
-#include "../ui/menu.h"
-
-#include "lib/get_merkle_leaf_element.h"
-#include "lib/get_preimage.h"
-#include "lib/policy.h"
-
+/* Local headers */
+#include "buffer_ext.h"
#include "client_commands.h"
-
+#include "commands.h"
+#include "constants.h"
+#include "crypto.h"
+#include "dispatcher.h"
+#include "display.h"
+#include "error_codes.h"
+#include "get_merkle_leaf_element.h"
+#include "get_preimage.h"
#include "handlers.h"
+#include "menu.h"
+#include "merkle.h"
+#include "policy.h"
+#include "sw.h"
+#include "wallet.h"
static bool is_policy_acceptable(const policy_node_t *policy);
static bool is_policy_name_acceptable(const char *name, size_t name_len);
diff --git a/src/handler/sign_message.c b/src/handler/sign_message.c
index 159f9a4..d4e4786 100644
--- a/src/handler/sign_message.c
+++ b/src/handler/sign_message.c
@@ -17,18 +17,21 @@
#include <stdint.h>
-#include "boilerplate/io.h"
-#include "boilerplate/dispatcher.h"
-#include "boilerplate/sw.h"
-#include "../common/bip32.h"
-#include "../commands.h"
-#include "../constants.h"
-#include "../crypto.h"
-#include "../ui/display.h"
-#include "../ui/menu.h"
-#include "lib/get_merkle_leaf_element.h"
-
+/* SDK headers */
+#include "bip32.h"
+
+/* Local headers */
+#include "buffer_ext.h"
+#include "commands.h"
+#include "constants.h"
+#include "crypto.h"
+#include "dispatcher.h"
+#include "display.h"
+#include "get_merkle_leaf_element.h"
#include "handlers.h"
+#include "io_ext.h"
+#include "menu.h"
+#include "sw.h"
extern const char GA_LOADING_MESSAGE[];
diff --git a/src/handler/sign_psbt.c b/src/handler/sign_psbt.c
index 865d41f..3cad8be 100644
--- a/src/handler/sign_psbt.c
+++ b/src/handler/sign_psbt.c
@@ -18,50 +18,48 @@
#include <stdint.h>
#include <stdlib.h>
-#include "lib_standard_app/crypto_helpers.h"
-
-#include "../boilerplate/dispatcher.h"
-#include "../boilerplate/sw.h"
-#include "../common/bitvector.h"
-#include "../common/merkle.h"
-#include "../common/psbt.h"
-#include "../common/read.h"
-#include "../common/script.h"
-#include "../common/varint.h"
-#include "../common/wallet.h"
-#include "../common/write.h"
-
-#include "../commands.h"
-#include "../constants.h"
-#include "../crypto.h"
-#include "../error_codes.h"
-#include "../ui/display.h"
-#include "../ui/menu.h"
+#include "sign_psbt.h"
+/* SDK headers */
+#include "crypto_helpers.h"
+#include "read.h"
+#include "varint.h"
+#include "write.h"
+
+/* Local headers */
+#include "amount_from_psbt.h"
+#include "bitvector.h"
+#include "buffer_ext.h"
+#include "check_merkle_tree_sorted.h"
#include "client_commands.h"
-
-#include "lib/policy.h"
-#include "lib/check_merkle_tree_sorted.h"
-#include "lib/get_preimage.h"
-#include "lib/get_merkleized_map.h"
-#include "lib/get_merkleized_map_value.h"
-#include "lib/get_merkle_leaf_element.h"
-#include "lib/psbt_parse_rawtx.h"
-
+#include "commands.h"
+#include "compare_wallet_script_at_path.h"
+#include "constants.h"
+#include "crypto.h"
+#include "dispatcher.h"
+#include "display.h"
+#include "error_codes.h"
+#include "extract_bip32_derivation.h"
+#include "get_merkle_leaf_element.h"
+#include "get_merkleized_map.h"
+#include "get_merkleized_map_value.h"
+#include "get_preimage.h"
+#include "handle_swap_sign_transaction.h"
#include "handlers.h"
-#include "sign_psbt.h"
-
-#include "sign_psbt/amount_from_psbt.h"
-#include "sign_psbt/compare_wallet_script_at_path.h"
-#include "sign_psbt/extract_bip32_derivation.h"
-#include "sign_psbt/musig_signing.h"
-#include "sign_psbt/txhashes.h"
-#include "sign_psbt/sign_psbt_cache.h"
-
-#include "../swap/swap_globals.h"
-#include "../swap/handle_swap_sign_transaction.h"
-#include "../musig/musig.h"
-#include "../musig/musig_sessions.h"
+#include "menu.h"
+#include "merkle.h"
+#include "musig.h"
+#include "musig_sessions.h"
+#include "musig_signing.h"
+#include "policy.h"
+#include "psbt.h"
+#include "psbt_parse_rawtx.h"
+#include "script.h"
+#include "sign_psbt_cache.h"
+#include "sw.h"
+#include "swap_globals.h"
+#include "txhashes.h"
+#include "wallet.h"
/*
Current assumptions during signing:
diff --git a/src/handler/sign_psbt.h b/src/handler/sign_psbt.h
index 7373b50..7ef9d00 100644
--- a/src/handler/sign_psbt.h
+++ b/src/handler/sign_psbt.h
@@ -1,8 +1,10 @@
#pragma once
-#include "../musig/musig_sessions.h"
-#include "../common/merkle.h"
-#include "../ui/display.h"
+
+/* Local headers */
+#include "display.h"
+#include "merkle.h"
+#include "musig_sessions.h"
// common info that applies to either the current input or the current output
typedef struct {
diff --git a/src/handler/sign_psbt/amount_from_psbt.c b/src/handler/sign_psbt/amount_from_psbt.c
index 15ae007..3b6ebcc 100644
--- a/src/handler/sign_psbt/amount_from_psbt.c
+++ b/src/handler/sign_psbt/amount_from_psbt.c
@@ -1,9 +1,9 @@
#include "amount_from_psbt.h"
-#include "../../common/psbt.h"
-
-#include "../lib/get_merkleized_map_value.h"
-#include "../lib/psbt_parse_rawtx.h"
+/* Local headers */
+#include "get_merkleized_map_value.h"
+#include "psbt.h"
+#include "psbt_parse_rawtx.h"
/*
Convenience function to get the amount and scriptpubkey from the non-witness-utxo of a certain
diff --git a/src/handler/sign_psbt/amount_from_psbt.h b/src/handler/sign_psbt/amount_from_psbt.h
index 873b2a6..aa578f3 100644
--- a/src/handler/sign_psbt/amount_from_psbt.h
+++ b/src/handler/sign_psbt/amount_from_psbt.h
@@ -1,7 +1,9 @@
#pragma once
-#include "../boilerplate/dispatcher.h"
-#include "../sign_psbt.h"
+
+/* Local headers */
+#include "dispatcher.h"
+#include "sign_psbt.h"
// These functions are used to extract the amount and scriptPubKey of an input from the witness-utxo
// or the non-witness-utxo of a PSBTv2.
diff --git a/src/handler/sign_psbt/compare_wallet_script_at_path.c b/src/handler/sign_psbt/compare_wallet_script_at_path.c
index fffc008..2fa12e7 100644
--- a/src/handler/sign_psbt/compare_wallet_script_at_path.c
+++ b/src/handler/sign_psbt/compare_wallet_script_at_path.c
@@ -3,10 +3,12 @@
#include "compare_wallet_script_at_path.h"
-#include "../lib/get_merkleized_map_value.h"
-#include "../lib/policy.h"
+/* SDK headers */
+#include "read.h"
-#include "../../common/read.h"
+/* Local headers */
+#include "get_merkleized_map_value.h"
+#include "policy.h"
int compare_wallet_script_at_path(dispatcher_context_t *dispatcher_context,
sign_psbt_cache_t *sign_psbt_cache,
diff --git a/src/handler/sign_psbt/compare_wallet_script_at_path.h b/src/handler/sign_psbt/compare_wallet_script_at_path.h
index 2940ebf..5b02ac3 100644
--- a/src/handler/sign_psbt/compare_wallet_script_at_path.h
+++ b/src/handler/sign_psbt/compare_wallet_script_at_path.h
@@ -1,9 +1,11 @@
#pragma once
-#include "../../boilerplate/dispatcher.h"
-#include "../../common/merkle.h"
-#include "../../common/wallet.h"
-#include "../../handler/sign_psbt/sign_psbt_cache.h"
+
+/* Local headers */
+#include "dispatcher.h"
+#include "merkle.h"
+#include "sign_psbt_cache.h"
+#include "wallet.h"
/**
* TODO
diff --git a/src/handler/sign_psbt/extract_bip32_derivation.c b/src/handler/sign_psbt/extract_bip32_derivation.c
index 496a381..b17739a 100644
--- a/src/handler/sign_psbt/extract_bip32_derivation.c
+++ b/src/handler/sign_psbt/extract_bip32_derivation.c
@@ -1,12 +1,16 @@
#include <stdint.h>
#include <string.h>
-#include "./extract_bip32_derivation.h"
+#include "extract_bip32_derivation.h"
-#include "../lib/stream_merkle_leaf_element.h"
+/* SDK headers */
+#include "read.h"
+#include "varint.h"
-#include "../../common/psbt.h"
-#include "../../common/read.h"
+/* Local headers */
+#include "buffer_ext.h"
+#include "psbt.h"
+#include "stream_merkle_leaf_element.h"
typedef struct {
int psbt_key_type;
@@ -129,4 +133,4 @@ int extract_bip32_derivation(dispatcher_context_t *dc,
}
return (callback_state.out_data_length / 4) - 1;
-}
\ No newline at end of file
+}
diff --git a/src/handler/sign_psbt/extract_bip32_derivation.h b/src/handler/sign_psbt/extract_bip32_derivation.h
index 2fbda42..4b87869 100644
--- a/src/handler/sign_psbt/extract_bip32_derivation.h
+++ b/src/handler/sign_psbt/extract_bip32_derivation.h
@@ -1,7 +1,11 @@
#pragma once
-#include "../../boilerplate/dispatcher.h"
-#include "../../common/bip32.h"
+/* SDK headers */
+#include "bip32.h"
+
+/* Local headers */
+#include "constants.h"
+#include "dispatcher.h"
/**
* Convenience function to extract the BIP32 derivation part from a PSBT field key type
@@ -14,4 +18,4 @@ int extract_bip32_derivation(dispatcher_context_t *dc,
const uint8_t values_root[static 32],
uint32_t merkle_tree_size,
int index,
- uint32_t out[static 1 + MAX_BIP32_PATH_STEPS]);
\ No newline at end of file
+ uint32_t out[static 1 + MAX_BIP32_PATH_STEPS]);
diff --git a/src/handler/sign_psbt/musig_signing.c b/src/handler/sign_psbt/musig_signing.c
index 4ae706e..896d1bc 100644
--- a/src/handler/sign_psbt/musig_signing.c
+++ b/src/handler/sign_psbt/musig_signing.c
@@ -1,12 +1,16 @@
#include <stdlib.h>
#include "musig_signing.h"
-#include "lib_standard_app/crypto_helpers.h"
-#include "../boilerplate/sw.h"
-#include "../common/psbt.h"
-#include "../client_commands.h"
-#include "../lib/get_merkleized_map_value.h"
-#include "../lib/policy.h"
+
+/* SDK headers */
+#include "crypto_helpers.h"
+
+/* Local headers */
+#include "client_commands.h"
+#include "get_merkleized_map_value.h"
+#include "policy.h"
+#include "psbt.h"
+#include "sw.h"
bool compute_musig_per_input_info(dispatcher_context_t *dc,
sign_psbt_state_t *st,
diff --git a/src/handler/sign_psbt/musig_signing.h b/src/handler/sign_psbt/musig_signing.h
index ae20c48..281be19 100644
--- a/src/handler/sign_psbt/musig_signing.h
+++ b/src/handler/sign_psbt/musig_signing.h
@@ -1,8 +1,11 @@
#include <stdint.h>
-#include "../common/wallet.h"
-#include "../musig/musig.h"
-#include "../boilerplate/dispatcher.h"
-#include "../sign_psbt.h"
+
+
+/* Local headers */
+#include "dispatcher.h"
+#include "musig.h"
+#include "sign_psbt.h"
+#include "wallet.h"
// Struct to hold the info computed for a given input in either of the two rounds
typedef struct {
diff --git a/src/handler/sign_psbt/sign_psbt_cache.h b/src/handler/sign_psbt/sign_psbt_cache.h
index fb87c73..b022a3e 100644
--- a/src/handler/sign_psbt/sign_psbt_cache.h
+++ b/src/handler/sign_psbt/sign_psbt_cache.h
@@ -1,7 +1,9 @@
#pragma once
-#include "../crypto.h"
-#include "../common/wallet.h"
+
+/* Local headers */
+#include "crypto.h"
+#include "wallet.h"
// This allows to keep the cache size small, while only paying a performance hit for any extremely
// complicated policy with more than 16 key expressions in total (should that occur in practice).
diff --git a/src/handler/sign_psbt/txhashes.c b/src/handler/sign_psbt/txhashes.c
index dbfb5ec..a3f9e11 100644
--- a/src/handler/sign_psbt/txhashes.c
+++ b/src/handler/sign_psbt/txhashes.c
@@ -1,12 +1,12 @@
#include "txhashes.h"
-#include "amount_from_psbt.h"
-
-#include "../../common/psbt.h"
-#include "../../error_codes.h"
-#include "../lib/get_merkleized_map.h"
-#include "../lib/get_merkleized_map_value.h"
-#include "../lib/stream_merkleized_map_value.h"
+/* Local headers */
+#include "amount_from_psbt.h"
+#include "error_codes.h"
+#include "get_merkleized_map.h"
+#include "get_merkleized_map_value.h"
+#include "psbt.h"
+#include "stream_merkleized_map_value.h"
/* BIP0341 tags for computing the tagged hashes when computing he sighash */
static const uint8_t BIP0341_sighash_tag[] = {'T', 'a', 'p', 'S', 'i', 'g', 'h', 'a', 's', 'h'};
@@ -28,7 +28,7 @@ static void cb_process_data(buffer_t *data, void *cb_state) {
callback_state_t *state = (callback_state_t *) cb_state;
size_t data_len = data->size - data->offset;
- uint8_t *data_start_ptr = data->ptr + data->offset;
+ uint8_t *data_start_ptr = (uint8_t *) data->ptr + data->offset;
if (state->hash_prefixed != NULL) {
crypto_hash_update(state->hash_prefixed, data_start_ptr, data_len);
diff --git a/src/handler/sign_psbt/txhashes.h b/src/handler/sign_psbt/txhashes.h
index e4b2833..61c5aec 100644
--- a/src/handler/sign_psbt/txhashes.h
+++ b/src/handler/sign_psbt/txhashes.h
@@ -1,7 +1,9 @@
#pragma once
-#include "../boilerplate/dispatcher.h"
-#include "../sign_psbt.h"
+
+/* Local headers */
+#include "dispatcher.h"
+#include "sign_psbt.h"
/**
* @brief Computes the transaction hashes required for signing.
diff --git a/src/main.c b/src/main.c
index 158365f..b00e16b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -15,37 +15,32 @@
* limitations under the License.
*****************************************************************************/
-#include <stdint.h> // uint*_t
-#include <string.h> // memset, explicit_bzero
-
#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+/* SDK headers */
+#include "nbgl_use_case.h"
#include "os.h"
#include "ux.h"
+/* Local headers */
+#include "commands.h"
+#include "constants.h"
+#include "debug.h"
+#include "dispatcher.h"
#include "globals.h"
-#include "io.h"
+#include "handle_check_address.h"
+#include "handle_get_printable_amount.h"
+#include "handle_swap_sign_transaction.h"
+#include "handlers.h"
+#include "io_ext.h"
+#include "menu.h"
+#include "parser.h"
#include "sw.h"
-#include "ui/menu.h"
-#include "boilerplate/apdu_parser.h"
-#include "boilerplate/constants.h"
-#include "boilerplate/dispatcher.h"
-
-#include "../debug-helpers/debug.h"
-
-#include "handler/handlers.h"
-#include "commands.h"
-
-#include "common/wallet.h"
-
-// common declarations between legacy and new code; will refactor it out later
-#include "swap/swap_lib_calls.h"
-#include "swap/swap_globals.h"
-#include "swap/handle_swap_sign_transaction.h"
-#include "swap/handle_get_printable_amount.h"
-#include "swap/handle_check_address.h"
-
-#include "nbgl_use_case.h"
+#include "swap_globals.h"
+#include "swap_lib_calls.h"
+#include "wallet.h"
#ifdef HAVE_BOLOS_APP_STACK_CANARY
extern unsigned int app_stack_canary;
diff --git a/src/musig/musig.c b/src/musig/musig.c
index f6ea51a..48982f2 100644
--- a/src/musig/musig.c
+++ b/src/musig/musig.c
@@ -1,11 +1,13 @@
#include <stdbool.h>
-#include "cx_errors.h"
-
#include "musig.h"
-#include "../crypto.h"
-#include "../secp256k1.h"
+/* SDK headers */
+#include "cx_errors.h"
+
+/* Local headers */
+#include "crypto.h"
+#include "secp256k1.h"
static const uint8_t BIP0327_keyagg_coeff_tag[] =
{'K', 'e', 'y', 'A', 'g', 'g', ' ', 'c', 'o', 'e', 'f', 'f', 'i', 'c', 'i', 'e', 'n', 't'};
diff --git a/src/musig/musig.h b/src/musig/musig.h
index 76e7030..e0fe8e9 100644
--- a/src/musig/musig.h
+++ b/src/musig/musig.h
@@ -1,7 +1,7 @@
#pragma once
-#include <stdint.h>
#include <stddef.h>
+#include <stdint.h>
#define MUSIG_PUBNONCE_SIZE 66
diff --git a/src/musig/musig_sessions.c b/src/musig/musig_sessions.c
index 33f24b3..9561da8 100644
--- a/src/musig/musig_sessions.c
+++ b/src/musig/musig_sessions.c
@@ -1,9 +1,12 @@
#include <string.h>
+#include "musig_sessions.h"
+
+/* SDK headers */
#include "cx.h"
-#include "musig_sessions.h"
-#include "../crypto.h"
+/* Local headers */
+#include "crypto.h"
typedef struct {
// Aligning by 4 is necessary due to platform limitations.
diff --git a/src/musig/musig_sessions.h b/src/musig/musig_sessions.h
index 01b6b3c..1ce3466 100644
--- a/src/musig/musig_sessions.h
+++ b/src/musig/musig_sessions.h
@@ -1,6 +1,9 @@
#pragma once
#include <stdbool.h>
+
+
+/* Local headers */
#include "musig.h"
/**
diff --git a/src/swap/bip32_path.c b/src/swap/bip32_path.c
index be272f4..64ed79d 100644
--- a/src/swap/bip32_path.c
+++ b/src/swap/bip32_path.c
@@ -1,7 +1,8 @@
#include "bip32_path.h"
-#include "../common/read.h"
+/* SDK headers */
+#include "read.h"
bool parse_serialized_path(bip32_path_t* path,
unsigned char* serialized_path,
diff --git a/src/swap/bip32_path.h b/src/swap/bip32_path.h
index 05a5b89..6e1b421 100644
--- a/src/swap/bip32_path.h
+++ b/src/swap/bip32_path.h
@@ -1,8 +1,10 @@
#pragma once
-#include "stdbool.h"
+#include <stdbool.h>
+
+/* SDK headers */
+#include "bip32.h"
-#define MAX_BIP32_PATH 10
#define MAX_BIP32_PATH_LENGTH (4 * MAX_BIP32_PATH) + 1
typedef struct bip32_path {
diff --git a/src/swap/handle_check_address.c b/src/swap/handle_check_address.c
index 21f23d2..733c2ed 100644
--- a/src/swap/handle_check_address.c
+++ b/src/swap/handle_check_address.c
@@ -1,12 +1,14 @@
#include <string.h>
-#include "os.h"
-
#include "handle_check_address.h"
+
+/* SDK headers */
#include "bip32_path.h"
+#include "os.h"
-#include "../common/segwit_addr.h"
-#include "../crypto.h"
+/* Local headers */
+#include "crypto.h"
+#include "segwit_addr.h"
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
diff --git a/src/swap/handle_check_address.h b/src/swap/handle_check_address.h
index ef717e9..457e763 100644
--- a/src/swap/handle_check_address.h
+++ b/src/swap/handle_check_address.h
@@ -1,5 +1,7 @@
#pragma once
+
+/* Local headers */
#include "swap_lib_calls.h"
int handle_check_address(check_address_parameters_t* check_address_params);
diff --git a/src/swap/handle_get_printable_amount.c b/src/swap/handle_get_printable_amount.c
index f77a1c7..75ca90b 100644
--- a/src/swap/handle_get_printable_amount.c
+++ b/src/swap/handle_get_printable_amount.c
@@ -1,7 +1,10 @@
+#include "handle_get_printable_amount.h"
+
+/* SDK headers */
#include "read.h"
+/* Local headers */
#include "display_utils.h"
-#include "handle_get_printable_amount.h"
#define MAX_NON_PRINTABLE_AMOUNT_LEN 8
diff --git a/src/swap/handle_get_printable_amount.h b/src/swap/handle_get_printable_amount.h
index a1a23f3..03b0e70 100644
--- a/src/swap/handle_get_printable_amount.h
+++ b/src/swap/handle_get_printable_amount.h
@@ -1,5 +1,7 @@
#pragma once
+
+/* Local headers */
#include "swap_lib_calls.h"
int handle_get_printable_amount(get_printable_amount_parameters_t* get_printable_amount_params);
\ No newline at end of file
diff --git a/src/swap/handle_swap_sign_transaction.c b/src/swap/handle_swap_sign_transaction.c
index f439ed5..cf5e134 100644
--- a/src/swap/handle_swap_sign_transaction.c
+++ b/src/swap/handle_swap_sign_transaction.c
@@ -1,15 +1,17 @@
#include <assert.h>
-#include "ux.h"
-#include "usbd_core.h"
-#include "os_io_seproxyhal.h"
-#include "os.h"
-
#include "handle_swap_sign_transaction.h"
-#include "../globals.h"
-#include "../swap/swap_globals.h"
-#include "../common/read.h"
+/* SDK headers */
+#include "os.h"
+#include "read.h"
+#include "ux.h"
+
+/* Local headers */
+#include "globals.h"
+#include "os_io_seproxyhal.h"
+#include "swap_globals.h"
+#include "usbd_core.h"
// Save the BSS address where we will write the return value when finished
static uint8_t* G_swap_sign_return_value_address;
diff --git a/src/swap/handle_swap_sign_transaction.h b/src/swap/handle_swap_sign_transaction.h
index bbd82b2..97e53ae 100644
--- a/src/swap/handle_swap_sign_transaction.h
+++ b/src/swap/handle_swap_sign_transaction.h
@@ -1,5 +1,7 @@
#pragma once
+
+/* Local headers */
#include "swap_lib_calls.h"
bool copy_transaction_parameters(create_transaction_parameters_t* sign_transaction_params);
diff --git a/src/swap/swap_lib_calls.h b/src/swap/swap_lib_calls.h
deleted file mode 100644
index dc88417..0000000
--- a/src/swap/swap_lib_calls.h
+++ /dev/null
@@ -1,80 +0,0 @@
-#pragma once
-
-/* This file is the shared API between Exchange and the apps started in Library mode for Exchange
- *
- * DO NOT MODIFY THIS FILE IN APPLICATIONS OTHER THAN EXCHANGE
- * On modification in Exchange, forward the changes to all applications supporting Exchange
- */
-
-#include "stdbool.h"
-#include "stdint.h"
-
-#define RUN_APPLICATION 1
-
-#define SIGN_TRANSACTION 2
-
-#define CHECK_ADDRESS 3
-
-#define GET_PRINTABLE_AMOUNT 4
-
-/*
- * Amounts are stored as bytes, with a max size of 16 (see protobuf
- * specifications). Max 16B integer is 340282366920938463463374607431768211455
- * in decimal, which is a 32-long char string.
- * The printable amount also contains spaces, the ticker symbol (with variable
- * size, up to 12 in Ethereum for instance) and a terminating null byte, so 50
- * bytes total should be a fair maximum.
- */
-#define MAX_PRINTABLE_AMOUNT_SIZE 50
-
-// structure that should be send to specific coin application to get address
-typedef struct check_address_parameters_s {
- // IN
- uint8_t *coin_configuration;
- uint8_t coin_configuration_length;
- // serialized path, segwit, version prefix, hash used, dictionary etc.
- // fields and serialization format depends on spesific coin app
- uint8_t *address_parameters;
- uint8_t address_parameters_length;
- char *address_to_check;
- char *extra_id_to_check;
- // OUT
- int result;
-} check_address_parameters_t;
-
-// structure that should be send to specific coin application to get printable amount
-typedef struct get_printable_amount_parameters_s {
- // IN
- uint8_t *coin_configuration;
- uint8_t coin_configuration_length;
- uint8_t *amount;
- uint8_t amount_length;
- bool is_fee;
- // OUT
- char printable_amount[MAX_PRINTABLE_AMOUNT_SIZE];
-} get_printable_amount_parameters_t;
-
-typedef struct create_transaction_parameters_s {
- // IN
- uint8_t *coin_configuration;
- uint8_t coin_configuration_length;
- uint8_t *amount;
- uint8_t amount_length;
- uint8_t *fee_amount;
- uint8_t fee_amount_length;
- char *destination_address;
- char *destination_address_extra_id;
- // OUT
- uint8_t result;
-} create_transaction_parameters_t;
-
-typedef struct libargs_s {
- unsigned int id;
- unsigned int command;
- unsigned int unused;
- union {
- check_address_parameters_t *check_address;
- create_transaction_parameters_t *create_transaction;
- get_printable_amount_parameters_t *get_printable_amount;
- };
-} libargs_t;
diff --git a/src/types.h b/src/types.h
index de3cbdc..6095dda 100644
--- a/src/types.h
+++ b/src/types.h
@@ -1,8 +1,11 @@
#pragma once
-#include <stddef.h> // size_t
-#include <stdint.h> // uint*_t
+#include <stddef.h>
+#include <stdint.h>
-#include "constants.h"
-#include "common/bip32.h"
+/* SDK headers */
+#include "bip32.h"
+
+/* Local headers */
#include "commands.h"
+#include "constants.h"
diff --git a/src/ui/display.c b/src/ui/display.c
index a00ba65..9feb7f5 100644
--- a/src/ui/display.c
+++ b/src/ui/display.c
@@ -1,16 +1,17 @@
#pragma GCC diagnostic ignored "-Wformat-invalid-specifier" // snprintf
#pragma GCC diagnostic ignored "-Wformat-extra-args" // snprintf
-#include <stdbool.h> // bool
-#include <stdio.h> // snprintf
-#include <string.h> // memset
+#include <stdbool.h>
#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include "display.h"
+
+/* SDK headers */
#include "os.h"
#include "ux.h"
-#include "./display.h"
-
// These globals are a workaround for a limitation of the UX library that
// does not allow to pass proper callbacks and context.
diff --git a/src/ui/display.h b/src/ui/display.h
index 0cbdc9b..c063af4 100644
--- a/src/ui/display.h
+++ b/src/ui/display.h
@@ -1,19 +1,21 @@
#pragma once
-#include <stdbool.h> // bool
-#include "../boilerplate/dispatcher.h"
-
-#include "../common/wallet.h"
-#include "./display.h"
-#include "./display_utils.h"
-#include "../constants.h"
-#include "../globals.h"
-#include "../boilerplate/io.h"
-#include "../boilerplate/sw.h"
-#include "../common/bip32.h"
-#include "../common/format.h"
-#include "../common/script.h"
-#include "../constants.h"
+#include <stdbool.h>
+
+/* SDK headers */
+#include "bip32.h"
+#include "format.h"
+
+/* Local headers */
+#include "constants.h"
+#include "dispatcher.h"
+#include "display.h"
+#include "display_utils.h"
+#include "globals.h"
+#include "io_ext.h"
+#include "script.h"
+#include "sw.h"
+#include "wallet.h"
#define MESSAGE_CHUNK_SIZE 64 // Protocol specific
// Displayed message length - if the message is too long we will not display it
diff --git a/src/ui/display_nbgl.c b/src/ui/display_nbgl.c
index c6f188e..00da4c1 100644
--- a/src/ui/display_nbgl.c
+++ b/src/ui/display_nbgl.c
@@ -1,11 +1,13 @@
+#include <assert.h>
#include <stdint.h>
+/* SDK headers */
#include "nbgl_use_case.h"
-#include "./display.h"
-#include "./menu.h"
-#include "io.h"
-#include <assert.h>
+/* Local headers */
+#include "display.h"
+#include "io_ext.h"
+#include "menu.h"
#define REVIEW_CONFIRM FIRST_USER_TOKEN + 1
diff --git a/src/ui/display_utils.c b/src/ui/display_utils.c
index b422153..2e4cc28 100644
--- a/src/ui/display_utils.c
+++ b/src/ui/display_utils.c
@@ -2,7 +2,7 @@
#include <stdio.h>
#include <string.h>
-#include "./display_utils.h"
+#include "display_utils.h"
static size_t n_digits(uint64_t number) {
size_t count = 0;
diff --git a/src/ui/display_utils.h b/src/ui/display_utils.h
index 4beb3bf..6d0da09 100644
--- a/src/ui/display_utils.h
+++ b/src/ui/display_utils.h
@@ -2,7 +2,9 @@
#include <stdint.h>
-#include "../constants.h"
+
+/* Local headers */
+#include "constants.h"
// up to 5 chars for ticker, 1 space, up to 20 digits (20 = digits of 2^64), + 1 decimal separator
#define MAX_AMOUNT_LENGTH (5 + 1 + 20 + 1)
diff --git a/src/ui/menu_nbgl.c b/src/ui/menu_nbgl.c
index f249a35..0e1d175 100644
--- a/src/ui/menu_nbgl.c
+++ b/src/ui/menu_nbgl.c
@@ -15,10 +15,13 @@
* limitations under the License.
*****************************************************************************/
+/* SDK headers */
+/* SDK headers */
#include "nbgl_use_case.h"
-#include "../globals.h"
-#include "./display.h"
+/* Local headers */
+#include "display.h"
+#include "globals.h"
#include "menu.h"
#define SETTING_INFO_NB 3
Why this scored 32/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.