Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 26 May 2017 20:20:40 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r318967 - head/sys/dev/cxgbe/crypto
Message-ID:  <201705262020.v4QKKecL096648@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Fri May 26 20:20:40 2017
New Revision: 318967
URL: https://svnweb.freebsd.org/changeset/base/318967

Log:
  Fail large requests with EFBIG.
  
  The adapter firmware in general does not accept PDUs larger than 64k - 1
  bytes in size.  Sending crypto requests larger than this size result in
  hangs or incorrect output, so reject them with EFBIG.  For requests
  chaining an AES cipher with an HMAC, the firmware appears to require
  slightly smaller requests (around 512 bytes).
  
  Sponsored by:	Chelsio Communications

Modified:
  head/sys/dev/cxgbe/crypto/t4_crypto.c

Modified: head/sys/dev/cxgbe/crypto/t4_crypto.c
==============================================================================
--- head/sys/dev/cxgbe/crypto/t4_crypto.c	Fri May 26 20:15:33 2017	(r318966)
+++ head/sys/dev/cxgbe/crypto/t4_crypto.c	Fri May 26 20:20:40 2017	(r318967)
@@ -117,6 +117,13 @@ __FBSDID("$FreeBSD$");
 #define	MAX_RX_PHYS_DSGL_SGE	32
 #define	DSGL_SGE_MAXLEN		65535
 
+/*
+ * The adapter only supports requests with a total input or output
+ * length of 64k-1 or smaller.  Longer requests either result in hung
+ * requests or incorrect results.
+ */
+#define	MAX_REQUEST_SIZE	65535
+
 static MALLOC_DEFINE(M_CCR, "ccr", "Chelsio T6 crypto");
 
 struct ccr_session_hmac {
@@ -412,6 +419,12 @@ ccr_hmac(struct ccr_softc *sc, uint32_t 
 	u_int imm_len, iopad_size;
 	int error, sgl_nsegs, sgl_len;
 
+	crd = crp->crp_desc;
+
+	/* Reject requests with too large of an input buffer. */
+	if (crd->crd_len > MAX_REQUEST_SIZE)
+		return (EFBIG);
+
 	axf = s->hmac.auth_hash;
 
 	/* PADs must be 128-bit aligned. */
@@ -425,7 +438,6 @@ ccr_hmac(struct ccr_softc *sc, uint32_t 
 	hash_size_in_response = axf->hashsize;
 	transhdr_len = HASH_TRANSHDR_SIZE(kctx_len);
 
-	crd = crp->crp_desc;
 	if (ccr_use_imm_data(transhdr_len, crd->crd_len)) {
 		imm_len = crd->crd_len;
 		sgl_nsegs = 0;
@@ -538,6 +550,10 @@ ccr_blkcipher(struct ccr_softc *sc, uint
 	    (crd->crd_len % AES_BLOCK_LEN) != 0)
 		return (EINVAL);
 
+	/* Reject requests with too large of an input buffer. */
+	if (crd->crd_len > MAX_REQUEST_SIZE)
+		return (EFBIG);
+
 	iv_loc = IV_NOP;
 	if (crd->crd_flags & CRD_F_ENCRYPT) {
 		op_type = CHCR_ENCRYPT_OP;
@@ -785,6 +801,13 @@ ccr_authenc(struct ccr_softc *sc, uint32
 	 * the hash when encrypting.  For decryption it only contains
 	 * the plain text.
 	 */
+	if (op_type == CHCR_ENCRYPT_OP) {
+		if (crde->crd_len + hash_size_in_response > MAX_REQUEST_SIZE)
+			return (EFBIG);
+	} else {
+		if (crde->crd_len > MAX_REQUEST_SIZE)
+			return (EFBIG);
+	}
 	sglist_reset(sc->sg_dsgl);
 	error = sglist_append_sglist(sc->sg_dsgl, sc->sg_crp, crde->crd_skip,
 	    crde->crd_len);
@@ -824,6 +847,17 @@ ccr_authenc(struct ccr_softc *sc, uint32
 	} else
 		aad_len = 0;
 	input_len = aad_len + crde->crd_len;
+
+	/*
+	 * The firmware hangs if sent a request which is a
+	 * bit smaller than MAX_REQUEST_SIZE.  In particular, the
+	 * firmware appears to require 512 - 16 bytes of spare room
+	 * along with the size of the hash even if the hash isn't
+	 * included in the input buffer.
+	 */
+	if (input_len + roundup2(axf->hashsize, 16) + (512 - 16) >
+	    MAX_REQUEST_SIZE)
+		return (EFBIG);
 	if (op_type == CHCR_DECRYPT_OP)
 		input_len += hash_size_in_response;
 	if (ccr_use_imm_data(transhdr_len, s->blkcipher.iv_len + input_len)) {
@@ -1105,6 +1139,13 @@ ccr_gcm(struct ccr_softc *sc, uint32_t s
 	 * the tag when encrypting.  For decryption it only contains
 	 * the plain text.
 	 */
+	if (op_type == CHCR_ENCRYPT_OP) {
+		if (crde->crd_len + hash_size_in_response > MAX_REQUEST_SIZE)
+			return (EFBIG);
+	} else {
+		if (crde->crd_len > MAX_REQUEST_SIZE)
+			return (EFBIG);
+	}
 	sglist_reset(sc->sg_dsgl);
 	error = sglist_append_sglist(sc->sg_dsgl, sc->sg_crp, crde->crd_skip,
 	    crde->crd_len);
@@ -1136,6 +1177,8 @@ ccr_gcm(struct ccr_softc *sc, uint32_t s
 	input_len = crda->crd_len + crde->crd_len;
 	if (op_type == CHCR_DECRYPT_OP)
 		input_len += hash_size_in_response;
+	if (input_len > MAX_REQUEST_SIZE)
+		return (EFBIG);
 	if (ccr_use_imm_data(transhdr_len, iv_len + input_len)) {
 		imm_len = input_len;
 		sgl_nsegs = 0;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201705262020.v4QKKecL096648>