From: Eric Biggers <ebiggers@kernel.org>
To: linux-crypto@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel <ardb@kernel.org>,
"Jason A . Donenfeld" <Jason@zx2c4.com>,
Herbert Xu <herbert@gondor.apana.org.au>,
Thomas Huth <thuth@redhat.com>,
Eric Biggers <ebiggers@kernel.org>
Subject: [PATCH v2 13/13] crypto: aes - Add CCM support using library
Date: Wed, 15 Jul 2026 15:11:53 -0700 [thread overview]
Message-ID: <20260715221153.246410-14-ebiggers@kernel.org> (raw)
In-Reply-To: <20260715221153.246410-1-ebiggers@kernel.org>
Implement the "ccm(aes)" crypto_aead algorithm using the corresponding
library functions.
Among other benefits, this allows the architecture-optimized AES-CCM
code to be migrated into the library while still leaving it accessible
via crypto_aead, eliminating lots of boilerplate code.
For now the cra_priority is set to just 110, since the
architecture-optimized implementations of this algorithm haven't yet
been migrated into the library. It will be boosted once that happens.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/Kconfig | 3 +-
crypto/aes.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 131 insertions(+), 1 deletion(-)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index bbd314c07fd7..981d5dc422d4 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -360,11 +360,12 @@ config CRYPTO_AES
select CRYPTO_LIB_AES
select CRYPTO_LIB_AES_CBC if CRYPTO_CBC != n || CRYPTO_CTS != n
select CRYPTO_LIB_AES_CBC_MACS if CRYPTO_CMAC != n || CRYPTO_XCBC != n || CRYPTO_CCM != n
+ select CRYPTO_LIB_AES_CCM if CRYPTO_CCM != n
select CRYPTO_LIB_AES_CTR if CRYPTO_CTR != n || CRYPTO_XCTR != n
select CRYPTO_LIB_AES_ECB if CRYPTO_ECB != n
select CRYPTO_LIB_AES_GCM if CRYPTO_GCM != n
select CRYPTO_LIB_AES_XTS if CRYPTO_XTS != n
- select CRYPTO_AEAD if CRYPTO_GCM != n
+ select CRYPTO_AEAD if CRYPTO_GCM != n || CRYPTO_CCM != n
select CRYPTO_HASH if CRYPTO_CMAC != n || CRYPTO_XCBC != n || CRYPTO_CCM != n
# CRYPTO_SKCIPHER should be selected only if a mode that needs it is
# enabled, but that doesn't work due to a recursive dependency caused by
diff --git a/crypto/aes.c b/crypto/aes.c
index 9fe106c9eed2..94791f481e98 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -7,6 +7,7 @@
#include <crypto/aes-cbc-macs.h>
#include <crypto/aes-cbc.h>
+#include <crypto/aes-ccm.h>
#include <crypto/aes-ctr.h>
#include <crypto/aes-ecb.h>
#include <crypto/aes-gcm.h>
@@ -871,6 +872,113 @@ static __maybe_unused int crypto_aes_rfc4106_decrypt(struct aead_request *req)
req->assoclen - 8);
}
+/* AES-CCM */
+
+static __maybe_unused int crypto_aes_ccm_setkey(struct crypto_aead *tfm,
+ const u8 *in_key,
+ unsigned int key_len)
+{
+ struct aes_ccm_key *key = crypto_aead_ctx(tfm);
+
+ return aes_ccm_preparekey(key, in_key, key_len,
+ crypto_aead_authsize(tfm));
+}
+
+static __maybe_unused int crypto_aes_ccm_setauthsize(struct crypto_aead *tfm,
+ unsigned int authsize)
+{
+ struct aes_ccm_key *key = crypto_aead_ctx(tfm);
+
+ if (authsize < 4 || authsize > 16 || authsize % 2)
+ return -EINVAL;
+ /* Synchronize the tag length to the struct aes_ccm_key. */
+ key->authtag_len = authsize;
+ return 0;
+}
+
+static int crypto_aes_ccm_init(struct aes_ccm_ctx *ctx,
+ struct aead_request *req, unsigned int data_len,
+ const struct aes_ccm_key *key)
+{
+ int nonce_len;
+ const u8 *nonce;
+ int err;
+
+ /*
+ * CCM accepts a variable-length nonce between 7 and 13 bytes
+ * inclusively, while crypto_aead assumes a fixed-length IV. This is
+ * worked around by requiring that iv[0] contain '14 - nonce_len' and
+ * iv[1..] contain the actual nonce. Extra bytes at the end are unused.
+ */
+ nonce_len = 14 - (int)req->iv[0];
+ if (unlikely(nonce_len < 7 || nonce_len > 13))
+ return -EINVAL;
+ nonce = &req->iv[1];
+ err = aes_ccm_init(ctx, data_len, req->assoclen, nonce, nonce_len, key);
+ if (unlikely(err))
+ return err;
+ AES_PROCESS_ASSOC_DATA(aes_ccm_auth_update, req->src, req->assoclen,
+ ctx);
+ return 0;
+}
+
+static void aes_ccm_encrypt_update_helper(u8 *dst, const u8 *src,
+ unsigned int len,
+ struct aes_ccm_ctx *ctx)
+{
+ aes_ccm_encrypt_update(ctx, dst, src, len);
+}
+
+static void aes_ccm_decrypt_update_helper(u8 *dst, const u8 *src,
+ unsigned int len,
+ struct aes_ccm_ctx *ctx)
+{
+ aes_ccm_decrypt_update(ctx, dst, src, len);
+}
+
+static __maybe_unused int crypto_aes_ccm_encrypt(struct aead_request *req)
+{
+ struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+ const struct aes_ccm_key *key = crypto_aead_ctx(tfm);
+ struct aes_ccm_ctx ctx;
+ u8 authtag[16];
+ int err;
+
+ err = crypto_aes_ccm_init(&ctx, req, req->cryptlen, key);
+ if (unlikely(err))
+ return err;
+ AES_CRYPT_SG(aes_ccm_encrypt_update_helper, req->dst, req->src,
+ req->cryptlen, req->assoclen, &ctx);
+ aes_ccm_encrypt_final(&ctx, authtag);
+ memcpy_to_sglist(req->dst, req->assoclen + req->cryptlen, authtag,
+ key->authtag_len);
+ memzero_explicit(authtag, sizeof(authtag));
+ return 0;
+}
+
+static __maybe_unused int crypto_aes_ccm_decrypt(struct aead_request *req)
+{
+ struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+ const struct aes_ccm_key *key = crypto_aead_ctx(tfm);
+ unsigned int data_len;
+ struct aes_ccm_ctx ctx;
+ u8 authtag[16];
+ int err;
+
+ /* crypto_aead_decrypt() already checked cryptlen >= authtag_len. */
+ data_len = req->cryptlen - key->authtag_len;
+ err = crypto_aes_ccm_init(&ctx, req, data_len, key);
+ if (unlikely(err))
+ return err;
+ AES_CRYPT_SG(aes_ccm_decrypt_update_helper, req->dst, req->src,
+ data_len, req->assoclen, &ctx);
+ memcpy_from_sglist(authtag, req->src, req->assoclen + data_len,
+ key->authtag_len);
+ err = aes_ccm_decrypt_final(&ctx, authtag);
+ memzero_explicit(authtag, sizeof(authtag));
+ return err;
+}
+
static struct aead_alg aead_algs[] = {
#if IS_ENABLED(CONFIG_CRYPTO_GCM)
{
@@ -904,6 +1012,23 @@ static struct aead_alg aead_algs[] = {
.chunksize = AES_BLOCK_SIZE,
},
#endif /* CONFIG_CRYPTO_GCM */
+#if IS_ENABLED(CONFIG_CRYPTO_CCM)
+ {
+ .base.cra_name = "ccm(aes)",
+ .base.cra_driver_name = "ccm-aes-lib",
+ .base.cra_priority = 110,
+ .base.cra_blocksize = 1,
+ .base.cra_ctxsize = sizeof(struct aes_ccm_key),
+ .base.cra_module = THIS_MODULE,
+ .setkey = crypto_aes_ccm_setkey,
+ .setauthsize = crypto_aes_ccm_setauthsize,
+ .encrypt = crypto_aes_ccm_encrypt,
+ .decrypt = crypto_aes_ccm_decrypt,
+ .ivsize = 16,
+ .maxauthsize = 16,
+ .chunksize = AES_BLOCK_SIZE,
+ },
+#endif /* CONFIG_CRYPTO_CCM */
};
static int __init crypto_aes_mod_init(void)
@@ -1006,3 +1131,7 @@ MODULE_ALIAS_CRYPTO("gcm-aes-lib");
MODULE_ALIAS_CRYPTO("rfc4106(gcm(aes))");
MODULE_ALIAS_CRYPTO("rfc4106-gcm-aes-lib");
#endif
+#if IS_ENABLED(CONFIG_CRYPTO_CCM)
+MODULE_ALIAS_CRYPTO("ccm(aes)");
+MODULE_ALIAS_CRYPTO("ccm-aes-lib");
+#endif
--
2.55.0
prev parent reply other threads:[~2026-07-15 22:12 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-15 22:11 [PATCH v2 00/13] Library APIs for AES encryption modes Eric Biggers
2026-07-15 22:11 ` [PATCH v2 01/13] crypto: xts - Split out __xts_verify_key() helper Eric Biggers
2026-07-15 22:11 ` [PATCH v2 02/13] lib/crypto: aes: Add ECB support Eric Biggers
2026-07-15 22:11 ` [PATCH v2 03/13] lib/crypto: aes: Add CBC and CBC-CTS support Eric Biggers
2026-07-15 22:11 ` [PATCH v2 04/13] lib/crypto: aes: Add CTR and XCTR support Eric Biggers
2026-07-15 22:11 ` [PATCH v2 05/13] lib/crypto: aes: Add XTS support Eric Biggers
2026-07-15 22:11 ` [PATCH v2 06/13] lib/crypto: aes: Add GCM support Eric Biggers
2026-07-15 22:11 ` [PATCH v2 07/13] lib/crypto: aes: Add CCM support Eric Biggers
2026-07-15 22:11 ` [PATCH v2 08/13] crypto: aes - Add ECB support using library Eric Biggers
2026-07-15 22:11 ` [PATCH v2 09/13] crypto: aes - Add CBC and CBC-CTS " Eric Biggers
2026-07-15 22:11 ` [PATCH v2 10/13] crypto: aes - Add CTR and XCTR " Eric Biggers
2026-07-15 22:11 ` [PATCH v2 11/13] crypto: aes - Add XTS " Eric Biggers
2026-07-15 22:11 ` [PATCH v2 12/13] crypto: aes - Add GCM " Eric Biggers
2026-07-15 22:11 ` Eric Biggers [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260715221153.246410-14-ebiggers@kernel.org \
--to=ebiggers@kernel.org \
--cc=Jason@zx2c4.com \
--cc=ardb@kernel.org \
--cc=herbert@gondor.apana.org.au \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.