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