Re: [webauthn] Recovering from Device Loss (#931)

>`S` must be kept secret, otherwise collaborating RPs can forge an otherwise valid credential id and test whether a user holds the corresponding private key, which uniquely identifies the user. This is a weak guessing attack violating unlinkability.

Aha, _there's_ the attack enabled by knowing `S`! We've known that anyone who knows `S` can create a valid credential ID that the backup authenticator would accept and use, but we hadn't found a way to leverage that into an attack. Thanks!

Might it make sense, then, to include an EDH key agreement in the import/export exchange, and encrypt `S` with the agreed ephemeral key? It wouldn't prevent a malicious client from active-MitMing the exchange and learning `S` (since we can't reasonably authenticate DH public keys across different authenticator vendors), but at least there would be forward secrecy and `S` wouldn't be in cleartext in client memory if the client is benign.

>Currently, Bob / the backup device is required to verify an alleged `E` is not invalid according to SEC 1, section 2.3.4. This procedure still allows for the `E` to be the point at infinity, which is invariant under scalar multiplication. This allows for a powerful attack on unlinkability:
>
>[...] The RP can then subtract `cred_key * G` from P to learn `S` which uniquely identifies the user.
>
>Consequently, devices must ensure `E` is not the point at infinity (or any low order point in a non-prime order group).

Good catch, we'll add that. This also has me thinking it might make sense to include the `rpIdHash` in the HKDF `info` parameter (in which case we could probably drop `rpIdHash` from the MAC)?

>Why use each half of `HKDF(e * S)` as opposed to two distinct invocations of HKDF with different labels? Wouldn't the latter be cleaner?

Yeah, that might be cleaner. It also shouldn't make a difference in terms of performance cost as you'd need to run one HKDF-Extract and two HMAC-Hash in either case.

>Why add `cred_key * G` to `S`? What purpose does it serve over using `cred_key * G` directly?

If you don't, then `p = credKey` and the main authenticator therefore knows the backup credential private key. With `P = cred_key * G + S`, you need to know `s` to compute `p = cred_key + s`, so only the backup authenticator is able to exercise its backup credentials.

@dainnilsson @ve7jtb thoughts on this?

-- 
GitHub Notification of comment by emlun
Please view or discuss this issue at https://github.com/w3c/webauthn/issues/931#issuecomment-542225765 using your GitHub account

Received on Tuesday, 15 October 2019 13:58:02 UTC