| 1 |
|
| 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 |
|
| 15 | struct aes_ccm_key {
|
| 16 |
|
| 17 | struct aes_enckey aes;
|
| 18 | size_t authtag_len;
|
| 19 | };
|
| 20 |
|
| 21 | |
| 22 | * aes_ccm_zeroize_key() - Zeroize an aes_ccm_key structure
|
| 23 | * @key: The aes_ccm_key to zeroize
|
| 24 |
|
| 25 | static 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 |
|
| 33 | struct aes_ccm_ctx {
|
| 34 |
|
| 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 |
|
| 47 | u8 ctr[AES_BLOCK_SIZE] __aligned(__alignof__(__be64));
|
| 48 |
|
| 49 | u8 keystream[AES_BLOCK_SIZE] __aligned(__alignof__(__be64));
|
| 50 |
|
| 51 | u8 s0[AES_BLOCK_SIZE] __aligned(__alignof__(__be64));
|
| 52 |
|
| 53 | u64 ad_remaining;
|
| 54 |
|
| 55 | u64 data_remaining;
|
| 56 |
|
| 57 | u32 partial_len;
|
| 58 |
|
| 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 |
|
| 66 | static 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 |
|
| 87 | int __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 |
|
| 113 | int __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 |
|
| 143 | int __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 |
|
| 196 | int __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 |
|
| 214 | void 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 |
|
| 231 | void 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 |
|
| 252 | void 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 |
|
| 265 | void 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 |
|
| 281 | int __must_check aes_ccm_decrypt_final(struct aes_ccm_ctx *ctx,
|
| 282 | const u8 *authtag);
|
| 283 |
|
| 284 | #endif
|