From eed0e3d305530066b4fc5370107cff8ef1a0d229 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 9 Aug 2025 10:19:39 -0700 Subject: [PATCH 1/5] KEYS: trusted_tpm1: Compare HMAC values in constant time To prevent timing attacks, HMAC value comparison needs to be constant time. Replace the memcmp() with the correct function, crypto_memneq(). [For the Fixes commit I used the commit that introduced the memcmp(). It predates the introduction of crypto_memneq(), but it was still a bug at the time even though a helper function didn't exist yet.] Fixes: d00a1c72f7f4 ("keys: add new trusted key-type") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- security/keys/trusted-keys/trusted_tpm1.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c index 89c9798d1800..e73f2c6c817a 100644 --- a/security/keys/trusted-keys/trusted_tpm1.c +++ b/security/keys/trusted-keys/trusted_tpm1.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -241,7 +242,7 @@ int TSS_checkhmac1(unsigned char *buffer, if (ret < 0) goto out; - if (memcmp(testhmac, authdata, SHA1_DIGEST_SIZE)) + if (crypto_memneq(testhmac, authdata, SHA1_DIGEST_SIZE)) ret = -EINVAL; out: kfree_sensitive(sdesc); @@ -334,7 +335,7 @@ static int TSS_checkhmac2(unsigned char *buffer, TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0); if (ret < 0) goto out; - if (memcmp(testhmac1, authdata1, SHA1_DIGEST_SIZE)) { + if (crypto_memneq(testhmac1, authdata1, SHA1_DIGEST_SIZE)) { ret = -EINVAL; goto out; } @@ -343,7 +344,7 @@ static int TSS_checkhmac2(unsigned char *buffer, TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0); if (ret < 0) goto out; - if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE)) + if (crypto_memneq(testhmac2, authdata2, SHA1_DIGEST_SIZE)) ret = -EINVAL; out: kfree_sensitive(sdesc); From 366284cfbc8ff4110c00fc23285449f53df739a7 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 9 Aug 2025 10:19:40 -0700 Subject: [PATCH 2/5] KEYS: trusted_tpm1: Use SHA-1 library instead of crypto_shash Use the SHA-1 and HMAC-SHA1 library functions instead of crypto_shash. This is simpler and faster. Replace the selection of CRYPTO, CRYPTO_HMAC, and CRYPTO_SHA1 with CRYPTO_LIB_SHA1 and CRYPTO_LIB_UTILS. The latter is needed for crypto_memneq() which was previously being pulled in via CRYPTO. Signed-off-by: Eric Biggers Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- security/keys/trusted-keys/Kconfig | 5 +- security/keys/trusted-keys/trusted_tpm1.c | 221 ++++------------------ 2 files changed, 36 insertions(+), 190 deletions(-) diff --git a/security/keys/trusted-keys/Kconfig b/security/keys/trusted-keys/Kconfig index 1fb8aa001995..204a68c1429d 100644 --- a/security/keys/trusted-keys/Kconfig +++ b/security/keys/trusted-keys/Kconfig @@ -5,10 +5,9 @@ config TRUSTED_KEYS_TPM bool "TPM-based trusted keys" depends on TCG_TPM >= TRUSTED_KEYS default y - select CRYPTO - select CRYPTO_HMAC - select CRYPTO_SHA1 select CRYPTO_HASH_INFO + select CRYPTO_LIB_SHA1 + select CRYPTO_LIB_UTILS select ASN1_ENCODER select OID_REGISTRY select ASN1 diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c index e73f2c6c817a..126437459a74 100644 --- a/security/keys/trusted-keys/trusted_tpm1.c +++ b/security/keys/trusted-keys/trusted_tpm1.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -15,78 +16,24 @@ #include #include #include -#include -#include -#include #include #include #include -static const char hmac_alg[] = "hmac(sha1)"; -static const char hash_alg[] = "sha1"; static struct tpm_chip *chip; static struct tpm_digest *digests; -struct sdesc { - struct shash_desc shash; - char ctx[]; -}; - -static struct crypto_shash *hashalg; -static struct crypto_shash *hmacalg; - -static struct sdesc *init_sdesc(struct crypto_shash *alg) -{ - struct sdesc *sdesc; - int size; - - size = sizeof(struct shash_desc) + crypto_shash_descsize(alg); - sdesc = kmalloc(size, GFP_KERNEL); - if (!sdesc) - return ERR_PTR(-ENOMEM); - sdesc->shash.tfm = alg; - return sdesc; -} - -static int TSS_sha1(const unsigned char *data, unsigned int datalen, - unsigned char *digest) -{ - struct sdesc *sdesc; - int ret; - - sdesc = init_sdesc(hashalg); - if (IS_ERR(sdesc)) { - pr_info("can't alloc %s\n", hash_alg); - return PTR_ERR(sdesc); - } - - ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest); - kfree_sensitive(sdesc); - return ret; -} - static int TSS_rawhmac(unsigned char *digest, const unsigned char *key, unsigned int keylen, ...) { - struct sdesc *sdesc; + struct hmac_sha1_ctx hmac_ctx; va_list argp; unsigned int dlen; unsigned char *data; - int ret; + int ret = 0; - sdesc = init_sdesc(hmacalg); - if (IS_ERR(sdesc)) { - pr_info("can't alloc %s\n", hmac_alg); - return PTR_ERR(sdesc); - } - - ret = crypto_shash_setkey(hmacalg, key, keylen); - if (ret < 0) - goto out; - ret = crypto_shash_init(&sdesc->shash); - if (ret < 0) - goto out; + hmac_sha1_init_usingrawkey(&hmac_ctx, key, keylen); va_start(argp, keylen); for (;;) { @@ -98,15 +45,11 @@ static int TSS_rawhmac(unsigned char *digest, const unsigned char *key, ret = -EINVAL; break; } - ret = crypto_shash_update(&sdesc->shash, data, dlen); - if (ret < 0) - break; + hmac_sha1_update(&hmac_ctx, data, dlen); } va_end(argp); if (!ret) - ret = crypto_shash_final(&sdesc->shash, digest); -out: - kfree_sensitive(sdesc); + hmac_sha1_final(&hmac_ctx, digest); return ret; } @@ -118,26 +61,18 @@ int TSS_authhmac(unsigned char *digest, const unsigned char *key, unsigned char *h2, unsigned int h3, ...) { unsigned char paramdigest[SHA1_DIGEST_SIZE]; - struct sdesc *sdesc; + struct sha1_ctx sha_ctx; unsigned int dlen; unsigned char *data; unsigned char c; - int ret; + int ret = 0; va_list argp; if (!chip) return -ENODEV; - sdesc = init_sdesc(hashalg); - if (IS_ERR(sdesc)) { - pr_info("can't alloc %s\n", hash_alg); - return PTR_ERR(sdesc); - } - c = !!h3; - ret = crypto_shash_init(&sdesc->shash); - if (ret < 0) - goto out; + sha1_init(&sha_ctx); va_start(argp, h3); for (;;) { dlen = va_arg(argp, unsigned int); @@ -148,19 +83,15 @@ int TSS_authhmac(unsigned char *digest, const unsigned char *key, ret = -EINVAL; break; } - ret = crypto_shash_update(&sdesc->shash, data, dlen); - if (ret < 0) - break; + sha1_update(&sha_ctx, data, dlen); } va_end(argp); if (!ret) - ret = crypto_shash_final(&sdesc->shash, paramdigest); + sha1_final(&sha_ctx, paramdigest); if (!ret) ret = TSS_rawhmac(digest, key, keylen, SHA1_DIGEST_SIZE, paramdigest, TPM_NONCE_SIZE, h1, TPM_NONCE_SIZE, h2, 1, &c, 0, 0); -out: - kfree_sensitive(sdesc); return ret; } EXPORT_SYMBOL_GPL(TSS_authhmac); @@ -183,7 +114,7 @@ int TSS_checkhmac1(unsigned char *buffer, unsigned char *authdata; unsigned char testhmac[SHA1_DIGEST_SIZE]; unsigned char paramdigest[SHA1_DIGEST_SIZE]; - struct sdesc *sdesc; + struct sha1_ctx sha_ctx; unsigned int dlen; unsigned int dpos; va_list argp; @@ -204,49 +135,29 @@ int TSS_checkhmac1(unsigned char *buffer, continueflag = authdata - 1; enonce = continueflag - TPM_NONCE_SIZE; - sdesc = init_sdesc(hashalg); - if (IS_ERR(sdesc)) { - pr_info("can't alloc %s\n", hash_alg); - return PTR_ERR(sdesc); - } - ret = crypto_shash_init(&sdesc->shash); - if (ret < 0) - goto out; - ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result, - sizeof result); - if (ret < 0) - goto out; - ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal, - sizeof ordinal); - if (ret < 0) - goto out; + sha1_init(&sha_ctx); + sha1_update(&sha_ctx, (const u8 *)&result, sizeof(result)); + sha1_update(&sha_ctx, (const u8 *)&ordinal, sizeof(ordinal)); va_start(argp, keylen); for (;;) { dlen = va_arg(argp, unsigned int); if (dlen == 0) break; dpos = va_arg(argp, unsigned int); - ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen); - if (ret < 0) - break; + sha1_update(&sha_ctx, buffer + dpos, dlen); } va_end(argp); - if (!ret) - ret = crypto_shash_final(&sdesc->shash, paramdigest); - if (ret < 0) - goto out; + sha1_final(&sha_ctx, paramdigest); ret = TSS_rawhmac(testhmac, key, keylen, SHA1_DIGEST_SIZE, paramdigest, TPM_NONCE_SIZE, enonce, TPM_NONCE_SIZE, ononce, 1, continueflag, 0, 0); if (ret < 0) - goto out; + return ret; if (crypto_memneq(testhmac, authdata, SHA1_DIGEST_SIZE)) - ret = -EINVAL; -out: - kfree_sensitive(sdesc); - return ret; + return -EINVAL; + return 0; } EXPORT_SYMBOL_GPL(TSS_checkhmac1); @@ -274,7 +185,7 @@ static int TSS_checkhmac2(unsigned char *buffer, unsigned char testhmac1[SHA1_DIGEST_SIZE]; unsigned char testhmac2[SHA1_DIGEST_SIZE]; unsigned char paramdigest[SHA1_DIGEST_SIZE]; - struct sdesc *sdesc; + struct sha1_ctx sha_ctx; unsigned int dlen; unsigned int dpos; va_list argp; @@ -297,22 +208,9 @@ static int TSS_checkhmac2(unsigned char *buffer, enonce1 = continueflag1 - TPM_NONCE_SIZE; enonce2 = continueflag2 - TPM_NONCE_SIZE; - sdesc = init_sdesc(hashalg); - if (IS_ERR(sdesc)) { - pr_info("can't alloc %s\n", hash_alg); - return PTR_ERR(sdesc); - } - ret = crypto_shash_init(&sdesc->shash); - if (ret < 0) - goto out; - ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result, - sizeof result); - if (ret < 0) - goto out; - ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal, - sizeof ordinal); - if (ret < 0) - goto out; + sha1_init(&sha_ctx); + sha1_update(&sha_ctx, (const u8 *)&result, sizeof(result)); + sha1_update(&sha_ctx, (const u8 *)&ordinal, sizeof(ordinal)); va_start(argp, keylen2); for (;;) { @@ -320,35 +218,26 @@ static int TSS_checkhmac2(unsigned char *buffer, if (dlen == 0) break; dpos = va_arg(argp, unsigned int); - ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen); - if (ret < 0) - break; + sha1_update(&sha_ctx, buffer + dpos, dlen); } va_end(argp); - if (!ret) - ret = crypto_shash_final(&sdesc->shash, paramdigest); - if (ret < 0) - goto out; + sha1_final(&sha_ctx, paramdigest); ret = TSS_rawhmac(testhmac1, key1, keylen1, SHA1_DIGEST_SIZE, paramdigest, TPM_NONCE_SIZE, enonce1, TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0); if (ret < 0) - goto out; - if (crypto_memneq(testhmac1, authdata1, SHA1_DIGEST_SIZE)) { - ret = -EINVAL; - goto out; - } + return ret; + if (crypto_memneq(testhmac1, authdata1, SHA1_DIGEST_SIZE)) + return -EINVAL; ret = TSS_rawhmac(testhmac2, key2, keylen2, SHA1_DIGEST_SIZE, paramdigest, TPM_NONCE_SIZE, enonce2, TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0); if (ret < 0) - goto out; + return ret; if (crypto_memneq(testhmac2, authdata2, SHA1_DIGEST_SIZE)) - ret = -EINVAL; -out: - kfree_sensitive(sdesc); - return ret; + return -EINVAL; + return 0; } /* @@ -499,9 +388,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype, /* calculate encrypted authorization value */ memcpy(td->xorwork, sess.secret, SHA1_DIGEST_SIZE); memcpy(td->xorwork + SHA1_DIGEST_SIZE, sess.enonce, SHA1_DIGEST_SIZE); - ret = TSS_sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash); - if (ret < 0) - goto out; + sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash); ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE); if (ret < 0) @@ -990,40 +877,6 @@ static int trusted_tpm_get_random(unsigned char *key, size_t key_len) return tpm_get_random(chip, key, key_len); } -static void trusted_shash_release(void) -{ - if (hashalg) - crypto_free_shash(hashalg); - if (hmacalg) - crypto_free_shash(hmacalg); -} - -static int __init trusted_shash_alloc(void) -{ - int ret; - - hmacalg = crypto_alloc_shash(hmac_alg, 0, 0); - if (IS_ERR(hmacalg)) { - pr_info("could not allocate crypto %s\n", - hmac_alg); - return PTR_ERR(hmacalg); - } - - hashalg = crypto_alloc_shash(hash_alg, 0, 0); - if (IS_ERR(hashalg)) { - pr_info("could not allocate crypto %s\n", - hash_alg); - ret = PTR_ERR(hashalg); - goto hashalg_fail; - } - - return 0; - -hashalg_fail: - crypto_free_shash(hmacalg); - return ret; -} - static int __init init_digests(void) { int i; @@ -1050,15 +903,10 @@ static int __init trusted_tpm_init(void) ret = init_digests(); if (ret < 0) goto err_put; - ret = trusted_shash_alloc(); - if (ret < 0) - goto err_free; ret = register_key_type(&key_type_trusted); if (ret < 0) - goto err_release; + goto err_free; return 0; -err_release: - trusted_shash_release(); err_free: kfree(digests); err_put: @@ -1071,7 +919,6 @@ static void trusted_tpm_exit(void) if (chip) { put_device(&chip->dev); kfree(digests); - trusted_shash_release(); unregister_key_type(&key_type_trusted); } } From 720a485d12c590750f40f4ffbe41e36725f43f3d Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 9 Aug 2025 10:19:41 -0700 Subject: [PATCH 3/5] KEYS: trusted_tpm1: Move private functionality out of public header Move functionality used only by trusted_tpm1.c out of the public header . Specifically, change the exported functions into static functions, since they are not used outside trusted_tpm1.c, and move various other definitions and inline functions to trusted_tpm1.c. Signed-off-by: Eric Biggers Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- include/keys/trusted_tpm.h | 79 ---------------------- security/keys/trusted-keys/trusted_tpm1.c | 80 ++++++++++++++++++++--- 2 files changed, 72 insertions(+), 87 deletions(-) diff --git a/include/keys/trusted_tpm.h b/include/keys/trusted_tpm.h index a088b33fd0e3..0fadc6a4f166 100644 --- a/include/keys/trusted_tpm.h +++ b/include/keys/trusted_tpm.h @@ -5,41 +5,8 @@ #include #include -/* implementation specific TPM constants */ -#define TPM_SIZE_OFFSET 2 -#define TPM_RETURN_OFFSET 6 -#define TPM_DATA_OFFSET 10 - -#define LOAD32(buffer, offset) (ntohl(*(uint32_t *)&buffer[offset])) -#define LOAD32N(buffer, offset) (*(uint32_t *)&buffer[offset]) -#define LOAD16(buffer, offset) (ntohs(*(uint16_t *)&buffer[offset])) - extern struct trusted_key_ops trusted_key_tpm_ops; -struct osapsess { - uint32_t handle; - unsigned char secret[SHA1_DIGEST_SIZE]; - unsigned char enonce[TPM_NONCE_SIZE]; -}; - -/* discrete values, but have to store in uint16_t for TPM use */ -enum { - SEAL_keytype = 1, - SRK_keytype = 4 -}; - -int TSS_authhmac(unsigned char *digest, const unsigned char *key, - unsigned int keylen, unsigned char *h1, - unsigned char *h2, unsigned int h3, ...); -int TSS_checkhmac1(unsigned char *buffer, - const uint32_t command, - const unsigned char *ononce, - const unsigned char *key, - unsigned int keylen, ...); - -int trusted_tpm_send(unsigned char *cmd, size_t buflen); -int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce); - int tpm2_seal_trusted(struct tpm_chip *chip, struct trusted_key_payload *payload, struct trusted_key_options *options); @@ -47,50 +14,4 @@ int tpm2_unseal_trusted(struct tpm_chip *chip, struct trusted_key_payload *payload, struct trusted_key_options *options); -#define TPM_DEBUG 0 - -#if TPM_DEBUG -static inline void dump_options(struct trusted_key_options *o) -{ - pr_info("sealing key type %d\n", o->keytype); - pr_info("sealing key handle %0X\n", o->keyhandle); - pr_info("pcrlock %d\n", o->pcrlock); - pr_info("pcrinfo %d\n", o->pcrinfo_len); - print_hex_dump(KERN_INFO, "pcrinfo ", DUMP_PREFIX_NONE, - 16, 1, o->pcrinfo, o->pcrinfo_len, 0); -} - -static inline void dump_sess(struct osapsess *s) -{ - print_hex_dump(KERN_INFO, "trusted-key: handle ", DUMP_PREFIX_NONE, - 16, 1, &s->handle, 4, 0); - pr_info("secret:\n"); - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, - 16, 1, &s->secret, SHA1_DIGEST_SIZE, 0); - pr_info("trusted-key: enonce:\n"); - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, - 16, 1, &s->enonce, SHA1_DIGEST_SIZE, 0); -} - -static inline void dump_tpm_buf(unsigned char *buf) -{ - int len; - - pr_info("\ntpm buffer\n"); - len = LOAD32(buf, TPM_SIZE_OFFSET); - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf, len, 0); -} -#else -static inline void dump_options(struct trusted_key_options *o) -{ -} - -static inline void dump_sess(struct osapsess *s) -{ -} - -static inline void dump_tpm_buf(unsigned char *buf) -{ -} -#endif #endif diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c index 126437459a74..636acb66a4f6 100644 --- a/security/keys/trusted-keys/trusted_tpm1.c +++ b/security/keys/trusted-keys/trusted_tpm1.c @@ -24,6 +24,74 @@ static struct tpm_chip *chip; static struct tpm_digest *digests; +/* implementation specific TPM constants */ +#define TPM_SIZE_OFFSET 2 +#define TPM_RETURN_OFFSET 6 +#define TPM_DATA_OFFSET 10 + +#define LOAD32(buffer, offset) (ntohl(*(uint32_t *)&buffer[offset])) +#define LOAD32N(buffer, offset) (*(uint32_t *)&buffer[offset]) +#define LOAD16(buffer, offset) (ntohs(*(uint16_t *)&buffer[offset])) + +struct osapsess { + uint32_t handle; + unsigned char secret[SHA1_DIGEST_SIZE]; + unsigned char enonce[TPM_NONCE_SIZE]; +}; + +/* discrete values, but have to store in uint16_t for TPM use */ +enum { + SEAL_keytype = 1, + SRK_keytype = 4 +}; + +#define TPM_DEBUG 0 + +#if TPM_DEBUG +static inline void dump_options(struct trusted_key_options *o) +{ + pr_info("sealing key type %d\n", o->keytype); + pr_info("sealing key handle %0X\n", o->keyhandle); + pr_info("pcrlock %d\n", o->pcrlock); + pr_info("pcrinfo %d\n", o->pcrinfo_len); + print_hex_dump(KERN_INFO, "pcrinfo ", DUMP_PREFIX_NONE, + 16, 1, o->pcrinfo, o->pcrinfo_len, 0); +} + +static inline void dump_sess(struct osapsess *s) +{ + print_hex_dump(KERN_INFO, "trusted-key: handle ", DUMP_PREFIX_NONE, + 16, 1, &s->handle, 4, 0); + pr_info("secret:\n"); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, + 16, 1, &s->secret, SHA1_DIGEST_SIZE, 0); + pr_info("trusted-key: enonce:\n"); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, + 16, 1, &s->enonce, SHA1_DIGEST_SIZE, 0); +} + +static inline void dump_tpm_buf(unsigned char *buf) +{ + int len; + + pr_info("\ntpm buffer\n"); + len = LOAD32(buf, TPM_SIZE_OFFSET); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf, len, 0); +} +#else +static inline void dump_options(struct trusted_key_options *o) +{ +} + +static inline void dump_sess(struct osapsess *s) +{ +} + +static inline void dump_tpm_buf(unsigned char *buf) +{ +} +#endif + static int TSS_rawhmac(unsigned char *digest, const unsigned char *key, unsigned int keylen, ...) { @@ -56,7 +124,7 @@ static int TSS_rawhmac(unsigned char *digest, const unsigned char *key, /* * calculate authorization info fields to send to TPM */ -int TSS_authhmac(unsigned char *digest, const unsigned char *key, +static int TSS_authhmac(unsigned char *digest, const unsigned char *key, unsigned int keylen, unsigned char *h1, unsigned char *h2, unsigned int h3, ...) { @@ -94,12 +162,11 @@ int TSS_authhmac(unsigned char *digest, const unsigned char *key, TPM_NONCE_SIZE, h2, 1, &c, 0, 0); return ret; } -EXPORT_SYMBOL_GPL(TSS_authhmac); /* * verify the AUTH1_COMMAND (Seal) result from TPM */ -int TSS_checkhmac1(unsigned char *buffer, +static int TSS_checkhmac1(unsigned char *buffer, const uint32_t command, const unsigned char *ononce, const unsigned char *key, @@ -159,7 +226,6 @@ int TSS_checkhmac1(unsigned char *buffer, return -EINVAL; return 0; } -EXPORT_SYMBOL_GPL(TSS_checkhmac1); /* * verify the AUTH2_COMMAND (unseal) result from TPM @@ -244,7 +310,7 @@ static int TSS_checkhmac2(unsigned char *buffer, * For key specific tpm requests, we will generate and send our * own TPM command packets using the drivers send function. */ -int trusted_tpm_send(unsigned char *cmd, size_t buflen) +static int trusted_tpm_send(unsigned char *cmd, size_t buflen) { struct tpm_buf buf; int rc; @@ -270,7 +336,6 @@ int trusted_tpm_send(unsigned char *cmd, size_t buflen) tpm_put_ops(chip); return rc; } -EXPORT_SYMBOL_GPL(trusted_tpm_send); /* * Lock a trusted key, by extending a selected PCR. @@ -324,7 +389,7 @@ static int osap(struct tpm_buf *tb, struct osapsess *s, /* * Create an object independent authorisation protocol (oiap) session */ -int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce) +static int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce) { int ret; @@ -341,7 +406,6 @@ int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce) TPM_NONCE_SIZE); return 0; } -EXPORT_SYMBOL_GPL(oiap); struct tpm_digests { unsigned char encauth[SHA1_DIGEST_SIZE]; From 9b8d24a49fe83787208479d51f320cead25e856c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 15 Sep 2025 21:14:43 +0300 Subject: [PATCH 4/5] KEYS: encrypted: Use SHA-256 library instead of crypto_shash Instead of the "sha256" crypto_shash, just use sha256(). Similarly, instead of the "hmac(sha256)" crypto_shash, just use hmac_sha256_usingrawkey(). This is simpler and faster. Signed-off-by: Eric Biggers Reviewed-by: Jarkko Sakkinen Reviewed-by: Mimi Zohar Signed-off-by: Jarkko Sakkinen --- security/keys/Kconfig | 3 +- security/keys/encrypted-keys/encrypted.c | 63 ++++-------------------- 2 files changed, 11 insertions(+), 55 deletions(-) diff --git a/security/keys/Kconfig b/security/keys/Kconfig index d4f5fc1e7263..64477e2c4a21 100644 --- a/security/keys/Kconfig +++ b/security/keys/Kconfig @@ -87,10 +87,9 @@ config ENCRYPTED_KEYS tristate "ENCRYPTED KEYS" depends on KEYS select CRYPTO - select CRYPTO_HMAC select CRYPTO_AES select CRYPTO_CBC - select CRYPTO_SHA256 + select CRYPTO_LIB_SHA256 select CRYPTO_RNG help This option provides support for create/encrypting/decrypting keys diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 831cb84fd75a..513c09e2b01c 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -37,8 +36,6 @@ static const char KEY_TRUSTED_PREFIX[] = "trusted:"; static const char KEY_USER_PREFIX[] = "user:"; -static const char hash_alg[] = "sha256"; -static const char hmac_alg[] = "hmac(sha256)"; static const char blkcipher_alg[] = "cbc(aes)"; static const char key_format_default[] = "default"; static const char key_format_ecryptfs[] = "ecryptfs"; @@ -54,8 +51,6 @@ static int blksize; #define MIN_DATA_SIZE 20 #define KEY_ENC32_PAYLOAD_LEN 32 -static struct crypto_shash *hash_tfm; - enum { Opt_new, Opt_load, Opt_update, Opt_err }; @@ -329,26 +324,6 @@ error: return ukey; } -static int calc_hmac(u8 *digest, const u8 *key, unsigned int keylen, - const u8 *buf, unsigned int buflen) -{ - struct crypto_shash *tfm; - int err; - - tfm = crypto_alloc_shash(hmac_alg, 0, 0); - if (IS_ERR(tfm)) { - pr_err("encrypted_key: can't alloc %s transform: %ld\n", - hmac_alg, PTR_ERR(tfm)); - return PTR_ERR(tfm); - } - - err = crypto_shash_setkey(tfm, key, keylen); - if (!err) - err = crypto_shash_tfm_digest(tfm, buf, buflen, digest); - crypto_free_shash(tfm); - return err; -} - enum derived_key_type { ENC_KEY, AUTH_KEY }; /* Derive authentication/encryption key from trusted key */ @@ -357,7 +332,6 @@ static int get_derived_key(u8 *derived_key, enum derived_key_type key_type, { u8 *derived_buf; unsigned int derived_buf_len; - int ret; derived_buf_len = strlen("AUTH_KEY") + 1 + master_keylen; if (derived_buf_len < HASH_SIZE) @@ -374,10 +348,9 @@ static int get_derived_key(u8 *derived_key, enum derived_key_type key_type, memcpy(derived_buf + strlen(derived_buf) + 1, master_key, master_keylen); - ret = crypto_shash_tfm_digest(hash_tfm, derived_buf, derived_buf_len, - derived_key); + sha256(derived_buf, derived_buf_len, derived_key); kfree_sensitive(derived_buf); - return ret; + return 0; } static struct skcipher_request *init_skcipher_req(const u8 *key, @@ -503,10 +476,10 @@ static int datablob_hmac_append(struct encrypted_key_payload *epayload, goto out; digest = epayload->format + epayload->datablob_len; - ret = calc_hmac(digest, derived_key, sizeof derived_key, - epayload->format, epayload->datablob_len); - if (!ret) - dump_hmac(NULL, digest, HASH_SIZE); + hmac_sha256_usingrawkey(derived_key, sizeof(derived_key), + epayload->format, epayload->datablob_len, + digest); + dump_hmac(NULL, digest, HASH_SIZE); out: memzero_explicit(derived_key, sizeof(derived_key)); return ret; @@ -534,9 +507,8 @@ static int datablob_hmac_verify(struct encrypted_key_payload *epayload, } else p = epayload->format; - ret = calc_hmac(digest, derived_key, sizeof derived_key, p, len); - if (ret < 0) - goto out; + hmac_sha256_usingrawkey(derived_key, sizeof(derived_key), p, len, + digest); ret = crypto_memneq(digest, epayload->format + epayload->datablob_len, sizeof(digest)); if (ret) { @@ -1011,29 +983,14 @@ static int __init init_encrypted(void) { int ret; - hash_tfm = crypto_alloc_shash(hash_alg, 0, 0); - if (IS_ERR(hash_tfm)) { - pr_err("encrypted_key: can't allocate %s transform: %ld\n", - hash_alg, PTR_ERR(hash_tfm)); - return PTR_ERR(hash_tfm); - } - ret = aes_get_sizes(); if (ret < 0) - goto out; - ret = register_key_type(&key_type_encrypted); - if (ret < 0) - goto out; - return 0; -out: - crypto_free_shash(hash_tfm); - return ret; - + return ret; + return register_key_type(&key_type_encrypted); } static void __exit cleanup_encrypted(void) { - crypto_free_shash(hash_tfm); unregister_key_type(&key_type_encrypted); } From 8be70a8fc667c33e69257a72e8092f07c828241e Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 27 Sep 2025 21:14:20 +0300 Subject: [PATCH 5/5] security: keys: use menuconfig for KEYS symbol Give the KEYS kconfig symbol and its associated symbols a separate menu space under Security options by using "menuconfig" instead of "config". This also makes it easier to find the security and LSM options. Signed-off-by: Randy Dunlap Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- security/keys/Kconfig | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/security/keys/Kconfig b/security/keys/Kconfig index 64477e2c4a21..84f39e50ca36 100644 --- a/security/keys/Kconfig +++ b/security/keys/Kconfig @@ -3,7 +3,7 @@ # Key management configuration # -config KEYS +menuconfig KEYS bool "Enable access key retention support" select ASSOCIATIVE_ARRAY help @@ -21,9 +21,10 @@ config KEYS If you are unsure as to whether this is required, answer N. +if KEYS + config KEYS_REQUEST_CACHE bool "Enable temporary caching of the last request_key() result" - depends on KEYS help This option causes the result of the last successful request_key() call that didn't upcall to the kernel to be cached temporarily in the @@ -41,7 +42,6 @@ config KEYS_REQUEST_CACHE config PERSISTENT_KEYRINGS bool "Enable register of persistent per-UID keyrings" - depends on KEYS help This option provides a register of persistent per-UID keyrings, primarily aimed at Kerberos key storage. The keyrings are persistent @@ -58,7 +58,6 @@ config PERSISTENT_KEYRINGS config BIG_KEYS bool "Large payload keys" - depends on KEYS depends on TMPFS select CRYPTO_LIB_CHACHA20POLY1305 help @@ -70,7 +69,6 @@ config BIG_KEYS config TRUSTED_KEYS tristate "TRUSTED KEYS" - depends on KEYS help This option provides support for creating, sealing, and unsealing keys in the kernel. Trusted keys are random number symmetric keys, @@ -85,7 +83,6 @@ endif config ENCRYPTED_KEYS tristate "ENCRYPTED KEYS" - depends on KEYS select CRYPTO select CRYPTO_AES select CRYPTO_CBC @@ -113,7 +110,6 @@ config USER_DECRYPTED_DATA config KEY_DH_OPERATIONS bool "Diffie-Hellman operations on retained keys" - depends on KEYS select CRYPTO select CRYPTO_KDF800108_CTR select CRYPTO_DH @@ -126,9 +122,11 @@ config KEY_DH_OPERATIONS config KEY_NOTIFICATIONS bool "Provide key/keyring change notifications" - depends on KEYS && WATCH_QUEUE + depends on WATCH_QUEUE help This option provides support for getting change notifications on keys and keyrings on which the caller has View permission. This makes use of pipes to handle the notification buffer and provides KEYCTL_WATCH_KEY to enable/disable watches. + +endif # KEYS