Merge pull request #10194 from douzzer/20260410-linuxkm-aes-ccm

20260410-linuxkm-aes-ccm
This commit is contained in:
David Garske
2026-04-13 09:19:17 -07:00
committed by GitHub
5 changed files with 591 additions and 8 deletions
+1
View File
@@ -63,6 +63,7 @@ CONFIG_COMPILER_OPTIMIZATION_PERF
CONFIG_COMPILER_OPTIMIZATION_SIZE
CONFIG_CRYPTO_AES
CONFIG_CRYPTO_CBC
CONFIG_CRYPTO_CCM
CONFIG_CRYPTO_CTR
CONFIG_CRYPTO_DH
CONFIG_CRYPTO_DH_RFC7919_GROUPS
+7
View File
@@ -10252,6 +10252,10 @@ then
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_AESGCM" ;;
'rfc4106(gcm(aes))') test "$ENABLED_AESGCM" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: AES-GCM implementation not enabled.])
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106" ;;
'ccm(aes)') test "$ENABLED_AESCCM" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: AES-CCM implementation not enabled.])
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_AESCCM" ;;
'rfc4309(ccm(aes))') test "$ENABLED_AESCCM" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: AES-CCM implementation not enabled.])
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309" ;;
'xts(aes)') test "$ENABLED_AESXTS" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: AES-XTS implementation not enabled.])
test "$ENABLED_AESXTS_STREAM" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: --enable-aesxts-stream is required for LKCAPI.])
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_AESXTS" ;;
@@ -10296,6 +10300,9 @@ then
'-gcm(aes)') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_AESGCM" ;;
'-rfc4106(gcm(aes))')
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_AESGCM_RFC4106" ;;
'-ccm(aes)') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_AESCCM" ;;
'-rfc4309(ccm(aes))')
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_AESCCM_RFC4309" ;;
'-xts(aes)') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_AESXTS" ;;
'-ctr(aes)') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_AESCTR" ;;
'-ofb(aes)') AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_DONT_REGISTER_AESOFB" ;;
+568 -7
View File
@@ -38,6 +38,8 @@
defined(LINUXKM_LKCAPI_REGISTER_AESCFB) || \
defined(LINUXKM_LKCAPI_REGISTER_AESGCM) || \
defined(LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106) || \
defined(LINUXKM_LKCAPI_REGISTER_AESCCM) || \
defined(LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309) || \
defined(LINUXKM_LKCAPI_REGISTER_AESXTS) || \
defined(LINUXKM_LKCAPI_REGISTER_AESCTR) || \
defined(LINUXKM_LKCAPI_REGISTER_AESOFB) || \
@@ -87,6 +89,8 @@
#define WOLFKM_AESCFB_NAME "cfb(aes)"
#define WOLFKM_AESGCM_NAME "gcm(aes)"
#define WOLFKM_AESGCM_RFC4106_NAME "rfc4106(gcm(aes))"
#define WOLFKM_AESCCM_NAME "ccm(aes)"
#define WOLFKM_AESCCM_RFC4309_NAME "rfc4309(ccm(aes))"
#define WOLFKM_AESXTS_NAME "xts(aes)"
#define WOLFKM_AESCTR_NAME "ctr(aes)"
#define WOLFKM_AESOFB_NAME "ofb(aes)"
@@ -107,6 +111,8 @@
#define WOLFKM_AESCFB_DRIVER ("cfb-aes" WOLFKM_AES_DRIVER_SUFFIX)
#define WOLFKM_AESGCM_DRIVER ("gcm-aes" WOLFKM_AES_DRIVER_SUFFIX)
#define WOLFKM_AESGCM_RFC4106_DRIVER ("rfc4106-gcm-aes" WOLFKM_AES_DRIVER_SUFFIX)
#define WOLFKM_AESCCM_DRIVER ("ccm-aes" WOLFKM_AES_DRIVER_SUFFIX)
#define WOLFKM_AESCCM_RFC4309_DRIVER ("rfc4309-ccm-aes" WOLFKM_AES_DRIVER_SUFFIX)
#define WOLFKM_AESXTS_DRIVER ("xts-aes" WOLFKM_AES_DRIVER_SUFFIX)
#define WOLFKM_AESCTR_DRIVER ("ctr-aes" WOLFKM_AES_DRIVER_SUFFIX)
#define WOLFKM_AESOFB_DRIVER ("ofb-aes" WOLFKM_AES_DRIVER_SUFFIX)
@@ -146,7 +152,8 @@
#define LINUXKM_LKCAPI_REGISTER_AESGCM
#endif
#if ((defined(LINUXKM_LKCAPI_REGISTER_ALL) || \
defined(LINUXKM_LKCAPI_REGISTER_AES_ALL)) && \
defined(LINUXKM_LKCAPI_REGISTER_AES_ALL) || \
(defined(LINUXKM_LKCAPI_REGISTER_ALL_KCONFIG) && defined(CONFIG_CRYPTO_GCM))) && \
!defined(LINUXKM_LKCAPI_DONT_REGISTER_AESGCM_RFC4106)) && \
!defined(LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106)
#define LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106
@@ -159,6 +166,29 @@
#undef LINUXKM_LKCAPI_REGISTER_AESGCM
#undef LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106
#endif
#ifdef HAVE_AESCCM
#if (defined(LINUXKM_LKCAPI_REGISTER_ALL) || \
defined(LINUXKM_LKCAPI_REGISTER_AES_ALL) || \
(defined(LINUXKM_LKCAPI_REGISTER_ALL_KCONFIG) && defined(CONFIG_CRYPTO_CCM))) && \
!defined(LINUXKM_LKCAPI_DONT_REGISTER_AESCCM) && \
!defined(LINUXKM_LKCAPI_REGISTER_AESCCM)
#define LINUXKM_LKCAPI_REGISTER_AESCCM
#endif
#if ((defined(LINUXKM_LKCAPI_REGISTER_ALL) || \
defined(LINUXKM_LKCAPI_REGISTER_AES_ALL) || \
(defined(LINUXKM_LKCAPI_REGISTER_ALL_KCONFIG) && defined(CONFIG_CRYPTO_CCM))) && \
!defined(LINUXKM_LKCAPI_DONT_REGISTER_AESCCM_RFC4309)) && \
!defined(LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309)
#define LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309
#endif
#else
#if defined(LINUXKM_LKCAPI_REGISTER_ALL_KCONFIG) && defined(CONFIG_CRYPTO_CCM) && \
!defined(LINUXKM_LKCAPI_DONT_REGISTER_AESCCM)
#error Config conflict: target kernel has CONFIG_CRYPTO_CCM, but module is missing HAVE_AESCCM.
#endif
#undef LINUXKM_LKCAPI_REGISTER_AESCCM
#undef LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309
#endif
#ifdef WOLFSSL_AES_XTS
#if (defined(LINUXKM_LKCAPI_REGISTER_ALL) || \
defined(LINUXKM_LKCAPI_REGISTER_AES_ALL) || \
@@ -227,6 +257,12 @@
#ifdef LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106
static int linuxkm_test_aesgcm_rfc4106(void);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESCCM
static int linuxkm_test_aesccm(void);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309
static int linuxkm_test_aesccm_rfc4309(void);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESXTS
static int linuxkm_test_aesxts(void);
#endif
@@ -246,7 +282,9 @@
defined(LINUXKM_LKCAPI_REGISTER_AESOFB) || \
defined(LINUXKM_LKCAPI_REGISTER_AESECB) || \
defined(LINUXKM_LKCAPI_REGISTER_AESGCM) || \
defined(LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106)
defined(LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106) || \
defined(LINUXKM_LKCAPI_REGISTER_AESCCM) || \
defined(LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309)
#define LINUXKM_LKCAPI_NEED_AES_COMMON_FUNCS
#endif
@@ -259,7 +297,9 @@
#endif
#if defined(LINUXKM_LKCAPI_REGISTER_AESGCM) || \
defined(LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106)
defined(LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106) || \
defined(LINUXKM_LKCAPI_REGISTER_AESCCM) || \
defined(LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309)
#define LINUXKM_LKCAPI_REGISTER_AEADS
#endif
@@ -275,8 +315,12 @@ struct km_AesCtx {
Aes *aes_encrypt_C; /* fallback if vector registers aren't available. */
Aes *aes_decrypt_C;
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106
byte rfc4106_nonce[4];
#if defined(LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106) || \
defined(LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309)
union {
byte rfc4106_nonce[4];
byte rfc4309_nonce[3];
};
#endif
};
@@ -1551,6 +1595,493 @@ static int gcmAesAead_rfc4106_loaded = 0;
#endif /* LINUXKM_LKCAPI_REGISTER_AESGCM || LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106 */
#if defined(LINUXKM_LKCAPI_REGISTER_AESCCM) || \
defined(LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309)
static int km_AesCcmInit(struct crypto_aead * tfm)
{
struct km_AesCtx * ctx = crypto_aead_ctx(tfm);
return km_AesInitCommon(ctx, WOLFKM_AESCCM_DRIVER, 0);
}
static void km_AesCcmExit(struct crypto_aead * tfm)
{
struct km_AesCtx * ctx = crypto_aead_ctx(tfm);
km_AesExitCommon(ctx);
}
#ifdef LINUXKM_LKCAPI_REGISTER_AESCCM
static int km_AesCcmSetKey(struct crypto_aead *tfm, const u8 *in_key,
unsigned int key_len)
{
int err;
struct km_AesCtx * ctx = crypto_aead_ctx(tfm);
err = wc_AesCcmSetKey(ctx->aes_encrypt, in_key, key_len);
if (unlikely(err)) {
if ((! disable_setkey_warnings) && ((key_len == 16) || (key_len == 24) || (key_len == 32)))
pr_err("%s: wc_AesCcmSetKey failed: %d\n",
crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)), err);
return -EINVAL;
}
#ifdef WC_LINUXKM_C_FALLBACK_IN_SHIMS
if (ctx->aes_encrypt->use_aesni) {
ctx->aes_encrypt_C->use_aesni = WC_FLAG_DONT_USE_VECTOR_OPS;
err = wc_AesCcmSetKey(ctx->aes_encrypt_C, in_key, key_len);
if (unlikely(err)) {
if ((! disable_setkey_warnings) && ((key_len == 16) || (key_len == 24) || (key_len == 32)))
pr_err("%s: wc_AesCcmSetKey failed: %d\n",
crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)), err);
return -EINVAL;
}
if (ctx->aes_encrypt_C->use_aesni)
pr_err("%s: after wc_AesCcmSetKey, ctx->aes_encrypt_C has AES-NI asserted.\n", WOLFKM_AESCCM_DRIVER);
}
#endif
#ifdef WOLFKM_DEBUG_AES
pr_info("info: exiting km_AesCcmSetKey: %d\n", key_len);
#endif /* WOLFKM_DEBUG_AES */
return 0;
}
#endif /* LINUXKM_LKCAPI_REGISTER_AESCCM */
#ifdef LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309
static int km_AesCcmSetKey_Rfc4309(struct crypto_aead *tfm, const u8 *in_key,
unsigned int key_len)
{
int err;
struct km_AesCtx * ctx = crypto_aead_ctx(tfm);
if (key_len < 3)
return -EINVAL;
key_len -= 3;
memcpy(ctx->rfc4309_nonce, in_key + key_len, 3);
err = wc_AesCcmSetKey(ctx->aes_encrypt, in_key, key_len);
if (unlikely(err)) {
if ((! disable_setkey_warnings) && ((key_len == 16) || (key_len == 24) || (key_len == 32)))
pr_err("%s: wc_AesCcmSetKey failed: %d\n",
crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)), err);
return -EINVAL;
}
#ifdef WC_LINUXKM_C_FALLBACK_IN_SHIMS
if (ctx->aes_encrypt->use_aesni) {
ctx->aes_encrypt_C->use_aesni = WC_FLAG_DONT_USE_VECTOR_OPS;
err = wc_AesCcmSetKey(ctx->aes_encrypt_C, in_key, key_len);
if (unlikely(err)) {
if ((! disable_setkey_warnings) && ((key_len == 16) || (key_len == 24) || (key_len == 32)))
pr_err("%s: wc_AesCcmSetKey failed: %d\n",
crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)), err);
return -EINVAL;
}
if (ctx->aes_encrypt_C->use_aesni)
pr_err("%s: after wc_AesCcmSetKey, ctx->aes_encrypt_C has AES-NI asserted.\n", WOLFKM_AESCCM_RFC4309_DRIVER);
}
#endif
#ifdef WOLFKM_DEBUG_AES
pr_info("info: exiting km_AesCcmSetKey_Rfc4309: %d\n", key_len);
#endif /* WOLFKM_DEBUG_AES */
return 0;
}
#endif /* LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309 */
#ifdef LINUXKM_LKCAPI_REGISTER_AESCCM
static int km_AesCcmSetAuthsize(struct crypto_aead *tfm, unsigned int authsize)
{
(void)tfm;
/* RFC 3610 section 2 */
switch (authsize) {
case 4:
case 6:
case 8:
case 10:
case 12:
case 14:
case 16:
return 0;
}
#ifdef WOLFSSL_LINUXKM_VERBOSE_LKCAPI_DEBUG
pr_err("%s: invalid authsize: %d\n",
crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)), authsize);
#endif
return -EINVAL;
}
#endif /* LINUXKM_LKCAPI_REGISTER_AESCCM */
#ifdef LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309
static int km_AesCcmSetAuthsize_Rfc4309(struct crypto_aead *tfm, unsigned int authsize)
{
(void)tfm;
/* RFC 4309 permits 8, 12, and 16; the kernel rfc4309 wrapper enforces
* the same set, so we match it.
*/
switch (authsize) {
case 8:
case 12:
case 16:
return 0;
}
#ifdef WOLFSSL_LINUXKM_VERBOSE_LKCAPI_DEBUG
pr_err("%s: invalid authsize: %d\n",
crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)), authsize);
#endif
return -EINVAL;
}
#endif /* LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309 */
/*
* ccm(aes) -- the generic kernel CCM convention. ivsize is 16,
* and req->iv is a partially-formed B0 block where
* req->iv[0] = L - 1, req->iv[1 .. 15-L] = nonce N,
* and bytes [16-L .. 15] are scratch (the kernel's
* generic ccm() template would write the message
* length there before encrypting B0). We don't need
* that scratch region: wc_AesCcmEncrypt rebuilds B0
* internally from (nonce, nonceSz, inSz, ...).
* So all we have to do is decode L from req->iv[0]
* and present (&req->iv[1], 15 - L) as the nonce.
*
* rfc4309(ccm(aes)) -- IPsec ESP convention per RFC 4309. The trailing
* three bytes of the key material are a per-SA salt
* that we stash at setkey time, and ivsize is 8 (the
* explicit per-packet IV). At request time we form
* an 11-byte nonce as salt(3) || req->iv(8), giving
* L = 4, matching RFC 4309 section 4. RFC 4309
* also packs an extra 8 bytes (a copy of the
* explicit IV) into the AAD region between the real
* AAD and the ciphertext, so the real AAD length is
* req->assoclen - 8, and the ciphertext starts at
* offset req->assoclen. This mirrors what the GCM
* rfc4106 path does.
*
* aead ciphers receive data in scatterlists in the following order:
* encrypt
* req->src: aad||plaintext
* req->dst: aad||ciphertext||tag
* decrypt
* req->src: aad||ciphertext||tag
* req->dst: aad||plaintext, return 0 or -EBADMSG
*
* For rfc4309 the AAD region additionally contains an inline 8-byte copy of
* the explicit IV between the real AAD and the (cipher)text, so:
* real AAD length = req->assoclen - 8
* (cipher)text offset = req->assoclen (skips the inline IV too)
*
* Note that wc_AesCcm has no streaming API, so we always linearize the
* scatterlists into a single bounce buffer when they aren't already
* contiguous, exactly as the !WOLFSSL_AESGCM_STREAM branch of the GCM glue
* does.
*/
static int AesCcmCrypt_1(struct aead_request *req, int decrypt_p, int rfc4309_p)
{
struct crypto_aead * tfm = NULL;
struct km_AesCtx * ctx = NULL;
struct skcipher_walk sk_walk;
struct scatter_walk in_walk, out_walk;
u8 *in_map = NULL, *out_map = NULL;
u8 authTag[WC_AES_BLOCK_SIZE];
int err;
unsigned int assoclen = req->assoclen;
u8 * assoc = NULL;
u8 * sg_buf = NULL;
Aes *aes_copy = NULL;
u8 * in_text = NULL;
u8 * out_text = NULL;
const byte * nonce = NULL;
word32 nonceSz = 0;
#ifdef LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309
byte rfc4309_iv[CCM_NONCE_MAX_SZ]; /* >= 11 */
#endif
tfm = crypto_aead_reqtfm(req);
ctx = crypto_aead_ctx(tfm);
if (decrypt_p) {
/* Copy out the original auth tag from req->src. */
scatterwalk_map_and_copy(authTag, req->src,
req->assoclen + req->cryptlen - tfm->authsize,
tfm->authsize, 0);
err = skcipher_walk_aead_decrypt(&sk_walk, req, false);
}
else {
err = skcipher_walk_aead_encrypt(&sk_walk, req, false);
}
if (unlikely(err)) {
pr_err("%s: %s failed: %d\n",
crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)),
decrypt_p ? "skcipher_walk_aead_decrypt" : "skcipher_walk_aead_encrypt",
err);
return -EINVAL;
}
err = km_AesGet(ctx, decrypt_p, 1 /* copy_p */, &aes_copy);
if (unlikely(err)) {
goto out;
}
#ifdef LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309
if (rfc4309_p) {
if (unlikely(assoclen != 16 && assoclen != 20)) {
err = -EINVAL;
goto out;
}
assoclen -= 8;
memcpy(rfc4309_iv, ctx->rfc4309_nonce, 3);
memcpy(rfc4309_iv + 3, sk_walk.iv, 8);
nonce = rfc4309_iv;
nonceSz = 11;
}
else
#else
(void)rfc4309_p;
#endif /* LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309 */
{
/* Generic ccm(aes): req->iv is a 16-byte buffer.
* req->iv[0] = L - 1 (2 <= L <= 8)
* req->iv[1 .. 15-L] = nonce N (length 15 - L = nonceSz)
* req->iv[16-L .. 15] = scratch (we don't read it)
*/
unsigned int L_minus_1 = ((byte *)sk_walk.iv)[0];
unsigned int L = L_minus_1 + 1U;
if (unlikely(L < 2U || L > 8U)) {
err = -EINVAL;
goto out;
}
nonceSz = 15U - L;
nonce = &((byte *)sk_walk.iv)[1];
}
if ((req->src->length >= req->assoclen + req->cryptlen) &&
(req->dst->length >= req->assoclen + req->cryptlen))
{
scatterwalk_start(&in_walk, req->src);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
scatterwalk_map(&in_walk);
in_map = in_walk.addr;
#else
in_map = scatterwalk_map(&in_walk);
#endif
if (unlikely(IS_ERR(in_map))) {
err = (int)PTR_ERR(in_map);
pr_err("%s: scatterwalk_map failed: %ld\n",
crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)),
PTR_ERR(in_map));
in_map = NULL;
goto out;
}
assoc = in_map;
in_text = in_map + req->assoclen;
scatterwalk_start(&out_walk, req->dst);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
scatterwalk_map(&out_walk);
out_map = out_walk.addr;
#else
out_map = scatterwalk_map(&out_walk);
#endif
if (unlikely(IS_ERR(out_map))) {
err = (int)PTR_ERR(out_map);
pr_err("%s: scatterwalk_map failed: %ld\n",
crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)),
PTR_ERR(out_map));
out_map = NULL;
goto out;
}
out_text = out_map + req->assoclen;
}
else {
sg_buf = malloc(req->assoclen + req->cryptlen);
if (unlikely(sg_buf == NULL)) {
err = -ENOMEM;
goto out;
}
if (decrypt_p)
scatterwalk_map_and_copy(sg_buf, req->src, 0, req->assoclen + req->cryptlen - tfm->authsize, 0);
else
scatterwalk_map_and_copy(sg_buf, req->src, 0, req->assoclen + req->cryptlen, 0);
assoc = sg_buf;
in_text = out_text = sg_buf + req->assoclen;
}
if (decrypt_p) {
err = wc_AesCcmDecrypt(aes_copy, out_text, in_text,
req->cryptlen - tfm->authsize,
nonce, nonceSz,
authTag, tfm->authsize,
assoc, assoclen);
if (unlikely(err)) {
#ifdef WOLFSSL_LINUXKM_VERBOSE_LKCAPI_DEBUG
pr_err("%s: wc_AesCcmDecrypt failed with return code %d\n",
crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)), err);
#endif
if (err == WC_NO_ERR_TRACE(AES_CCM_AUTH_E)) {
err = -EBADMSG;
goto out;
}
else {
err = -EINVAL;
goto out;
}
}
}
else {
err = wc_AesCcmEncrypt(aes_copy, out_text, in_text, req->cryptlen,
nonce, nonceSz,
authTag, tfm->authsize,
assoc, assoclen);
if (unlikely(err)) {
pr_err("%s: wc_AesCcmEncrypt failed: %d\n",
crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)), err);
err = -EINVAL;
goto out;
}
}
if (sg_buf) {
if (decrypt_p)
scatterwalk_map_and_copy(sg_buf, req->dst, 0, req->assoclen + req->cryptlen - tfm->authsize, 1);
else
scatterwalk_map_and_copy(sg_buf, req->dst, 0, req->assoclen + req->cryptlen, 1);
}
if (! decrypt_p) {
/* Now copy the auth tag into the request scatterlist. */
scatterwalk_map_and_copy(authTag, req->dst,
req->assoclen + req->cryptlen,
tfm->authsize, 1);
}
out:
if (sg_buf) {
free(sg_buf);
}
else {
if (in_map) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
scatterwalk_unmap(&in_walk);
#else
scatterwalk_unmap(in_map);
#endif
}
if (out_map) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
scatterwalk_unmap(&out_walk);
#else
scatterwalk_unmap(out_map);
#endif
}
}
km_AesFree(&aes_copy);
#ifdef WOLFKM_DEBUG_AES
pr_info("info: exiting AesCcmCrypt_1: err %d, dec %d, cryptlen %d, "
"assoclen %d\n", err, decrypt_p,
req->cryptlen, req->assoclen);
#endif /* WOLFKM_DEBUG_AES */
return err;
}
#ifdef LINUXKM_LKCAPI_REGISTER_AESCCM
static int km_AesCcmEncrypt(struct aead_request *req) {
return AesCcmCrypt_1(req, 0 /* decrypt_p */, 0 /* rfc4309_p */);
}
static int km_AesCcmDecrypt(struct aead_request *req) {
return AesCcmCrypt_1(req, 1 /* decrypt_p */, 0 /* rfc4309_p */);
}
static struct aead_alg ccmAesAead = {
.base.cra_name = WOLFKM_AESCCM_NAME,
.base.cra_driver_name = WOLFKM_AESCCM_DRIVER,
.base.cra_priority = WOLFSSL_LINUXKM_LKCAPI_PRIORITY,
.base.cra_blocksize = 1,
.base.cra_ctxsize = sizeof(struct km_AesCtx),
.base.cra_module = THIS_MODULE,
.init = km_AesCcmInit,
.exit = km_AesCcmExit,
.setkey = km_AesCcmSetKey,
.setauthsize = km_AesCcmSetAuthsize,
.encrypt = km_AesCcmEncrypt,
.decrypt = km_AesCcmDecrypt,
.ivsize = WC_AES_BLOCK_SIZE,
.maxauthsize = WC_AES_BLOCK_SIZE,
.chunksize = 1,
};
static int ccmAesAead_loaded = 0;
#endif /* LINUXKM_LKCAPI_REGISTER_AESCCM */
#ifdef LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309
static int km_AesCcmEncrypt_Rfc4309(struct aead_request *req) {
return AesCcmCrypt_1(req, 0 /* decrypt_p */, 1 /* rfc4309_p */);
}
static int km_AesCcmDecrypt_Rfc4309(struct aead_request *req) {
return AesCcmCrypt_1(req, 1 /* decrypt_p */, 1 /* rfc4309_p */);
}
static struct aead_alg ccmAesAead_rfc4309 = {
.base.cra_name = WOLFKM_AESCCM_RFC4309_NAME,
.base.cra_driver_name = WOLFKM_AESCCM_RFC4309_DRIVER,
.base.cra_priority = WOLFSSL_LINUXKM_LKCAPI_PRIORITY,
.base.cra_blocksize = 1,
.base.cra_ctxsize = sizeof(struct km_AesCtx),
.base.cra_module = THIS_MODULE,
.init = km_AesCcmInit,
.exit = km_AesCcmExit,
.setkey = km_AesCcmSetKey_Rfc4309,
.setauthsize = km_AesCcmSetAuthsize_Rfc4309,
.encrypt = km_AesCcmEncrypt_Rfc4309,
.decrypt = km_AesCcmDecrypt_Rfc4309,
.ivsize = 8,
.maxauthsize = WC_AES_BLOCK_SIZE,
.chunksize = 1,
};
static int ccmAesAead_rfc4309_loaded = 0;
#endif /* LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309 */
#endif /* LINUXKM_LKCAPI_REGISTER_AESCCM || LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309 */
#ifdef LINUXKM_LKCAPI_REGISTER_AESXTS
#ifndef WOLFSSL_AESXTS_STREAM
@@ -2692,9 +3223,9 @@ static int linuxkm_test_aescfb(void)
if (aes == NULL)
return MEMORY_E;
ret = aesofb_test();
ret = aes_cfb_test();
if (ret) {
wc_test_render_error_message("aesgcm_test failed: ", ret);
wc_test_render_error_message("aes_cfb_test failed: ", ret);
ret = WC_TEST_RET_DEC_EC(ret);
goto test_cfb_end;
}
@@ -3165,6 +3696,36 @@ static int linuxkm_test_aesgcm_rfc4106(void)
#endif /* LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106 */
#if defined(LINUXKM_LKCAPI_REGISTER_AESCCM) || defined(LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309)
static int aesccm_test_once(void) {
static int once = 0;
static int ret;
if (! once) {
ret = aesccm_test();
once = 1;
}
return ret;
}
#ifdef LINUXKM_LKCAPI_REGISTER_AESCCM
static int linuxkm_test_aesccm(void) {
return aesccm_test_once();
}
#endif /* LINUXKM_LKCAPI_REGISTER_AESCCM */
#ifdef LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309
static int linuxkm_test_aesccm_rfc4309(void) {
return aesccm_test_once();
}
#endif /* LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309 */
#endif /* LINUXKM_LKCAPI_REGISTER_AESCCM || LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309 */
#ifdef LINUXKM_LKCAPI_REGISTER_AESXTS
/* test vectors from
+13 -1
View File
@@ -431,7 +431,7 @@ static int linuxkm_lkcapi_register(void)
(alg).base.cra_driver_name, ret); \
} \
(crypto_unregister_ ## alg_class)(&(alg)); \
if (! (alg.base.cra_flags & CRYPTO_ALG_DEAD)) { \
if (! ((alg).base.cra_flags & CRYPTO_ALG_DEAD)) { \
pr_err("ERROR: alg %s not _DEAD " \
"after crypto_unregister_%s -- " \
"marking as loaded despite test failure.", \
@@ -460,6 +460,12 @@ static int linuxkm_lkcapi_register(void)
#ifdef LINUXKM_LKCAPI_REGISTER_AESGCM
REGISTER_ALG(gcmAesAead, aead, linuxkm_test_aesgcm);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309
REGISTER_ALG(ccmAesAead_rfc4309, aead, linuxkm_test_aesccm_rfc4309);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESCCM
REGISTER_ALG(ccmAesAead, aead, linuxkm_test_aesccm);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESXTS
REGISTER_ALG(xtsAesAlg, skcipher, linuxkm_test_aesxts);
#endif
@@ -831,6 +837,12 @@ static int linuxkm_lkcapi_unregister(void)
#ifdef LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106
UNREGISTER_ALG(gcmAesAead_rfc4106, aead);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESCCM
UNREGISTER_ALG(ccmAesAead, aead);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESCCM_RFC4309
UNREGISTER_ALG(ccmAesAead_rfc4309, aead);
#endif
#ifdef LINUXKM_LKCAPI_REGISTER_AESXTS
UNREGISTER_ALG(xtsAesAlg, skcipher);
#endif
+2
View File
@@ -1728,9 +1728,11 @@ static int updateFipsHash(void)
FIPS_IN_CORE_DIGEST_SIZE,
coreKey,
desc,
/* NOLINTBEGIN(clang-diagnostic-cast-function-type-strict) */
(wc_fips_verifyCore_hmac_setkey_fn)linux_fips_hmac_setkey,
(wc_fips_verifyCore_hmac_update_fn)linux_fips_hmac_update,
(wc_fips_verifyCore_hmac_final_fn)linux_fips_hmac_final,
/* NOLINTEND(clang-diagnostic-cast-function-type-strict) */
verifyCore,
&verifyCore_size,
#if defined(DEBUG_LINUXKM_PIE_SUPPORT) && defined(WC_SYM_RELOC_TABLES)