git: 38b8a2be5c48 - stable/13 - cryptodev: Permit explicit IV/nonce and MAC/tag lengths.

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Thu, 21 Oct 2021 22:04:12 UTC
The branch stable/13 has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=38b8a2be5c48436a5db059080b97ff0f8c02ef27

commit 38b8a2be5c48436a5db059080b97ff0f8c02ef27
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2021-10-06 21:08:46 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2021-10-21 21:05:11 +0000

    cryptodev: Permit explicit IV/nonce and MAC/tag lengths.
    
    Add 'ivlen' and 'maclen' fields to the structure used for CIOGSESSION2
    to specify the explicit IV/nonce and MAC/tag lengths for crypto
    sessions.  If these fields are zero, the default lengths are used.
    
    This permits selecting an alternate nonce length for AEAD ciphers such
    as AES-CCM which support multiple nonce leengths.  It also supports
    truncated MACs as input to AEAD or ETA requests.
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D32107
    
    (cherry picked from commit 16676123fc85233334983e0071cb446357abec8d)
---
 share/man/man4/crypto.4    | 24 ++++++++++++++++++++----
 sys/opencrypto/cryptodev.c | 29 +++++++++++++++++++++++++++--
 sys/opencrypto/cryptodev.h |  9 +++++++--
 3 files changed, 54 insertions(+), 8 deletions(-)

diff --git a/share/man/man4/crypto.4 b/share/man/man4/crypto.4
index f146b50ecd4b..83d00050af28 100644
--- a/share/man/man4/crypto.4
+++ b/share/man/man4/crypto.4
@@ -1,13 +1,16 @@
 .\"	$NetBSD: crypto.4,v 1.24 2014/01/27 21:23:59 pgoyette Exp $
 .\"
 .\" Copyright (c) 2008 The NetBSD Foundation, Inc.
-.\" Copyright (c) 2014 The FreeBSD Foundation
+.\" Copyright (c) 2014-2021 The FreeBSD Foundation
 .\" All rights reserved.
 .\"
 .\" Portions of this documentation were written by John-Mark Gurney
 .\" under sponsorship of the FreeBSD Foundation and
 .\" Rubicon Communications, LLC (Netgate).
 .\"
+.\" Portions of this documentation were written by Ararat River
+.\" Consulting, LLC under sponsorship of the FreeBSD Foundation.
+.\"
 .\" This code is derived from software contributed to The NetBSD Foundation
 .\" by Coyote Point Systems, Inc.
 .\"
@@ -60,7 +63,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 24, 2020
+.Dd October 6, 2021
 .Dt CRYPTO 4
 .Os
 .Sh NAME
@@ -265,14 +268,27 @@ struct session2_op {
 
     uint32_t ses;	/* returns: ses # */
     int	crid;		/* driver id + flags (rw) */
-    int	pad[4];		/* for future expansion */
+    int ivlen;		/* length of nonce/IV */
+    int maclen;		/* length of MAC/tag */
+    int	pad[2];		/* for future expansion */
 };
 
 .Ed
-This request is similar to CIOGSESSION except that
+This request is similar to CIOGSESSION but adds additional fields.
+.Pp
 .Fa sessp-\*[Gt]crid
 requests either a specific crypto device or a class of devices (software vs
 hardware).
+.Pp
+.Fa sessp-\*[Gt]ivlen
+specifies the length of the IV or nonce supplied with each request.
+If this field is set to zero, the default IV or nonce length is used.
+.Pp
+.Fa sessp-\*[Gt]maclen
+specifies the length of the MAC or authentication tag supplied or computed by
+each request.
+If this field is set to zero, the full MAC is used.
+.Pp
 The
 .Fa sessp-\*[Gt]pad
 field must be initialized to zero.
diff --git a/sys/opencrypto/cryptodev.c b/sys/opencrypto/cryptodev.c
index 9f581e68fe92..ffdf4c67d2f0 100644
--- a/sys/opencrypto/cryptodev.c
+++ b/sys/opencrypto/cryptodev.c
@@ -103,7 +103,9 @@ struct session2_op32 {
 	uint32_t	mackey;
 	uint32_t	ses;
 	int		crid;
-	int		pad[4];
+	int		ivlen;
+	int		maclen;
+	int		pad[2];
 };
 
 struct crypt_op32 {
@@ -172,6 +174,8 @@ session2_op_from_32(const struct session2_op32 *from, struct session2_op *to)
 
 	session_op_from_32((const struct session_op32 *)from, to);
 	CP(*from, *to, crid);
+	CP(*from, *to, ivlen);
+	CP(*from, *to, maclen);
 }
 
 static void
@@ -662,6 +666,25 @@ cse_create(struct fcrypt *fcr, struct session2_op *sop)
 			csp.csp_ivlen = AES_CCM_IV_LEN;
 	}
 
+	if (sop->ivlen != 0) {
+		if (csp.csp_ivlen == 0) {
+			CRYPTDEB("does not support an IV");
+			error = EINVAL;
+			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+			goto bail;
+		}
+		csp.csp_ivlen = sop->ivlen;
+	}
+	if (sop->maclen != 0) {
+		if (!(thash != NULL || csp.csp_mode == CSP_MODE_AEAD)) {
+			CRYPTDEB("does not support a MAC");
+			error = EINVAL;
+			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+			goto bail;
+		}
+		csp.csp_auth_mlen = sop->maclen;
+	}
+
 	crid = sop->crid;
 	error = checkforsoftware(&crid);
 	if (error) {
@@ -683,7 +706,9 @@ cse_create(struct fcrypt *fcr, struct session2_op *sop)
 	cse->mackey = mackey;
 	cse->cses = cses;
 	cse->txform = txform;
-	if (thash != NULL)
+	if (sop->maclen != 0)
+		cse->hashsize = sop->maclen;
+	else if (thash != NULL)
 		cse->hashsize = thash->hashsize;
 	else if (csp.csp_cipher_alg == CRYPTO_AES_NIST_GCM_16)
 		cse->hashsize = AES_GMAC_HASH_LEN;
diff --git a/sys/opencrypto/cryptodev.h b/sys/opencrypto/cryptodev.h
index 4d9b735366b8..046f67de418e 100644
--- a/sys/opencrypto/cryptodev.h
+++ b/sys/opencrypto/cryptodev.h
@@ -23,13 +23,16 @@
  * PURPOSE.
  *
  * Copyright (c) 2001 Theo de Raadt
- * Copyright (c) 2014 The FreeBSD Foundation
+ * Copyright (c) 2014-2021 The FreeBSD Foundation
  * All rights reserved.
  *
  * Portions of this software were developed by John-Mark Gurney
  * under sponsorship of the FreeBSD Foundation and
  * Rubicon Communications, LLC (Netgate).
  *
+ * Portions of this software were developed by Ararat River
+ * Consulting, LLC under sponsorship of the FreeBSD Foundation.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -246,7 +249,9 @@ struct session2_op {
 
   	uint32_t	ses;		/* returns: session # */ 
 	int		crid;		/* driver id + flags (rw) */
-	int		pad[4];		/* for future expansion */
+	int		ivlen;		/* length of nonce/IV */
+	int		maclen;		/* length of MAC/tag */
+	int		pad[2];		/* for future expansion */
 };
 
 struct crypt_op {