external: add and use secp256k1-zkp directly, remove libwally-core
What changed, and why it matters
This commit swaps out an internal cryptographic library dependency. The firmware previously used a library called libwally-core, which bundled a special version of the secp256k1 elliptic-curve code. The change removes libwally-core and uses secp256k1-zkp directly. This is a build-system and dependency refactor, not a fix for a known attack. It slightly reduces firmware size and changes how the code is compiled and linked. There is no direct evidence in the commit that this resolves a security vulnerability, but any change to core crypto code carries a small risk that build settings could alter behavior.
Treat this as a routine dependency refactor with low security urgency. Verify that the new secp256k1-zkp build options preserve the intended memory/performance trade-offs and that no libwally-core-specific functionality was silently lost. Run the existing cryptographic test suite and firmware integration tests. If a security advisory is later published for libwally-core or the old bundled secp256k1, reassess.
Security signals we found
Change to core elliptic-curve cryptography dependency (secp256k1)
Build configuration changes for secp256k1-zkp (ecmult window size, gen precision bits, module recovery)
Removal of libwally-core wrapper, which may have provided additional abstraction or hardening
No explicit security bug, CVE, or vulnerability description in commit or references
Evidence from the diff
The commit removes the external/libwally-core Git submodule and adds external/secp256k1-zkp as a direct submodule. It replaces the autotools-based ExternalProject build of libwally-core with a CMake add_subdirectory() build of secp256k1-zkp. Key configuration changes include setting SECP256K1_ENABLE_MODULE_RECOVERY ON, SECP256K1_ECMULT_WINDOW_SIZE=2, and SECP256K1_ECMULT_GEN_PREC_BITS=2, suppressing warnings with -w, and forcing BUILD_SHARED_LIBS OFF. Link targets are updated to drop wallycore and link only secp256k1, and include paths are updated from libwally-core/src/secp256k1/include to external/secp256k1-zkp/include. The commit message frames this as a size-reduction and dependency-simplification change (~6.4 kB saved).
Changed components
external/CMakeLists.txtsrc/CMakeLists.txtsrc/rust/bitbox02-sys/build.rstest/hardware-fakes/CMakeLists.txtexternal/secp256k1-zkp (new submodule)external/libwally-core (removed submodule)Inspect captured patch +23 / −75
diff --git a/.gitmodules b/.gitmodules
index 828fd9d..1f05a5c 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,9 +1,6 @@
[submodule "external/cryptoauthlib"]
path = external/cryptoauthlib
url = https://github.com/BitBoxSwiss/cryptoauthlib.git
-[submodule "external/libwally-core"]
- path = external/libwally-core
- url = https://github.com/BitBoxSwiss/libwally-core.git
[submodule "tools/ttf2ugui"]
path = tools/ttf2ugui
url = https://github.com/BitBoxSwiss/ttf2ugui
@@ -13,3 +10,6 @@
[submodule "external/embedded-swd"]
path = external/embedded-swd
url = https://github.com/BitBoxSwiss/embedded-swd
+[submodule "external/secp256k1-zkp"]
+ path = external/secp256k1-zkp
+ url = https://github.com/BitBoxSwiss/secp256k1-zkp.git
diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt
index 0299703..ee7e6d5 100644
--- a/external/CMakeLists.txt
+++ b/external/CMakeLists.txt
@@ -1,5 +1,9 @@
include(ExternalProject)
+# Tell `add_library()` to default to STATIC.
+# Needed because secp256k1-zkp/CMakeLists.txt sets it to ON.
+set(BUILD_SHARED_LIBS OFF)
+
if(CMAKE_CROSSCOMPILING)
set(CONFIGURE_FLAGS
--host=${CMAKE_SYSTEM_PROCESSOR}-none-eabi
@@ -14,71 +18,19 @@ string(REPLACE "-mfloat-abi=softfp" "" MODIFIED_C_FLAGS_TMP ${CMAKE_C_FLAGS})
string(REPLACE "-mfpu=fpv4-sp-d16" "" MODIFIED_C_FLAGS ${MODIFIED_C_FLAGS_TMP})
#----------------------
-# wally-core
-
-# configure flags for secp256k1 bundled in libwally core, to reduce memory consumption
-set(LIBWALLY_SECP256k1_FLAGS --with-ecmult-window=2 --with-ecmult-gen-precision=2 --enable-ecmult-static-precomputation --enable-module-schnorrsig --enable-module-ecdsa-adaptor)
-set(LIBWALLY_CONFIGURE_FLAGS --enable-static --disable-shared --disable-tests ${LIBWALLY_SECP256k1_FLAGS})
-if(SANITIZE_ADDRESS)
- set(LIBWALLY_CFLAGS "-fsanitize=address")
-endif()
-if(SANITIZE_UNDEFINED)
- set(LIBWALLY_CFLAGS "${LIBWALLY_CFLAGS} -fsanitize=undefined")
-endif()
-# _DEFAULT_SOURCE enables the BSD explicit_bzero function referenced by libwally.
-set(LIBWALLY_CFLAGS "\
- ${LIBWALLY_CFLAGS} \
- ${MODIFIED_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE}} \
- -D_DEFAULT_SOURCE \
- -fno-strict-aliasing \
-")
-if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
- string(APPEND LIBWALLY_CFLAGS " -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
-endif()
-# Hide some warnings
-set(LIBWALLY_CFLAGS "${LIBWALLY_CFLAGS} -Wno-cast-qual -Wno-cast-align \
- -Wno-missing-prototypes -Wno-redundant-decls \
- -Wno-switch-default -Wno-missing-declarations \
- -Wno-array-bounds -Wno-unused-label -Wno-sign-compare -Wno-type-limits \
-")
-if(CMAKE_CROSSCOMPILING)
- set(LIBWALLY_LDFLAGS --specs=nosys.specs)
-endif()
-set(LIBWALLY_LDFLAGS "${LIBWALLY_LDFLAGS} ${CMAKE_C_LINK_FLAGS}")
+## secp256k1-zkp
-ExternalProject_Add(libwally-core
- PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libwally-core
- STEP_TARGETS build-libwally
- SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libwally-core
- CONFIGURE_COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_CURRENT_SOURCE_DIR}/libwally-core tools/autogen.sh
- COMMAND ${CMAKE_COMMAND} -E env
- "CFLAGS=${LIBWALLY_CFLAGS}"
- "LDFLAGS=${LIBWALLY_LDFLAGS}"
- ${CMAKE_CURRENT_SOURCE_DIR}/libwally-core/configure
- ${CONFIGURE_FLAGS}
- ${LIBWALLY_CONFIGURE_FLAGS}
- INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}
- COMMAND ${CMAKE_COMMAND} -E copy
- ${CMAKE_CURRENT_BINARY_DIR}/libwally-core/src/libwally-core-build/src/.libs/libwallycore.a
- ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libwallycore.a
- COMMAND ${CMAKE_COMMAND} -E copy
- ${CMAKE_CURRENT_BINARY_DIR}/libwally-core/src/libwally-core-build/src/secp256k1/.libs/libsecp256k1.a
- ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libsecp256k1.a
+# Override
+set(SECP256K1_ENABLE_MODULE_RECOVERY ON) # needed only in Rust unit tests.
+set(SECP256K1_ECMULT_WINDOW_SIZE 2 CACHE STRING "Window size for ecmult precomputation for verification, specified as integer in range [2..24]. \"AUTO\" is a reasonable setting for desktop machines (currently 15). [default=AUTO]" FORCE)
+set(SECP256K1_ECMULT_GEN_PREC_BITS 2 CACHE STRING "Precision bits to tune the precomputed table size for signing, specified as integer 2, 4 or 8. \"AUTO\" is a reasonable setting for desktop machines (currently 4). [default=AUTO]" FORCE)
+# Suppress all warnings in this directory, we don't have control over them.
+set_directory_properties(PROPERTIES
+ COMPILE_OPTIONS "-w"
+ DIRECTORY secp256k1-zkp
)
-
-add_library(wallycore STATIC IMPORTED GLOBAL)
-set_property(TARGET wallycore
- PROPERTY IMPORTED_LOCATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libwallycore.a)
-set_target_properties(wallycore PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/libwally-core/include)
-set_target_properties(wallycore PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/libwally-core/include)
-
-add_library(secp256k1 STATIC IMPORTED GLOBAL)
-set_property(TARGET secp256k1
- PROPERTY IMPORTED_LOCATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libsecp256k1.a)
-set_target_properties(secp256k1 PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/libwally-core/src/secp256k1/include)
-set_target_properties(secp256k1 PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/libwally-core/src/secp256k1/include)
-
+add_subdirectory(secp256k1-zkp)
if(CMAKE_CROSSCOMPILING)
# Cortex Microcontroller Software Interface Standard
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 539130a..a592518 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -235,7 +235,7 @@ else()
set(RUSTFLAGS "--remap-path-prefix=${CMAKE_CURRENT_SOURCE_DIR}/rust=src --remap-path-prefix=$ENV{HOME}=")
endif()
-# Use libsecp256k1 that we link ourselves (included via external/libwally-core).
+# Use libsecp256k1 that we link ourselves.
# See https://github.com/rust-bitcoin/rust-secp256k1/tree/7c8270a8506e31731e540fab7ee1abde1f48314e/secp256k1-sys#linking-to-external-symbols
set(RUSTFLAGS "${RUSTFLAGS} --cfg=rust_secp_no_symbol_renaming")
@@ -277,7 +277,7 @@ add_custom_target(rust-cbindgen
# Test rust crates that contain business logic. Avoid testing crates that depend on hardware.
if(NOT CMAKE_CROSSCOMPILING)
- set(RUSTFLAGS_TESTS ${RUSTFLAGS} -L${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} -lbitbox_merged -lwallycore -lsecp256k1 -lfatfs -lhardware-fakes)
+ set(RUSTFLAGS_TESTS ${RUSTFLAGS} -L${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} -lbitbox_merged -lsecp256k1 -lfatfs -lhardware-fakes)
# Since we build with all features we need to use a separate build directory.
# Otherwise we invalidate the result from the normal compilation that uses a
@@ -293,7 +293,7 @@ if(NOT CMAKE_CROSSCOMPILING)
${CARGO} test $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:-v> --all-features --target-dir ${RUST_BINARY_DIR}/all-features ${RUST_CARGO_FLAGS} -- --nocapture --test-threads 1
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/rust/
)
- add_dependencies(rust-test generate-protobufs bitbox_merged libwally-core fatfs)
+ add_dependencies(rust-test generate-protobufs bitbox_merged fatfs)
add_custom_target(rust-clippy
COMMAND
@@ -520,8 +520,7 @@ if(CMAKE_CROSSCOMPILING)
target_link_libraries(${elf} PRIVATE "-Wl,-Map=\"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${firmware}.map\" -T\"${CMAKE_SOURCE_DIR}/firmware.ld\"")
target_link_libraries(${elf} PRIVATE -Wl,--defsym=STACK_SIZE=${STACK_SIZE} -Wl,-defsym=HEAP_SIZE=${HEAP_SIZE})
- add_dependencies(${elf} libwally-core)
- target_link_libraries(${elf} PRIVATE wallycore secp256k1)
+ target_link_libraries(${elf} PRIVATE secp256k1)
target_link_libraries(${elf} PRIVATE ${QTOUCHLIB_A} ${QTOUCHLIB_B} ${QTOUCHLIB_T})
# Select the smaller version of libc called nano.
diff --git a/src/rust/bitbox02-sys/build.rs b/src/rust/bitbox02-sys/build.rs
index 550f5f7..b5ae6a5 100644
--- a/src/rust/bitbox02-sys/build.rs
+++ b/src/rust/bitbox02-sys/build.rs
@@ -213,7 +213,7 @@ pub fn main() -> Result<(), &'static str> {
"../../usb/class/hid/hww",
"../../usb/class/hid/u2f",
// $SECP256k1_INCLUDES
- "../../../external/libwally-core/src/secp256k1/include",
+ "../../../external/secp256k1-zkp/include",
];
if cross_compiling {
diff --git a/test/hardware-fakes/CMakeLists.txt b/test/hardware-fakes/CMakeLists.txt
index de44e2f..7ab6d67 100644
--- a/test/hardware-fakes/CMakeLists.txt
+++ b/test/hardware-fakes/CMakeLists.txt
@@ -55,11 +55,8 @@ target_include_directories(
${INCLUDES}
${CMAKE_BINARY_DIR}/src
$<TARGET_PROPERTY:fatfs,INTERFACE_INCLUDE_DIRECTORIES>
- $<TARGET_PROPERTY:wallycore,INTERFACE_INCLUDE_DIRECTORIES>
)
-target_link_libraries(hardware-fakes PUBLIC wallycore)
-
if(SANITIZE_ADDRESS)
target_compile_options(hardware-fakes PUBLIC "-fsanitize=address")
endif()
Why this scored 13/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.