Skip to content

Commit d967efa

Browse files
ZorvaltJF002
authored andcommitted
Fix biased BLE pass key generation
1 parent 5938b4b commit d967efa

1 file changed

Lines changed: 22 additions & 1 deletion

File tree

src/components/ble/NimbleController.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,28 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) {
278278
if (event->passkey.params.action == BLE_SM_IOACT_DISP) {
279279
struct ble_sm_io pkey = {0};
280280
pkey.action = event->passkey.params.action;
281-
pkey.passkey = ble_ll_rand() % 1000000;
281+
282+
/*
283+
* Passkey is a 6 digits code (1'000'000 possibilities).
284+
* It is important every possible value has an equal probability
285+
* of getting generated. Simply applying a modulo creates a bias
286+
* since 2^32 is not a multiple of 1'000'000.
287+
* To prevent that, we can reject values greater than 999'999.
288+
*
289+
* Rejecting values would happen a lot since 2^32-1 is way greater
290+
* than 1'000'000. An optimisation is to use a multiple of 1'000'000.
291+
* The greatest multiple of 1'000'000 lesser than 2^32-1 is
292+
* 4'294'000'000.
293+
*
294+
* Great explanation at:
295+
* https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
296+
*/
297+
uint32_t passkey_rand;
298+
do {
299+
passkey_rand = ble_ll_rand();
300+
} while (passkey_rand > 4293999999);
301+
pkey.passkey = passkey_rand % 1000000;
302+
282303
bleController.SetPairingKey(pkey.passkey);
283304
systemTask.PushMessage(Pinetime::System::Messages::OnPairing);
284305
ble_sm_inject_io(event->passkey.conn_handle, &pkey);

0 commit comments

Comments
 (0)