2019-02-13 22:49:07

by Pavel Machek

[permalink] [raw]
Subject: [PATCH] pre-shared passcode: secure pairing for "no keyboard, no display" devices

Hi!

Currently, "no keyboard, no display" devices can be paired, but
pairing is not secure against active attacker.

Can we do better? Not for the first pairing; but for the next ones --
yes, I believe we can.

BLE device in this case has internal storage, and Linux running
there. From factory, random 6-digit number is stored in the
flash. Legitimate user knows the number, and system is manipulated so
that pairing passkey will be this pre-shared passkey. After pairing,
user is allowed to change it.

[Or maybe passkey is 000000 from the factory; this is still win for
the user, as long as he can change the key to something random in a
secure cave.]

Fortunately, kernel support for this is rather easy; patch is attached
below.

Does someone see a security issue with proposal above?

What would be suitable interface for setting pre-shared passkey?
Module parameter is really easy.

Signed-off-by: Pavel Machek <[email protected]>

diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 621146d..7a2b06595 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -2674,6 +2674,11 @@ static u8 sc_select_method(struct smp_chan *smp)
return method;
}

+static int preshared_passkey = -1;
+
+module_param(preshared_passkey, int, 0600);
+MODULE_PARM_DESC(preshared_passkey, "Preshared passkey for device w/o keyboard or display");
+
static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_public_key *key = (void *) skb->data;
@@ -2752,9 +2757,11 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);

if (smp->method == DSP_PASSKEY) {
get_random_bytes(&hcon->passkey_notify,
sizeof(hcon->passkey_notify));
+ if (preshared_passkey != -1)
+ hcon->passkey_notify = preshared_passkey;
hcon->passkey_notify %= 1000000;
hcon->passkey_entered = 0;
smp->passkey_round = 0;
if (mgmt_user_passkey_notify(hdev, &hcon->dst, hcon->type,




--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


Attachments:
(No filename) (2.07 kB)
signature.asc (181.00 B)
Digital signature
Download all attachments

2019-02-14 15:28:18

by Emil Lenngren

[permalink] [raw]
Subject: Re: [PATCH] pre-shared passcode: secure pairing for "no keyboard, no display" devices

Hi Pavel,

Den tors 14 feb. 2019 kl 14:59 skrev Pavel Machek <[email protected]>:
>
> Hi!
>
> Currently, "no keyboard, no display" devices can be paired, but
> pairing is not secure against active attacker.
>
> Can we do better? Not for the first pairing; but for the next ones --
> yes, I believe we can.
>
> BLE device in this case has internal storage, and Linux running
> there. From factory, random 6-digit number is stored in the
> flash. Legitimate user knows the number, and system is manipulated so
> that pairing passkey will be this pre-shared passkey. After pairing,
> user is allowed to change it.
>
> [Or maybe passkey is 000000 from the factory; this is still win for
> the user, as long as he can change the key to something random in a
> secure cave.]
>
> Fortunately, kernel support for this is rather easy; patch is attached
> below.
>
> Does someone see a security issue with proposal above?

Assuming "LE Secure Connections" is used, the protocol is only secure
if the passkey is not reused. A 6 digit passkey means 20 bits. The
protocol is performed in 20 steps, where one bit is compared and
revealed in every step. This means the attacker will know for every
attempt the first bit that is incorrect in the attempted passkey. If
the passkey is reused, the attacker can just try the same passkey with
the incorrect bit flipped. In average it takes 10 attempts to crack
the key and maximum 20 attempts. Hence, a static key doesn't really
add much security compared to Just Works and might give a false sense
of security.

A static key for Legacy Pairing has comparable security as using a
random key. The security is kind of the same as logging in to a
website over unencrypted HTTP, assuming the static key is stored on
the peripheral and the user enters the passkey on the central. In the
case where the passkey is entered by the user on the peripheral
instead of the central, the protocol is completely broken
(https://eprint.iacr.org/2013/309.pdf).

/Emil

2019-02-15 11:46:32

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH] pre-shared passcode: secure pairing for "no keyboard, no display" devices

Hi!

> > Currently, "no keyboard, no display" devices can be paired, but
> > pairing is not secure against active attacker.
> >
> > Can we do better? Not for the first pairing; but for the next ones --
> > yes, I believe we can.
> >
> > BLE device in this case has internal storage, and Linux running
> > there. From factory, random 6-digit number is stored in the
> > flash. Legitimate user knows the number, and system is manipulated so
> > that pairing passkey will be this pre-shared passkey. After pairing,
> > user is allowed to change it.
> >
> > [Or maybe passkey is 000000 from the factory; this is still win for
> > the user, as long as he can change the key to something random in a
> > secure cave.]
> >
> > Fortunately, kernel support for this is rather easy; patch is attached
> > below.
> >
> > Does someone see a security issue with proposal above?
>
> Assuming "LE Secure Connections" is used, the protocol is only secure
> if the passkey is not reused. A 6 digit passkey means 20 bits. The
> protocol is performed in 20 steps, where one bit is compared and
> revealed in every step. This means the attacker will know for every
> attempt the first bit that is incorrect in the attempted passkey. If
> the passkey is reused, the attacker can just try the same passkey with
> the incorrect bit flipped. In average it takes 10 attempts to crack
> the key and maximum 20 attempts. Hence, a static key doesn't really
> add much security compared to Just Works and might give a false sense
> of security.

Thanks a lot for quick reply. And no, that is not good.

Just Works basically means that there's no security at all, anyone
within range can connect when owner is not around, and do whatever
they want.

Is there some common way this is solved?

We do have pre-shared passkey, if only 20 bits. If we set
passkey = sha( pre-shared passkey + pairing_attempt++ ), would we get
some kind of meaningful security? Perhaps with limiting pairing
attempt to say 10 a day?

Best regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


Attachments:
(No filename) (2.10 kB)
signature.asc (181.00 B)
Digital signature
Download all attachments

2019-02-15 12:22:03

by Emil Lenngren

[permalink] [raw]
Subject: Re: [PATCH] pre-shared passcode: secure pairing for "no keyboard, no display" devices

Hi,
Den fre 15 feb. 2019 kl 12:46 skrev Pavel Machek <[email protected]>:
>
> Hi!
>
> > > Currently, "no keyboard, no display" devices can be paired, but
> > > pairing is not secure against active attacker.
> > >
> > > Can we do better? Not for the first pairing; but for the next ones --
> > > yes, I believe we can.
> > >
> > > BLE device in this case has internal storage, and Linux running
> > > there. From factory, random 6-digit number is stored in the
> > > flash. Legitimate user knows the number, and system is manipulated so
> > > that pairing passkey will be this pre-shared passkey. After pairing,
> > > user is allowed to change it.
> > >
> > > [Or maybe passkey is 000000 from the factory; this is still win for
> > > the user, as long as he can change the key to something random in a
> > > secure cave.]
> > >
> > > Fortunately, kernel support for this is rather easy; patch is attached
> > > below.
> > >
> > > Does someone see a security issue with proposal above?
> >
> > Assuming "LE Secure Connections" is used, the protocol is only secure
> > if the passkey is not reused. A 6 digit passkey means 20 bits. The
> > protocol is performed in 20 steps, where one bit is compared and
> > revealed in every step. This means the attacker will know for every
> > attempt the first bit that is incorrect in the attempted passkey. If
> > the passkey is reused, the attacker can just try the same passkey with
> > the incorrect bit flipped. In average it takes 10 attempts to crack
> > the key and maximum 20 attempts. Hence, a static key doesn't really
> > add much security compared to Just Works and might give a false sense
> > of security.
>
> Thanks a lot for quick reply. And no, that is not good.
>
> Just Works basically means that there's no security at all, anyone
> within range can connect when owner is not around, and do whatever
> they want.
>
> Is there some common way this is solved?
>
> We do have pre-shared passkey, if only 20 bits. If we set
> passkey = sha( pre-shared passkey + pairing_attempt++ ), would we get
> some kind of meaningful security? Perhaps with limiting pairing
> attempt to say 10 a day?

I see two issues with that approach. First, the user needs to know the
correct counter of pairing_attempt (how?) and perform the sha
calculation and map that to a passkey. Second, if you eavesdrop a
pairing attempt that succeeds, you can just bruteforce sha over all
possible pre-shared passkeys (1 million if you have 6 digits) times
the number of different pairing_attempt counters you want to test, and
match that with the recorded pairing messages. That shouldn't take
more than a few seconds on a normal PC.

What people really do that wants proper security over BLE when they
need to use static passkeys, is using a PAKE algorithm in the
application layer to establish a session key, and then use some AEAD
cipher with that session key also in the application layer (or
potentially start BLE encryption using that session key as LTK, but I
haven't seen that). Unencrypted BLE is just used then as a transport
layer.

/Emil