Splitting up MAX_BIP388_XPUB_DERIVATION_STEPS and MAX_BIP32_PATH_STEPS
What changed, and why it matters
This commit renames and splits two related constants for Bitcoin derivation paths. Previously, the same limit was used both for wallet-policy xpub derivations and for full signing paths. The change gives xpub derivations their own smaller limit (8 steps) while keeping the full signing path limit at 10 steps (8 + 2 for change/address index). It also fixes a potential off-by-one check when parsing xpub derivations by changing '>' to '>='. Most of the file changes are cosmetic whitespace removals.
Treat as a defensive hardening/refactoring patch. Review whether any downstream code assumes MAX_BIP32_PATH_STEPS == MAX_BIP388_XPUB_DERIVATION_STEPS, and verify the static assert holds across SDK versions. No urgent action required absent additional vulnerability evidence.
Security signals we found
Off-by-one hardening in derivation-step parsing (wallet.c: '>' changed to '>=')
Separation of xpub derivation limit from full signing-path limit to reduce buffer sizing confusion
Static assertion tying MAX_BIP32_PATH_STEPS to SDK MAX_BIP32_PATH
Array size in wallet.h reduced from MAX_BIP32_PATH_STEPS to MAX_BIP388_XPUB_DERIVATION_STEPS
Evidence from the diff
The patch introduces MAX_BIP388_XPUB_DERIVATION_STEPS (8) separate from MAX_BIP32_PATH_STEPS (MAX_BIP388_XPUB_DERIVATION_STEPS + 2, asserted equal to SDK’s MAX_BIP32_PATH). It updates policy_map_key_info_t’s master_key_derivation array to use the new xpub limit and changes the loop guard in parse_policy_map_key_info from ‘>’ to ‘>=’ so that exceeding 8 steps is rejected before writing the 9th element. Swap code now uses MAX_BIP32_PATH_STEPS instead of the SDK’s MAX_BIP32_PATH directly. A static assert enforces the two constants stay in sync with the SDK.
Changed components
src/common/wallet.csrc/common/wallet.hsrc/constants.hsrc/swap/bip32_path.csrc/swap/bip32_path.hInspect captured patch +22 / −41
diff --git a/src/common/buffer_ext.c b/src/common/buffer_ext.c
index 05211f7..6344474 100644
--- a/src/common/buffer_ext.c
+++ b/src/common/buffer_ext.c
@@ -14,6 +14,11 @@
* limitations under the License.
*****************************************************************************/
+/*
+ * NOTE: The SDK's buffer_t type uses `const uint8_t *ptr` for both read and write.
+ * Write functions cast away const; callers must ensure underlying memory is mutable.
+ */
+
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
diff --git a/src/common/wallet.c b/src/common/wallet.c
index 56a9f63..a16a535 100644
--- a/src/common/wallet.c
+++ b/src/common/wallet.c
@@ -339,7 +339,7 @@ int parse_policy_map_key_info(buffer_t *buffer, policy_map_key_info_t *out, int
// read all the given derivation steps
out->master_key_derivation_len = 0;
while (consume_character(buffer, '/')) {
- if (out->master_key_derivation_len > MAX_BIP32_PATH_STEPS) {
+ if (out->master_key_derivation_len >= MAX_BIP388_XPUB_DERIVATION_STEPS) {
return WITH_ERROR(-1, "Too many derivation steps");
}
diff --git a/src/common/wallet.h b/src/common/wallet.h
index 605bcd0..1714805 100644
--- a/src/common/wallet.h
+++ b/src/common/wallet.h
@@ -88,7 +88,7 @@
#define MAX_TAPTREE_POLICY_DEPTH 9
typedef struct {
- uint32_t master_key_derivation[MAX_BIP32_PATH_STEPS];
+ uint32_t master_key_derivation[MAX_BIP388_XPUB_DERIVATION_STEPS];
uint8_t master_key_fingerprint[4];
uint8_t master_key_derivation_len;
uint8_t has_key_origin;
diff --git a/src/constants.h b/src/constants.h
index 352be68..a01c69f 100644
--- a/src/constants.h
+++ b/src/constants.h
@@ -95,16 +95,21 @@
#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.
+ * Maximum number of derivation steps for a wallet policy xpub (BIP-388).
+ */
+#define MAX_BIP388_XPUB_DERIVATION_STEPS 8
+
+/**
+ * Maximum number of derivation steps allowed for SIGN_PSBT operations,
+ * taking "/change/addr_index" steps into account.
*/
-#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)
+#define MAX_BIP32_PATH_STEPS (MAX_BIP388_XPUB_DERIVATION_STEPS + 2)
+/* Build-time check to ensure our constant matches the SDK's MAX_BIP32_PATH */
+_Static_assert(MAX_BIP32_PATH_STEPS == MAX_BIP32_PATH,
+ "MAX_BIP32_PATH_STEPS must equal MAX_BIP32_PATH from SDK");
/**
* Maximum length of a string representing a BIP32 derivation path.
diff --git a/src/debug-helpers/debug.c b/src/debug-helpers/debug.c
index 95db14d..f64245b 100644
--- a/src/debug-helpers/debug.c
+++ b/src/debug-helpers/debug.c
@@ -1,7 +1,6 @@
#include <stdarg.h>
#include <stdio.h>
-
/* Local headers */
#include "printf.h"
diff --git a/src/handler/get_master_fingerprint.c b/src/handler/get_master_fingerprint.c
index 2e18acc..5941bb6 100644
--- a/src/handler/get_master_fingerprint.c
+++ b/src/handler/get_master_fingerprint.c
@@ -17,7 +17,6 @@
#include <stdint.h>
-
/* Local headers */
#include "commands.h"
#include "crypto.h"
diff --git a/src/handler/handlers.h b/src/handler/handlers.h
index 5dbb536..4e302f2 100644
--- a/src/handler/handlers.h
+++ b/src/handler/handlers.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "dispatcher.h"
diff --git a/src/handler/lib/check_merkle_tree_sorted.h b/src/handler/lib/check_merkle_tree_sorted.h
index 38a79ca..234cc95 100644
--- a/src/handler/lib/check_merkle_tree_sorted.h
+++ b/src/handler/lib/check_merkle_tree_sorted.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "dispatcher.h"
#include "merkle.h"
diff --git a/src/handler/lib/get_merkle_leaf_element.h b/src/handler/lib/get_merkle_leaf_element.h
index 4979e7e..7212fe7 100644
--- a/src/handler/lib/get_merkle_leaf_element.h
+++ b/src/handler/lib/get_merkle_leaf_element.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "dispatcher.h"
diff --git a/src/handler/lib/get_merkle_leaf_hash.h b/src/handler/lib/get_merkle_leaf_hash.h
index f6f6962..6585e43 100644
--- a/src/handler/lib/get_merkle_leaf_hash.h
+++ b/src/handler/lib/get_merkle_leaf_hash.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "dispatcher.h"
diff --git a/src/handler/lib/get_merkle_leaf_index.c b/src/handler/lib/get_merkle_leaf_index.c
index c9086e9..8f220c6 100644
--- a/src/handler/lib/get_merkle_leaf_index.c
+++ b/src/handler/lib/get_merkle_leaf_index.c
@@ -1,6 +1,5 @@
#include <string.h>
-
/* Local headers */
#include "client_commands.h"
#include "get_merkle_leaf_hash.h"
diff --git a/src/handler/lib/get_merkle_leaf_index.h b/src/handler/lib/get_merkle_leaf_index.h
index 808e228..c14ea4e 100644
--- a/src/handler/lib/get_merkle_leaf_index.h
+++ b/src/handler/lib/get_merkle_leaf_index.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "dispatcher.h"
diff --git a/src/handler/lib/get_merkle_preimage.h b/src/handler/lib/get_merkle_preimage.h
index c1d3519..1bd457b 100644
--- a/src/handler/lib/get_merkle_preimage.h
+++ b/src/handler/lib/get_merkle_preimage.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "dispatcher.h"
diff --git a/src/handler/lib/get_merkleized_map.h b/src/handler/lib/get_merkleized_map.h
index 6e4119f..c7ddc01 100644
--- a/src/handler/lib/get_merkleized_map.h
+++ b/src/handler/lib/get_merkleized_map.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "check_merkle_tree_sorted.h"
#include "dispatcher.h"
diff --git a/src/handler/lib/get_merkleized_map_value_hash.h b/src/handler/lib/get_merkleized_map_value_hash.h
index 3213413..b3b42b3 100644
--- a/src/handler/lib/get_merkleized_map_value_hash.h
+++ b/src/handler/lib/get_merkleized_map_value_hash.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "dispatcher.h"
#include "merkle.h"
diff --git a/src/handler/lib/get_preimage.c b/src/handler/lib/get_preimage.c
index 733a7ae..aac7cf1 100644
--- a/src/handler/lib/get_preimage.c
+++ b/src/handler/lib/get_preimage.c
@@ -1,6 +1,5 @@
#include <string.h>
-
/* Local headers */
#include "buffer_ext.h"
#include "client_commands.h"
diff --git a/src/handler/lib/get_preimage.h b/src/handler/lib/get_preimage.h
index 627a5b4..1726c58 100644
--- a/src/handler/lib/get_preimage.h
+++ b/src/handler/lib/get_preimage.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "dispatcher.h"
diff --git a/src/handler/lib/policy.h b/src/handler/lib/policy.h
index b1c5a22..9e01cda 100644
--- a/src/handler/lib/policy.h
+++ b/src/handler/lib/policy.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "dispatcher.h"
#include "sign_psbt_cache.h"
diff --git a/src/handler/lib/psbt_parse_rawtx.h b/src/handler/lib/psbt_parse_rawtx.h
index daeb92f..dbd67e6 100644
--- a/src/handler/lib/psbt_parse_rawtx.h
+++ b/src/handler/lib/psbt_parse_rawtx.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "constants.h"
#include "dispatcher.h"
diff --git a/src/handler/lib/stream_merkle_leaf_element.h b/src/handler/lib/stream_merkle_leaf_element.h
index ba2872a..8704499 100644
--- a/src/handler/lib/stream_merkle_leaf_element.h
+++ b/src/handler/lib/stream_merkle_leaf_element.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "dispatcher.h"
#include "merkle.h"
diff --git a/src/handler/lib/stream_merkleized_map_value.h b/src/handler/lib/stream_merkleized_map_value.h
index 4c77954..d9dbf47 100644
--- a/src/handler/lib/stream_merkleized_map_value.h
+++ b/src/handler/lib/stream_merkleized_map_value.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "dispatcher.h"
#include "merkle.h"
diff --git a/src/handler/lib/stream_preimage.h b/src/handler/lib/stream_preimage.h
index fb9b28f..ac1cd0d 100644
--- a/src/handler/lib/stream_preimage.h
+++ b/src/handler/lib/stream_preimage.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "dispatcher.h"
diff --git a/src/handler/sign_psbt.h b/src/handler/sign_psbt.h
index 7ef9d00..d35b1f4 100644
--- a/src/handler/sign_psbt.h
+++ b/src/handler/sign_psbt.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "display.h"
#include "merkle.h"
diff --git a/src/handler/sign_psbt/amount_from_psbt.h b/src/handler/sign_psbt/amount_from_psbt.h
index aa578f3..98b4ccf 100644
--- a/src/handler/sign_psbt/amount_from_psbt.h
+++ b/src/handler/sign_psbt/amount_from_psbt.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "dispatcher.h"
#include "sign_psbt.h"
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 5b02ac3..146c80c 100644
--- a/src/handler/sign_psbt/compare_wallet_script_at_path.h
+++ b/src/handler/sign_psbt/compare_wallet_script_at_path.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "dispatcher.h"
#include "merkle.h"
diff --git a/src/handler/sign_psbt/musig_signing.h b/src/handler/sign_psbt/musig_signing.h
index 281be19..60fc35b 100644
--- a/src/handler/sign_psbt/musig_signing.h
+++ b/src/handler/sign_psbt/musig_signing.h
@@ -1,6 +1,5 @@
#include <stdint.h>
-
/* Local headers */
#include "dispatcher.h"
#include "musig.h"
diff --git a/src/handler/sign_psbt/sign_psbt_cache.h b/src/handler/sign_psbt/sign_psbt_cache.h
index b022a3e..1677858 100644
--- a/src/handler/sign_psbt/sign_psbt_cache.h
+++ b/src/handler/sign_psbt/sign_psbt_cache.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "crypto.h"
#include "wallet.h"
diff --git a/src/handler/sign_psbt/txhashes.h b/src/handler/sign_psbt/txhashes.h
index 61c5aec..5051ff5 100644
--- a/src/handler/sign_psbt/txhashes.h
+++ b/src/handler/sign_psbt/txhashes.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "dispatcher.h"
#include "sign_psbt.h"
diff --git a/src/musig/musig_sessions.h b/src/musig/musig_sessions.h
index 1ce3466..7d94e89 100644
--- a/src/musig/musig_sessions.h
+++ b/src/musig/musig_sessions.h
@@ -2,7 +2,6 @@
#include <stdbool.h>
-
/* Local headers */
#include "musig.h"
diff --git a/src/swap/bip32_path.c b/src/swap/bip32_path.c
index 64ed79d..2d08007 100644
--- a/src/swap/bip32_path.c
+++ b/src/swap/bip32_path.c
@@ -7,7 +7,7 @@
bool parse_serialized_path(bip32_path_t* path,
unsigned char* serialized_path,
unsigned char serialized_path_length) {
- if (serialized_path_length < 1 || serialized_path[0] > MAX_BIP32_PATH ||
+ if (serialized_path_length < 1 || serialized_path[0] > MAX_BIP32_PATH_STEPS ||
serialized_path[0] * 4 + 1 > serialized_path_length)
return false;
path->length = serialized_path[0];
diff --git a/src/swap/bip32_path.h b/src/swap/bip32_path.h
index 6e1b421..8abf7ad 100644
--- a/src/swap/bip32_path.h
+++ b/src/swap/bip32_path.h
@@ -4,12 +4,13 @@
/* SDK headers */
#include "bip32.h"
+#include "constants.h"
-#define MAX_BIP32_PATH_LENGTH (4 * MAX_BIP32_PATH) + 1
+#define MAX_BIP32_PATH_LENGTH (4 * MAX_BIP32_PATH_STEPS) + 1
typedef struct bip32_path {
unsigned char length;
- unsigned int path[MAX_BIP32_PATH];
+ unsigned int path[MAX_BIP32_PATH_STEPS];
} bip32_path_t;
bool parse_serialized_path(bip32_path_t* path,
diff --git a/src/swap/handle_check_address.h b/src/swap/handle_check_address.h
index 457e763..f022b89 100644
--- a/src/swap/handle_check_address.h
+++ b/src/swap/handle_check_address.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "swap_lib_calls.h"
diff --git a/src/swap/handle_get_printable_amount.h b/src/swap/handle_get_printable_amount.h
index 03b0e70..a3619a1 100644
--- a/src/swap/handle_get_printable_amount.h
+++ b/src/swap/handle_get_printable_amount.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "swap_lib_calls.h"
diff --git a/src/swap/handle_swap_sign_transaction.h b/src/swap/handle_swap_sign_transaction.h
index 97e53ae..9516ab6 100644
--- a/src/swap/handle_swap_sign_transaction.h
+++ b/src/swap/handle_swap_sign_transaction.h
@@ -1,6 +1,5 @@
#pragma once
-
/* Local headers */
#include "swap_lib_calls.h"
diff --git a/src/ui/display_utils.h b/src/ui/display_utils.h
index 6d0da09..087b445 100644
--- a/src/ui/display_utils.h
+++ b/src/ui/display_utils.h
@@ -2,7 +2,6 @@
#include <stdint.h>
-
/* Local headers */
#include "constants.h"
diff --git a/src/ui/menu_nbgl.c b/src/ui/menu_nbgl.c
index 0e1d175..7718a2e 100644
--- a/src/ui/menu_nbgl.c
+++ b/src/ui/menu_nbgl.c
@@ -15,7 +15,6 @@
* limitations under the License.
*****************************************************************************/
-/* SDK headers */
/* SDK headers */
#include "nbgl_use_case.h"
Why this scored 33/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.