What changed, and why it matters
This commit removes a small C wrapper file (salt.c/salt.h) and replaces its use with direct calls to an equivalent Rust function. The actual password-stretching and hashing logic is unchanged; it is only moved from one place in the code to another. There is no indication this fixes or introduces a security vulnerability.
No security action required. Treat as routine code cleanup. If reviewing, verify that rust_salt_hash_data enforces the same preconditions (non-null purpose/hash_out, data null only when data_len is zero) as the removed wrapper.
Security signals we found
Refactor only: function inlining with no semantic change to hashing/salting logic
Same purpose strings and 32-byte output buffers retained
No new input validation paths or memory handling introduced
No vendor mention of security relevance, CVE, or bug fix
Evidence from the diff
The change deletes the thin C wrapper salt_hash_data() and inlines calls to rust_salt_hash_data() in atecc.c and optiga.c. The wrapper previously validated non-null pointers and then called the Rust function with rust_util_bytes()/rust_util_bytes_mut(). The new call sites perform the same validation implicitly through the Rust Bytes/BytesMut helpers and use the same purpose strings and 32-byte output buffers. Test fakes and linker wraps are updated accordingly. No cryptographic algorithm, salt handling, or password flow is altered.
Changed components
src/salt.csrc/salt.hsrc/atecc/atecc.csrc/optiga/optiga.ctest/hardware-fakes/src/fake_securechip.ctest/unit-test/test_optiga.cInspect captured patch +49 / −91
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d4217e1..c50128d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -18,7 +18,6 @@ set(DBB-FIRMWARE-SOURCES
${CMAKE_SOURCE_DIR}/src/memory/spi_mem.c
${CMAKE_SOURCE_DIR}/src/memory/memory_spi.c
${CMAKE_SOURCE_DIR}/src/memory/smarteeprom.c
- ${CMAKE_SOURCE_DIR}/src/salt.c
${CMAKE_SOURCE_DIR}/src/i2c_ecc.c
${CMAKE_SOURCE_DIR}/src/touch/gestures.c
${CMAKE_SOURCE_DIR}/src/reset.c
diff --git a/src/atecc/atecc.c b/src/atecc/atecc.c
index 905d6d0..b43011d 100644
--- a/src/atecc/atecc.c
+++ b/src/atecc/atecc.c
@@ -6,7 +6,6 @@
#include <i2c_ecc.h>
#include <memory/memory.h>
#include <rust/rust.h>
-#include <salt.h>
#include <util.h>
// disabling some warnings, as it's an external library.
@@ -599,11 +598,10 @@ int atecc_stretch_password(
uint8_t password_salted_hashed[32] = {0};
UTIL_CLEANUP_32(password_salted_hashed);
- if (!salt_hash_data(
- (const uint8_t*)password,
- strlen(password),
+ if (!rust_salt_hash_data(
+ rust_util_bytes((const uint8_t*)password, strlen(password)),
"keystore_seed_access_in",
- password_salted_hashed)) {
+ rust_util_bytes_mut(password_salted_hashed, sizeof(password_salted_hashed)))) {
return SC_ERR_SALT;
}
@@ -625,11 +623,10 @@ int atecc_stretch_password(
}
}
- if (!salt_hash_data(
- (const uint8_t*)password,
- strlen(password),
+ if (!rust_salt_hash_data(
+ rust_util_bytes((const uint8_t*)password, strlen(password)),
"keystore_seed_access_out",
- password_salted_hashed)) {
+ rust_util_bytes_mut(password_salted_hashed, sizeof(password_salted_hashed)))) {
return SC_ERR_SALT;
}
rust_hmac_sha256(
diff --git a/src/optiga/optiga.c b/src/optiga/optiga.c
index 883e99b..7e93f26 100644
--- a/src/optiga/optiga.c
+++ b/src/optiga/optiga.c
@@ -14,7 +14,6 @@
#include <optiga_crypt.h>
#include <optiga_util.h>
#include <rust/rust.h>
-#include <salt.h>
#include <securechip/securechip.h>
#include <util.h>
@@ -1137,8 +1136,11 @@ static int _set_password(
goto cleanup;
}
- if (!salt_hash_data(
- auth_password, auth_password_len, "optiga_password", auth_password_salted_hashed)) {
+ if (!rust_salt_hash_data(
+ rust_util_bytes(auth_password, auth_password_len),
+ "optiga_password",
+ rust_util_bytes_mut(
+ auth_password_salted_hashed, sizeof(auth_password_salted_hashed)))) {
res = SC_ERR_SALT;
goto cleanup;
}
@@ -1234,8 +1236,11 @@ static int _set_hmac_writeprotected(
{
uint8_t auth_password_salted_hashed[32] = {0};
UTIL_CLEANUP_32(auth_password_salted_hashed);
- if (!salt_hash_data(
- auth_password, auth_password_len, "optiga_password", auth_password_salted_hashed)) {
+ if (!rust_salt_hash_data(
+ rust_util_bytes(auth_password, auth_password_len),
+ "optiga_password",
+ rust_util_bytes_mut(
+ auth_password_salted_hashed, sizeof(auth_password_salted_hashed)))) {
return SC_ERR_SALT;
}
@@ -1270,11 +1275,10 @@ static int _v1_get_auth_password(
{
uint8_t password_salted_hashed[32] = {0};
UTIL_CLEANUP_32(password_salted_hashed);
- if (!salt_hash_data(
- (const uint8_t*)password,
- strlen(password),
+ if (!rust_salt_hash_data(
+ rust_util_bytes((const uint8_t*)password, strlen(password)),
"optiga_password_stretch_in",
- password_salted_hashed)) {
+ rust_util_bytes_mut(password_salted_hashed, sizeof(password_salted_hashed)))) {
return SC_ERR_SALT;
}
@@ -1315,11 +1319,10 @@ static int _v1_combine(
uint8_t password_salted_hashed[32] = {0};
UTIL_CLEANUP_32(password_salted_hashed);
- if (!salt_hash_data(
- (const uint8_t*)password,
- strlen(password),
+ if (!rust_salt_hash_data(
+ rust_util_bytes((const uint8_t*)password, strlen(password)),
"optiga_password_stretch_out",
- password_salted_hashed)) {
+ rust_util_bytes_mut(password_salted_hashed, sizeof(password_salted_hashed)))) {
return SC_ERR_SALT;
}
rust_hmac_sha256(
@@ -1414,11 +1417,10 @@ static int _optiga_verify_password_v0(const char* password, uint8_t* password_se
{
uint8_t password_salted_hashed[32] = {0};
UTIL_CLEANUP_32(password_salted_hashed);
- if (!salt_hash_data(
- (const uint8_t*)password,
- strlen(password),
+ if (!rust_salt_hash_data(
+ rust_util_bytes((const uint8_t*)password, strlen(password)),
"optiga_password",
- password_salted_hashed)) {
+ rust_util_bytes_mut(password_salted_hashed, sizeof(password_salted_hashed)))) {
return SC_ERR_SALT;
}
@@ -1467,7 +1469,11 @@ static int _optiga_verify_password_v1(const uint8_t* auth_password, uint8_t* pas
{
uint8_t auth_password_salted_hashed[32] = {0};
UTIL_CLEANUP_32(auth_password_salted_hashed);
- if (!salt_hash_data(auth_password, 32, "optiga_password", auth_password_salted_hashed)) {
+ if (!rust_salt_hash_data(
+ rust_util_bytes(auth_password, 32),
+ "optiga_password",
+ rust_util_bytes_mut(
+ auth_password_salted_hashed, sizeof(auth_password_salted_hashed)))) {
return SC_ERR_SALT;
}
@@ -1713,11 +1719,10 @@ static int _stretch_password_v0(const char* password, uint8_t* stretched_out)
{
uint8_t password_salted_hashed[32] = {0};
UTIL_CLEANUP_32(password_salted_hashed);
- if (!salt_hash_data(
- (const uint8_t*)password,
- strlen(password),
+ if (!rust_salt_hash_data(
+ rust_util_bytes((const uint8_t*)password, strlen(password)),
"optiga_password_stretch_in",
- password_salted_hashed)) {
+ rust_util_bytes_mut(password_salted_hashed, sizeof(password_salted_hashed)))) {
return SC_ERR_SALT;
}
@@ -1753,11 +1758,10 @@ static int _stretch_password_v0(const char* password, uint8_t* stretched_out)
rust_hmac_sha256(password_secret, sizeof(password_secret), stretched_out, 32, stretched_out);
- if (!salt_hash_data(
- (const uint8_t*)password,
- strlen(password),
+ if (!rust_salt_hash_data(
+ rust_util_bytes((const uint8_t*)password, strlen(password)),
"optiga_password_stretch_out",
- password_salted_hashed)) {
+ rust_util_bytes_mut(password_salted_hashed, sizeof(password_salted_hashed)))) {
return SC_ERR_SALT;
}
rust_hmac_sha256(
diff --git a/src/rust/bitbox02-sys/build.rs b/src/rust/bitbox02-sys/build.rs
index f968142..99bd089 100644
--- a/src/rust/bitbox02-sys/build.rs
+++ b/src/rust/bitbox02-sys/build.rs
@@ -227,7 +227,6 @@ const BITBOX02_SOURCES: &[&str] = &[
"src/queue.c",
"src/random.c",
"src/reset.c",
- "src/salt.c",
"src/screen.c",
"src/sd.c",
"src/system.c",
diff --git a/src/salt.c b/src/salt.c
deleted file mode 100644
index 6f60bd9..0000000
--- a/src/salt.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-#include "salt.h"
-#include "memory/memory.h"
-#include "util.h"
-#include <rust/rust.h>
-
-#include <string.h>
-
-bool salt_hash_data(const uint8_t* data, size_t data_len, const char* purpose, uint8_t* hash_out)
-{
- if ((data_len > 0 && data == NULL) || purpose == NULL || hash_out == NULL) {
- return false;
- }
- return rust_salt_hash_data(
- rust_util_bytes(data, data_len), purpose, rust_util_bytes_mut(hash_out, 32));
-}
diff --git a/src/salt.h b/src/salt.h
deleted file mode 100644
index 4f39e22..0000000
--- a/src/salt.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-#ifndef _SALT_H_
-#define _SALT_H_
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-/**
- * Creates sha256(<salt root><purpose><data>), where <salt root> is a persisted salt (static until
- * device reset).
- * @param[in] data data to salt and hash.
- * @param[in] purpose a string which is part of the hash, to put a namespace on the use.
- * @param[out] hash_out must be 32 bytes.
- * @return false if the salt root could not be retrieved.
- */
-bool salt_hash_data(const uint8_t* data, size_t data_len, const char* purpose, uint8_t* hash_out);
-
-#endif
diff --git a/test/hardware-fakes/src/fake_securechip.c b/test/hardware-fakes/src/fake_securechip.c
index e24272e..0591b7e 100644
--- a/test/hardware-fakes/src/fake_securechip.c
+++ b/test/hardware-fakes/src/fake_securechip.c
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
#include <rust/rust.h>
-#include <salt.h>
#include <securechip/securechip.h>
#include <stdio.h>
#include <string.h>
diff --git a/test/unit-test/CMakeLists.txt b/test/unit-test/CMakeLists.txt
index a662483..ae3a3ba 100644
--- a/test/unit-test/CMakeLists.txt
+++ b/test/unit-test/CMakeLists.txt
@@ -36,7 +36,7 @@ else()
random
"-Wl,--wrap=rand,--wrap=rust_sha256"
optiga
- "-Wl,--wrap=salt_hash_data"
+ "-Wl,--wrap=rust_salt_hash_data"
ui_components
""
ui_util
diff --git a/test/unit-test/test_optiga.c b/test/unit-test/test_optiga.c
index ed27873..69293eb 100644
--- a/test/unit-test/test_optiga.c
+++ b/test/unit-test/test_optiga.c
@@ -15,7 +15,6 @@
#include <optiga_util.h>
#include <pal/pal_os_timer.h>
#include <rust/rust.h>
-#include <salt.h>
#include <stdint.h>
#include <string.h>
@@ -173,26 +172,18 @@ static const securechip_interface_functions_t _ifs = {
};
//------------------------------------------------------------------------------
-// Linker-wrapped salt_hash_data: same as salt.rs, but with a fixed salt_root.
+// Linker-wrapped rust_salt_hash_data: same as salt.rs, but with a fixed salt_root.
-bool __wrap_salt_hash_data(
- const uint8_t* data,
- size_t data_len,
- const char* purpose,
- uint8_t* hash_out)
+bool __wrap_rust_salt_hash_data(struct Bytes data, const char* purpose, struct BytesMut hash_out)
{
- if ((data_len > 0 && data == NULL) || purpose == NULL || hash_out == NULL) {
- return false;
- }
-
void* ctx = rust_sha256_new();
if (ctx == NULL) {
return false;
}
rust_sha256_update(ctx, _salt_root_fixed, sizeof(_salt_root_fixed));
rust_sha256_update(ctx, purpose, strlen(purpose));
- rust_sha256_update(ctx, data, data_len);
- rust_sha256_finish(&ctx, hash_out);
+ rust_sha256_update(ctx, data.buf, data.len);
+ rust_sha256_finish(&ctx, hash_out.buf);
return true;
}
@@ -753,7 +744,10 @@ static void test_optiga_stretch_password_v0_success(void** state)
_setup_test();
// Seed the OID_PASSWORD and OID_PASSWORD_COUNTER objects as if they were provisioned earlier.
- assert_true(salt_hash_data((const uint8_t*)"pw", 2, "optiga_password", _oid_password));
+ assert_true(rust_salt_hash_data(
+ rust_util_bytes((const uint8_t*)"pw", 2),
+ "optiga_password",
+ rust_util_bytes_mut(_oid_password, sizeof(_oid_password))));
_oid_password_set = true;
const uint8_t counter_reset_buf[8] = {0, 0, 0, 0, 0, 0, 0, SMALL_MONOTONIC_COUNTER_MAX_USE};
memcpy(_oid_counter_password_buf, counter_reset_buf, sizeof(_oid_counter_password_buf));
@@ -774,7 +768,10 @@ static void test_optiga_stretch_password_v0_attempt_counter(void** state)
_setup_test();
// Seed the OID_PASSWORD and OID_PASSWORD_COUNTER objects as if they were provisioned earlier.
- assert_true(salt_hash_data((const uint8_t*)"pw", 2, "optiga_password", _oid_password));
+ assert_true(rust_salt_hash_data(
+ rust_util_bytes((const uint8_t*)"pw", 2),
+ "optiga_password",
+ rust_util_bytes_mut(_oid_password, sizeof(_oid_password))));
_oid_password_set = true;
const uint8_t counter_reset_buf[8] = {0, 0, 0, 0, 0, 0, 0, SMALL_MONOTONIC_COUNTER_MAX_USE};
memcpy(_oid_counter_password_buf, counter_reset_buf, sizeof(_oid_counter_password_buf));
Why this scored 17/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.