da14531: switch C to Rust API and clean up
What changed, and why it matters
This commit is a routine code cleanup: it removes several C functions that control the Bluetooth chip and replaces their use with equivalent Rust functions. There is no indication in the commit itself that this fixes a security bug or introduces a vulnerability. It is a refactoring change.
No security action required. Treat as normal refactoring; verify the new Rust implementations provide equivalent behavior and bounds checking in a separate review if desired.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch deletes the C implementations of da14531_reset, da14531_power_down, da14531_set_product, da14531_set_name, and da14531_get_connection_state from src/da14531/da14531.c and removes their declarations from da14531.h. All call sites are updated to use new Rust wrappers (rust_da14531_*), passing a RustUtilBytes struct instead of raw pointer/length pairs. The build.rs allowlist is updated to drop the removed C symbols. The change is purely an API migration and cleanup.
Changed components
src/da14531/da14531.csrc/da14531/da14531.hsrc/da14531/da14531_handler.csrc/bootloader/bootloader.csrc/bootloader/startup.csrc/factorysetup.csrc/reset.csrc/system.csrc/rust/bitbox02-sys/build.rsInspect captured patch +13 / −119
diff --git a/src/bootloader/bootloader.c b/src/bootloader/bootloader.c
index 3d27134..1455158 100644
--- a/src/bootloader/bootloader.c
+++ b/src/bootloader/bootloader.c
@@ -890,7 +890,7 @@ static size_t _api_command(const uint8_t* input, uint8_t* output, const size_t m
case OP_REBOOT: {
#if PLATFORM_BITBOX02PLUS == 1
- da14531_set_product(NULL, 0, uart_write_queue);
+ rust_da14531_set_product(rust_util_bytes(NULL, 0), uart_write_queue);
// Send it now, because we are about to reset ourselves
while (rust_bytequeue_num(uart_write_queue)) {
uart_poll(NULL, 0, NULL, uart_write_queue);
diff --git a/src/bootloader/startup.c b/src/bootloader/startup.c
index b3a739c..71dbca6 100644
--- a/src/bootloader/startup.c
+++ b/src/bootloader/startup.c
@@ -93,17 +93,18 @@ int main(void)
size_t product_len;
da14531_handler_current_product = (const uint8_t*)platform_product(&product_len);
da14531_handler_current_product_len = product_len;
- da14531_set_product(
- da14531_handler_current_product, da14531_handler_current_product_len, uart_write_queue);
+ rust_da14531_set_product(
+ rust_util_bytes(da14531_handler_current_product, da14531_handler_current_product_len),
+ uart_write_queue);
// Set device name, the MCU and BLE chip will probably not have the same name after a reset of
// only the MCU.
char buf[MEMORY_DEVICE_MAX_LEN_WITH_NULL] = {0};
memory_random_name(buf);
- da14531_set_name(buf, uart_write_queue);
+ rust_da14531_set_name(rust_util_bytes((const uint8_t*)buf, strlen(buf)), uart_write_queue);
// Ask for the current conection state
- da14531_get_connection_state(uart_write_queue);
+ rust_da14531_get_connection_state(uart_write_queue);
da14531_protocol_init();
#endif
@@ -129,7 +130,7 @@ int main(void)
#if PLATFORM_BITBOX02PLUS == 1
if (rust_communication_mode_ble_enabled()) {
// Enqueue a power down command to the da14531
- da14531_power_down(uart_write_queue);
+ rust_da14531_power_down(uart_write_queue);
// Flush out the power down command. This will be the last UART communication we do.
while (rust_bytequeue_num(uart_write_queue) > 0) {
uart_poll(NULL, 0, NULL, uart_write_queue);
diff --git a/src/da14531/da14531.c b/src/da14531/da14531.c
index cd54505..c044690 100644
--- a/src/da14531/da14531.c
+++ b/src/da14531/da14531.c
@@ -1,91 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
#include "da14531.h"
-#include "da14531_protocol.h"
-#include "hardfault.h"
-#include "util.h"
-#include <rust/rust.h>
-#include <utils_assert.h>
enum da14531_connected_state da14531_connected_state = DA14531_CONNECTED_ADVERTISING;
-
-void da14531_reset(struct RustByteQueue* uart_out)
-{
- util_log("da14531_reset");
- uint8_t payload = CTRL_CMD_BLE_CHIP_RESET;
- uint8_t buf[12 + sizeof(payload) * 2] = {0};
- uint16_t len = da14531_protocol_format(
- &buf[0], sizeof(buf), DA14531_PROTOCOL_PACKET_TYPE_CTRL_DATA, &payload, 1);
- ASSERT(len <= sizeof(buf));
- for (int i = 0; i < len; i++) {
- rust_bytequeue_put(uart_out, buf[i]);
- }
-}
-
-void da14531_power_down(struct RustByteQueue* uart_out)
-{
- util_log("da14531_power_down");
- uint8_t payload[2] = {CTRL_CMD_BLE_POWER_DOWN, 0};
- uint8_t buf[12 + sizeof(payload) * 2] = {0};
- uint16_t len = da14531_protocol_format(
- &buf[0], sizeof(buf), DA14531_PROTOCOL_PACKET_TYPE_CTRL_DATA, &payload[0], sizeof(payload));
- ASSERT(len <= sizeof(buf));
- for (int i = 0; i < len; i++) {
- rust_bytequeue_put(uart_out, buf[i]);
- }
-}
-
-void da14531_set_product(
- volatile const uint8_t* product,
- volatile uint16_t product_len,
- struct RustByteQueue* uart_out)
-{
- uint8_t payload[64] = {0};
- if (product_len > sizeof(payload) - 1) {
- Abort("product string too large");
- return;
- }
- payload[0] = CTRL_CMD_PRODUCT_STRING;
- for (int i = 0; i < product_len; i++) {
- payload[1 + i] = product[i];
- }
- uint8_t tmp[12 + sizeof(payload) * 2];
- uint16_t tmp_len = da14531_protocol_format(
- &tmp[0], sizeof(tmp), DA14531_PROTOCOL_PACKET_TYPE_CTRL_DATA, &payload[0], 1 + product_len);
- ASSERT(tmp_len <= sizeof(tmp));
- for (int i = 0; i < tmp_len; i++) {
- rust_bytequeue_put(uart_out, tmp[i]);
- }
-}
-
-void da14531_set_name(const char* name, struct RustByteQueue* uart_out)
-{
- size_t name_len = strlen(name);
- uint8_t payload[64] = {0};
- size_t payload_name_len = MIN(name_len, sizeof(payload) - 1);
- payload[0] = CTRL_CMD_DEVICE_NAME;
- memcpy(&payload[1], name, payload_name_len);
- uint8_t tmp[12 + sizeof(payload) * 2];
- uint16_t tmp_len = da14531_protocol_format(
- &tmp[0],
- sizeof(tmp),
- DA14531_PROTOCOL_PACKET_TYPE_CTRL_DATA,
- &payload[0],
- 1 + payload_name_len);
- ASSERT(tmp_len <= sizeof(tmp));
- for (int i = 0; i < tmp_len; i++) {
- rust_bytequeue_put(uart_out, tmp[i]);
- }
-}
-
-void da14531_get_connection_state(struct RustByteQueue* uart_out)
-{
- uint8_t payload = CTRL_CMD_BLE_STATUS;
- uint8_t tmp[12 + sizeof(payload) * 2];
- uint16_t tmp_len = da14531_protocol_format(
- &tmp[0], sizeof(tmp), DA14531_PROTOCOL_PACKET_TYPE_CTRL_DATA, &payload, 1);
- ASSERT(tmp_len <= sizeof(tmp));
- for (int i = 0; i < tmp_len; i++) {
- rust_bytequeue_put(uart_out, tmp[i]);
- }
-}
diff --git a/src/da14531/da14531.h b/src/da14531/da14531.h
index 0574c2e..a15b8f0 100644
--- a/src/da14531/da14531.h
+++ b/src/da14531/da14531.h
@@ -27,23 +27,4 @@ enum da14531_connected_state {
};
extern enum da14531_connected_state da14531_connected_state;
-
-struct RustByteQueue;
-
-void da14531_power_down(struct RustByteQueue* uart_out);
-
-void da14531_reset(struct RustByteQueue* uart_out);
-
-// product is an array of characters to be set as product characteristic (not null terminated)
-// procuct_len is the number of characters in the product array
-// uart_out is the queue where to put the outgoing serially encoded bytes
-void da14531_set_product(
- volatile const uint8_t* product,
- volatile uint16_t product_len,
- struct RustByteQueue* uart_out);
-
-void da14531_set_name(const char* name, struct RustByteQueue* uart_out);
-
-void da14531_get_connection_state(struct RustByteQueue* uart_out);
-
#endif
diff --git a/src/da14531/da14531_handler.c b/src/da14531/da14531_handler.c
index 3d03f51..7c72262 100644
--- a/src/da14531/da14531_handler.c
+++ b/src/da14531/da14531_handler.c
@@ -225,8 +225,9 @@ static void _ctrl_handler(const struct da14531_ctrl_frame* frame, struct RustByt
} break;
case CTRL_CMD_PRODUCT_STRING: {
// util_log("da14531: get device mode");
- da14531_set_product(
- da14531_handler_current_product, da14531_handler_current_product_len, queue);
+ rust_da14531_set_product(
+ rust_util_bytes(da14531_handler_current_product, da14531_handler_current_product_len),
+ queue);
} break;
case CTRL_CMD_IDENTITY_ADDRESS: {
// util_log("da14531: get addr");
diff --git a/src/factorysetup.c b/src/factorysetup.c
index 4e8fa3e..583d5ca 100644
--- a/src/factorysetup.c
+++ b/src/factorysetup.c
@@ -1126,7 +1126,7 @@ static ble_error_code_t _setup_ble(void)
}
// If the BLE chip already was successfully booted, for example by running the factory-setup
// once already and not power cycled, we need to reset it to trigger a complete setup again.
- da14531_reset(uart_write_queue);
+ rust_da14531_reset(uart_write_queue);
int32_t timeout = 1000000;
while (timeout-- > 0) {
uart_poll(uart_read_buf, sizeof(uart_read_buf), &uart_read_buf_len, uart_write_queue);
diff --git a/src/reset.c b/src/reset.c
index 307afd8..b3d148e 100644
--- a/src/reset.c
+++ b/src/reset.c
@@ -22,7 +22,7 @@ void reset_ble(void)
if (uart_queue == NULL) {
return;
}
- da14531_reset(uart_queue);
+ rust_da14531_reset(uart_queue);
while (rust_bytequeue_num(uart_queue)) {
uart_poll(NULL, 0, NULL, uart_queue);
}
diff --git a/src/rust/bitbox02-sys/build.rs b/src/rust/bitbox02-sys/build.rs
index 565f1ea..2e0253f 100644
--- a/src/rust/bitbox02-sys/build.rs
+++ b/src/rust/bitbox02-sys/build.rs
@@ -65,10 +65,7 @@ const ALLOWLIST_FNS: &[&str] = &[
"delay_ms",
"delay_us",
"da14531_handler",
- "da14531_power_down",
"da14531_protocol_poll",
- "da14531_set_product",
- "da14531_set_name",
"emit_event",
"empty_create",
"fake_memory_factoryreset",
diff --git a/src/system.c b/src/system.c
index 4e36057..d0f6119 100644
--- a/src/system.c
+++ b/src/system.c
@@ -17,7 +17,7 @@ static void _ble_clear_product(void)
if (uart_queue == NULL) {
return;
}
- da14531_set_product(NULL, 0, uart_queue);
+ rust_da14531_set_product(rust_util_bytes(NULL, 0), uart_queue);
while (rust_bytequeue_num(uart_queue)) {
#ifndef TESTING
uart_poll(NULL, 0, NULL, uart_queue);
Why this scored 11/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.