Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of Reliable, Secure and Universal Backup for U2F Token on Nitrokey #13

Open
Pantamis opened this issue Nov 3, 2018 · 6 comments

Comments

@Pantamis
Copy link

Pantamis commented Nov 3, 2018

Hi,

First, thanks to propose an open source U2F token on the market, I didn't buy U2FZero when it came out and it becomes impossible to find so I really like the initiative of Nitrokey.

I would like to know if the backup strategy proposed in this post is possible with Nitrokey : https://dmitryfrank.com/articles/backup_u2f_token

In summary : this strategy can be used only if two conditions are meet on the U2F token :

  • we can set the device secret by ourself at setup
  • we can set the initial value of the hardware counter at setup

The goal is to set the same device secret on two U2F keys but one is primary, initial value of counter is 0, and the other is backup, initial value of counter is high (2^31 if counter takes value until 2^32). That way backup does not need to be register on the remote service (as it will generate the same public-private key pair for the same input since the device secret is the same) and will invalidate primary token on that service (because initial value of backup counter is already set higher than the number of possible authentication in a whole life so counter would decrease if primary is used again). In my view: the perfect backup.

https://dmitryfrank.com/articles/backup_u2f_token shows also how to do it with U2FZero ! He forked the U2FZero firmware to add the possibility of giving values of wkey and rkey: https://github.com/dimonomid/u2f-zero .

MY_WKEY and MY_RKEY are env variables containing random values for wkey and rkey
To create primary token, with original firmware of U2FZero :
./setup_device.sh -w ${MY_WKEY} -r ${MY_RKEY} gencert/ca/key.pem gencert/ca/cert.der

For backup token, we need to modify the return of the function u2f_count in firmware/src/u2f_atecc.c by return le32toh(*(uint32_t*)res.buf) + 2000000000; then rebuild the firmware and setup the device as before.

My question is precisely : given that Nitrokey fimware is a fork of U2FZero, can I expect that if I follow the exact same instructions of the post, it will work and creates the primary-backup pair keys ? (Assuming I find a way to correctly specify wkey and rkey to Nitrokey firmware)

Thank you in advance,

Feel free to ask me to open this issue in support forum of nitrokey.com if it is relevent in your point of view.

@szszszsz
Copy link
Member

szszszsz commented Nov 3, 2018

Hi!

Thank you for the interesting read! We have used a similar solution (before 49185ae was introduced) during the early development to make a reproducible firmware for testing purposes.

To directly reply to the question: with current firmware it is not possible to apply actions as mentioned in the article, to make a cloned device with the offset counter. At the moment the wkey and rkey, as well as additional device specific secrets, all are generated on-device (using its own RNG) during the configuration phase, and these cannot be set manually.

This solution was chosen with the assumption, that services will allow for a backup U2F token (and I think this should be the only safe way for handling this issue - please push Twitter for changing its implementation!). Generating device's secret on host allows a greater possibility of leaking them. Such procedure should be done with the highest caution (e.g. on air gapped PC, started from an ISO image). Otherwise, when allowing such a feature, if the attacker would intercept the secrets, he could set the counter further and take over the account easily.

It is not impossible however to add such routines for a custom firmware. The u2f_zero_const, wkey and rkey are stored in the writeable flash (with the read protection enabled), and can be changed without firmware recompilation (this is exactly done on the factory-reset operation, which is available with the Nitrokey FIDO U2F device; usable e.g. when one would like to deny his connection to given account). It should be easy to do so (just replace RNG input with the desired content, e.g. using the client.py tool). The counter offset could be stored dynamically as well, which would allow to not recompile the firmware.

Whether it should get to the official firmware, is a space for discussion.

Project's issues are perfectly fine for discussing enhancements or reporting bugs. I think forum is best for asking for help in using the device, where other users could response as well.

@Pantamis
Copy link
Author

Pantamis commented Nov 4, 2018

Hi,

Thank you for your quick reply and I'm glad it interest you. By the way, I disclaim that I'm not very aware of firmware/hardware data processing.

I totally understand the implementation choice you made, setting the device secret is an absolutely critical step in terms of security in U2F protocol, indeed having this possibility in official firmware is quite sensitive.

If I understand well, you mean that it is impossible for me to do anything at the current state since we need a custom firmware ? But is it possible for me to fork the firmware source code and make the same modification of the fork of https://github.com/dimonomid/u2f-zero so that I can flash the custom firmware to the Nitrokey and do the same ?

In fact, I don't get exactly what you mean by "It is not impossible however to add such routines for a custom firmware" , factory-reset basically calls do_wipe so I don't see where I can change RNG by a deterministic input.

Thank you for the clarification,

@rugk
Copy link

rugk commented Nov 13, 2018

BTW, instead of backing up secrets on the U2F key itself, the better method is to just:

  • Add another U2F key in your online services.

Literally all services I've tried so far; do support adding multiple keys. (I even guess it is required by some standard,) You can also always set a name, so you can differentiate them and e.g. delete one key when it gets lost. You then still have the other key for logging in.

That is both more secure than cloning any key and it also likely fulfills your use case. Or what is your use case even, I see it nowhere clearly explained. (Maybe we'd better discuss that first, before discussing a solution to that.)

@jans23
Copy link
Member

jans23 commented Nov 14, 2018

My main concern regarding the original backup proposal is that we must not put users at risk who don't use that feature. For example users who get a (resold) device which device key has been cloned by the previous owner or users who are at risk by receiving a device which got compromised during shipment.

We could tackle this by not equipping the device with a (secret) attestation key. This would allow websites to distinguish the device category. However, AFAIK the attestation key isn't used in practice so that attestation key doesn't really solve this issue. Alternatively we could print a different label on the device. However, I'm not sure this would be a sufficient solution.

Also in the referenced blog post the reasoning of disabling previous device by counter is insufficient. The counter is handled by the firmware which is on the MCU and which therefore could be modified or replaced with relative ease. Consequently in case of lost device you better render your device (its device key!) invalid at all the websites you use. Therefore you don't need a backup device. A backup device would only help if your primary device stops working (but isn't lost).

@Pantamis
Copy link
Author

Hi, sorry for my late reply.

Thank you for the remarks,

@rugk : I agree that when it is possible to register multiple keys this is a good backup strategy, and often services propose another way to login (Twitter doesn't allow you to use multiple U2F Keys but they give you a single use backup code).

The "use case" describes in the post I linked is a kind of extreme backup strategy : your backup device is inaccessible (from the post linked : "I could secretly brick it up into the wall in the villa's basement, or bury somewhere in the forest"), it would cost you so much to get it back that you want to use it only if you lose the main device.
When your backup doesn't share the same secret, then each time you register a U2F device for a new service, you have to grab the backup and register it (and not forget to do it) so you can't put your U2F backup in a place hard to access because you may need it later (to register it, not as backup).

So in this case you need to put the same secret in the backup. I agree this is less secure but you have a "true" backup that you will use only once (to register another U2F main device). My question was only to know if it is possible to do this with Nitrokey since U2FZero allows it, it isn't the case, I understand the security concern since this is a kind of extreme situation.

@jans23 I understand your concern. The average user must have a device working and not compromised no matter what. The average user will not generate and put it's own device secret at reception (or do they if a nice software for this is provided ?). However during shipment, a devil employee may compromise the device by writing his own device secret so no one can assure anymore the integrity. Another possibility is to package a commercial offer where you sell directly a matched pair of U2F device (from the discussion in the post it seems that Conor proposed it before).

About the remark on the counter, it is clear that the backup is used only once on each website to do exactly what you mean : disable the primary (and so backup) to register a new U2F key. But you may need the backup to do that since you can't authenticate at all because your primary device is not usable (and if services doesn't propose a limited use backup if 2FA is lost).

I think the conclusion of this discussion is that a such feature (writing the device secret) should be available only for advanced users because they would have to set up the device secret by themselves before use to be sure that the device is not compromise. People who use PGP key for example can understand and do it but there aren't the majority of people who buy Nitrokey.

Still, I think it would be nice to have an hardware security device where we free to write the secret key like a "PGP card equivalent for U2F", but yeah it's for "crypto nerd's".

@szszszsz
Copy link
Member

szszszsz commented Jan 2, 2019

If I understand well, you mean that it is impossible for me to do anything at the current state since we need a custom firmware ? But is it possible for me to fork the firmware source code and make the same modification of the fork of https://github.com/dimonomid/u2f-zero so that I can flash the custom firmware to the Nitrokey and do the same ?
In fact, I don't get exactly what you mean by "It is not impossible however to add such routines for a custom firmware" , factory-reset basically calls do_wipe so I don't see where I can change RNG by a deterministic input.

Hi @Pantamis ! Sorry for the late reply.
I meant, that one needs to add new commands to the firmware, to directly write to the device's secret constants, kept both on MCU's flash, and on secure element. Function do_wipe() shows the constants generation process, which one could reference to (e.g. memory location written etc).
Nitrokey's U2F FIDO firmware contains over 350 commits more over U2F-Zero, so it is rather a heavily modified fork. Firmware modification guides will most probably not work between these two directly, however they share the same general concepts, so the guides will have to be adjusted. One can also browse the old versions of the firmware, where the direct secret writes were used for development, to see the used idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants