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