On Sat, May 4, 2024 at 5:35 PM Jarkko Sakkinen <jarkko@xxxxxxxxxx> wrote: > > On Sat May 4, 2024 at 5:51 PM EEST, Jarkko Sakkinen wrote: > > On Sat May 4, 2024 at 4:55 PM EEST, Ben Boeckel wrote: > > > On Sat, May 04, 2024 at 03:21:11 +0300, Jarkko Sakkinen wrote: > > > > I have no idea for what the key created with this is even used, which > > > > makes this impossible to review. > > > > > > Additionally, there is nothing in Documentation/ for how userspace might > > > use or create them. This includes things like their description format > > > and describing available options. > > > > The whole user story is plain out broken. Documenting a feature that has > > no provable use case won't fix that part. > > > > So it is better to start with the cover letter. With the *existing* > > knowledge of the *real* issue I don't think we need this tbh. > > As for code I'd suggest the "Describe your changes" part from > > https://www.kernel.org/doc/html/latest/process/submitting-patches.html > > and most essentially how to split them properly. > > My best bet could something along the lines that perhaps there is some > issue to be sorted out but I don't honestly believe that this will ever > be a solution for any possible problem that exist in this planet. Sorry, I must admit I wrote the description hastingly and too high-level (it was pre-travelling, so probably not the right focus and in a rush). Let me restart from scratch and describe particular use-cases we're concerned about: Trusted and encrypted keys are a great way to manage cryptographic keys inside the kernel, while never exposing plaintext cryptographic material to userspace: keys can only be read to userspace as encrypted blobs and with trusted keys - these blobs are created with the TPM, so only the TPM can unwrap the blobs. One of the simplest way to create a trusted key is for an application to request the kernel to generate a new one [1], like below with the help of keyctl utility from keyutils: $ keyctl add trusted kmk "new 32 keyhandle=0x81000001" @u However, after the application generates a trusted key, it is the responsibility of the application to manage/store it. For example, if the application wants to reuse the key after a reboot, it needs to read the key into userspace as an encrypted blob and store it on persistent storage. This is challenging and sometimes not possible for stateless/immutable/ephemeral systems, so such systems are effectively locked out from using hardware-protected cryptographic keys. Another point: while the fact that the application can't read the plaintext cryptographic material into userspace is a feature of trusted keys, it can also be a disadvantage. Since keys in plaintext exist only in kernel context, they are useful mostly for in-kernel systems, like dm-crypt, IMA, ecryptfs. Applications cannot easily use trusted keys for cryptographic purposes for their own workloads: for example, generating encrypted or MACed configuration files or encrypting in-transit data. While since commit 7984ceb134bf ("crypto: af_alg - Support symmetric encryption via keyring keys") it is possible to use a trusted key via Linux Crypto API userspace interface [2], it might not always be practical/desirable: * due to limitations in the Linux Crypto API implementation it is not possible to process more than ~64Kb of data using AEAD ciphers [3] * needed algorithm implementations might not be enabled in the kernel configuration file * compliance constraints: the utilised cryptographic implementation must be FIPS-validated * performance constraints: passing large blobs of data to the kernel for encryption is slow even with Crypto API's "zero-copy" interface [3] TPM derived keys attempt to address the above use cases by allowing applications to deterministically derive unique cryptographic keys for their own purposes directly from the TPM seed in the owner hierarchy. The idea is that when an application requests a new key, instead of generating a random key and wrapping it with the TPM, the implementation generates a key via KDF(hierarchy seed, application specific info). Therefore, the resulting keys will always be cryptographically bound to the application itself and the device they were generated on. The applications then may either use in-kernel facilities, like [2], to do crypto operations inside the kernel, so the generated cryptographic material is never exposed to userspace (similar to trusted/encrypted keys). Or, if they are subject to performance/compliance/other constraints mentioned above, they can read the key material to userspace and use a userspace crypto library. Even with the latter approach they still get the benefit of using a key, security of which is rooted in the TPM. TPM derived keys also address the key storage problem for stateless/immutable/ephemeral systems: since the derivation process is deterministic, the same application can always re-create their keys on the same system and doesn't need to store or back up any wrapped key blobs. One notable use case (ironically not for a stateless system) can be setting up proper full-disk encryption (dm-crypt plain mode without a LUKS header), for example, to provide deniable encryption or better resiliency to damage of encrypted media [4]. Current implementation provides two options for KDF's input for application specific info to ensure key uniqueness: 1. A key, which is unique to a filesystem path: $ keyctl add derived test '32 path' Above will derive a 32 byte key based on the TPM seed and the filesystem path of the requesting application. That is /usr/bin/keyctl and /opt/bin/keyctl would generate different keys. 2. A key, which is cryptographically bound to the code of the requesting application: $ keyctl add derived test '32 csum' Above will derive a 32 byte key based on the TPM seed and the IMA measurement of the requesting application. That is /usr/bin/keyctl and /opt/bin/keyctl would generate the same key if and only if their code exactly matches bit for bit. The implementation does not measure the requesting binary itself, but rather relies on already available measurement. This means for this mode to work IMA needs to be enabled and configured for requesting applications. For example: # echo 'audit func=BPRM_CHECK' > \ /sys/kernel/security/integrity/ima/policy Open questions: * should any other modes/derivation parameters be considered as part of application specific info? * apparently in checksum mode, when calling keyring syscalls from scripts, we mix in the measurement of the interpreter, not the script itself. Is there any way to improve this? I would like to mention that in Cloudflare we have found large infrastructure key management based on derived keys from per-device unique seeds quite convenient and almost infinitely scalable and I believe TPM derived keys can be the next evolution bringing hardware security to the table. I understand that folks here are not required to follow links for additional information, but if someone is interested in more details for our approach, which has been working well for almost 9 years, see [5]. Hope it is better this time. Ignat [1]: https://www.kernel.org/doc/html/latest/security/keys/trusted-encrypted.html#examples-of-trusted-and-encrypted-key-usage [2]: https://www.kernel.org/doc/html/latest/crypto/userspace-if.html [3]: https://blog.cloudflare.com/the-linux-crypto-api-for-user-applications [4]: https://wiki.archlinux.org/title/Dm-crypt/Encrypting_an_entire_system#Plain_dm-crypt [5]: https://youtu.be/2RPcIbP2xsM?si=nKbyY0gss50i04CG > BR, Jarkko