git: 655eb762c310 - main - aesni: Support AES-CCM requests with a truncated tag.

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Wed, 06 Oct 2021 21:10:35 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=655eb762c31044a791e8c8c6355515e7c89c07ef

commit 655eb762c31044a791e8c8c6355515e7c89c07ef
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2021-10-06 21:08:48 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2021-10-06 21:08:48 +0000

    aesni: Support AES-CCM requests with a truncated tag.
    
    Reviewed by:    sef
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D32115
---
 sys/crypto/aesni/aesni.c     | 18 +++++++++++-------
 sys/crypto/aesni/aesni.h     |  8 ++++----
 sys/crypto/aesni/aesni_ccm.c | 10 ++--------
 3 files changed, 17 insertions(+), 19 deletions(-)

diff --git a/sys/crypto/aesni/aesni.c b/sys/crypto/aesni/aesni.c
index 7d4dbd2c1604..de797abd1af5 100644
--- a/sys/crypto/aesni/aesni.c
+++ b/sys/crypto/aesni/aesni.c
@@ -319,9 +319,6 @@ aesni_probesession(device_t dev, const struct crypto_session_params *csp)
 				CRYPTDEB("invalid CCM key length");
 				return (EINVAL);
 			}
-			if (csp->csp_auth_mlen != 0 &&
-			    csp->csp_auth_mlen != AES_CBC_MAC_HASH_LEN)
-				return (EINVAL);
 			if (!sc->has_aes)
 				return (EINVAL);
 			break;
@@ -610,6 +607,11 @@ aesni_cipher_setup(struct aesni_session *ses,
 		error = aesni_authprepare(ses, csp->csp_auth_klen);
 		if (error != 0)
 			return (error);
+	} else if (csp->csp_cipher_alg == CRYPTO_AES_CCM_16) {
+		if (csp->csp_auth_mlen == 0)
+			ses->mlen = AES_CBC_MAC_HASH_LEN;
+		else
+			ses->mlen = csp->csp_auth_mlen;
 	}
 
 	kt = is_fpu_kern_thread(0) || (csp->csp_cipher_alg == 0);
@@ -809,15 +811,17 @@ aesni_cipher_crypt(struct aesni_session *ses, struct cryptop *crp,
 			memset(tag, 0, sizeof(tag));			
 			AES_CCM_encrypt(buf, outbuf, authbuf, iv, tag,
 			    crp->crp_payload_length, crp->crp_aad_length,
-			    csp->csp_ivlen, ses->enc_schedule, ses->rounds);
-			crypto_copyback(crp, crp->crp_digest_start, sizeof(tag),
+			    csp->csp_ivlen, ses->mlen, ses->enc_schedule,
+			    ses->rounds);
+			crypto_copyback(crp, crp->crp_digest_start, ses->mlen,
 			    tag);
 		} else {
-			crypto_copydata(crp, crp->crp_digest_start, sizeof(tag),
+			crypto_copydata(crp, crp->crp_digest_start, ses->mlen,
 			    tag);
 			if (!AES_CCM_decrypt(buf, outbuf, authbuf, iv, tag,
 			    crp->crp_payload_length, crp->crp_aad_length,
-			    csp->csp_ivlen, ses->enc_schedule, ses->rounds))
+			    csp->csp_ivlen, ses->mlen, ses->enc_schedule,
+			    ses->rounds))
 				error = EBADMSG;
 		}
 		break;
diff --git a/sys/crypto/aesni/aesni.h b/sys/crypto/aesni/aesni.h
index 284bf6fba0fc..77ceec7b382a 100644
--- a/sys/crypto/aesni/aesni.h
+++ b/sys/crypto/aesni/aesni.h
@@ -112,12 +112,12 @@ int AES_GCM_decrypt(const unsigned char *in, unsigned char *out,
 /* CCM + CBC-MAC functions */
 void AES_CCM_encrypt(const unsigned char *in, unsigned char *out,
     const unsigned char *addt, const unsigned char *ivec,
-    unsigned char *tag, uint32_t nbytes, uint32_t abytes, int ibytes,
-    const unsigned char *key, int nr);
+    unsigned char *tag, uint32_t nbytes, uint32_t abytes, int nlen,
+    int tag_length, const unsigned char *key, int nr);
 int AES_CCM_decrypt(const unsigned char *in, unsigned char *out,
     const unsigned char *addt, const unsigned char *ivec,
-    const unsigned char *tag, uint32_t nbytes, uint32_t abytes, int ibytes,
-    const unsigned char *key, int nr);
+    const unsigned char *tag, uint32_t nbytes, uint32_t abytes, int nlen,
+    int tag_length, const unsigned char *key, int nr);
 void aesni_cipher_setup_common(struct aesni_session *ses,
     const struct crypto_session_params *csp, const uint8_t *key, int keylen);
 
diff --git a/sys/crypto/aesni/aesni_ccm.c b/sys/crypto/aesni/aesni_ccm.c
index 34b61a633907..c7edaa0b9d5c 100644
--- a/sys/crypto/aesni/aesni_ccm.c
+++ b/sys/crypto/aesni/aesni_ccm.c
@@ -185,10 +185,6 @@ cbc_mac_start(const unsigned char *auth_data, size_t auth_len,
  * Implement AES CCM+CBC-MAC encryption and authentication.
  *
  * A couple of notes:
- * The specification allows for a different number of tag lengths;
- * however, they're always truncated from 16 bytes, and the tag
- * length isn't passed in.  (This could be fixed by changing the
- * code in aesni.c:aesni_cipher_crypt().)
  * Since abytes is limited to a 32 bit value here, the AAD is
  * limited to 4 gigabytes or less.
  */
@@ -196,9 +192,8 @@ void
 AES_CCM_encrypt(const unsigned char *in, unsigned char *out,
 		const unsigned char *addt, const unsigned char *nonce,
 		unsigned char *tag, uint32_t nbytes, uint32_t abytes, int nlen,
-		const unsigned char *key, int nr)
+		int tag_length, const unsigned char *key, int nr)
 {
-	static const int tag_length = 16;	/* 128 bits */
 	int L;
 	int counter = 1;	/* S0 has 0, S1 has 1 */
 	size_t copy_amt, total = 0;
@@ -367,9 +362,8 @@ int
 AES_CCM_decrypt(const unsigned char *in, unsigned char *out,
 		const unsigned char *addt, const unsigned char *nonce,
 		const unsigned char *tag, uint32_t nbytes, uint32_t abytes, int nlen,
-		const unsigned char *key, int nr)
+		int tag_length, const unsigned char *key, int nr)
 {
-	static const int tag_length = 16;	/* 128 bits */
 	int L;
 	__m128i s0, rolling_mac, staging_block;
 	uint8_t *byte_ptr;