From owner-svn-src-head@freebsd.org Fri May 26 20:20:41 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id B536BD83440; Fri, 26 May 2017 20:20:41 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 909161F3F; Fri, 26 May 2017 20:20:41 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v4QKKekQ096649; Fri, 26 May 2017 20:20:40 GMT (envelope-from jhb@FreeBSD.org) Received: (from jhb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v4QKKecL096648; Fri, 26 May 2017 20:20:40 GMT (envelope-from jhb@FreeBSD.org) Message-Id: <201705262020.v4QKKecL096648@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jhb set sender to jhb@FreeBSD.org using -f From: John Baldwin Date: Fri, 26 May 2017 20:20:40 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r318967 - head/sys/dev/cxgbe/crypto X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 26 May 2017 20:20:41 -0000 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;