mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 19:20:49 +02:00
Merge pull request #10194 from douzzer/20260410-linuxkm-aes-ccm
20260410-linuxkm-aes-ccm
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user