net/sock_dtls: add public key verification#20048
Conversation
|
I'm wondering whether this feature should actually be opt-out instead. |
Teufelchen1
left a comment
There was a problem hiding this comment.
Some nits. Manually and successfully tested on native.
I found the code in the example to be confusing due to naming of the key variables and lack of comments. If you want to go the extra mile and and a bit of ✨ that would be neat but totally optional for this PR.
I gave it a try. It's still not perfect, but I think much clearer. I tried clearly splitting both sets of credentials. A bonus: now the client can actively use the PSK hint to decide on the key to use. |
| } | ||
| if (IS_ACTIVE(CONFIG_DTLS_PSK)) { | ||
| /* make the new credential available to the sock */ | ||
| if (sock_dtls_add_credential(&dtls_sock, SOCK_DTLS_CLIENT_TAG_1) < 0) { |
There was a problem hiding this comment.
I was always very confused about what's the idea behind credman.
Shouldn't a credential be associated with a host? So what does it mean to add multiple credentials to a socket?
At first I thought it would do the host <-> credential mapping, but that's not the case.
So what's the advantage of the credential IDs ('tags') as opposed to just passing pointers?
There was a problem hiding this comment.
I was always very confused about what's the idea behind credman.
Yeah, I know what you mean...
Shouldn't a credential be associated with a host? So what does it mean to add multiple credentials to a socket?
Not necessarily. I mean, you can already see the example of the server with more than one pair of keys. IMO one of the greatest problems of this module is that a credential is a single "private key" and 0 or more "client keys". Like I commented in the example, the way it currently works looks more like a keyring of client keys and your own.
So what's the advantage of the credential IDs ('tags') as opposed to just passing pointers?
In key management using tags is not uncommon, this is crucial for instance when integrating secure elements or other backends where the key is directly not reachable, but a tag is passed to the crypto backend. I'm not sure why this was the case for credman, as it clearly doesn't support any other backend than a buffer in memory.
IMO we are in need of a rethinking of the credentials management in RIOT. We would really benefit from:
- not only DTLS credentials (of course)
- possibility of multiple backends including secure elements
- more types of credentials
- ability to indicate scope and capabilities of the credentials
There was a problem hiding this comment.
Hey @Einhornhool! Take a look at this comment please 🐅
(Also, maybe this comment should be an issue instead?)
There was a problem hiding this comment.
Hmm most of the points in Leandros credentials requirement list could be handled by the PSA Crypto key management. It might be worth looking into patching tinydtls to use PSA for crypto operations and credential storage, instead of implementing the same features twice.
|
This needs a rebase |
30a9e0e to
01b6e77
Compare
|
Rebased. I also modified a bit the example: the server only stores one client public key, but has two key pairs. It allows the user to select which one to use on the handshake. As the client knows both public keys form the server, any will work. I think this showcases a bit better the usage of the callbacks and multiple credentials. I also updated the docs including this and the new command. |
|
This is great! Way easier to understand! |
01b6e77 to
a57bdb7
Compare
|
Fixed and squashed! |
| #endif | ||
|
|
||
| res = sock_dtls_establish_session(&udp_sock, &dtls_sock, &session, tag, | ||
| &local, &remote, buf, sizeof(buf)); |
There was a problem hiding this comment.
Why move away from the sock_dtls_establish_session() helper and open-code the handshake again?
There was a problem hiding this comment.
Because it doesn't allow me to register the extra credentials before initiating the handshake.
There was a problem hiding this comment.
Same with the callbacks
There was a problem hiding this comment.
tbh I didn't quite understand the requirement when adding that helper, so if you think the API can be improved that would be great - leaving the handshake to the user seemed like a bad example.
There was a problem hiding this comment.
Hm I don't feel like this example is bad. It's not overly complicated or lengthy, the reader should get along well.
While a single helper function is nice and clean, it is clear the existing one is insufficient for this particular task. Adjusting that helper would mess with an API that is out of scope for this PR.
- Can we resolve this comment on these terms?
- Do you think the API needs a rework? If so, we should open an issue for that.
- Makes me wonder, should we integrate credman closer with dtls?
There was a problem hiding this comment.
Sure, this shouldn't block this PR, I just took the opportunity to try to get some open questions about credman / DTLS answered 😅
I'd very much welcome an overhaul of credman as it seems still a bit unclear what it actually is and what's it's purpose.
Maybe it would also fit into PSA crypto?
a57bdb7 to
4321cf1
Compare
| /** | ||
| * @brief The identity hint of the PSK 0 | ||
| */ | ||
| #define CLIENT_PSK_IDENTITY_0_HINT "Prefer_Id_0" |
There was a problem hiding this comment.
Would the hint be something like a hostname / node ID or serial number?
There was a problem hiding this comment.
This is actually application-specific (https://datatracker.ietf.org/doc/html/rfc4279#section-5.2), so the content is not really restricted as long as it can be understood by the peer.
There was a problem hiding this comment.
Sure, but since this is an example I think some comment of what this would be in a real-world use case would be valuable.
There was a problem hiding this comment.
something like a hostname / node ID or serial number
This would somehow imply that the key is only to be used with a single client, this is not necessarily the case. Searching for examples I found this summary: https://stackoverflow.com/a/8753393/5633371 seems that many implementations send encoded information on how to derive the keys.
I think this hint is fine for the didactic purpose of the example: It's easily readable in code and when sniffing the handshake, and it describes its intention.
4321cf1 to
c424a76
Compare
|
Ping? |
benpicco
left a comment
There was a problem hiding this comment.
Thank you for the ping.
@Teufelchen1 I see you approved this, any reason not to press the merge button?
082638b to
9b18399
Compare
9b18399 to
6d9a9a3
Compare
|
Thanks for the review! |
Contribution description
This adds a pseudomodule to enable public key verification of peers. When
sock_dtls_verify_public_keyis enabled the public key sent by the peer is checked against the registered keys on the corresponding sock. The implementation for tinydtls is added, as well as the corresponding changes to use it on thedtls-sockexample.Testing procedure
Run
examples/dtls-sockwith ECC enabled, the public key should be verified. You can try removing the server's public key from the client, the connection should be aborted.Issues/PRs references
Loosely related to #19838