-
Notifications
You must be signed in to change notification settings - Fork 126
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
Persistent TLS keys #783
Persistent TLS keys #783
Conversation
fe58d8b
to
182ce01
Compare
Add a function to return the payload of a key. Signed-off-by: Hannes Reinecke <hare@suse.de>
Add a function to export a TLS key in the PSK interchange format as defined in the NVMe TCP transport specification. Signed-off-by: Hannes Reinecke <hare@suse.de>
Add a function to import a TLS key in the PSK interchange format as defined in the NVMe TCP transport specification. Signed-off-by: Hannes Reinecke <hare@suse.de>
We really should not update existing keys as this will confuse existing users of that key. Rather we should revoke the old key and insert a new one. Signed-off-by: Hannes Reinecke <hare@suse.de>
Use the default '.nvme' keyring when nvme_lookup_keyring() is called with a NULL argument. Signed-off-by: Hannes Reinecke <hare@suse.de>
nvme_configure_ctrl() is reading the values from sysfs, so we should be reading the TLS key, too, if present. Signed-off-by: Hannes Reinecke <hare@suse.de>
Rather than printing the key serial number (which will only be valid for this session) we should be exporting the actual key in PSK interchange format to make it persistent across reboots. Signed-off-by: Hannes Reinecke <hare@suse.de>
As now the JSON configuration file holds the TLS key in PSK interchange format we should be parsing that key and inserting it into the kernel keystore to make it available for TLS. Signed-off-by: Hannes Reinecke <hare@suse.de>
TLS keys and keyrings are stored as strings, not as integers. Signed-off-by: Hannes Reinecke <hare@suse.de>
The keyring identifier is a 'long', not an integer. Signed-off-by: Hannes Reinecke <hare@suse.de>
182ce01
to
beaa3c9
Compare
"tls_key": { | ||
"description": "TLS key for the connection", | ||
"type": "string" | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these changes should be in config-schema.json.in
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course.
@@ -0,0 +1,100 @@ | |||
// SPDX-License-Identifier: GPL-2.0-or-later |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The library is LGPL 2.1. So this is not compatible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sadly, Rustys code is for crc32c (not crc32), and the crc source code from ccan also has GPLv2. So ccan doesn't help. The second implementation should be fine, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But ever so slightly complicated to use. Switching to the freebsd implementation, which actually has a copy with a permissible license.
@@ -0,0 +1,11 @@ | |||
/* SPDX-License-Identifier: GPL-2.0-or-later */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again this license doesn't work for the library.
* @key_len: Length of @key_data | ||
* | ||
* Returns @key_data in the PSK Interchange format as defined in section | ||
* 3.6.1.5 of the NVMe TCP Transport specification. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and NULL with errno set in failure case.
I suppose updating the docs would also be good. |
This approach should be generalized in order to be future-proof, and because Keys can be retrieved directly from the json string text, from a file on the file system, or from a socket. Independently from how they are retrieved, keys can be unencrypted or encrypted, to be decrypted either with a user-supplied pass phrase, a PKCS#11 or FIDO2 key, or a TPM (where in the latter case the decryption can additionally be bound to a set of PCRs), or any other method that the security people may come up with in the future. Therefore I propose to use some sort of URI format for
An addition to that, we could add a Obviously, we don't need to implement this now, but we should make sure that we don't need to change the syntax when we add features. |
In principle a good idea. But how do we differentiate which format to use when writing out the json config file? |
And there another issue. we have the option '--tls' (indicating that we should start TLS, and use the default key), and the option '--tls_key' (indicating that we should be using the specified TLS key. But once the TLS connection is started the negotiated key serial is presented in the 'tls_key' sysfs entry. But there is no indicator whether this was the default TLS key or the user-specified one. So with the current interface we cannot reliably write the configuration file from a given connection, ie 'nvme config --dump --scan' will always write 'tls_key', but won't be able to figure out if 'tls' was given. |
A key that can be replaced by key rotation is by definition not "persistent", is it? We shouldn't store such keys in a static configuration file. As far as I understand TP 8018, this applies to generated PSKs. Updating rotaded keys in the kernel keyring should indeed be the responsibility of some external entity 1. IMO that means that we don't need a We could have a Hope this makes sense, I'm still trying to understand how all this works together. Footnotes
|
Remember: 'retained key' != 'persistent key'. A 'retained key' is everything which is not auto-generated via 'secure concatenation'. As the patchset for this is still pending (and needs reviews, BTW) the current code only supports 'retained keys'. |
Maybe: |
The way I read TP8018, it's possible but not allowed for retained keys. At least that's my understanding of Fig. 18, which says that the retained key is "retained indefinitely", whereas the generated PSK is "replaced periodically or on demand".
I think this kind of key rotation, irrespective whether allowed or not, could be made work by changing the key selection code in |
Authoritative answer from NVMexpress: The statement in figure 518 for Retained PSK: (retained indefinitely, associate with the hash of the selected cipher suite) is not intended to read 'retained permanently'. 'Indefinitely' here simply means: without a defined limit, ie no limit is given by the spec. But there might be limit imposed externally, and retained keys can be rotated. |
Superseded by #786 . |
Hi all,
this pull request implements persistent TLS key handling. The original idea of storing the key serial number in the JSON configuration file doesn't really work out as the key serial number is ephemeral, and might change whenever a key is updated/revoked or somesuch. So after a reboot the key won't be present, the we won't be able to load the keys at all.
With the pull request we now store the TLS keys in 'PSK interchange format' as mandated in the NVMe TCP transport specification, which then contains the actual key data. And, obviously, the parser has been updated to read the TLS keys
from the PSK interchange format, too.
With that we fixup a design flaw in the JSON configuration, and ensure that TLS keys are persistent across reboots.