Nitrokey / opcard-rs

OpenPGP card implementation
49 stars 1 forks source link

Deriving shared secret using bytearray(b"\xff" * 32) fails while random public keys work #168

Closed rrottmann closed 8 months ago

rrottmann commented 1 year ago

Summary

Investigation is needed (possibly with a Nitrokey 3 and a debugging probe), why deriving a shared secret using calculate_shared_secret(card, bytearray(b"\xff" * 32), pin) does not work while random public keys do work.

Further Information

Thread at Nitrokey Support forum.

Relevant info provided by the developer of ~arx10/openpgpcard-wireguard-go:

Ah, thanks for trying that out! It must be the case that 32 0xFF bytes is a magic value for the Nitrokey 3 or its firmware -- I will fix the test_card() function to use a more "realistic" test value (xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=), which shouldn't trigger a "false positive" failure on any cards. The opcard-rs developers might want to investigate why that particular value doesn't work -- but as long as it's just that value (or just that and a few other special values), it shouldn't affect real-world use of the agent.

Otherwise, it's also possible that the opcard-rs firmware is expecting something slightly different than what the agent is sending. What the agent is sending is this (in hex bytes):

00: class byte
2A: PSO decipher (instruction byte)
80: return plain value (parameter byte 1)
86: enciphered data present in data field (parameter byte 2)
27: length of data field
A6: cipher DO
25: length of rest of data
7F: public key DO (first byte)
49: public key DO (second byte)
22: length of rest of data
86: external public key
20: length of public key
(32 bytes of public key)

From a quick perusal of the opcard-rs source code, however, it looks to me like that's the same as what the run_decrypt() function from the command-response.rs test is doing:

https://github.com/Nitrokey/opcard-rs/blob/main/tests/command-response.rs#L843

So I can't see any obvious reason why the opcard-rs firmware wouldn't work with the openpgpcard-x25519-agent. It probably needs to be stepped through with a debugger while the PSO decipher command from the agent is being sent to it to figure out where the disconnect is.

sosthene-nitrokey commented 1 year ago

Hi, thanks for the report.

There is actually no need to have access to special hardware as this can be reproduced with the virtualsmartcard example. It looks indeed like Opcard rejects non-canonical public keys for X25519 key agreements, which does not appear to be the case of other X25519 implementations. I will look into it.

sosthene-nitrokey commented 1 year ago

Hi, thanks for the report.

There is actually no need to have access to special hardware as this can be reproduced with the virtualsmartcard example. It looks indeed like Opcard rejects non-canonical public keys for X25519 key agreements, which does not appear to be the case of other X25519 implementations. I created an issue with our X25519 implementation: https://github.com/ycrypto/salty/issues/31

sosthene-nitrokey commented 8 months ago

Closing as this issue has been fixed upstream.