Skip to content

Commit d15449d

Browse files
committed
memory: return unique default device name for BB02+
To disambiguate multiple BitBoxes in the Bluetooth devices list, we use a unique name of the form "BitBox ABCD" (four random uppercase letters) until a device name is set by the user. The random letters are not picked perfectly uniformely, but this is not security critical - it's merely to create a unique name to be able to disambiguate. This change only applies to BB02+, and this random device name is displayed on the lockscreen visible before pairing.
1 parent 4430931 commit d15449d

File tree

3 files changed

+76
-6
lines changed

3 files changed

+76
-6
lines changed

src/memory/memory.c

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,13 +253,47 @@ bool memory_set_device_name(const char* name)
253253
return _write_chunk(CHUNK_1, chunk.bytes);
254254
}
255255

256+
static void _random_name(char* name_out)
257+
{
258+
static char cached_name[MEMORY_DEVICE_NAME_MAX_LEN] = {0};
259+
260+
if (cached_name[0] == 0x00) {
261+
// Generate 4 random uppercase letters
262+
uint8_t random[32] = {0};
263+
_interface_functions->random_32_bytes(random);
264+
uint8_t letters[4];
265+
for (size_t i = 0; i < sizeof(letters); i++) {
266+
letters[i] = 'A' + (random[i] % 26);
267+
}
268+
269+
// Format into cached name
270+
snprintf(
271+
cached_name,
272+
MEMORY_DEVICE_NAME_MAX_LEN,
273+
"BitBox %c%c%c%c",
274+
letters[0],
275+
letters[1],
276+
letters[2],
277+
letters[3]);
278+
}
279+
280+
// Copy cached result to output
281+
snprintf(name_out, MEMORY_DEVICE_NAME_MAX_LEN, "%s", cached_name);
282+
}
283+
256284
void memory_get_device_name(char* name_out)
257285
{
258286
chunk_1_t chunk = {0};
259287
CLEANUP_CHUNK(chunk);
260288
_read_chunk(CHUNK_1, chunk_bytes);
261289
if (chunk.fields.device_name[0] == 0xFF) {
262-
snprintf(name_out, MEMORY_DEVICE_NAME_MAX_LEN, "%s", MEMORY_DEFAULT_DEVICE_NAME);
290+
if (memory_get_platform() == MEMORY_PLATFORM_BITBOX02_PLUS) {
291+
// For Bluetooth, we want to use an unambiguous default name so this BitBox can be
292+
// identified if multiple BitBoxes are advertising at the same time.
293+
_random_name(name_out);
294+
} else {
295+
snprintf(name_out, MEMORY_DEVICE_NAME_MAX_LEN, "%s", MEMORY_DEFAULT_DEVICE_NAME);
296+
}
263297
} else {
264298
snprintf(name_out, MEMORY_DEVICE_NAME_MAX_LEN, "%s", chunk.fields.device_name);
265299
}

src/memory/memory.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ extern const char* MEMORY_DEFAULT_DEVICE_NAME;
7070
// size (including the null terminator) is MEMORY_DEVICE_NAME_MAX_LEN bytes.
7171
USE_RESULT bool memory_set_device_name(const char* name);
7272

73-
// name_out must have MEMORY_DEVICE_NAME_MAX_LEN bytes in size. Returns `MEMORY_DEFAULT_DEVICE_NAME`
74-
// if no device name is set.
73+
// name_out must have MEMORY_DEVICE_NAME_MAX_LEN bytes in size. If no device name is set, we return:
74+
// - `MEMORY_DEFAULT_DEVICE_NAME` for non-bluetooth enabled BitBoxes
75+
// - "BitBox ABCD" for Bluetooth-enabled BitBoxes, where ABCD are four random uppercase letters.
76+
// The name is cached in RAM, so the same random name is returned until reboot.
7577
void memory_get_device_name(char* name_out);
7678

7779
/**

test/unit-test/test_memory.c

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,13 @@
1818
#include <cmocka.h>
1919

2020
#include <memory/memory.h>
21+
#include <memory/memory_shared.h>
2122

2223
#include <stdint.h>
2324
#include <stdio.h>
2425
#include <string.h>
2526

26-
#define CHUNK_SIZE (16 * 512) // 8kB.
27-
2827
#define FLASH_APP_DATA_LEN (0x000010000)
29-
#define FLASH_SHARED_DATA_START (0xe000)
3028

3129
// chunk 0
3230
static const int _addr_factory_setup_done = 0;
@@ -386,10 +384,45 @@ static void _test_memory_get_device_name_default(void** state)
386384
EMPTYCHUNK(empty_chunk);
387385
expect_value(__wrap_memory_read_chunk_mock, chunk_num, 1);
388386
will_return(__wrap_memory_read_chunk_mock, empty_chunk);
387+
388+
EMPTYCHUNK(empty_shared_chunk);
389+
will_return(__wrap_memory_read_shared_bootdata_mock, empty_shared_chunk);
390+
389391
memory_get_device_name(name_out);
390392
assert_string_equal(MEMORY_DEFAULT_DEVICE_NAME, name_out);
391393
}
392394

395+
// For Bluetooth devices (BitBox02+), the default name is "BitBox ABCD" where ABCD are four random
396+
// uppercase letters.
397+
static void _test_memory_get_device_name_default_bluetooth(void** state)
398+
{
399+
uint8_t entropy[32] = {0};
400+
memcpy(entropy, "\x00\x19\xFE\xFF", 4);
401+
402+
char name_out[MEMORY_DEVICE_NAME_MAX_LEN] = {0};
403+
EMPTYCHUNK(empty_chunk);
404+
expect_value(__wrap_memory_read_chunk_mock, chunk_num, 1);
405+
will_return(__wrap_memory_read_chunk_mock, empty_chunk);
406+
407+
EMPTYCHUNK(empty_shared_chunk);
408+
chunk_shared_t shared_chunk = {0};
409+
memcpy(shared_chunk.bytes, empty_shared_chunk, CHUNK_SIZE);
410+
shared_chunk.fields.platform = MEMORY_PLATFORM_BITBOX02_PLUS;
411+
will_return(__wrap_memory_read_shared_bootdata_mock, shared_chunk.bytes);
412+
413+
will_return(_mock_random_32_bytes, entropy);
414+
415+
memory_get_device_name(name_out);
416+
assert_string_equal("BitBox AZUV", name_out);
417+
418+
// Calling it again does not re-generate a new random name but reuses the already generated one.
419+
expect_value(__wrap_memory_read_chunk_mock, chunk_num, 1);
420+
will_return(__wrap_memory_read_chunk_mock, empty_chunk);
421+
will_return(__wrap_memory_read_shared_bootdata_mock, shared_chunk.bytes);
422+
memory_get_device_name(name_out);
423+
assert_string_equal("BitBox AZUV", name_out);
424+
}
425+
393426
static void _test_memory_get_device_name(void** state)
394427
{
395428
char name_out[MEMORY_DEVICE_NAME_MAX_LEN] = {0};
@@ -527,6 +560,7 @@ int main(void)
527560
cmocka_unit_test(_test_memory_set_mnemonic_passphrase_enabled),
528561
cmocka_unit_test(_test_memory_reset_hww),
529562
cmocka_unit_test(_test_memory_get_device_name_default),
563+
cmocka_unit_test(_test_memory_get_device_name_default_bluetooth),
530564
cmocka_unit_test(_test_memory_get_device_name),
531565
cmocka_unit_test(_test_memory_device_name),
532566
cmocka_unit_test(_test_memory_set_seed_birthdate),

0 commit comments

Comments
 (0)