1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
.. SPDX-License-Identifier: GPL-2.0-or-later
Crypto Key Zeroization
======================
This document describes the conventions for zeroizing crypto structures in the
kernel.
Note: the kernel follows traditional cryptographic terminology by using
the term "zeroizing" to mean erasing sensitive parameters to prevent
their disclosure if the system is later compromised. This distinguishes
it from zeroing memory for other purposes such as initialization.
.. contents::
Overview
--------
Cryptographic key material and intermediate state (such as HMAC contexts) must
be zeroized after use to prevent sensitive data from lingering on the stack or
heap, where it could be leaked through memory disclosure vulnerabilities,
crash dumps, or cold-boot attacks.
For memory that has been allocated with kmalloc() or a similar function,
kfree_sensitive() should be used instead of kfree() to release the memory.
For other cases, the kernel provides memzero_explicit() for clearing the
memory. Unlike plain memset(), memzero_explicit() is guaranteed not
to be optimized away by the compiler, even when the memory being cleared
appears to be dead.
The crypto library builds on memzero_explicit() by providing typed
zeroization helpers for each key and context structure. These helpers serve
two purposes:
1. They make __cleanup() annotations possible, so that structures on
the stack are automatically zeroized when they go out of scope.
2. They improve readability by replacing ``memzero_explicit(&key, sizeof(key))``
with a self-documenting call like ``aes_zeroize_key(&key)``.
What to zeroize
---------------
The following types of structures hold sensitive material and should be
zeroized after use:
- **Key structures** (e.g. ``struct aes_key``, ``struct hmac_sha256_key``):
contain expanded round keys or prepared key material.
- **HMAC/MAC context structures** (e.g. ``struct hmac_sha256_ctx``,
``struct aes_cmac_ctx``): contain inner and outer hash states derived from
the key.
- **Hash context structures** (e.g. ``struct sha256_ctx``): may contain
sensitive data being hashed.
Not all of these require explicit cleanup by callers. Many ``..._final()``
functions already zeroize their context internally (see `Automatic vs. manual
zeroization`_ below).
Zeroization helpers
-------------------
Each crypto structure that callers may need to zeroize should have a
corresponding inline helper function. The naming convention is::
<algorithm>_zeroize_<type>(struct <algorithm>_<type> *p);
For example::
void aes_zeroize_key(struct aes_key *key);
void aes_zeroize_enckey(struct aes_enckey *key);
void hmac_sha256_zeroize_ctx(struct hmac_sha256_ctx *ctx);
void aes_cmac_zeroize_key(struct aes_cmac_key *key);
void aes_cmac_zeroize_ctx(struct aes_cmac_ctx *ctx);
Each helper is a ``static inline`` function in the algorithm's header that
wraps ``memzero_explicit()``, for example::
static inline void hmac_sha256_zeroize_ctx(struct hmac_sha256_ctx *ctx)
{
memzero_explicit(ctx, sizeof(*ctx));
}
Using __cleanup for automatic zeroization
-----------------------------------------
The preferred way to zeroize stack-allocated key and context structures is
with the __cleanup() attribute. This ensures zeroization happens on all
exit paths, including error returns and early exits. For example::
static int my_aesxts_setkey(..., const u8 *key, unsigned int len)
{
struct crypto_aes_ctx aes __cleanup(aes_zeroize_ctx);
...
/* Only half of the key data is cipher key */
keylen = (len >> 1);
ret = aes_expandkey(&aes, key, keylen);
if (ret)
return ret;
... do something with the cipher key ...
/* The other half is the tweak key */
ret = aes_expandkey(&aes, (u8 *)(key + keylen), keylen);
if (ret)
return ret; /* <-- Could leak cipher key without __cleanup */
... do something with the tweak key ...
/* No need for memzero_explicit() at the end thanks to the __cleanup */
return 0;
}
Note that __cleanup() attributes should not be used in functions that use
"goto" statements. The benefit of cleanup helpers is the removal of "gotos",
and that "goto" statements can jump between scopes, so the expectation is
that usage of "goto" and cleanup helpers is never mixed in the same function.
Automatic vs. manual zeroization
--------------------------------
Many ``..._final()`` functions in the crypto library automatically zeroize
their context before returning. When this is the case, the kernel-doc for the
function documents it::
After finishing, this zeroizes @ctx. So the caller does not need to do it.
In these cases, callers on simple code paths (where ``..._final()`` is always
reached) do not need to add __cleanup() or explicit zeroization.
However, __cleanup() is still recommended whenever there are error paths
that bypass ``..._final()``, as it ensures zeroization on all paths.
For algorithms where ``..._final()`` does *not* zeroize the context (such as
the SHAKE XOFs, where ``shake_squeeze()`` can be called multiple times),
callers must explicitly zeroize the context by calling the appropriate helper
or using __cleanup(), for example::
struct shake_ctx ctx __cleanup(shake_zeroize_ctx);
shake256_init(&ctx);
shake_update(&ctx, data, data_len);
shake_squeeze(&ctx, out, out_len);
/* ctx is automatically zeroized at end of scope */
|