crypto: Add __cleanup functions for zeroizing aes_cmac_key & aes_cmac_ctx
Subsystems (10)
v2 cover crypto: Add __cleanup functions for zeroizing aes_cmac_key & aes_cmac_ctx
Code that uses AES-CMAC might need to zeroize their local aes_cmac_key and/or aes_cmac_ctx structures after use to avoid leaking sensitive material on the stack.
The first patch introduces an aes_cmac_zeroize_key() and an aes_cmac_zeroize_ctx() helper function that can be used with __cleanup() to automatically clear the key and context when they go out of scope.
Patches 2 - 4 add the __cleanup markers to spots in the code that missed to clean up the structures so far.
The final two patches are just cosmetics and change some memzero_explicit() calls to use the __cleanup() way instead.
Note: There are more spots in the smb, tcp-ao and bluetooth code that need some zeroization of sensitive data on the stack. I will tackle those in later patches, this series here focuses on the new __cleanup wrappers.
v2:
- Update comments and positions of the functions in the 1st patch
- Also clear tmp[] in the bluetooth patch (the patch is pointless otherwise)
Thomas Huth (6):
crypto: Provide wrapper functions for zeroizing aes_cmac_key and
aes_cmac_ctx
smb: clear the aes_cmac_key and aes_cmac_ctx when done net/tcp-ao: clear the aes_cmac_key when done
Bluetooth: SMP: clear the aes_cmac_key when done lib/crypto: aes: Use _cleanup() for aes_cmac_key instead of
memzero_explicit()
mac80211: fils_aead: Use _cleanup for aes_cmac_key instead of
memzero_explicit
fs/smb/client/smb2transport.c | 4 ++-- fs/smb/server/auth.c | 2 +- include/crypto/aes-cbc-macs.h | 34 ++++++++++++++++++++++++++++++++++ lib/crypto/aes.c | 3 +-- net/bluetooth/smp.c | 3 ++- net/ipv4/tcp_ao.c | 2 +- net/mac80211/fils_aead.c | 3 +-- 7 files changed, 42 insertions(+), 9 deletions(-)
Signature · 1 line
2.55.0
PATCH v2 1/6 crypto: Provide wrapper functions for zeroizing aes_cmac_key and aes_cmac_ctx
From: Thomas Huth <[email protected]>
Code that uses AES-CMAC might need to zeroize their local aes_cmac_key and/or aes_cmac_ctx structures after use to avoid leaking sensitive material on the stack.
Provide an aes_cmac_zeroize_key() and an aes_cmac_zeroize_ctx() helper function that can be used with __cleanup() to automatically clear the key and context when they go out of scope.
--- include/crypto/aes-cbc-macs.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
include/crypto/aes-cbc-macs.h +34 -0
@@ -8,6 +8,7 @@#define _CRYPTO_AES_CBC_MACS_H#include <crypto/aes.h> +#include <linux/string.h> /** * struct aes_cmac_key - Prepared key for AES-CMAC or AES-XCBC-MAC
@@ -24,6 +25,19 @@ struct aes_cmac_key { } k_final[2 ]; }; +/** +* aes_cmac_zeroize_key() - Zeroize an aes_cmac_key structure +* @key: The location of the key structure that should be zeroized +* +* Explicitly fills the aes_cmac_key with zeroes. This should be done once +* the key is not required anymore to avoid that its contents are leaked +* on the stack or heap (if not using kfree_sensitive()). +*/ +static inline void aes_cmac_zeroize_key (struct aes_cmac_key *key) +{ +memzero_explicit (key,sizeof (*key)); +} +/** * struct aes_cmac_ctx - Context for computing an AES-CMAC or AES-XCBC-MAC value * @key: Pointer to the key struct. A pointer is used rather than a copy of the
@@ -40,6 +54,19 @@ struct aes_cmac_ctx {u8 h[AES_BLOCK_SIZE ]; }; +/** +* aes_cmac_zeroize_ctx() - Zeroize an aes_cmac_ctx structure +* @ctx: The location of the context that should be zeroized +* +* Explicitly fills the aes_cmac_ctx with zeroes. This should be done once +* the context is not required anymore to avoid that its contents are +* leaked on the stack or heap. Only required if not using aes_cmac_final(). +*/ +static inline void aes_cmac_zeroize_ctx (struct aes_cmac_ctx *ctx) +{ +memzero_explicit (ctx,sizeof (*ctx)); +} +/** * aes_cmac_preparekey() - Prepare a key for AES-CMAC * @key: (output) The key struct to initialize
@@ -47,6 +74,10 @@ struct aes_cmac_ctx {* @key_len: Length of the raw key in bytes. The supported values are * AES_KEYSIZE_128, AES_KEYSIZE_192, and AES_KEYSIZE_256. * +* On success, the caller should ensure that the prepared key is zeroized +* at the end of its lifetime, e.g. by calling aes_cmac_zeroize_key() or +* kfree_sensitive(). +* * Context: Any context. * Return: 0 on success or -EINVAL if the given key length is invalid. No other * errors are possible, so callers that always pass a valid key length
@@ -79,6 +110,9 @@ void aes_xcbcmac_preparekey(struct aes_cmac_key *key,* * This supports both AES-CMAC and AES-XCBC-MAC. Which one is done depends on * whether aes_cmac_preparekey() or aes_xcbcmac_preparekey() was called. +* +* The caller should ensure that the context is zeroized at the end of its +* lifetime, e.g. by calling aes_cmac_final() or aes_cmac_zeroize_ctx(). */ static inline void aes_cmac_init (struct aes_cmac_ctx *ctx,const struct aes_cmac_key *key)
Signature · 1 line
2.55.0
PATCH v2 2/6 smb: clear the aes_cmac_key and aes_cmac_ctx when done
In reply to Thomas HuthFrom: Thomas Huth <[email protected]>
Clear the local crypto-related structures via __cleanup() functions when we're done with them to avoid that sensitive data could leak on the stack.
Note: cmac_ctx in ksmbd_sign_smb3_pdu() gets cleared in aes_cmac_final() already, so this does not need a __cleanup() marker.
--- fs/smb/client/smb2transport.c | 4 ++-- fs/smb/server/auth.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
fs/smb/client/smb2transport.c +2 -2
@@ -464,8 +464,8 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)unsigned char smb3_signature[SMB2_CMACAES_SIZE ];struct kvec *iov = rqst->rq_iov;struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0 ].iov_base; -struct aes_cmac_key cmac_key; -struct aes_cmac_ctx cmac_ctx; + struct aes_cmac_key cmac_key __cleanup(aes_cmac_zeroize_key); + struct aes_cmac_ctx cmac_ctx __cleanup(aes_cmac_zeroize_ctx);struct smb_rqst drqst;u8 key[SMB3_SIGN_KEY_SIZE ];
fs/smb/server/auth.c +1 -1
@@ -509,7 +509,7 @@ void ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,void ksmbd_sign_smb3_pdu (struct ksmbd_conn *conn,char *key,struct kvec *iov,int n_vec,char *sig) { -struct aes_cmac_key cmac_key; + struct aes_cmac_key cmac_key __cleanup(aes_cmac_zeroize_key);struct aes_cmac_ctx cmac_ctx;int i;
Signature · 1 line
2.55.0
Namjae Jeon
maintainerRe: [PATCH v2 2/6] smb: clear the aes_cmac_key and aes_cmac_ctx when done
Quoted 5 lines
fs/smb/client/smb2transport.c +0
-0
fs/smb/client/smb2transport.c smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) · line 470
Quoted 9 lines
fs/smb/client/smb2transport.c +2
-2@@ -464,8 +464,8 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)unsigned char smb3_signature[SMB2_CMACAES_SIZE ];struct kvec *iov = rqst->rq_iov;struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0 ].iov_base; -struct aes_cmac_key cmac_key; -struct aes_cmac_ctx cmac_ctx; + struct aes_cmac_key cmac_key __cleanup(aes_cmac_zeroize_key); + struct aes_cmac_ctx cmac_ctx __cleanup(aes_cmac_zeroize_ctx);struct smb_rqst drqst;u8 key[SMB3_SIGN_KEY_SIZE ];
Shouldn’t we also clear the raw key with memzero_explicit(key, sizeof(key)) immediately after aes_cmac_preparekey() ?
rc = aes_cmac_preparekey(&cmac_key, key, SMB2_CMACAES_SIZE);
+ memzero_explicit(key, sizeof(key));
if (rc) {
cifs_server_dbg(VFS, "%s: Could not set key for cmac
aes\n", __func__);
return rc;
}Re: [PATCH v2 2/6] smb: clear the aes_cmac_key and aes_cmac_ctx when done
Quoted 17 lines · Namjae Jeon
Quoted 5 lines
fs/smb/client/smb2transport.c +0
-0fs/smb/client/smb2transport.c smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) · line 470
Quoted 9 lines
fs/smb/client/smb2transport.c +2
-2@@ -464,8 +464,8 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)unsigned char smb3_signature[SMB2_CMACAES_SIZE ];struct kvec *iov = rqst->rq_iov;struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0 ].iov_base; -struct aes_cmac_key cmac_key; -struct aes_cmac_ctx cmac_ctx; + struct aes_cmac_key cmac_key __cleanup(aes_cmac_zeroize_key); + struct aes_cmac_ctx cmac_ctx __cleanup(aes_cmac_zeroize_ctx);struct smb_rqst drqst;u8 key[SMB3_SIGN_KEY_SIZE ];Shouldn’t we also clear the raw key with
memzero_explicit(key, sizeof(key))immediately afteraes_cmac_preparekey()?
Quoted 7 lines
rc = aes_cmac_preparekey(&cmac_key, key, SMB2_CMACAES_SIZE);
+ memzero_explicit(key, sizeof(key));
if (rc) {
cifs_server_dbg(VFS, "%s: Could not set key for cmac
aes\n", __func__);
return rc;
}Yes, but I was planning to do all the scrubbing for such other spots in a separate patch series (similar to what I've posted for the smb/server code already) ... this patch series here focuses on aes_cmac_zeroize_key and aes_cmac_zeroize_ctx only. I hope that's ok?
Thomas
Re: [PATCH v2 2/6] smb: clear the aes_cmac_key and aes_cmac_ctx when done
Quoted 26 lines · Thomas Huth
Quoted 17 lines · Namjae Jeon
Quoted 5 lines
fs/smb/client/smb2transport.c +0
-0fs/smb/client/smb2transport.c smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) · line 470
Quoted 9 lines
fs/smb/client/smb2transport.c +2
-2@@ -464,8 +464,8 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)unsigned char smb3_signature[SMB2_CMACAES_SIZE ];struct kvec *iov = rqst->rq_iov;struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0 ].iov_base; -struct aes_cmac_key cmac_key; -struct aes_cmac_ctx cmac_ctx; + struct aes_cmac_key cmac_key __cleanup(aes_cmac_zeroize_key); + struct aes_cmac_ctx cmac_ctx __cleanup(aes_cmac_zeroize_ctx);struct smb_rqst drqst;u8 key[SMB3_SIGN_KEY_SIZE ];Shouldn’t we also clear the raw key with
memzero_explicit(key, sizeof(key))immediately afteraes_cmac_preparekey()?Quoted 7 lines
rc = aes_cmac_preparekey(&cmac_key, key, SMB2_CMACAES_SIZE); + memzero_explicit(key, sizeof(key)); if (rc) { cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__); return rc; }
Quoted 4 lines
Yes, but I was planning to do all the scrubbing for such other spots in a separate patch series (similar to what I've posted for the smb/server code already) ... this patch series here focuses on
aes_cmac_zeroize_keyandaes_cmac_zeroize_ctxonly. I hope that's ok?
Thanks.
PATCH v2 3/6 net/tcp-ao: clear the aes_cmac_key when done
In reply to Thomas HuthFrom: Thomas Huth <[email protected]>
Clear the local aes_cmac_key structure via __cleanup() function when we're done with it to avoid that sensitive data could leak on the stack.
--- net/ipv4/tcp_ao.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/tcp_ao.c +1 -1
@@ -141,7 +141,7 @@ void tcp_ao_calc_traffic_key(const struct tcp_ao_key *mkt, u8 *traffic_key, traffic_key);return ;case TCP_AO_ALGO_AES_128_CMAC : { -struct aes_cmac_key k; + struct aes_cmac_key k __cleanup(aes_cmac_zeroize_key);aes_cmac_preparekey (&k, mkt->key,AES_KEYSIZE_128 );aes_cmac (&k, input, input_len, traffic_key);
Signature · 1 line
2.55.0
Re: [PATCH v2 3/6] net/tcp-ao: clear the aes_cmac_key when done
net/ipv4/tcp_ao.c void tcp_ao_calc_traffic_key(const struct tcp_ao_key *mkt, u8 *traffic_key, · line 144
Quoted 2 lines · On Fri, 7 Aug 2026 14:58:40 +0200 Thomas Huth wrote:
net/ipv4/tcp_ao.c +1
-1-struct aes_cmac_key k; + struct aes_cmac_key k __cleanup(aes_cmac_zeroize_key);
Nak, we don't like the auto-cleanup stuff in networking. If y'all need a garbage collector there're jobs programming in Java.
Re: [PATCH v2 3/6] net/tcp-ao: clear the aes_cmac_key when done
Quoted 5 lines · Jakub Kicinski
net/ipv4/tcp_ao.c void tcp_ao_calc_traffic_key(const struct tcp_ao_key *mkt, u8 *traffic_key, · line 144
Quoted 2 lines · On Fri, 7 Aug 2026 14:58:40 +0200 Thomas Huth wrote:
net/ipv4/tcp_ao.c +1
-1-struct aes_cmac_key k; + struct aes_cmac_key k __cleanup(aes_cmac_zeroize_key);Nak, we don't like the auto-cleanup stuff in networking.
Ok, if you don't like it, then let's drop this patch.
Quoted 1 line
If y'all need a garbage collector there're jobs programming in Java.
No need for derogatory statements, Jakub. That's really inappropriate.
Thomas
PATCH v2 4/6 Bluetooth: SMP: clear the aes_cmac_key when done
In reply to Thomas HuthFrom: Thomas Huth <[email protected]>
Clear the local aes_cmac_key structure via __cleanup() function when we're done with it to avoid that sensitive data could leak on the stack.
While we're at it, also clear the tmp[] array here that is populated with a raw version of the original key and thus would leak the same information via the stack otherwise.
--- net/bluetooth/smp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/bluetooth/smp.c +2 -1
@@ -164,7 +164,7 @@ static inline void swap_buf(const u8 *src, u8 *dst, size_t len)static int smp_aes_cmac (const u8 k[16 ],const u8 *m,size_t len,u8 mac[16 ]) {uint8_t tmp[16 ], mac_msb[16 ], msg_msb[CMAC_MSG_MAX ]; -struct aes_cmac_key key; + struct aes_cmac_key key __cleanup(aes_cmac_zeroize_key);int err;if (len >CMAC_MSG_MAX )
@@ -178,6 +178,7 @@ static int smp_aes_cmac(const u8 k[16], const u8 *m, size_t len, u8 mac[16])SMP_DBG ("key %16phN" , k); err =aes_cmac_preparekey (&key, tmp,16 ); +memzero_explicit (tmp,sizeof (tmp));if (WARN_ON_ONCE (err))/* Should never happen, as 16 is valid keylen */ return err;aes_cmac (&key, msg_msb, len, mac_msb);
Signature · 1 line
2.55.0
PATCH v2 5/6 lib/crypto: aes: Use __cleanup() for aes_cmac_key instead of memzero_explicit()
In reply to Thomas HuthFrom: Thomas Huth <[email protected]>
By using __cleanup(aes_cmac_zeroize_key) for clearing the key data, we can save one line of code here.
--- lib/crypto/aes.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
lib/crypto/aes.c +1 -2
@@ -740,7 +740,7 @@ EXPORT_SYMBOL_NS_GPL(aes_cbcmac_final, "CRYPTO_INTERNAL");/* FIPS cryptographic algorithm self-test for AES-CMAC */ static void __init aes_cmac_fips_test (void ) { -struct aes_cmac_key key; + struct aes_cmac_key key __cleanup(aes_cmac_zeroize_key);u8 mac[AES_BLOCK_SIZE ]; if (aes_cmac_preparekey(&key, fips_test_key, sizeof(fips_test_key)) !=
@@ -749,7 +749,6 @@ static void __init aes_cmac_fips_test(void)aes_cmac (&key, fips_test_data,sizeof (fips_test_data), mac);if (memcmp (fips_test_aes_cmac_value, mac,sizeof (mac)) !=0 ) panic("aes: CMAC FIPS self-test failed (wrong MAC)\n"); - memzero_explicit(&key, sizeof(key)); }#else /* CONFIG_CRYPTO_LIB_AES_CBC_MACS */ static inline void aes_cmac_fips_test (void )
Signature · 1 line
2.55.0
PATCH v2 6/6 mac80211: fils_aead: Use __cleanup() for aes_cmac_key instead of memzero_explicit()
In reply to Thomas HuthFrom: Thomas Huth <[email protected]>
By using __cleanup(aes_cmac_zeroize_key) for clearing the key data, we can save one line of code here.
--- net/mac80211/fils_aead.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
net/mac80211/fils_aead.c +1 -2
@@ -24,7 +24,7 @@ static int aes_s2v(const u8 *in_key, size_t key_len, size_t num_elem, const u8 *addr[], size_t len[], u8 *v) { u8 d[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE] = {}; -struct aes_cmac_key key; + struct aes_cmac_key key __cleanup(aes_cmac_zeroize_key);struct aes_cmac_ctx ctx;size_t i;int res;
@@ -62,7 +62,6 @@ static int aes_s2v(const u8 *in_key, size_t key_len,aes_cmac_update (&ctx, d,AES_BLOCK_SIZE );aes_cmac_final (&ctx, v); -memzero_explicit (&key,sizeof (key));return 0 ; }
Signature · 1 line
2.55.0
Re: [PATCH v2 6/6] mac80211: fils_aead: Use __cleanup() for aes_cmac_key instead of memzero_explicit()
Quoted 4 lines · Thomas Huth
From: Thomas Huth <[email protected]>
By using
__cleanup(aes_cmac_zeroize_key)for clearing the key data, we can save one line of code here.
I'm assuming this won't be going via my tree, since it's part of a bigger series.
johannes
Eric Biggers
maintainerQuoted 34 lines · Thomas Huth
Code that uses AES-CMAC might need to zeroize their local
aes_cmac_keyand/oraes_cmac_ctxstructures after use to avoid leaking sensitive material on the stack.The first patch introduces an
aes_cmac_zeroize_key()and anaes_cmac_zeroize_ctx()helper function that can be used with__cleanup()to automatically clear the key and context when they go out of scope.Patches 2 - 4 add the
__cleanupmarkers to spots in the code that missed to clean up the structures so far.The final two patches are just cosmetics and change some
memzero_explicit()calls to use the__cleanup()way instead.Note: There are more spots in the smb, tcp-ao and bluetooth code that need some zeroization of sensitive data on the stack. I will tackle those in later patches, this series here focuses on the new
__cleanupwrappers.v2:
- Update comments and positions of the functions in the 1st patch
- Also clear tmp[] in the bluetooth patch (the patch is pointless otherwise)Thomas Huth (6):
crypto: Provide wrapper functions for zeroizingaes_cmac_keyand
aes_cmac_ctx
smb: clear theaes_cmac_keyandaes_cmac_ctxwhen donenet/tcp-ao: clear theaes_cmac_keywhen done
Bluetooth: SMP: clear theaes_cmac_keywhen done lib/crypto: aes: Use_cleanup()foraes_cmac_keyinstead of
memzero_explicit()
mac80211:fils_aead: Use_cleanupforaes_cmac_keyinstead of
memzero_explicit
Quoted 8 lines
fs/smb/client/smb2transport.c | 4 ++-- fs/smb/server/auth.c | 2 +- include/crypto/aes-cbc-macs.h | 34 ++++++++++++++++++++++++++++++++++ lib/crypto/aes.c | 3 +-- net/bluetooth/smp.c | 3 ++- net/ipv4/tcp_ao.c | 2 +- net/mac80211/fils_aead.c | 3 +-- 7 files changed, 42 insertions(+), 9 deletions(-)
Applied all except patch 3 to
https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/log/?h=libcrypto-next
- Eric