projects/linux·blob master · refs

284 lines · 10.4 KiB

1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * AES-CCM authenticated encryption and decryption
4 *
5 * Copyright 2026 Google LLC
6 */
7#ifndef _CRYPTO_AES_CCM_H
8#define _CRYPTO_AES_CCM_H
9
10#include <crypto/aes.h>
11
12/**
13 * struct aes_ccm_key - A key prepared for AES-CCM encryption and decryption
14 */
15struct aes_ccm_key {
16 /* private: */
17 struct aes_enckey aes;
18 size_t authtag_len; /* Length of authentication tags in bytes */
19};
20
21/**
22 * aes_ccm_zeroize_key() - Zeroize an aes_ccm_key structure
23 * @key: The aes_ccm_key to zeroize
24 */
25static inline void aes_ccm_zeroize_key(struct aes_ccm_key *key)
26{
27 memzero_explicit(key, sizeof(*key));
28}
29
30/**
31 * struct aes_ccm_ctx - Context for incrementally en/decrypting a message
32 */
33struct aes_ccm_ctx {
34 /* private: */
35 /*
36 * Pointer to the key, which is assumed to live at least as long as this
37 * struct.
38 */
39 const struct aes_ccm_key *key;
40 /*
41 * The current CBC-MAC chaining value. When not on a block boundary,
42 * the partial block has been XOR'ed into this. The number of partial
43 * bytes is 'partial_len'.
44 */
45 u8 mac[AES_BLOCK_SIZE] __aligned(__alignof__(__be64));
46 /* The current counter, a 128-bit big endian value */
47 u8 ctr[AES_BLOCK_SIZE] __aligned(__alignof__(__be64));
48 /* Buffered keystream for partial block updates */
49 u8 keystream[AES_BLOCK_SIZE] __aligned(__alignof__(__be64));
50 /* Encrypted counter of 0. This gets XOR'ed with the tag at the end. */
51 u8 s0[AES_BLOCK_SIZE] __aligned(__alignof__(__be64));
52 /* Number of associated data bytes remaining to be provided */
53 u64 ad_remaining;
54 /* Number of en/decrypted data bytes remaining to be provided */
55 u64 data_remaining;
56 /* Current partial block length, 0 <= partial_len < AES_BLOCK_SIZE */
57 u32 partial_len;
58 /* True if associated data padding has been done */
59 bool ad_padded;
60};
61
62/**
63 * aes_ccm_zeroize_ctx() - Zeroize an aes_ccm_ctx structure
64 * @ctx: The aes_ccm_ctx to zeroize
65 */
66static inline void aes_ccm_zeroize_ctx(struct aes_ccm_ctx *ctx)
67{
68 memzero_explicit(ctx, sizeof(*ctx));
69}
70
71/**
72 * aes_ccm_preparekey() - Prepare a key for AES-CCM encryption and decryption
73 * @key: (output) The key structure to initialize
74 * @in_key: The raw AES-CCM key
75 * @key_len: Length of the raw key in bytes: 16, 24, or 32
76 * @authtag_len: Length of the authentication tag in bytes:
77 * 4, 6, 8, 10, 12, 14, or 16. 16 is recommended.
78 *
79 * Users should use aes_ccm_zeroize_key() to zeroize the key struct at the end
80 * of its lifetime. (But if this function fails, zeroization is unnecessary.)
81 *
82 * Context: Any context.
83 * Return:
84 * * 0 on success
85 * * -EINVAL if either of the lengths is invalid
86 */
87int __must_check aes_ccm_preparekey(struct aes_ccm_key *key, const u8 *in_key,
88 size_t key_len, size_t authtag_len);
89
90/**
91 * aes_ccm_encrypt() - Encrypt a message with AES-CCM
92 * @dst: The destination ciphertext data. Can be in-place or out-of-place.
93 * For other overlaps the behavior is unspecified.
94 * @src: The source plaintext data
95 * @data_len: Length of plaintext in bytes (and ciphertext excluding the tag):
96 * at most 2^(120 - (8 * @nonce_len)) - 1
97 * @authtag: The output authentication tag. Length is the authtag_len that was
98 * passed to aes_ccm_preparekey(). Usually protocols using AES-CCM
99 * put the tag at the end of the ciphertext, in which case this should
100 * be set to @dst + @data_len and @dst must have room for the tag.
101 * @ad: The associated data
102 * @ad_len: Length of associated data in bytes
103 * @nonce: The nonce. All (key, nonce) pairs used MUST be distinct.
104 * @nonce_len: Length of the nonce in bytes: between 7 and 13 inclusive
105 * @key: The key, already prepared using aes_ccm_preparekey()
106 *
107 * Context: Any context.
108 * Return:
109 * * 0 on success
110 * * -EINVAL if @nonce_len is invalid
111 * * -EOVERFLOW if @data_len is too large for the selected @nonce_len
112 */
113int __must_check aes_ccm_encrypt(u8 *dst, const u8 *src, size_t data_len,
114 u8 *authtag, const u8 *ad, size_t ad_len,
115 const u8 *nonce, size_t nonce_len,
116 const struct aes_ccm_key *key);
117
118/**
119 * aes_ccm_decrypt() - Decrypt a message with AES-CCM
120 * @dst: The destination plaintext data. Can be in-place or out-of-place.
121 * For other overlaps the behavior is unspecified.
122 * @src: The source ciphertext data
123 * @data_len: Length of plaintext in bytes (and ciphertext excluding the tag):
124 * at most 2^(120 - (8 * @nonce_len)) - 1
125 * @authtag: The stored authentication tag. Length is the authtag_len that was
126 * passed to aes_ccm_preparekey(). Usually protocols using AES-CCM
127 * put the tag at the end of the ciphertext, in which case this should
128 * be set to @src + @data_len and @src must have room for the tag.
129 * @ad: The associated data
130 * @ad_len: Length of associated data in bytes
131 * @nonce: The nonce
132 * @nonce_len: Length of the nonce in bytes: between 7 and 13 inclusive
133 * @key: The key, already prepared using aes_ccm_preparekey()
134 *
135 * Context: Any context.
136 * Return:
137 * * 0 on success. This is the only case where any decrypted or associated data
138 * can be used.
139 * * -EBADMSG if the message is inauthentic
140 * * -EINVAL if @nonce_len is invalid
141 * * -EOVERFLOW if @data_len is too large for the selected @nonce_len
142 */
143int __must_check aes_ccm_decrypt(u8 *dst, const u8 *src, size_t data_len,
144 const u8 *authtag, const u8 *ad, size_t ad_len,
145 const u8 *nonce, size_t nonce_len,
146 const struct aes_ccm_key *key);
147
148/**
149 * aes_ccm_init() - Initialize context for incremental AES-CCM encryption or
150 * decryption
151 * @ctx: The context to initialize
152 * @data_len: Length of the en/decrypted data that will be provided in bytes:
153 * at most 2^(120 - (8 * @nonce_len)) - 1
154 * @ad_len: Length of the associated data that will be provided in bytes
155 * @nonce: The nonce. All (key, nonce) pairs used for encryption MUST be
156 * distinct.
157 * @nonce_len: Length of the nonce in bytes: between 7 and 13 inclusive
158 * @key: The key, already prepared using aes_ccm_preparekey(). Note that a
159 * pointer to the key is saved in the context, so the key must live at
160 * least as long as the context.
161 *
162 * Unlike AES-GCM, AES-CCM requires the total lengths of the associated data and
163 * the en/decrypted data to be known during initialization. Callers MUST ensure
164 * that these lengths are correct.
165 *
166 * If this function returns success, the context should be zeroized at the end
167 * of its lifetime. Normally that happens in aes_ccm_encrypt_final() or
168 * aes_ccm_decrypt_final(), but callers that abandon a context without
169 * finalizing it should explicitly zeroize it.
170 *
171 * IMPORTANT: Callers that are decrypting MUST NOT assume that any decrypted or
172 * associated data is authentic until the authentication tag has been verified.
173 * This incremental API is provided solely to support callers that can't
174 * efficiently use the one-shot functions due to using a nonlinear data layout.
175 *
176 * For incremental AES-CCM encryption, use:
177 *
178 * 1. aes_ccm_init()
179 * 2. aes_ccm_auth_update() (any number of times)
180 * 3. aes_ccm_encrypt_update() (any number of times)
181 * 4. aes_ccm_encrypt_final()
182 *
183 * For incremental AES-CCM decryption, use:
184 *
185 * 1. aes_ccm_init()
186 * 2. aes_ccm_auth_update() (any number of times)
187 * 3. aes_ccm_decrypt_update() (any number of times)
188 * 4. aes_ccm_decrypt_final()
189 *
190 * Context: Any context.
191 * Return:
192 * * 0 on success
193 * * -EINVAL if @nonce_len is invalid
194 * * -EOVERFLOW if @data_len is too large for the selected @nonce_len
195 */
196int __must_check aes_ccm_init(struct aes_ccm_ctx *ctx, u64 data_len, u64 ad_len,
197 const u8 *nonce, size_t nonce_len,
198 const struct aes_ccm_key *key);
199
200/**
201 * aes_ccm_auth_update() - Incrementally process AES-CCM associated data
202 * @ctx: An AES-CCM context
203 * @ad: The associated data
204 * @len: Length of the associated data in bytes
205 *
206 * IMPORTANT: Callers MUST NOT assume that any decrypted or associated data is
207 * authentic until the authentication tag has been verified.
208 *
209 * The total length of the associated data (over all calls to this function)
210 * MUST match the ad_len that was passed to aes_ccm_init().
211 *
212 * Context: Any context.
213 */
214void aes_ccm_auth_update(struct aes_ccm_ctx *ctx, const u8 *ad, size_t len);
215
216/**
217 * aes_ccm_encrypt_update() - Incrementally encrypt data with AES-CCM
218 * @ctx: An AES-CCM context
219 * @dst: The destination buffer. Can be in-place or out-of-place. For other
220 * overlaps the behavior is unspecified.
221 * @src: The source plaintext data
222 * @len: Number of bytes to encrypt
223 *
224 * This can be called only after all associated data has been processed.
225 *
226 * The total length of the encrypted data (over all calls to this function) MUST
227 * match the data_len that was passed to aes_ccm_init().
228 *
229 * Context: Any context.
230 */
231void aes_ccm_encrypt_update(struct aes_ccm_ctx *ctx, u8 *dst, const u8 *src,
232 size_t len);
233
234/**
235 * aes_ccm_decrypt_update() - Incrementally decrypt data with AES-CCM
236 * @ctx: An AES-CCM context
237 * @dst: The destination buffer. Can be in-place or out-of-place. For other
238 * overlaps the behavior is unspecified.
239 * @src: The source ciphertext data (not including auth tag)
240 * @len: Number of bytes to decrypt
241 *
242 * This can be called only after all associated data has been processed.
243 *
244 * The total length of the decrypted data (over all calls to this function) MUST
245 * match the data_len that was passed to aes_ccm_init().
246 *
247 * IMPORTANT: Callers MUST NOT assume that any decrypted or associated data is
248 * authentic until the authentication tag has been verified.
249 *
250 * Context: Any context.
251 */
252void aes_ccm_decrypt_update(struct aes_ccm_ctx *ctx, u8 *dst, const u8 *src,
253 size_t len);
254
255/**
256 * aes_ccm_encrypt_final() - Finish encrypting a message with AES-CCM
257 * @ctx: An AES-CCM context
258 * @authtag: The output authentication tag. Length is the authtag_len that was
259 * passed to aes_ccm_preparekey().
260 *
261 * This also zeroizes @ctx, so the caller doesn't need to do it.
262 *
263 * Context: Any context.
264 */
265void aes_ccm_encrypt_final(struct aes_ccm_ctx *ctx, u8 *authtag);
266
267/**
268 * aes_ccm_decrypt_final() - Finish decrypting a message with AES-CCM
269 * @ctx: An AES-CCM context
270 * @authtag: The stored authentication tag. Length is the authtag_len that was
271 * passed to aes_ccm_preparekey().
272 *
273 * This also zeroizes @ctx, so the caller doesn't need to do it.
274 *
275 * Context: Any context.
276 * Return:
277 * * 0 on success. This is the only case where any decrypted or associated data
278 * can be used.
279 * * -EBADMSG if the message is inauthentic
280 */
281int __must_check aes_ccm_decrypt_final(struct aes_ccm_ctx *ctx,
282 const u8 *authtag);
283
284#endif /* _CRYPTO_AES_CCM_H */