xref: /freebsd/sys/dev/cxgbe/crypto/t4_crypto.c (revision b670c9bafc0e31c7609969bf374b2e80bdc00211)
15033c43bSJohn Baldwin /*-
25033c43bSJohn Baldwin  * Copyright (c) 2017 Chelsio Communications, Inc.
31833d604SJohn Baldwin  * Copyright (c) 2021 The FreeBSD Foundation
45033c43bSJohn Baldwin  * All rights reserved.
55033c43bSJohn Baldwin  * Written by: John Baldwin <jhb@FreeBSD.org>
65033c43bSJohn Baldwin  *
71833d604SJohn Baldwin  * Portions of this software were developed by Ararat River
81833d604SJohn Baldwin  * Consulting, LLC under sponsorship of the FreeBSD Foundation.
91833d604SJohn Baldwin  *
105033c43bSJohn Baldwin  * Redistribution and use in source and binary forms, with or without
115033c43bSJohn Baldwin  * modification, are permitted provided that the following conditions
125033c43bSJohn Baldwin  * are met:
135033c43bSJohn Baldwin  * 1. Redistributions of source code must retain the above copyright
145033c43bSJohn Baldwin  *    notice, this list of conditions and the following disclaimer.
155033c43bSJohn Baldwin  * 2. Redistributions in binary form must reproduce the above copyright
165033c43bSJohn Baldwin  *    notice, this list of conditions and the following disclaimer in the
175033c43bSJohn Baldwin  *    documentation and/or other materials provided with the distribution.
185033c43bSJohn Baldwin  *
195033c43bSJohn Baldwin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
205033c43bSJohn Baldwin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
215033c43bSJohn Baldwin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
225033c43bSJohn Baldwin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
235033c43bSJohn Baldwin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
245033c43bSJohn Baldwin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
255033c43bSJohn Baldwin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
265033c43bSJohn Baldwin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
275033c43bSJohn Baldwin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
285033c43bSJohn Baldwin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
295033c43bSJohn Baldwin  * SUCH DAMAGE.
305033c43bSJohn Baldwin  */
315033c43bSJohn Baldwin 
325033c43bSJohn Baldwin #include <sys/types.h>
335033c43bSJohn Baldwin #include <sys/bus.h>
345033c43bSJohn Baldwin #include <sys/lock.h>
355033c43bSJohn Baldwin #include <sys/malloc.h>
365033c43bSJohn Baldwin #include <sys/mutex.h>
375033c43bSJohn Baldwin #include <sys/module.h>
385033c43bSJohn Baldwin #include <sys/sglist.h>
395033c43bSJohn Baldwin 
405033c43bSJohn Baldwin #include <opencrypto/cryptodev.h>
415033c43bSJohn Baldwin #include <opencrypto/xform.h>
425033c43bSJohn Baldwin 
435033c43bSJohn Baldwin #include "cryptodev_if.h"
445033c43bSJohn Baldwin 
455033c43bSJohn Baldwin #include "common/common.h"
465033c43bSJohn Baldwin #include "crypto/t4_crypto.h"
475033c43bSJohn Baldwin 
485033c43bSJohn Baldwin /*
495033c43bSJohn Baldwin  * Requests consist of:
505033c43bSJohn Baldwin  *
515033c43bSJohn Baldwin  * +-------------------------------+
525033c43bSJohn Baldwin  * | struct fw_crypto_lookaside_wr |
535033c43bSJohn Baldwin  * +-------------------------------+
545033c43bSJohn Baldwin  * | struct ulp_txpkt              |
555033c43bSJohn Baldwin  * +-------------------------------+
565033c43bSJohn Baldwin  * | struct ulptx_idata            |
575033c43bSJohn Baldwin  * +-------------------------------+
585033c43bSJohn Baldwin  * | struct cpl_tx_sec_pdu         |
595033c43bSJohn Baldwin  * +-------------------------------+
605033c43bSJohn Baldwin  * | struct cpl_tls_tx_scmd_fmt    |
615033c43bSJohn Baldwin  * +-------------------------------+
625033c43bSJohn Baldwin  * | key context header            |
635033c43bSJohn Baldwin  * +-------------------------------+
645033c43bSJohn Baldwin  * | AES key                       |  ----- For requests with AES
65567a3784SJohn Baldwin  * +-------------------------------+
66567a3784SJohn Baldwin  * | Hash state                    |  ----- For hash-only requests
675033c43bSJohn Baldwin  * +-------------------------------+ -
685033c43bSJohn Baldwin  * | IPAD (16-byte aligned)        |  \
695033c43bSJohn Baldwin  * +-------------------------------+  +---- For requests with HMAC
705033c43bSJohn Baldwin  * | OPAD (16-byte aligned)        |  /
715033c43bSJohn Baldwin  * +-------------------------------+ -
725033c43bSJohn Baldwin  * | GMAC H                        |  ----- For AES-GCM
735033c43bSJohn Baldwin  * +-------------------------------+ -
745033c43bSJohn Baldwin  * | struct cpl_rx_phys_dsgl       |  \
755033c43bSJohn Baldwin  * +-------------------------------+  +---- Destination buffer for
765033c43bSJohn Baldwin  * | PHYS_DSGL entries             |  /     non-hash-only requests
775033c43bSJohn Baldwin  * +-------------------------------+ -
78567a3784SJohn Baldwin  * | 16 dummy bytes                |  ----- Only for HMAC/hash-only requests
795033c43bSJohn Baldwin  * +-------------------------------+
805033c43bSJohn Baldwin  * | IV                            |  ----- If immediate IV
815033c43bSJohn Baldwin  * +-------------------------------+
825033c43bSJohn Baldwin  * | Payload                       |  ----- If immediate Payload
835033c43bSJohn Baldwin  * +-------------------------------+ -
845033c43bSJohn Baldwin  * | struct ulptx_sgl              |  \
855033c43bSJohn Baldwin  * +-------------------------------+  +---- If payload via SGL
865033c43bSJohn Baldwin  * | SGL entries                   |  /
875033c43bSJohn Baldwin  * +-------------------------------+ -
885033c43bSJohn Baldwin  *
895033c43bSJohn Baldwin  * Note that the key context must be padded to ensure 16-byte alignment.
905033c43bSJohn Baldwin  * For HMAC requests, the key consists of the partial hash of the IPAD
915033c43bSJohn Baldwin  * followed by the partial hash of the OPAD.
925033c43bSJohn Baldwin  *
935033c43bSJohn Baldwin  * Replies consist of:
945033c43bSJohn Baldwin  *
955033c43bSJohn Baldwin  * +-------------------------------+
965033c43bSJohn Baldwin  * | struct cpl_fw6_pld            |
975033c43bSJohn Baldwin  * +-------------------------------+
985033c43bSJohn Baldwin  * | hash digest                   |  ----- For HMAC request with
995033c43bSJohn Baldwin  * +-------------------------------+        'hash_size' set in work request
1005033c43bSJohn Baldwin  *
1015033c43bSJohn Baldwin  * A 32-bit big-endian error status word is supplied in the last 4
1025033c43bSJohn Baldwin  * bytes of data[0] in the CPL_FW6_PLD message.  bit 0 indicates a
1035033c43bSJohn Baldwin  * "MAC" error and bit 1 indicates a "PAD" error.
1045033c43bSJohn Baldwin  *
1055033c43bSJohn Baldwin  * The 64-bit 'cookie' field from the fw_crypto_lookaside_wr message
1065033c43bSJohn Baldwin  * in the request is returned in data[1] of the CPL_FW6_PLD message.
1075033c43bSJohn Baldwin  *
1085033c43bSJohn Baldwin  * For block cipher replies, the updated IV is supplied in data[2] and
1095033c43bSJohn Baldwin  * data[3] of the CPL_FW6_PLD message.
1105033c43bSJohn Baldwin  *
1115033c43bSJohn Baldwin  * For hash replies where the work request set 'hash_size' to request
1125033c43bSJohn Baldwin  * a copy of the hash in the reply, the hash digest is supplied
1135033c43bSJohn Baldwin  * immediately following the CPL_FW6_PLD message.
1145033c43bSJohn Baldwin  */
1155033c43bSJohn Baldwin 
1165033c43bSJohn Baldwin /*
117acaabdbbSJohn Baldwin  * The crypto engine supports a maximum AAD size of 511 bytes.
118acaabdbbSJohn Baldwin  */
119acaabdbbSJohn Baldwin #define	MAX_AAD_LEN		511
120acaabdbbSJohn Baldwin 
121acaabdbbSJohn Baldwin /*
122bf5b6620SJohn Baldwin  * The documentation for CPL_RX_PHYS_DSGL claims a maximum of 32 SG
123bf5b6620SJohn Baldwin  * entries.  While the CPL includes a 16-bit length field, the T6 can
124bf5b6620SJohn Baldwin  * sometimes hang if an error occurs while processing a request with a
125bf5b6620SJohn Baldwin  * single DSGL entry larger than 2k.
1265033c43bSJohn Baldwin  */
1275033c43bSJohn Baldwin #define	MAX_RX_PHYS_DSGL_SGE	32
128bf5b6620SJohn Baldwin #define	DSGL_SGE_MAXLEN		2048
1295033c43bSJohn Baldwin 
130d68990a1SJohn Baldwin /*
131d68990a1SJohn Baldwin  * The adapter only supports requests with a total input or output
132d68990a1SJohn Baldwin  * length of 64k-1 or smaller.  Longer requests either result in hung
133d68990a1SJohn Baldwin  * requests or incorrect results.
134d68990a1SJohn Baldwin  */
135d68990a1SJohn Baldwin #define	MAX_REQUEST_SIZE	65535
136d68990a1SJohn Baldwin 
1375033c43bSJohn Baldwin static MALLOC_DEFINE(M_CCR, "ccr", "Chelsio T6 crypto");
1385033c43bSJohn Baldwin 
1395033c43bSJohn Baldwin struct ccr_session_hmac {
140d8787d4fSMark Johnston 	const struct auth_hash *auth_hash;
1415033c43bSJohn Baldwin 	int hash_len;
1425033c43bSJohn Baldwin 	unsigned int partial_digest_len;
1435033c43bSJohn Baldwin 	unsigned int auth_mode;
1445033c43bSJohn Baldwin 	unsigned int mk_size;
145a1b2b6e1SJohn Baldwin 	char pads[CHCR_HASH_MAX_BLOCK_SIZE_128 * 2];
1465033c43bSJohn Baldwin };
1475033c43bSJohn Baldwin 
1485033c43bSJohn Baldwin struct ccr_session_gmac {
1495033c43bSJohn Baldwin 	int hash_len;
1505033c43bSJohn Baldwin 	char ghash_h[GMAC_BLOCK_LEN];
1515033c43bSJohn Baldwin };
1525033c43bSJohn Baldwin 
1536b0451d6SJohn Baldwin struct ccr_session_ccm_mac {
1546b0451d6SJohn Baldwin 	int hash_len;
1556b0451d6SJohn Baldwin };
1566b0451d6SJohn Baldwin 
157762f1dcbSJohn Baldwin struct ccr_session_cipher {
1585033c43bSJohn Baldwin 	unsigned int cipher_mode;
1595033c43bSJohn Baldwin 	unsigned int key_len;
1605033c43bSJohn Baldwin 	unsigned int iv_len;
1615033c43bSJohn Baldwin 	__be32 key_ctx_hdr;
1625033c43bSJohn Baldwin 	char enckey[CHCR_AES_MAX_KEY_LEN];
1635033c43bSJohn Baldwin 	char deckey[CHCR_AES_MAX_KEY_LEN];
1645033c43bSJohn Baldwin };
1655033c43bSJohn Baldwin 
16694fad5ffSJohn Baldwin struct ccr_port {
16794fad5ffSJohn Baldwin 	struct sge_wrq *txq;
16894fad5ffSJohn Baldwin 	struct sge_rxq *rxq;
1698f885fd1SJohn Baldwin 	int rx_channel_id;
17094fad5ffSJohn Baldwin 	int tx_channel_id;
17194fad5ffSJohn Baldwin 	u_int active_sessions;
1729c5137beSJohn Baldwin 
1739c5137beSJohn Baldwin 	counter_u64_t stats_queued;
1749c5137beSJohn Baldwin 	counter_u64_t stats_completed;
17594fad5ffSJohn Baldwin };
17694fad5ffSJohn Baldwin 
17794578db2SJohn Baldwin struct ccr_softc {
17894578db2SJohn Baldwin 	struct adapter *adapter;
17994578db2SJohn Baldwin 	device_t dev;
18094578db2SJohn Baldwin 	uint32_t cid;
18194578db2SJohn Baldwin 	struct mtx lock;
18294578db2SJohn Baldwin 	bool detaching;
18394578db2SJohn Baldwin 	struct ccr_port ports[MAX_NPORTS];
18494578db2SJohn Baldwin 	u_int port_mask;
1858f885fd1SJohn Baldwin 	int first_rxq_id;
1865033c43bSJohn Baldwin 
1875929c9fbSJohn Baldwin 	/*
1885929c9fbSJohn Baldwin 	 * Pre-allocate a dummy output buffer for the IV and AAD for
1895929c9fbSJohn Baldwin 	 * AEAD requests.
1905929c9fbSJohn Baldwin 	 */
1915929c9fbSJohn Baldwin 	char *iv_aad_buf;
1925929c9fbSJohn Baldwin 	struct sglist *sg_iv_aad;
1935929c9fbSJohn Baldwin 
1945033c43bSJohn Baldwin 	/* Statistics. */
195762f1dcbSJohn Baldwin 	counter_u64_t stats_cipher_encrypt;
196762f1dcbSJohn Baldwin 	counter_u64_t stats_cipher_decrypt;
19794578db2SJohn Baldwin 	counter_u64_t stats_hash;
19894578db2SJohn Baldwin 	counter_u64_t stats_hmac;
19994578db2SJohn Baldwin 	counter_u64_t stats_eta_encrypt;
20094578db2SJohn Baldwin 	counter_u64_t stats_eta_decrypt;
20194578db2SJohn Baldwin 	counter_u64_t stats_gcm_encrypt;
20294578db2SJohn Baldwin 	counter_u64_t stats_gcm_decrypt;
20394578db2SJohn Baldwin 	counter_u64_t stats_ccm_encrypt;
20494578db2SJohn Baldwin 	counter_u64_t stats_ccm_decrypt;
20594578db2SJohn Baldwin 	counter_u64_t stats_wr_nomem;
20694578db2SJohn Baldwin 	counter_u64_t stats_inflight;
20794578db2SJohn Baldwin 	counter_u64_t stats_mac_error;
20894578db2SJohn Baldwin 	counter_u64_t stats_pad_error;
20994578db2SJohn Baldwin 	counter_u64_t stats_sglist_error;
21094578db2SJohn Baldwin 	counter_u64_t stats_process_error;
21194578db2SJohn Baldwin 	counter_u64_t stats_sw_fallback;
212a727d953SNavdeep Parhar 
213a727d953SNavdeep Parhar 	struct sysctl_ctx_list ctx;
2145033c43bSJohn Baldwin };
2155033c43bSJohn Baldwin 
2167063b997SJohn Baldwin struct ccr_session {
2177063b997SJohn Baldwin #ifdef INVARIANTS
2187063b997SJohn Baldwin 	int pending;
2197063b997SJohn Baldwin #endif
2207063b997SJohn Baldwin 	enum { HASH, HMAC, CIPHER, ETA, GCM, CCM } mode;
2217063b997SJohn Baldwin 	struct ccr_softc *sc;
2227063b997SJohn Baldwin 	struct ccr_port *port;
2237063b997SJohn Baldwin 	union {
2247063b997SJohn Baldwin 		struct ccr_session_hmac hmac;
2257063b997SJohn Baldwin 		struct ccr_session_gmac gmac;
2267063b997SJohn Baldwin 		struct ccr_session_ccm_mac ccm_mac;
2277063b997SJohn Baldwin 	};
2287063b997SJohn Baldwin 	struct ccr_session_cipher cipher;
2297063b997SJohn Baldwin 	struct mtx lock;
2307063b997SJohn Baldwin 
2317063b997SJohn Baldwin 	/*
2327063b997SJohn Baldwin 	 * A fallback software session is used for certain GCM/CCM
2337063b997SJohn Baldwin 	 * requests that the hardware can't handle such as requests
2347063b997SJohn Baldwin 	 * with only AAD and no payload.
2357063b997SJohn Baldwin 	 */
2367063b997SJohn Baldwin 	crypto_session_t sw_session;
2377063b997SJohn Baldwin 
2387063b997SJohn Baldwin 	/*
2397063b997SJohn Baldwin 	 * Pre-allocate S/G lists used when preparing a work request.
2407063b997SJohn Baldwin 	 * 'sg_input' contains an sglist describing the entire input
2417063b997SJohn Baldwin 	 * buffer for a 'struct cryptop'.  'sg_output' contains an
2427063b997SJohn Baldwin 	 * sglist describing the entire output buffer.  'sg_ulptx' is
2437063b997SJohn Baldwin 	 * used to describe the data the engine should DMA as input
2447063b997SJohn Baldwin 	 * via ULPTX_SGL.  'sg_dsgl' is used to describe the
2457063b997SJohn Baldwin 	 * destination that cipher text and a tag should be written
2467063b997SJohn Baldwin 	 * to.
2477063b997SJohn Baldwin 	 */
2487063b997SJohn Baldwin 	struct sglist *sg_input;
2497063b997SJohn Baldwin 	struct sglist *sg_output;
2507063b997SJohn Baldwin 	struct sglist *sg_ulptx;
2517063b997SJohn Baldwin 	struct sglist *sg_dsgl;
2527063b997SJohn Baldwin };
2537063b997SJohn Baldwin 
2545033c43bSJohn Baldwin /*
2555033c43bSJohn Baldwin  * Crypto requests involve two kind of scatter/gather lists.
2565033c43bSJohn Baldwin  *
2575033c43bSJohn Baldwin  * Non-hash-only requests require a PHYS_DSGL that describes the
2585033c43bSJohn Baldwin  * location to store the results of the encryption or decryption
2595033c43bSJohn Baldwin  * operation.  This SGL uses a different format (PHYS_DSGL) and should
260c0341432SJohn Baldwin  * exclude the skip bytes at the start of the data as well as any AAD
261c0341432SJohn Baldwin  * or IV.  For authenticated encryption requests it should include the
262c0341432SJohn Baldwin  * destination of the hash or tag.
2635033c43bSJohn Baldwin  *
2645033c43bSJohn Baldwin  * The input payload may either be supplied inline as immediate data,
2655033c43bSJohn Baldwin  * or via a standard ULP_TX SGL.  This SGL should include AAD,
2665033c43bSJohn Baldwin  * ciphertext, and the hash or tag for authenticated decryption
2675033c43bSJohn Baldwin  * requests.
2685033c43bSJohn Baldwin  *
2695033c43bSJohn Baldwin  * These scatter/gather lists can describe different subsets of the
2709c0e3d3aSJohn Baldwin  * buffers described by the crypto operation.  ccr_populate_sglist()
2719c0e3d3aSJohn Baldwin  * generates a scatter/gather list that covers an entire crypto
2725033c43bSJohn Baldwin  * operation buffer that is then used to construct the other
2735033c43bSJohn Baldwin  * scatter/gather lists.
2745033c43bSJohn Baldwin  */
2755033c43bSJohn Baldwin static int
ccr_populate_sglist(struct sglist * sg,struct crypto_buffer * cb)2769c0e3d3aSJohn Baldwin ccr_populate_sglist(struct sglist *sg, struct crypto_buffer *cb)
2775033c43bSJohn Baldwin {
2785033c43bSJohn Baldwin 	int error;
2795033c43bSJohn Baldwin 
2805033c43bSJohn Baldwin 	sglist_reset(sg);
2819c0e3d3aSJohn Baldwin 	switch (cb->cb_type) {
282c0341432SJohn Baldwin 	case CRYPTO_BUF_MBUF:
2839c0e3d3aSJohn Baldwin 		error = sglist_append_mbuf(sg, cb->cb_mbuf);
284c0341432SJohn Baldwin 		break;
285883a0196SJohn Baldwin 	case CRYPTO_BUF_SINGLE_MBUF:
286883a0196SJohn Baldwin 		error = sglist_append_single_mbuf(sg, cb->cb_mbuf);
287883a0196SJohn Baldwin 		break;
288c0341432SJohn Baldwin 	case CRYPTO_BUF_UIO:
2899c0e3d3aSJohn Baldwin 		error = sglist_append_uio(sg, cb->cb_uio);
290c0341432SJohn Baldwin 		break;
291c0341432SJohn Baldwin 	case CRYPTO_BUF_CONTIG:
2929c0e3d3aSJohn Baldwin 		error = sglist_append(sg, cb->cb_buf, cb->cb_buf_len);
293c0341432SJohn Baldwin 		break;
294e6f6d0c9SAlan Somers 	case CRYPTO_BUF_VMPAGE:
295e6f6d0c9SAlan Somers 		error = sglist_append_vmpages(sg, cb->cb_vm_page,
29670efe1a2SJohn Baldwin 		    cb->cb_vm_page_offset, cb->cb_vm_page_len);
297e6f6d0c9SAlan Somers 		break;
298c0341432SJohn Baldwin 	default:
299c0341432SJohn Baldwin 		error = EINVAL;
300c0341432SJohn Baldwin 	}
3015033c43bSJohn Baldwin 	return (error);
3025033c43bSJohn Baldwin }
3035033c43bSJohn Baldwin 
3045033c43bSJohn Baldwin /*
3055033c43bSJohn Baldwin  * Segments in 'sg' larger than 'maxsegsize' are counted as multiple
3065033c43bSJohn Baldwin  * segments.
3075033c43bSJohn Baldwin  */
3085033c43bSJohn Baldwin static int
ccr_count_sgl(struct sglist * sg,int maxsegsize)3095033c43bSJohn Baldwin ccr_count_sgl(struct sglist *sg, int maxsegsize)
3105033c43bSJohn Baldwin {
3115033c43bSJohn Baldwin 	int i, nsegs;
3125033c43bSJohn Baldwin 
3135033c43bSJohn Baldwin 	nsegs = 0;
3145033c43bSJohn Baldwin 	for (i = 0; i < sg->sg_nseg; i++)
3155033c43bSJohn Baldwin 		nsegs += howmany(sg->sg_segs[i].ss_len, maxsegsize);
3165033c43bSJohn Baldwin 	return (nsegs);
3175033c43bSJohn Baldwin }
3185033c43bSJohn Baldwin 
3195033c43bSJohn Baldwin /* These functions deal with PHYS_DSGL for the reply buffer. */
3205033c43bSJohn Baldwin static inline int
ccr_phys_dsgl_len(int nsegs)3215033c43bSJohn Baldwin ccr_phys_dsgl_len(int nsegs)
3225033c43bSJohn Baldwin {
3235033c43bSJohn Baldwin 	int len;
3245033c43bSJohn Baldwin 
3255033c43bSJohn Baldwin 	len = (nsegs / 8) * sizeof(struct phys_sge_pairs);
3265033c43bSJohn Baldwin 	if ((nsegs % 8) != 0) {
3275033c43bSJohn Baldwin 		len += sizeof(uint16_t) * 8;
3285033c43bSJohn Baldwin 		len += roundup2(nsegs % 8, 2) * sizeof(uint64_t);
3295033c43bSJohn Baldwin 	}
3305033c43bSJohn Baldwin 	return (len);
3315033c43bSJohn Baldwin }
3325033c43bSJohn Baldwin 
3335033c43bSJohn Baldwin static void
ccr_write_phys_dsgl(struct ccr_session * s,void * dst,int nsegs)33494578db2SJohn Baldwin ccr_write_phys_dsgl(struct ccr_session *s, void *dst, int nsegs)
3355033c43bSJohn Baldwin {
3365033c43bSJohn Baldwin 	struct sglist *sg;
3375033c43bSJohn Baldwin 	struct cpl_rx_phys_dsgl *cpl;
3385033c43bSJohn Baldwin 	struct phys_sge_pairs *sgl;
3395033c43bSJohn Baldwin 	vm_paddr_t paddr;
3405033c43bSJohn Baldwin 	size_t seglen;
3415033c43bSJohn Baldwin 	u_int i, j;
3425033c43bSJohn Baldwin 
34394578db2SJohn Baldwin 	sg = s->sg_dsgl;
3445033c43bSJohn Baldwin 	cpl = dst;
3455033c43bSJohn Baldwin 	cpl->op_to_tid = htobe32(V_CPL_RX_PHYS_DSGL_OPCODE(CPL_RX_PHYS_DSGL) |
3465033c43bSJohn Baldwin 	    V_CPL_RX_PHYS_DSGL_ISRDMA(0));
3475033c43bSJohn Baldwin 	cpl->pcirlxorder_to_noofsgentr = htobe32(
3485033c43bSJohn Baldwin 	    V_CPL_RX_PHYS_DSGL_PCIRLXORDER(0) |
3495033c43bSJohn Baldwin 	    V_CPL_RX_PHYS_DSGL_PCINOSNOOP(0) |
3505033c43bSJohn Baldwin 	    V_CPL_RX_PHYS_DSGL_PCITPHNTENB(0) | V_CPL_RX_PHYS_DSGL_DCAID(0) |
3515033c43bSJohn Baldwin 	    V_CPL_RX_PHYS_DSGL_NOOFSGENTR(nsegs));
3525033c43bSJohn Baldwin 	cpl->rss_hdr_int.opcode = CPL_RX_PHYS_ADDR;
35394fad5ffSJohn Baldwin 	cpl->rss_hdr_int.qid = htobe16(s->port->rxq->iq.abs_id);
3545033c43bSJohn Baldwin 	cpl->rss_hdr_int.hash_val = 0;
3558f885fd1SJohn Baldwin 	cpl->rss_hdr_int.channel = s->port->rx_channel_id;
3565033c43bSJohn Baldwin 	sgl = (struct phys_sge_pairs *)(cpl + 1);
3575033c43bSJohn Baldwin 	j = 0;
3585033c43bSJohn Baldwin 	for (i = 0; i < sg->sg_nseg; i++) {
3595033c43bSJohn Baldwin 		seglen = sg->sg_segs[i].ss_len;
3605033c43bSJohn Baldwin 		paddr = sg->sg_segs[i].ss_paddr;
3615033c43bSJohn Baldwin 		do {
3625033c43bSJohn Baldwin 			sgl->addr[j] = htobe64(paddr);
3635033c43bSJohn Baldwin 			if (seglen > DSGL_SGE_MAXLEN) {
3645033c43bSJohn Baldwin 				sgl->len[j] = htobe16(DSGL_SGE_MAXLEN);
3655033c43bSJohn Baldwin 				paddr += DSGL_SGE_MAXLEN;
3665033c43bSJohn Baldwin 				seglen -= DSGL_SGE_MAXLEN;
3675033c43bSJohn Baldwin 			} else {
3685033c43bSJohn Baldwin 				sgl->len[j] = htobe16(seglen);
3695033c43bSJohn Baldwin 				seglen = 0;
3705033c43bSJohn Baldwin 			}
3715033c43bSJohn Baldwin 			j++;
3725033c43bSJohn Baldwin 			if (j == 8) {
3735033c43bSJohn Baldwin 				sgl++;
3745033c43bSJohn Baldwin 				j = 0;
3755033c43bSJohn Baldwin 			}
3765033c43bSJohn Baldwin 		} while (seglen != 0);
3775033c43bSJohn Baldwin 	}
3785033c43bSJohn Baldwin 	MPASS(j + 8 * (sgl - (struct phys_sge_pairs *)(cpl + 1)) == nsegs);
3795033c43bSJohn Baldwin }
3805033c43bSJohn Baldwin 
3815033c43bSJohn Baldwin /* These functions deal with the ULPTX_SGL for input payload. */
3825033c43bSJohn Baldwin static inline int
ccr_ulptx_sgl_len(int nsegs)3835033c43bSJohn Baldwin ccr_ulptx_sgl_len(int nsegs)
3845033c43bSJohn Baldwin {
3855033c43bSJohn Baldwin 	u_int n;
3865033c43bSJohn Baldwin 
3875033c43bSJohn Baldwin 	nsegs--; /* first segment is part of ulptx_sgl */
3885033c43bSJohn Baldwin 	n = sizeof(struct ulptx_sgl) + 8 * ((3 * nsegs) / 2 + (nsegs & 1));
3895033c43bSJohn Baldwin 	return (roundup2(n, 16));
3905033c43bSJohn Baldwin }
3915033c43bSJohn Baldwin 
3925033c43bSJohn Baldwin static void
ccr_write_ulptx_sgl(struct ccr_session * s,void * dst,int nsegs)39394578db2SJohn Baldwin ccr_write_ulptx_sgl(struct ccr_session *s, void *dst, int nsegs)
3945033c43bSJohn Baldwin {
3955033c43bSJohn Baldwin 	struct ulptx_sgl *usgl;
3965033c43bSJohn Baldwin 	struct sglist *sg;
3975033c43bSJohn Baldwin 	struct sglist_seg *ss;
3985033c43bSJohn Baldwin 	int i;
3995033c43bSJohn Baldwin 
40094578db2SJohn Baldwin 	sg = s->sg_ulptx;
4015033c43bSJohn Baldwin 	MPASS(nsegs == sg->sg_nseg);
4025033c43bSJohn Baldwin 	ss = &sg->sg_segs[0];
4035033c43bSJohn Baldwin 	usgl = dst;
4045033c43bSJohn Baldwin 	usgl->cmd_nsge = htobe32(V_ULPTX_CMD(ULP_TX_SC_DSGL) |
4055033c43bSJohn Baldwin 	    V_ULPTX_NSGE(nsegs));
4065033c43bSJohn Baldwin 	usgl->len0 = htobe32(ss->ss_len);
4075033c43bSJohn Baldwin 	usgl->addr0 = htobe64(ss->ss_paddr);
4085033c43bSJohn Baldwin 	ss++;
4095033c43bSJohn Baldwin 	for (i = 0; i < sg->sg_nseg - 1; i++) {
4105033c43bSJohn Baldwin 		usgl->sge[i / 2].len[i & 1] = htobe32(ss->ss_len);
4115033c43bSJohn Baldwin 		usgl->sge[i / 2].addr[i & 1] = htobe64(ss->ss_paddr);
4125033c43bSJohn Baldwin 		ss++;
4135033c43bSJohn Baldwin 	}
4145033c43bSJohn Baldwin }
4155033c43bSJohn Baldwin 
4165033c43bSJohn Baldwin static bool
ccr_use_imm_data(u_int transhdr_len,u_int input_len)4175033c43bSJohn Baldwin ccr_use_imm_data(u_int transhdr_len, u_int input_len)
4185033c43bSJohn Baldwin {
4195033c43bSJohn Baldwin 
4205033c43bSJohn Baldwin 	if (input_len > CRYPTO_MAX_IMM_TX_PKT_LEN)
4215033c43bSJohn Baldwin 		return (false);
4225033c43bSJohn Baldwin 	if (roundup2(transhdr_len, 16) + roundup2(input_len, 16) >
4235033c43bSJohn Baldwin 	    SGE_MAX_WR_LEN)
4245033c43bSJohn Baldwin 		return (false);
4255033c43bSJohn Baldwin 	return (true);
4265033c43bSJohn Baldwin }
4275033c43bSJohn Baldwin 
4285033c43bSJohn Baldwin static void
ccr_populate_wreq(struct ccr_softc * sc,struct ccr_session * s,struct chcr_wr * crwr,u_int kctx_len,u_int wr_len,u_int imm_len,u_int sgl_len,u_int hash_size,struct cryptop * crp)42994fad5ffSJohn Baldwin ccr_populate_wreq(struct ccr_softc *sc, struct ccr_session *s,
43094fad5ffSJohn Baldwin     struct chcr_wr *crwr, u_int kctx_len, u_int wr_len, u_int imm_len,
43194fad5ffSJohn Baldwin     u_int sgl_len, u_int hash_size, struct cryptop *crp)
4325033c43bSJohn Baldwin {
4336b0451d6SJohn Baldwin 	u_int cctx_size, idata_len;
4345033c43bSJohn Baldwin 
4355033c43bSJohn Baldwin 	cctx_size = sizeof(struct _key_ctx) + kctx_len;
4365033c43bSJohn Baldwin 	crwr->wreq.op_to_cctx_size = htobe32(
4375033c43bSJohn Baldwin 	    V_FW_CRYPTO_LOOKASIDE_WR_OPCODE(FW_CRYPTO_LOOKASIDE_WR) |
4385033c43bSJohn Baldwin 	    V_FW_CRYPTO_LOOKASIDE_WR_COMPL(0) |
4395033c43bSJohn Baldwin 	    V_FW_CRYPTO_LOOKASIDE_WR_IMM_LEN(imm_len) |
4405033c43bSJohn Baldwin 	    V_FW_CRYPTO_LOOKASIDE_WR_CCTX_LOC(1) |
4415033c43bSJohn Baldwin 	    V_FW_CRYPTO_LOOKASIDE_WR_CCTX_SIZE(cctx_size >> 4));
4425033c43bSJohn Baldwin 	crwr->wreq.len16_pkd = htobe32(
4435033c43bSJohn Baldwin 	    V_FW_CRYPTO_LOOKASIDE_WR_LEN16(wr_len / 16));
4441b0909d5SConrad Meyer 	crwr->wreq.session_id = 0;
4455033c43bSJohn Baldwin 	crwr->wreq.rx_chid_to_rx_q_id = htobe32(
4468f885fd1SJohn Baldwin 	    V_FW_CRYPTO_LOOKASIDE_WR_RX_CHID(s->port->rx_channel_id) |
4475033c43bSJohn Baldwin 	    V_FW_CRYPTO_LOOKASIDE_WR_LCB(0) |
4485033c43bSJohn Baldwin 	    V_FW_CRYPTO_LOOKASIDE_WR_PHASH(0) |
449020ce53aSJohn Baldwin 	    V_FW_CRYPTO_LOOKASIDE_WR_IV(IV_NOP) |
4505033c43bSJohn Baldwin 	    V_FW_CRYPTO_LOOKASIDE_WR_FQIDX(0) |
4518f885fd1SJohn Baldwin 	    V_FW_CRYPTO_LOOKASIDE_WR_TX_CH(0) |	/* unused in firmware */
45294fad5ffSJohn Baldwin 	    V_FW_CRYPTO_LOOKASIDE_WR_RX_Q_ID(s->port->rxq->iq.abs_id));
4535033c43bSJohn Baldwin 	crwr->wreq.key_addr = 0;
4545033c43bSJohn Baldwin 	crwr->wreq.pld_size_hash_size = htobe32(
4555033c43bSJohn Baldwin 	    V_FW_CRYPTO_LOOKASIDE_WR_PLD_SIZE(sgl_len) |
4565033c43bSJohn Baldwin 	    V_FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE(hash_size));
4575033c43bSJohn Baldwin 	crwr->wreq.cookie = htobe64((uintptr_t)crp);
4585033c43bSJohn Baldwin 
4595033c43bSJohn Baldwin 	crwr->ulptx.cmd_dest = htobe32(V_ULPTX_CMD(ULP_TX_PKT) |
4605033c43bSJohn Baldwin 	    V_ULP_TXPKT_DATAMODIFY(0) |
46194fad5ffSJohn Baldwin 	    V_ULP_TXPKT_CHANNELID(s->port->tx_channel_id) |
46294fad5ffSJohn Baldwin 	    V_ULP_TXPKT_DEST(0) |
4638f885fd1SJohn Baldwin 	    V_ULP_TXPKT_FID(sc->first_rxq_id) | V_ULP_TXPKT_RO(1));
4645033c43bSJohn Baldwin 	crwr->ulptx.len = htobe32(
4655033c43bSJohn Baldwin 	    ((wr_len - sizeof(struct fw_crypto_lookaside_wr)) / 16));
4665033c43bSJohn Baldwin 
4675033c43bSJohn Baldwin 	crwr->sc_imm.cmd_more = htobe32(V_ULPTX_CMD(ULP_TX_SC_IMM) |
4686b0451d6SJohn Baldwin 	    V_ULP_TX_SC_MORE(sgl_len != 0 ? 1 : 0));
4696b0451d6SJohn Baldwin 	idata_len = wr_len - offsetof(struct chcr_wr, sec_cpl) - sgl_len;
4706b0451d6SJohn Baldwin 	if (imm_len % 16 != 0)
4716b0451d6SJohn Baldwin 		idata_len -= 16 - imm_len % 16;
4726b0451d6SJohn Baldwin 	crwr->sc_imm.len = htobe32(idata_len);
4735033c43bSJohn Baldwin }
4745033c43bSJohn Baldwin 
4755033c43bSJohn Baldwin static int
ccr_hash(struct ccr_softc * sc,struct ccr_session * s,struct cryptop * crp)476567a3784SJohn Baldwin ccr_hash(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp)
4775033c43bSJohn Baldwin {
4785033c43bSJohn Baldwin 	struct chcr_wr *crwr;
4795033c43bSJohn Baldwin 	struct wrqe *wr;
480d8787d4fSMark Johnston 	const struct auth_hash *axf;
4815033c43bSJohn Baldwin 	char *dst;
4825033c43bSJohn Baldwin 	u_int hash_size_in_response, kctx_flits, kctx_len, transhdr_len, wr_len;
483567a3784SJohn Baldwin 	u_int hmac_ctrl, imm_len, iopad_size;
484567a3784SJohn Baldwin 	int error, sgl_nsegs, sgl_len, use_opad;
4855033c43bSJohn Baldwin 
486d68990a1SJohn Baldwin 	/* Reject requests with too large of an input buffer. */
487c0341432SJohn Baldwin 	if (crp->crp_payload_length > MAX_REQUEST_SIZE)
488d68990a1SJohn Baldwin 		return (EFBIG);
489d68990a1SJohn Baldwin 
4905033c43bSJohn Baldwin 	axf = s->hmac.auth_hash;
4915033c43bSJohn Baldwin 
492567a3784SJohn Baldwin 	if (s->mode == HMAC) {
493567a3784SJohn Baldwin 		use_opad = 1;
494d09389fdSJohn Baldwin 		hmac_ctrl = SCMD_HMAC_CTRL_NO_TRUNC;
495567a3784SJohn Baldwin 	} else {
496567a3784SJohn Baldwin 		use_opad = 0;
497d09389fdSJohn Baldwin 		hmac_ctrl = SCMD_HMAC_CTRL_NOP;
498567a3784SJohn Baldwin 	}
499567a3784SJohn Baldwin 
5005033c43bSJohn Baldwin 	/* PADs must be 128-bit aligned. */
5015033c43bSJohn Baldwin 	iopad_size = roundup2(s->hmac.partial_digest_len, 16);
5025033c43bSJohn Baldwin 
5035033c43bSJohn Baldwin 	/*
5045033c43bSJohn Baldwin 	 * The 'key' part of the context includes the aligned IPAD and
5055033c43bSJohn Baldwin 	 * OPAD.
5065033c43bSJohn Baldwin 	 */
507567a3784SJohn Baldwin 	kctx_len = iopad_size;
508567a3784SJohn Baldwin 	if (use_opad)
509567a3784SJohn Baldwin 		kctx_len += iopad_size;
5105033c43bSJohn Baldwin 	hash_size_in_response = axf->hashsize;
5115033c43bSJohn Baldwin 	transhdr_len = HASH_TRANSHDR_SIZE(kctx_len);
5125033c43bSJohn Baldwin 
513c0341432SJohn Baldwin 	if (crp->crp_payload_length == 0) {
5144623e047SJohn Baldwin 		imm_len = axf->blocksize;
5154623e047SJohn Baldwin 		sgl_nsegs = 0;
5164623e047SJohn Baldwin 		sgl_len = 0;
517c0341432SJohn Baldwin 	} else if (ccr_use_imm_data(transhdr_len, crp->crp_payload_length)) {
518c0341432SJohn Baldwin 		imm_len = crp->crp_payload_length;
5195033c43bSJohn Baldwin 		sgl_nsegs = 0;
5205033c43bSJohn Baldwin 		sgl_len = 0;
5215033c43bSJohn Baldwin 	} else {
5225033c43bSJohn Baldwin 		imm_len = 0;
52394578db2SJohn Baldwin 		sglist_reset(s->sg_ulptx);
52494578db2SJohn Baldwin 		error = sglist_append_sglist(s->sg_ulptx, s->sg_input,
525c0341432SJohn Baldwin 		    crp->crp_payload_start, crp->crp_payload_length);
5265033c43bSJohn Baldwin 		if (error)
5275033c43bSJohn Baldwin 			return (error);
52894578db2SJohn Baldwin 		sgl_nsegs = s->sg_ulptx->sg_nseg;
5295033c43bSJohn Baldwin 		sgl_len = ccr_ulptx_sgl_len(sgl_nsegs);
5305033c43bSJohn Baldwin 	}
5315033c43bSJohn Baldwin 
5325033c43bSJohn Baldwin 	wr_len = roundup2(transhdr_len, 16) + roundup2(imm_len, 16) + sgl_len;
533f7b61e2fSJohn Baldwin 	if (wr_len > SGE_MAX_WR_LEN)
534f7b61e2fSJohn Baldwin 		return (EFBIG);
53594fad5ffSJohn Baldwin 	wr = alloc_wrqe(wr_len, s->port->txq);
5365033c43bSJohn Baldwin 	if (wr == NULL) {
53794578db2SJohn Baldwin 		counter_u64_add(sc->stats_wr_nomem, 1);
5385033c43bSJohn Baldwin 		return (ENOMEM);
5395033c43bSJohn Baldwin 	}
5405033c43bSJohn Baldwin 	crwr = wrtod(wr);
5415033c43bSJohn Baldwin 	memset(crwr, 0, wr_len);
5425033c43bSJohn Baldwin 
54394fad5ffSJohn Baldwin 	ccr_populate_wreq(sc, s, crwr, kctx_len, wr_len, imm_len, sgl_len,
544020ce53aSJohn Baldwin 	    hash_size_in_response, crp);
5455033c43bSJohn Baldwin 
5465033c43bSJohn Baldwin 	crwr->sec_cpl.op_ivinsrtofst = htobe32(
5475033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_OPCODE(CPL_TX_SEC_PDU) |
5488f885fd1SJohn Baldwin 	    V_CPL_TX_SEC_PDU_RXCHID(s->port->rx_channel_id) |
5495033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_ACKFOLLOWS(0) | V_CPL_TX_SEC_PDU_ULPTXLPBK(1) |
5505033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_CPLLEN(2) | V_CPL_TX_SEC_PDU_PLACEHOLDER(0) |
5515033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_IVINSRTOFST(0));
5525033c43bSJohn Baldwin 
553c0341432SJohn Baldwin 	crwr->sec_cpl.pldlen = htobe32(crp->crp_payload_length == 0 ?
554c0341432SJohn Baldwin 	    axf->blocksize : crp->crp_payload_length);
5555033c43bSJohn Baldwin 
5565033c43bSJohn Baldwin 	crwr->sec_cpl.cipherstop_lo_authinsert = htobe32(
5575033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_AUTHSTART(1) | V_CPL_TX_SEC_PDU_AUTHSTOP(0));
5585033c43bSJohn Baldwin 
5595033c43bSJohn Baldwin 	/* These two flits are actually a CPL_TLS_TX_SCMD_FMT. */
5605033c43bSJohn Baldwin 	crwr->sec_cpl.seqno_numivs = htobe32(
5615033c43bSJohn Baldwin 	    V_SCMD_SEQ_NO_CTRL(0) |
562d09389fdSJohn Baldwin 	    V_SCMD_PROTO_VERSION(SCMD_PROTO_VERSION_GENERIC) |
563d09389fdSJohn Baldwin 	    V_SCMD_CIPH_MODE(SCMD_CIPH_MODE_NOP) |
5645033c43bSJohn Baldwin 	    V_SCMD_AUTH_MODE(s->hmac.auth_mode) |
565567a3784SJohn Baldwin 	    V_SCMD_HMAC_CTRL(hmac_ctrl));
5665033c43bSJohn Baldwin 	crwr->sec_cpl.ivgen_hdrlen = htobe32(
5674623e047SJohn Baldwin 	    V_SCMD_LAST_FRAG(0) |
568c0341432SJohn Baldwin 	    V_SCMD_MORE_FRAGS(crp->crp_payload_length == 0 ? 1 : 0) |
569c0341432SJohn Baldwin 	    V_SCMD_MAC_ONLY(1));
5705033c43bSJohn Baldwin 
571a1b2b6e1SJohn Baldwin 	memcpy(crwr->key_ctx.key, s->hmac.pads, kctx_len);
5725033c43bSJohn Baldwin 
5735033c43bSJohn Baldwin 	/* XXX: F_KEY_CONTEXT_SALT_PRESENT set, but 'salt' not set. */
5745033c43bSJohn Baldwin 	kctx_flits = (sizeof(struct _key_ctx) + kctx_len) / 16;
5755033c43bSJohn Baldwin 	crwr->key_ctx.ctx_hdr = htobe32(V_KEY_CONTEXT_CTX_LEN(kctx_flits) |
576567a3784SJohn Baldwin 	    V_KEY_CONTEXT_OPAD_PRESENT(use_opad) |
577567a3784SJohn Baldwin 	    V_KEY_CONTEXT_SALT_PRESENT(1) |
5785033c43bSJohn Baldwin 	    V_KEY_CONTEXT_CK_SIZE(CHCR_KEYCTX_NO_KEY) |
5795033c43bSJohn Baldwin 	    V_KEY_CONTEXT_MK_SIZE(s->hmac.mk_size) | V_KEY_CONTEXT_VALID(1));
5805033c43bSJohn Baldwin 
5815033c43bSJohn Baldwin 	dst = (char *)(crwr + 1) + kctx_len + DUMMY_BYTES;
582c0341432SJohn Baldwin 	if (crp->crp_payload_length == 0) {
5834623e047SJohn Baldwin 		dst[0] = 0x80;
584a2ad169eSJohn Baldwin 		if (s->mode == HMAC)
5854623e047SJohn Baldwin 			*(uint64_t *)(dst + axf->blocksize - sizeof(uint64_t)) =
5864623e047SJohn Baldwin 			    htobe64(axf->blocksize << 3);
5874623e047SJohn Baldwin 	} else if (imm_len != 0)
588c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_payload_start,
589c0341432SJohn Baldwin 		    crp->crp_payload_length, dst);
5905033c43bSJohn Baldwin 	else
59194578db2SJohn Baldwin 		ccr_write_ulptx_sgl(s, dst, sgl_nsegs);
5925033c43bSJohn Baldwin 
5935033c43bSJohn Baldwin 	/* XXX: TODO backpressure */
5945033c43bSJohn Baldwin 	t4_wrq_tx(sc->adapter, wr);
5955033c43bSJohn Baldwin 
5965033c43bSJohn Baldwin 	return (0);
5975033c43bSJohn Baldwin }
5985033c43bSJohn Baldwin 
5995033c43bSJohn Baldwin static int
ccr_hash_done(struct ccr_softc * sc,struct ccr_session * s,struct cryptop * crp,const struct cpl_fw6_pld * cpl,int error)600567a3784SJohn Baldwin ccr_hash_done(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp,
6015033c43bSJohn Baldwin     const struct cpl_fw6_pld *cpl, int error)
6025033c43bSJohn Baldwin {
603c0341432SJohn Baldwin 	uint8_t hash[HASH_MAX_LEN];
6045033c43bSJohn Baldwin 
605c0341432SJohn Baldwin 	if (error)
6065033c43bSJohn Baldwin 		return (error);
607c0341432SJohn Baldwin 
608c0341432SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
609c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, s->hmac.hash_len,
610c0341432SJohn Baldwin 		    hash);
611c0341432SJohn Baldwin 		if (timingsafe_bcmp((cpl + 1), hash, s->hmac.hash_len) != 0)
612c0341432SJohn Baldwin 			return (EBADMSG);
613c0341432SJohn Baldwin 	} else
614c0341432SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, s->hmac.hash_len,
615c0341432SJohn Baldwin 		    (cpl + 1));
616c0341432SJohn Baldwin 	return (0);
6175033c43bSJohn Baldwin }
6185033c43bSJohn Baldwin 
6195033c43bSJohn Baldwin static int
ccr_cipher(struct ccr_softc * sc,struct ccr_session * s,struct cryptop * crp)620762f1dcbSJohn Baldwin ccr_cipher(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp)
6215033c43bSJohn Baldwin {
6225033c43bSJohn Baldwin 	char iv[CHCR_MAX_CRYPTO_IV_LEN];
6235033c43bSJohn Baldwin 	struct chcr_wr *crwr;
6245033c43bSJohn Baldwin 	struct wrqe *wr;
6255033c43bSJohn Baldwin 	char *dst;
626d3f25aa1SJohn Baldwin 	u_int kctx_len, key_half, op_type, transhdr_len, wr_len;
627c0341432SJohn Baldwin 	u_int imm_len, iv_len;
6285033c43bSJohn Baldwin 	int dsgl_nsegs, dsgl_len;
6295033c43bSJohn Baldwin 	int sgl_nsegs, sgl_len;
6305033c43bSJohn Baldwin 	int error;
6315033c43bSJohn Baldwin 
632762f1dcbSJohn Baldwin 	if (s->cipher.key_len == 0 || crp->crp_payload_length == 0)
6335033c43bSJohn Baldwin 		return (EINVAL);
634762f1dcbSJohn Baldwin 	if (s->cipher.cipher_mode == SCMD_CIPH_MODE_AES_CBC &&
635c0341432SJohn Baldwin 	    (crp->crp_payload_length % AES_BLOCK_LEN) != 0)
6365033c43bSJohn Baldwin 		return (EINVAL);
6375033c43bSJohn Baldwin 
638d68990a1SJohn Baldwin 	/* Reject requests with too large of an input buffer. */
639c0341432SJohn Baldwin 	if (crp->crp_payload_length > MAX_REQUEST_SIZE)
640d68990a1SJohn Baldwin 		return (EFBIG);
641d68990a1SJohn Baldwin 
642c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
6435033c43bSJohn Baldwin 		op_type = CHCR_ENCRYPT_OP;
6445033c43bSJohn Baldwin 	else
6455033c43bSJohn Baldwin 		op_type = CHCR_DECRYPT_OP;
6465033c43bSJohn Baldwin 
64794578db2SJohn Baldwin 	sglist_reset(s->sg_dsgl);
6482adc3c94SJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp))
64994578db2SJohn Baldwin 		error = sglist_append_sglist(s->sg_dsgl, s->sg_output,
6502adc3c94SJohn Baldwin 		    crp->crp_payload_output_start, crp->crp_payload_length);
6512adc3c94SJohn Baldwin 	else
65294578db2SJohn Baldwin 		error = sglist_append_sglist(s->sg_dsgl, s->sg_input,
653c0341432SJohn Baldwin 		    crp->crp_payload_start, crp->crp_payload_length);
6545033c43bSJohn Baldwin 	if (error)
6555033c43bSJohn Baldwin 		return (error);
65694578db2SJohn Baldwin 	dsgl_nsegs = ccr_count_sgl(s->sg_dsgl, DSGL_SGE_MAXLEN);
6575033c43bSJohn Baldwin 	if (dsgl_nsegs > MAX_RX_PHYS_DSGL_SGE)
6585033c43bSJohn Baldwin 		return (EFBIG);
6595033c43bSJohn Baldwin 	dsgl_len = ccr_phys_dsgl_len(dsgl_nsegs);
6605033c43bSJohn Baldwin 
6615033c43bSJohn Baldwin 	/* The 'key' must be 128-bit aligned. */
662762f1dcbSJohn Baldwin 	kctx_len = roundup2(s->cipher.key_len, 16);
6635033c43bSJohn Baldwin 	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dsgl_len);
6645033c43bSJohn Baldwin 
665c0341432SJohn Baldwin 	/* For AES-XTS we send a 16-byte IV in the work request. */
666762f1dcbSJohn Baldwin 	if (s->cipher.cipher_mode == SCMD_CIPH_MODE_AES_XTS)
667c0341432SJohn Baldwin 		iv_len = AES_BLOCK_LEN;
668c0341432SJohn Baldwin 	else
669762f1dcbSJohn Baldwin 		iv_len = s->cipher.iv_len;
670c0341432SJohn Baldwin 
671c0341432SJohn Baldwin 	if (ccr_use_imm_data(transhdr_len, crp->crp_payload_length + iv_len)) {
672c0341432SJohn Baldwin 		imm_len = crp->crp_payload_length;
6735033c43bSJohn Baldwin 		sgl_nsegs = 0;
6745033c43bSJohn Baldwin 		sgl_len = 0;
6755033c43bSJohn Baldwin 	} else {
6765033c43bSJohn Baldwin 		imm_len = 0;
67794578db2SJohn Baldwin 		sglist_reset(s->sg_ulptx);
67894578db2SJohn Baldwin 		error = sglist_append_sglist(s->sg_ulptx, s->sg_input,
679c0341432SJohn Baldwin 		    crp->crp_payload_start, crp->crp_payload_length);
6805033c43bSJohn Baldwin 		if (error)
6815033c43bSJohn Baldwin 			return (error);
68294578db2SJohn Baldwin 		sgl_nsegs = s->sg_ulptx->sg_nseg;
6835033c43bSJohn Baldwin 		sgl_len = ccr_ulptx_sgl_len(sgl_nsegs);
6845033c43bSJohn Baldwin 	}
6855033c43bSJohn Baldwin 
686c0341432SJohn Baldwin 	wr_len = roundup2(transhdr_len, 16) + iv_len +
687d3f25aa1SJohn Baldwin 	    roundup2(imm_len, 16) + sgl_len;
688f7b61e2fSJohn Baldwin 	if (wr_len > SGE_MAX_WR_LEN)
689f7b61e2fSJohn Baldwin 		return (EFBIG);
69094fad5ffSJohn Baldwin 	wr = alloc_wrqe(wr_len, s->port->txq);
6915033c43bSJohn Baldwin 	if (wr == NULL) {
69294578db2SJohn Baldwin 		counter_u64_add(sc->stats_wr_nomem, 1);
6935033c43bSJohn Baldwin 		return (ENOMEM);
6945033c43bSJohn Baldwin 	}
6955033c43bSJohn Baldwin 	crwr = wrtod(wr);
6965033c43bSJohn Baldwin 	memset(crwr, 0, wr_len);
6975033c43bSJohn Baldwin 
69829fe41ddSJohn Baldwin 	crypto_read_iv(crp, iv);
699c0341432SJohn Baldwin 
700c0341432SJohn Baldwin 	/* Zero the remainder of the IV for AES-XTS. */
701762f1dcbSJohn Baldwin 	memset(iv + s->cipher.iv_len, 0, iv_len - s->cipher.iv_len);
7022bc40b6cSJohn Baldwin 
70394fad5ffSJohn Baldwin 	ccr_populate_wreq(sc, s, crwr, kctx_len, wr_len, imm_len, sgl_len, 0,
704020ce53aSJohn Baldwin 	    crp);
7055033c43bSJohn Baldwin 
7065033c43bSJohn Baldwin 	crwr->sec_cpl.op_ivinsrtofst = htobe32(
7075033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_OPCODE(CPL_TX_SEC_PDU) |
7088f885fd1SJohn Baldwin 	    V_CPL_TX_SEC_PDU_RXCHID(s->port->rx_channel_id) |
7095033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_ACKFOLLOWS(0) | V_CPL_TX_SEC_PDU_ULPTXLPBK(1) |
7105033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_CPLLEN(2) | V_CPL_TX_SEC_PDU_PLACEHOLDER(0) |
7115033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_IVINSRTOFST(1));
7125033c43bSJohn Baldwin 
713c0341432SJohn Baldwin 	crwr->sec_cpl.pldlen = htobe32(iv_len + crp->crp_payload_length);
7145033c43bSJohn Baldwin 
7155033c43bSJohn Baldwin 	crwr->sec_cpl.aadstart_cipherstop_hi = htobe32(
716c0341432SJohn Baldwin 	    V_CPL_TX_SEC_PDU_CIPHERSTART(iv_len + 1) |
7175033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_CIPHERSTOP_HI(0));
7185033c43bSJohn Baldwin 	crwr->sec_cpl.cipherstop_lo_authinsert = htobe32(
7195033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_CIPHERSTOP_LO(0));
7205033c43bSJohn Baldwin 
7215033c43bSJohn Baldwin 	/* These two flits are actually a CPL_TLS_TX_SCMD_FMT. */
7225033c43bSJohn Baldwin 	crwr->sec_cpl.seqno_numivs = htobe32(
7235033c43bSJohn Baldwin 	    V_SCMD_SEQ_NO_CTRL(0) |
724d09389fdSJohn Baldwin 	    V_SCMD_PROTO_VERSION(SCMD_PROTO_VERSION_GENERIC) |
7255033c43bSJohn Baldwin 	    V_SCMD_ENC_DEC_CTRL(op_type) |
726762f1dcbSJohn Baldwin 	    V_SCMD_CIPH_MODE(s->cipher.cipher_mode) |
727d09389fdSJohn Baldwin 	    V_SCMD_AUTH_MODE(SCMD_AUTH_MODE_NOP) |
728d09389fdSJohn Baldwin 	    V_SCMD_HMAC_CTRL(SCMD_HMAC_CTRL_NOP) |
729c0341432SJohn Baldwin 	    V_SCMD_IV_SIZE(iv_len / 2) |
7305033c43bSJohn Baldwin 	    V_SCMD_NUM_IVS(0));
7315033c43bSJohn Baldwin 	crwr->sec_cpl.ivgen_hdrlen = htobe32(
7325033c43bSJohn Baldwin 	    V_SCMD_IV_GEN_CTRL(0) |
7335033c43bSJohn Baldwin 	    V_SCMD_MORE_FRAGS(0) | V_SCMD_LAST_FRAG(0) | V_SCMD_MAC_ONLY(0) |
7345033c43bSJohn Baldwin 	    V_SCMD_AADIVDROP(1) | V_SCMD_HDR_LEN(dsgl_len));
7355033c43bSJohn Baldwin 
736762f1dcbSJohn Baldwin 	crwr->key_ctx.ctx_hdr = s->cipher.key_ctx_hdr;
737762f1dcbSJohn Baldwin 	switch (s->cipher.cipher_mode) {
738c0341432SJohn Baldwin 	case SCMD_CIPH_MODE_AES_CBC:
739c0341432SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
740762f1dcbSJohn Baldwin 			memcpy(crwr->key_ctx.key, s->cipher.enckey,
741762f1dcbSJohn Baldwin 			    s->cipher.key_len);
7425033c43bSJohn Baldwin 		else
743762f1dcbSJohn Baldwin 			memcpy(crwr->key_ctx.key, s->cipher.deckey,
744762f1dcbSJohn Baldwin 			    s->cipher.key_len);
7455033c43bSJohn Baldwin 		break;
746c0341432SJohn Baldwin 	case SCMD_CIPH_MODE_AES_CTR:
747762f1dcbSJohn Baldwin 		memcpy(crwr->key_ctx.key, s->cipher.enckey,
748762f1dcbSJohn Baldwin 		    s->cipher.key_len);
7495033c43bSJohn Baldwin 		break;
750c0341432SJohn Baldwin 	case SCMD_CIPH_MODE_AES_XTS:
751762f1dcbSJohn Baldwin 		key_half = s->cipher.key_len / 2;
752762f1dcbSJohn Baldwin 		memcpy(crwr->key_ctx.key, s->cipher.enckey + key_half,
7535033c43bSJohn Baldwin 		    key_half);
754c0341432SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
7555033c43bSJohn Baldwin 			memcpy(crwr->key_ctx.key + key_half,
756762f1dcbSJohn Baldwin 			    s->cipher.enckey, key_half);
7575033c43bSJohn Baldwin 		else
7585033c43bSJohn Baldwin 			memcpy(crwr->key_ctx.key + key_half,
759762f1dcbSJohn Baldwin 			    s->cipher.deckey, key_half);
7605033c43bSJohn Baldwin 		break;
7615033c43bSJohn Baldwin 	}
7625033c43bSJohn Baldwin 
7635033c43bSJohn Baldwin 	dst = (char *)(crwr + 1) + kctx_len;
76494578db2SJohn Baldwin 	ccr_write_phys_dsgl(s, dst, dsgl_nsegs);
7655033c43bSJohn Baldwin 	dst += sizeof(struct cpl_rx_phys_dsgl) + dsgl_len;
766c0341432SJohn Baldwin 	memcpy(dst, iv, iv_len);
767c0341432SJohn Baldwin 	dst += iv_len;
7685033c43bSJohn Baldwin 	if (imm_len != 0)
769c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_payload_start,
770c0341432SJohn Baldwin 		    crp->crp_payload_length, dst);
7715033c43bSJohn Baldwin 	else
77294578db2SJohn Baldwin 		ccr_write_ulptx_sgl(s, dst, sgl_nsegs);
7735033c43bSJohn Baldwin 
7745033c43bSJohn Baldwin 	/* XXX: TODO backpressure */
7755033c43bSJohn Baldwin 	t4_wrq_tx(sc->adapter, wr);
7765033c43bSJohn Baldwin 
7771a4a7e98SJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
7785033c43bSJohn Baldwin 	return (0);
7795033c43bSJohn Baldwin }
7805033c43bSJohn Baldwin 
7815033c43bSJohn Baldwin static int
ccr_cipher_done(struct ccr_softc * sc,struct ccr_session * s,struct cryptop * crp,const struct cpl_fw6_pld * cpl,int error)782762f1dcbSJohn Baldwin ccr_cipher_done(struct ccr_softc *sc, struct ccr_session *s,
7835033c43bSJohn Baldwin     struct cryptop *crp, const struct cpl_fw6_pld *cpl, int error)
7845033c43bSJohn Baldwin {
7855033c43bSJohn Baldwin 
7865033c43bSJohn Baldwin 	/*
7875033c43bSJohn Baldwin 	 * The updated IV to permit chained requests is at
7885033c43bSJohn Baldwin 	 * cpl->data[2], but OCF doesn't permit chained requests.
7895033c43bSJohn Baldwin 	 */
7905033c43bSJohn Baldwin 	return (error);
7915033c43bSJohn Baldwin }
7925033c43bSJohn Baldwin 
7935033c43bSJohn Baldwin /*
7945033c43bSJohn Baldwin  * 'hashsize' is the length of a full digest.  'authsize' is the
7955033c43bSJohn Baldwin  * requested digest length for this operation which may be less
7965033c43bSJohn Baldwin  * than 'hashsize'.
7975033c43bSJohn Baldwin  */
7985033c43bSJohn Baldwin static int
ccr_hmac_ctrl(unsigned int hashsize,unsigned int authsize)7995033c43bSJohn Baldwin ccr_hmac_ctrl(unsigned int hashsize, unsigned int authsize)
8005033c43bSJohn Baldwin {
8015033c43bSJohn Baldwin 
8025033c43bSJohn Baldwin 	if (authsize == 10)
803d09389fdSJohn Baldwin 		return (SCMD_HMAC_CTRL_TRUNC_RFC4366);
8045033c43bSJohn Baldwin 	if (authsize == 12)
805d09389fdSJohn Baldwin 		return (SCMD_HMAC_CTRL_IPSEC_96BIT);
8065033c43bSJohn Baldwin 	if (authsize == hashsize / 2)
807d09389fdSJohn Baldwin 		return (SCMD_HMAC_CTRL_DIV2);
808d09389fdSJohn Baldwin 	return (SCMD_HMAC_CTRL_NO_TRUNC);
8095033c43bSJohn Baldwin }
8105033c43bSJohn Baldwin 
8115033c43bSJohn Baldwin static int
ccr_eta(struct ccr_softc * sc,struct ccr_session * s,struct cryptop * crp)812c0341432SJohn Baldwin ccr_eta(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp)
8135033c43bSJohn Baldwin {
8145033c43bSJohn Baldwin 	char iv[CHCR_MAX_CRYPTO_IV_LEN];
8155033c43bSJohn Baldwin 	struct chcr_wr *crwr;
8165033c43bSJohn Baldwin 	struct wrqe *wr;
817d8787d4fSMark Johnston 	const struct auth_hash *axf;
8185033c43bSJohn Baldwin 	char *dst;
819d3f25aa1SJohn Baldwin 	u_int kctx_len, key_half, op_type, transhdr_len, wr_len;
820c0341432SJohn Baldwin 	u_int hash_size_in_response, imm_len, iopad_size, iv_len;
821c0341432SJohn Baldwin 	u_int aad_start, aad_stop;
822c0341432SJohn Baldwin 	u_int auth_insert;
8235033c43bSJohn Baldwin 	u_int cipher_start, cipher_stop;
8245033c43bSJohn Baldwin 	u_int hmac_ctrl, input_len;
8255033c43bSJohn Baldwin 	int dsgl_nsegs, dsgl_len;
8265033c43bSJohn Baldwin 	int sgl_nsegs, sgl_len;
8275033c43bSJohn Baldwin 	int error;
8285033c43bSJohn Baldwin 
8294623e047SJohn Baldwin 	/*
8304623e047SJohn Baldwin 	 * If there is a need in the future, requests with an empty
8314623e047SJohn Baldwin 	 * payload could be supported as HMAC-only requests.
8324623e047SJohn Baldwin 	 */
833762f1dcbSJohn Baldwin 	if (s->cipher.key_len == 0 || crp->crp_payload_length == 0)
8345033c43bSJohn Baldwin 		return (EINVAL);
835762f1dcbSJohn Baldwin 	if (s->cipher.cipher_mode == SCMD_CIPH_MODE_AES_CBC &&
836c0341432SJohn Baldwin 	    (crp->crp_payload_length % AES_BLOCK_LEN) != 0)
8375033c43bSJohn Baldwin 		return (EINVAL);
8385033c43bSJohn Baldwin 
839c0341432SJohn Baldwin 	/* For AES-XTS we send a 16-byte IV in the work request. */
840762f1dcbSJohn Baldwin 	if (s->cipher.cipher_mode == SCMD_CIPH_MODE_AES_XTS)
841c0341432SJohn Baldwin 		iv_len = AES_BLOCK_LEN;
842acaabdbbSJohn Baldwin 	else
843762f1dcbSJohn Baldwin 		iv_len = s->cipher.iv_len;
844c0341432SJohn Baldwin 
845c0341432SJohn Baldwin 	if (crp->crp_aad_length + iv_len > MAX_AAD_LEN)
846acaabdbbSJohn Baldwin 		return (EINVAL);
8475033c43bSJohn Baldwin 
8485033c43bSJohn Baldwin 	axf = s->hmac.auth_hash;
8495033c43bSJohn Baldwin 	hash_size_in_response = s->hmac.hash_len;
850c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
8515033c43bSJohn Baldwin 		op_type = CHCR_ENCRYPT_OP;
8525033c43bSJohn Baldwin 	else
8535033c43bSJohn Baldwin 		op_type = CHCR_DECRYPT_OP;
8545033c43bSJohn Baldwin 
8555033c43bSJohn Baldwin 	/*
8565033c43bSJohn Baldwin 	 * The output buffer consists of the cipher text followed by
8575033c43bSJohn Baldwin 	 * the hash when encrypting.  For decryption it only contains
8585033c43bSJohn Baldwin 	 * the plain text.
8595929c9fbSJohn Baldwin 	 *
8605929c9fbSJohn Baldwin 	 * Due to a firmware bug, the output buffer must include a
8615929c9fbSJohn Baldwin 	 * dummy output buffer for the IV and AAD prior to the real
8625929c9fbSJohn Baldwin 	 * output buffer.
8635033c43bSJohn Baldwin 	 */
864d68990a1SJohn Baldwin 	if (op_type == CHCR_ENCRYPT_OP) {
865c0341432SJohn Baldwin 		if (iv_len + crp->crp_aad_length + crp->crp_payload_length +
8665929c9fbSJohn Baldwin 		    hash_size_in_response > MAX_REQUEST_SIZE)
867d68990a1SJohn Baldwin 			return (EFBIG);
868d68990a1SJohn Baldwin 	} else {
869c0341432SJohn Baldwin 		if (iv_len + crp->crp_aad_length + crp->crp_payload_length >
8705929c9fbSJohn Baldwin 		    MAX_REQUEST_SIZE)
871d68990a1SJohn Baldwin 			return (EFBIG);
872d68990a1SJohn Baldwin 	}
87394578db2SJohn Baldwin 	sglist_reset(s->sg_dsgl);
87494578db2SJohn Baldwin 	error = sglist_append_sglist(s->sg_dsgl, sc->sg_iv_aad, 0,
875c0341432SJohn Baldwin 	    iv_len + crp->crp_aad_length);
8765929c9fbSJohn Baldwin 	if (error)
8775929c9fbSJohn Baldwin 		return (error);
8782adc3c94SJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp))
87994578db2SJohn Baldwin 		error = sglist_append_sglist(s->sg_dsgl, s->sg_output,
8802adc3c94SJohn Baldwin 		    crp->crp_payload_output_start, crp->crp_payload_length);
8812adc3c94SJohn Baldwin 	else
88294578db2SJohn Baldwin 		error = sglist_append_sglist(s->sg_dsgl, s->sg_input,
883c0341432SJohn Baldwin 		    crp->crp_payload_start, crp->crp_payload_length);
8845033c43bSJohn Baldwin 	if (error)
8855033c43bSJohn Baldwin 		return (error);
8865033c43bSJohn Baldwin 	if (op_type == CHCR_ENCRYPT_OP) {
8872adc3c94SJohn Baldwin 		if (CRYPTO_HAS_OUTPUT_BUFFER(crp))
88894578db2SJohn Baldwin 			error = sglist_append_sglist(s->sg_dsgl, s->sg_output,
8892adc3c94SJohn Baldwin 			    crp->crp_digest_start, hash_size_in_response);
8902adc3c94SJohn Baldwin 		else
89194578db2SJohn Baldwin 			error = sglist_append_sglist(s->sg_dsgl, s->sg_input,
892c0341432SJohn Baldwin 			    crp->crp_digest_start, hash_size_in_response);
8935033c43bSJohn Baldwin 		if (error)
8945033c43bSJohn Baldwin 			return (error);
8955033c43bSJohn Baldwin 	}
89694578db2SJohn Baldwin 	dsgl_nsegs = ccr_count_sgl(s->sg_dsgl, DSGL_SGE_MAXLEN);
8975033c43bSJohn Baldwin 	if (dsgl_nsegs > MAX_RX_PHYS_DSGL_SGE)
8985033c43bSJohn Baldwin 		return (EFBIG);
8995033c43bSJohn Baldwin 	dsgl_len = ccr_phys_dsgl_len(dsgl_nsegs);
9005033c43bSJohn Baldwin 
9015033c43bSJohn Baldwin 	/* PADs must be 128-bit aligned. */
9025033c43bSJohn Baldwin 	iopad_size = roundup2(s->hmac.partial_digest_len, 16);
9035033c43bSJohn Baldwin 
9045033c43bSJohn Baldwin 	/*
9055033c43bSJohn Baldwin 	 * The 'key' part of the key context consists of the key followed
9065033c43bSJohn Baldwin 	 * by the IPAD and OPAD.
9075033c43bSJohn Baldwin 	 */
908762f1dcbSJohn Baldwin 	kctx_len = roundup2(s->cipher.key_len, 16) + iopad_size * 2;
9095033c43bSJohn Baldwin 	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dsgl_len);
9105033c43bSJohn Baldwin 
9115033c43bSJohn Baldwin 	/*
9125033c43bSJohn Baldwin 	 * The input buffer consists of the IV, any AAD, and then the
9135033c43bSJohn Baldwin 	 * cipher/plain text.  For decryption requests the hash is
9145033c43bSJohn Baldwin 	 * appended after the cipher text.
9152bc40b6cSJohn Baldwin 	 *
9162bc40b6cSJohn Baldwin 	 * The IV is always stored at the start of the input buffer
9172bc40b6cSJohn Baldwin 	 * even though it may be duplicated in the payload.  The
9182bc40b6cSJohn Baldwin 	 * crypto engine doesn't work properly if the IV offset points
9192bc40b6cSJohn Baldwin 	 * inside of the AAD region, so a second copy is always
9202bc40b6cSJohn Baldwin 	 * required.
9215033c43bSJohn Baldwin 	 */
922c0341432SJohn Baldwin 	input_len = crp->crp_aad_length + crp->crp_payload_length;
923d68990a1SJohn Baldwin 
924d68990a1SJohn Baldwin 	/*
925d68990a1SJohn Baldwin 	 * The firmware hangs if sent a request which is a
926d68990a1SJohn Baldwin 	 * bit smaller than MAX_REQUEST_SIZE.  In particular, the
927d68990a1SJohn Baldwin 	 * firmware appears to require 512 - 16 bytes of spare room
928d68990a1SJohn Baldwin 	 * along with the size of the hash even if the hash isn't
929d68990a1SJohn Baldwin 	 * included in the input buffer.
930d68990a1SJohn Baldwin 	 */
931d68990a1SJohn Baldwin 	if (input_len + roundup2(axf->hashsize, 16) + (512 - 16) >
932d68990a1SJohn Baldwin 	    MAX_REQUEST_SIZE)
933d68990a1SJohn Baldwin 		return (EFBIG);
9345033c43bSJohn Baldwin 	if (op_type == CHCR_DECRYPT_OP)
9355033c43bSJohn Baldwin 		input_len += hash_size_in_response;
936c0341432SJohn Baldwin 
937c0341432SJohn Baldwin 	if (ccr_use_imm_data(transhdr_len, iv_len + input_len)) {
9385033c43bSJohn Baldwin 		imm_len = input_len;
9395033c43bSJohn Baldwin 		sgl_nsegs = 0;
9405033c43bSJohn Baldwin 		sgl_len = 0;
9415033c43bSJohn Baldwin 	} else {
9425033c43bSJohn Baldwin 		imm_len = 0;
94394578db2SJohn Baldwin 		sglist_reset(s->sg_ulptx);
944c0341432SJohn Baldwin 		if (crp->crp_aad_length != 0) {
9456deb4131SJohn Baldwin 			if (crp->crp_aad != NULL)
94694578db2SJohn Baldwin 				error = sglist_append(s->sg_ulptx,
9476deb4131SJohn Baldwin 				    crp->crp_aad, crp->crp_aad_length);
9486deb4131SJohn Baldwin 			else
94994578db2SJohn Baldwin 				error = sglist_append_sglist(s->sg_ulptx,
95094578db2SJohn Baldwin 				    s->sg_input, crp->crp_aad_start,
9516deb4131SJohn Baldwin 				    crp->crp_aad_length);
9525033c43bSJohn Baldwin 			if (error)
9535033c43bSJohn Baldwin 				return (error);
9545033c43bSJohn Baldwin 		}
95594578db2SJohn Baldwin 		error = sglist_append_sglist(s->sg_ulptx, s->sg_input,
956c0341432SJohn Baldwin 		    crp->crp_payload_start, crp->crp_payload_length);
9575033c43bSJohn Baldwin 		if (error)
9585033c43bSJohn Baldwin 			return (error);
9595033c43bSJohn Baldwin 		if (op_type == CHCR_DECRYPT_OP) {
96094578db2SJohn Baldwin 			error = sglist_append_sglist(s->sg_ulptx, s->sg_input,
961c0341432SJohn Baldwin 			    crp->crp_digest_start, hash_size_in_response);
9625033c43bSJohn Baldwin 			if (error)
9635033c43bSJohn Baldwin 				return (error);
9645033c43bSJohn Baldwin 		}
96594578db2SJohn Baldwin 		sgl_nsegs = s->sg_ulptx->sg_nseg;
9665033c43bSJohn Baldwin 		sgl_len = ccr_ulptx_sgl_len(sgl_nsegs);
9675033c43bSJohn Baldwin 	}
9685033c43bSJohn Baldwin 
9696deb4131SJohn Baldwin 	/* Any AAD comes after the IV. */
970c0341432SJohn Baldwin 	if (crp->crp_aad_length != 0) {
971c0341432SJohn Baldwin 		aad_start = iv_len + 1;
972c0341432SJohn Baldwin 		aad_stop = aad_start + crp->crp_aad_length - 1;
9735033c43bSJohn Baldwin 	} else {
9745033c43bSJohn Baldwin 		aad_start = 0;
9755033c43bSJohn Baldwin 		aad_stop = 0;
9765033c43bSJohn Baldwin 	}
977c0341432SJohn Baldwin 	cipher_start = iv_len + crp->crp_aad_length + 1;
9785033c43bSJohn Baldwin 	if (op_type == CHCR_DECRYPT_OP)
9795033c43bSJohn Baldwin 		cipher_stop = hash_size_in_response;
9805033c43bSJohn Baldwin 	else
9815033c43bSJohn Baldwin 		cipher_stop = 0;
9825033c43bSJohn Baldwin 	if (op_type == CHCR_DECRYPT_OP)
9835033c43bSJohn Baldwin 		auth_insert = hash_size_in_response;
9845033c43bSJohn Baldwin 	else
9855033c43bSJohn Baldwin 		auth_insert = 0;
9865033c43bSJohn Baldwin 
987c0341432SJohn Baldwin 	wr_len = roundup2(transhdr_len, 16) + iv_len + roundup2(imm_len, 16) +
988c0341432SJohn Baldwin 	    sgl_len;
989f7b61e2fSJohn Baldwin 	if (wr_len > SGE_MAX_WR_LEN)
990f7b61e2fSJohn Baldwin 		return (EFBIG);
99194fad5ffSJohn Baldwin 	wr = alloc_wrqe(wr_len, s->port->txq);
9925033c43bSJohn Baldwin 	if (wr == NULL) {
99394578db2SJohn Baldwin 		counter_u64_add(sc->stats_wr_nomem, 1);
9945033c43bSJohn Baldwin 		return (ENOMEM);
9955033c43bSJohn Baldwin 	}
9965033c43bSJohn Baldwin 	crwr = wrtod(wr);
9975033c43bSJohn Baldwin 	memset(crwr, 0, wr_len);
9985033c43bSJohn Baldwin 
99929fe41ddSJohn Baldwin 	crypto_read_iv(crp, iv);
1000c0341432SJohn Baldwin 
1001c0341432SJohn Baldwin 	/* Zero the remainder of the IV for AES-XTS. */
1002762f1dcbSJohn Baldwin 	memset(iv + s->cipher.iv_len, 0, iv_len - s->cipher.iv_len);
10032bc40b6cSJohn Baldwin 
100494fad5ffSJohn Baldwin 	ccr_populate_wreq(sc, s, crwr, kctx_len, wr_len, imm_len, sgl_len,
1005020ce53aSJohn Baldwin 	    op_type == CHCR_DECRYPT_OP ? hash_size_in_response : 0, crp);
10065033c43bSJohn Baldwin 
10075033c43bSJohn Baldwin 	crwr->sec_cpl.op_ivinsrtofst = htobe32(
10085033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_OPCODE(CPL_TX_SEC_PDU) |
10098f885fd1SJohn Baldwin 	    V_CPL_TX_SEC_PDU_RXCHID(s->port->rx_channel_id) |
10105033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_ACKFOLLOWS(0) | V_CPL_TX_SEC_PDU_ULPTXLPBK(1) |
10115033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_CPLLEN(2) | V_CPL_TX_SEC_PDU_PLACEHOLDER(0) |
10125033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_IVINSRTOFST(1));
10135033c43bSJohn Baldwin 
1014c0341432SJohn Baldwin 	crwr->sec_cpl.pldlen = htobe32(iv_len + input_len);
10155033c43bSJohn Baldwin 
10165033c43bSJohn Baldwin 	crwr->sec_cpl.aadstart_cipherstop_hi = htobe32(
10175033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_AADSTART(aad_start) |
10185033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_AADSTOP(aad_stop) |
10195033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_CIPHERSTART(cipher_start) |
10205033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_CIPHERSTOP_HI(cipher_stop >> 4));
10215033c43bSJohn Baldwin 	crwr->sec_cpl.cipherstop_lo_authinsert = htobe32(
10225033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_CIPHERSTOP_LO(cipher_stop & 0xf) |
1023c0341432SJohn Baldwin 	    V_CPL_TX_SEC_PDU_AUTHSTART(cipher_start) |
1024c0341432SJohn Baldwin 	    V_CPL_TX_SEC_PDU_AUTHSTOP(cipher_stop) |
10255033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_AUTHINSERT(auth_insert));
10265033c43bSJohn Baldwin 
10275033c43bSJohn Baldwin 	/* These two flits are actually a CPL_TLS_TX_SCMD_FMT. */
10285033c43bSJohn Baldwin 	hmac_ctrl = ccr_hmac_ctrl(axf->hashsize, hash_size_in_response);
10295033c43bSJohn Baldwin 	crwr->sec_cpl.seqno_numivs = htobe32(
10305033c43bSJohn Baldwin 	    V_SCMD_SEQ_NO_CTRL(0) |
1031d09389fdSJohn Baldwin 	    V_SCMD_PROTO_VERSION(SCMD_PROTO_VERSION_GENERIC) |
10325033c43bSJohn Baldwin 	    V_SCMD_ENC_DEC_CTRL(op_type) |
10335033c43bSJohn Baldwin 	    V_SCMD_CIPH_AUTH_SEQ_CTRL(op_type == CHCR_ENCRYPT_OP ? 1 : 0) |
1034762f1dcbSJohn Baldwin 	    V_SCMD_CIPH_MODE(s->cipher.cipher_mode) |
10355033c43bSJohn Baldwin 	    V_SCMD_AUTH_MODE(s->hmac.auth_mode) |
10365033c43bSJohn Baldwin 	    V_SCMD_HMAC_CTRL(hmac_ctrl) |
1037c0341432SJohn Baldwin 	    V_SCMD_IV_SIZE(iv_len / 2) |
10385033c43bSJohn Baldwin 	    V_SCMD_NUM_IVS(0));
10395033c43bSJohn Baldwin 	crwr->sec_cpl.ivgen_hdrlen = htobe32(
10405033c43bSJohn Baldwin 	    V_SCMD_IV_GEN_CTRL(0) |
10415033c43bSJohn Baldwin 	    V_SCMD_MORE_FRAGS(0) | V_SCMD_LAST_FRAG(0) | V_SCMD_MAC_ONLY(0) |
10425929c9fbSJohn Baldwin 	    V_SCMD_AADIVDROP(0) | V_SCMD_HDR_LEN(dsgl_len));
10435033c43bSJohn Baldwin 
1044762f1dcbSJohn Baldwin 	crwr->key_ctx.ctx_hdr = s->cipher.key_ctx_hdr;
1045762f1dcbSJohn Baldwin 	switch (s->cipher.cipher_mode) {
1046c0341432SJohn Baldwin 	case SCMD_CIPH_MODE_AES_CBC:
1047c0341432SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
1048762f1dcbSJohn Baldwin 			memcpy(crwr->key_ctx.key, s->cipher.enckey,
1049762f1dcbSJohn Baldwin 			    s->cipher.key_len);
10505033c43bSJohn Baldwin 		else
1051762f1dcbSJohn Baldwin 			memcpy(crwr->key_ctx.key, s->cipher.deckey,
1052762f1dcbSJohn Baldwin 			    s->cipher.key_len);
10535033c43bSJohn Baldwin 		break;
1054c0341432SJohn Baldwin 	case SCMD_CIPH_MODE_AES_CTR:
1055762f1dcbSJohn Baldwin 		memcpy(crwr->key_ctx.key, s->cipher.enckey,
1056762f1dcbSJohn Baldwin 		    s->cipher.key_len);
10575033c43bSJohn Baldwin 		break;
1058c0341432SJohn Baldwin 	case SCMD_CIPH_MODE_AES_XTS:
1059762f1dcbSJohn Baldwin 		key_half = s->cipher.key_len / 2;
1060762f1dcbSJohn Baldwin 		memcpy(crwr->key_ctx.key, s->cipher.enckey + key_half,
10615033c43bSJohn Baldwin 		    key_half);
1062c0341432SJohn Baldwin 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
10635033c43bSJohn Baldwin 			memcpy(crwr->key_ctx.key + key_half,
1064762f1dcbSJohn Baldwin 			    s->cipher.enckey, key_half);
10655033c43bSJohn Baldwin 		else
10665033c43bSJohn Baldwin 			memcpy(crwr->key_ctx.key + key_half,
1067762f1dcbSJohn Baldwin 			    s->cipher.deckey, key_half);
10685033c43bSJohn Baldwin 		break;
10695033c43bSJohn Baldwin 	}
10705033c43bSJohn Baldwin 
1071762f1dcbSJohn Baldwin 	dst = crwr->key_ctx.key + roundup2(s->cipher.key_len, 16);
1072a1b2b6e1SJohn Baldwin 	memcpy(dst, s->hmac.pads, iopad_size * 2);
10735033c43bSJohn Baldwin 
10745033c43bSJohn Baldwin 	dst = (char *)(crwr + 1) + kctx_len;
107594578db2SJohn Baldwin 	ccr_write_phys_dsgl(s, dst, dsgl_nsegs);
10765033c43bSJohn Baldwin 	dst += sizeof(struct cpl_rx_phys_dsgl) + dsgl_len;
1077c0341432SJohn Baldwin 	memcpy(dst, iv, iv_len);
1078c0341432SJohn Baldwin 	dst += iv_len;
10795033c43bSJohn Baldwin 	if (imm_len != 0) {
1080c0341432SJohn Baldwin 		if (crp->crp_aad_length != 0) {
10816deb4131SJohn Baldwin 			if (crp->crp_aad != NULL)
10826deb4131SJohn Baldwin 				memcpy(dst, crp->crp_aad, crp->crp_aad_length);
10836deb4131SJohn Baldwin 			else
1084c0341432SJohn Baldwin 				crypto_copydata(crp, crp->crp_aad_start,
1085c0341432SJohn Baldwin 				    crp->crp_aad_length, dst);
1086c0341432SJohn Baldwin 			dst += crp->crp_aad_length;
10875033c43bSJohn Baldwin 		}
1088c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_payload_start,
1089c0341432SJohn Baldwin 		    crp->crp_payload_length, dst);
1090c0341432SJohn Baldwin 		dst += crp->crp_payload_length;
10915033c43bSJohn Baldwin 		if (op_type == CHCR_DECRYPT_OP)
1092c0341432SJohn Baldwin 			crypto_copydata(crp, crp->crp_digest_start,
1093c0341432SJohn Baldwin 			    hash_size_in_response, dst);
10945033c43bSJohn Baldwin 	} else
109594578db2SJohn Baldwin 		ccr_write_ulptx_sgl(s, dst, sgl_nsegs);
10965033c43bSJohn Baldwin 
10975033c43bSJohn Baldwin 	/* XXX: TODO backpressure */
10985033c43bSJohn Baldwin 	t4_wrq_tx(sc->adapter, wr);
10995033c43bSJohn Baldwin 
11001a4a7e98SJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
11015033c43bSJohn Baldwin 	return (0);
11025033c43bSJohn Baldwin }
11035033c43bSJohn Baldwin 
11045033c43bSJohn Baldwin static int
ccr_eta_done(struct ccr_softc * sc,struct ccr_session * s,struct cryptop * crp,const struct cpl_fw6_pld * cpl,int error)1105c0341432SJohn Baldwin ccr_eta_done(struct ccr_softc *sc, struct ccr_session *s,
11065033c43bSJohn Baldwin     struct cryptop *crp, const struct cpl_fw6_pld *cpl, int error)
11075033c43bSJohn Baldwin {
11085033c43bSJohn Baldwin 
11095033c43bSJohn Baldwin 	/*
11105033c43bSJohn Baldwin 	 * The updated IV to permit chained requests is at
11115033c43bSJohn Baldwin 	 * cpl->data[2], but OCF doesn't permit chained requests.
11125033c43bSJohn Baldwin 	 */
11135033c43bSJohn Baldwin 	return (error);
11145033c43bSJohn Baldwin }
11155033c43bSJohn Baldwin 
11165033c43bSJohn Baldwin static int
ccr_gcm(struct ccr_softc * sc,struct ccr_session * s,struct cryptop * crp)1117c0341432SJohn Baldwin ccr_gcm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp)
11185033c43bSJohn Baldwin {
11195033c43bSJohn Baldwin 	char iv[CHCR_MAX_CRYPTO_IV_LEN];
11205033c43bSJohn Baldwin 	struct chcr_wr *crwr;
11215033c43bSJohn Baldwin 	struct wrqe *wr;
11225033c43bSJohn Baldwin 	char *dst;
1123d3f25aa1SJohn Baldwin 	u_int iv_len, kctx_len, op_type, transhdr_len, wr_len;
11245033c43bSJohn Baldwin 	u_int hash_size_in_response, imm_len;
11255033c43bSJohn Baldwin 	u_int aad_start, aad_stop, cipher_start, cipher_stop, auth_insert;
11265033c43bSJohn Baldwin 	u_int hmac_ctrl, input_len;
11275033c43bSJohn Baldwin 	int dsgl_nsegs, dsgl_len;
11285033c43bSJohn Baldwin 	int sgl_nsegs, sgl_len;
11295033c43bSJohn Baldwin 	int error;
11305033c43bSJohn Baldwin 
1131762f1dcbSJohn Baldwin 	if (s->cipher.key_len == 0)
11325033c43bSJohn Baldwin 		return (EINVAL);
11335033c43bSJohn Baldwin 
11345033c43bSJohn Baldwin 	/*
113504043b3dSJohn Baldwin 	 * The crypto engine doesn't handle GCM requests with an empty
113604043b3dSJohn Baldwin 	 * payload, so handle those in software instead.
113704043b3dSJohn Baldwin 	 */
1138c0341432SJohn Baldwin 	if (crp->crp_payload_length == 0)
113904043b3dSJohn Baldwin 		return (EMSGSIZE);
114004043b3dSJohn Baldwin 
1141c0341432SJohn Baldwin 	if (crp->crp_aad_length + AES_BLOCK_LEN > MAX_AAD_LEN)
114204043b3dSJohn Baldwin 		return (EMSGSIZE);
1143acaabdbbSJohn Baldwin 
11445033c43bSJohn Baldwin 	hash_size_in_response = s->gmac.hash_len;
1145c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
11465033c43bSJohn Baldwin 		op_type = CHCR_ENCRYPT_OP;
11475033c43bSJohn Baldwin 	else
11485033c43bSJohn Baldwin 		op_type = CHCR_DECRYPT_OP;
11495033c43bSJohn Baldwin 
11505033c43bSJohn Baldwin 	iv_len = AES_BLOCK_LEN;
11515033c43bSJohn Baldwin 
11525033c43bSJohn Baldwin 	/*
1153c0341432SJohn Baldwin 	 * GCM requests should always provide an explicit IV.
1154c0341432SJohn Baldwin 	 */
1155c0341432SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
1156c0341432SJohn Baldwin 		return (EINVAL);
1157c0341432SJohn Baldwin 
1158c0341432SJohn Baldwin 	/*
11595033c43bSJohn Baldwin 	 * The output buffer consists of the cipher text followed by
11605033c43bSJohn Baldwin 	 * the tag when encrypting.  For decryption it only contains
11615033c43bSJohn Baldwin 	 * the plain text.
11625929c9fbSJohn Baldwin 	 *
11635929c9fbSJohn Baldwin 	 * Due to a firmware bug, the output buffer must include a
11645929c9fbSJohn Baldwin 	 * dummy output buffer for the IV and AAD prior to the real
11655929c9fbSJohn Baldwin 	 * output buffer.
11665033c43bSJohn Baldwin 	 */
1167d68990a1SJohn Baldwin 	if (op_type == CHCR_ENCRYPT_OP) {
1168c0341432SJohn Baldwin 		if (iv_len + crp->crp_aad_length + crp->crp_payload_length +
11695929c9fbSJohn Baldwin 		    hash_size_in_response > MAX_REQUEST_SIZE)
1170d68990a1SJohn Baldwin 			return (EFBIG);
1171d68990a1SJohn Baldwin 	} else {
1172c0341432SJohn Baldwin 		if (iv_len + crp->crp_aad_length + crp->crp_payload_length >
1173c0341432SJohn Baldwin 		    MAX_REQUEST_SIZE)
1174d68990a1SJohn Baldwin 			return (EFBIG);
1175d68990a1SJohn Baldwin 	}
117694578db2SJohn Baldwin 	sglist_reset(s->sg_dsgl);
117794578db2SJohn Baldwin 	error = sglist_append_sglist(s->sg_dsgl, sc->sg_iv_aad, 0, iv_len +
1178c0341432SJohn Baldwin 	    crp->crp_aad_length);
11795929c9fbSJohn Baldwin 	if (error)
11805929c9fbSJohn Baldwin 		return (error);
11812adc3c94SJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp))
118294578db2SJohn Baldwin 		error = sglist_append_sglist(s->sg_dsgl, s->sg_output,
11832adc3c94SJohn Baldwin 		    crp->crp_payload_output_start, crp->crp_payload_length);
11842adc3c94SJohn Baldwin 	else
118594578db2SJohn Baldwin 		error = sglist_append_sglist(s->sg_dsgl, s->sg_input,
1186c0341432SJohn Baldwin 		    crp->crp_payload_start, crp->crp_payload_length);
11875033c43bSJohn Baldwin 	if (error)
11885033c43bSJohn Baldwin 		return (error);
11895033c43bSJohn Baldwin 	if (op_type == CHCR_ENCRYPT_OP) {
11902adc3c94SJohn Baldwin 		if (CRYPTO_HAS_OUTPUT_BUFFER(crp))
119194578db2SJohn Baldwin 			error = sglist_append_sglist(s->sg_dsgl, s->sg_output,
11922adc3c94SJohn Baldwin 			    crp->crp_digest_start, hash_size_in_response);
11932adc3c94SJohn Baldwin 		else
119494578db2SJohn Baldwin 			error = sglist_append_sglist(s->sg_dsgl, s->sg_input,
1195c0341432SJohn Baldwin 			    crp->crp_digest_start, hash_size_in_response);
11965033c43bSJohn Baldwin 		if (error)
11975033c43bSJohn Baldwin 			return (error);
11985033c43bSJohn Baldwin 	}
119994578db2SJohn Baldwin 	dsgl_nsegs = ccr_count_sgl(s->sg_dsgl, DSGL_SGE_MAXLEN);
12005033c43bSJohn Baldwin 	if (dsgl_nsegs > MAX_RX_PHYS_DSGL_SGE)
12015033c43bSJohn Baldwin 		return (EFBIG);
12025033c43bSJohn Baldwin 	dsgl_len = ccr_phys_dsgl_len(dsgl_nsegs);
12035033c43bSJohn Baldwin 
12045033c43bSJohn Baldwin 	/*
12055033c43bSJohn Baldwin 	 * The 'key' part of the key context consists of the key followed
12065033c43bSJohn Baldwin 	 * by the Galois hash key.
12075033c43bSJohn Baldwin 	 */
1208762f1dcbSJohn Baldwin 	kctx_len = roundup2(s->cipher.key_len, 16) + GMAC_BLOCK_LEN;
12095033c43bSJohn Baldwin 	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dsgl_len);
12105033c43bSJohn Baldwin 
12115033c43bSJohn Baldwin 	/*
12125033c43bSJohn Baldwin 	 * The input buffer consists of the IV, any AAD, and then the
12135033c43bSJohn Baldwin 	 * cipher/plain text.  For decryption requests the hash is
12145033c43bSJohn Baldwin 	 * appended after the cipher text.
12152bc40b6cSJohn Baldwin 	 *
12162bc40b6cSJohn Baldwin 	 * The IV is always stored at the start of the input buffer
12172bc40b6cSJohn Baldwin 	 * even though it may be duplicated in the payload.  The
12182bc40b6cSJohn Baldwin 	 * crypto engine doesn't work properly if the IV offset points
12192bc40b6cSJohn Baldwin 	 * inside of the AAD region, so a second copy is always
12202bc40b6cSJohn Baldwin 	 * required.
12215033c43bSJohn Baldwin 	 */
1222c0341432SJohn Baldwin 	input_len = crp->crp_aad_length + crp->crp_payload_length;
12235033c43bSJohn Baldwin 	if (op_type == CHCR_DECRYPT_OP)
12245033c43bSJohn Baldwin 		input_len += hash_size_in_response;
1225d68990a1SJohn Baldwin 	if (input_len > MAX_REQUEST_SIZE)
1226d68990a1SJohn Baldwin 		return (EFBIG);
12275033c43bSJohn Baldwin 	if (ccr_use_imm_data(transhdr_len, iv_len + input_len)) {
12285033c43bSJohn Baldwin 		imm_len = input_len;
12295033c43bSJohn Baldwin 		sgl_nsegs = 0;
12305033c43bSJohn Baldwin 		sgl_len = 0;
12315033c43bSJohn Baldwin 	} else {
12325033c43bSJohn Baldwin 		imm_len = 0;
123394578db2SJohn Baldwin 		sglist_reset(s->sg_ulptx);
1234c0341432SJohn Baldwin 		if (crp->crp_aad_length != 0) {
12356deb4131SJohn Baldwin 			if (crp->crp_aad != NULL)
123694578db2SJohn Baldwin 				error = sglist_append(s->sg_ulptx,
12376deb4131SJohn Baldwin 				    crp->crp_aad, crp->crp_aad_length);
12386deb4131SJohn Baldwin 			else
123994578db2SJohn Baldwin 				error = sglist_append_sglist(s->sg_ulptx,
124094578db2SJohn Baldwin 				    s->sg_input, crp->crp_aad_start,
12416deb4131SJohn Baldwin 				    crp->crp_aad_length);
12425033c43bSJohn Baldwin 			if (error)
12435033c43bSJohn Baldwin 				return (error);
12445033c43bSJohn Baldwin 		}
124594578db2SJohn Baldwin 		error = sglist_append_sglist(s->sg_ulptx, s->sg_input,
1246c0341432SJohn Baldwin 		    crp->crp_payload_start, crp->crp_payload_length);
12475033c43bSJohn Baldwin 		if (error)
12485033c43bSJohn Baldwin 			return (error);
12495033c43bSJohn Baldwin 		if (op_type == CHCR_DECRYPT_OP) {
125094578db2SJohn Baldwin 			error = sglist_append_sglist(s->sg_ulptx, s->sg_input,
1251c0341432SJohn Baldwin 			    crp->crp_digest_start, hash_size_in_response);
12525033c43bSJohn Baldwin 			if (error)
12535033c43bSJohn Baldwin 				return (error);
12545033c43bSJohn Baldwin 		}
125594578db2SJohn Baldwin 		sgl_nsegs = s->sg_ulptx->sg_nseg;
12565033c43bSJohn Baldwin 		sgl_len = ccr_ulptx_sgl_len(sgl_nsegs);
12575033c43bSJohn Baldwin 	}
12585033c43bSJohn Baldwin 
1259c0341432SJohn Baldwin 	if (crp->crp_aad_length != 0) {
12605033c43bSJohn Baldwin 		aad_start = iv_len + 1;
1261c0341432SJohn Baldwin 		aad_stop = aad_start + crp->crp_aad_length - 1;
12625033c43bSJohn Baldwin 	} else {
12635033c43bSJohn Baldwin 		aad_start = 0;
12645033c43bSJohn Baldwin 		aad_stop = 0;
12655033c43bSJohn Baldwin 	}
1266c0341432SJohn Baldwin 	cipher_start = iv_len + crp->crp_aad_length + 1;
12675033c43bSJohn Baldwin 	if (op_type == CHCR_DECRYPT_OP)
12685033c43bSJohn Baldwin 		cipher_stop = hash_size_in_response;
12695033c43bSJohn Baldwin 	else
12705033c43bSJohn Baldwin 		cipher_stop = 0;
12715033c43bSJohn Baldwin 	if (op_type == CHCR_DECRYPT_OP)
12725033c43bSJohn Baldwin 		auth_insert = hash_size_in_response;
12735033c43bSJohn Baldwin 	else
12745033c43bSJohn Baldwin 		auth_insert = 0;
12755033c43bSJohn Baldwin 
1276d3f25aa1SJohn Baldwin 	wr_len = roundup2(transhdr_len, 16) + iv_len + roundup2(imm_len, 16) +
1277d3f25aa1SJohn Baldwin 	    sgl_len;
1278f7b61e2fSJohn Baldwin 	if (wr_len > SGE_MAX_WR_LEN)
1279f7b61e2fSJohn Baldwin 		return (EFBIG);
128094fad5ffSJohn Baldwin 	wr = alloc_wrqe(wr_len, s->port->txq);
12815033c43bSJohn Baldwin 	if (wr == NULL) {
128294578db2SJohn Baldwin 		counter_u64_add(sc->stats_wr_nomem, 1);
12835033c43bSJohn Baldwin 		return (ENOMEM);
12845033c43bSJohn Baldwin 	}
12855033c43bSJohn Baldwin 	crwr = wrtod(wr);
12865033c43bSJohn Baldwin 	memset(crwr, 0, wr_len);
12875033c43bSJohn Baldwin 
1288cb128893SJohn Baldwin 	crypto_read_iv(crp, iv);
12892bc40b6cSJohn Baldwin 	*(uint32_t *)&iv[12] = htobe32(1);
12902bc40b6cSJohn Baldwin 
129194fad5ffSJohn Baldwin 	ccr_populate_wreq(sc, s, crwr, kctx_len, wr_len, imm_len, sgl_len, 0,
12921b0909d5SConrad Meyer 	    crp);
12935033c43bSJohn Baldwin 
12945033c43bSJohn Baldwin 	crwr->sec_cpl.op_ivinsrtofst = htobe32(
12955033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_OPCODE(CPL_TX_SEC_PDU) |
12968f885fd1SJohn Baldwin 	    V_CPL_TX_SEC_PDU_RXCHID(s->port->rx_channel_id) |
12975033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_ACKFOLLOWS(0) | V_CPL_TX_SEC_PDU_ULPTXLPBK(1) |
12985033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_CPLLEN(2) | V_CPL_TX_SEC_PDU_PLACEHOLDER(0) |
12995033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_IVINSRTOFST(1));
13005033c43bSJohn Baldwin 
13015033c43bSJohn Baldwin 	crwr->sec_cpl.pldlen = htobe32(iv_len + input_len);
13025033c43bSJohn Baldwin 
13035033c43bSJohn Baldwin 	/*
13045033c43bSJohn Baldwin 	 * NB: cipherstop is explicitly set to 0.  On encrypt it
1305c0341432SJohn Baldwin 	 * should normally be set to 0 anyway.  However, for decrypt
1306c0341432SJohn Baldwin 	 * the cipher ends before the tag in the ETA case (and
1307c0341432SJohn Baldwin 	 * authstop is set to stop before the tag), but for GCM the
1308c0341432SJohn Baldwin 	 * cipher still runs to the end of the buffer.  Not sure if
1309c0341432SJohn Baldwin 	 * this is intentional or a firmware quirk, but it is required
1310c0341432SJohn Baldwin 	 * for working tag validation with GCM decryption.
13115033c43bSJohn Baldwin 	 */
13125033c43bSJohn Baldwin 	crwr->sec_cpl.aadstart_cipherstop_hi = htobe32(
13135033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_AADSTART(aad_start) |
13145033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_AADSTOP(aad_stop) |
13155033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_CIPHERSTART(cipher_start) |
13165033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_CIPHERSTOP_HI(0));
13175033c43bSJohn Baldwin 	crwr->sec_cpl.cipherstop_lo_authinsert = htobe32(
13185033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_CIPHERSTOP_LO(0) |
13195033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_AUTHSTART(cipher_start) |
13205033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_AUTHSTOP(cipher_stop) |
13215033c43bSJohn Baldwin 	    V_CPL_TX_SEC_PDU_AUTHINSERT(auth_insert));
13225033c43bSJohn Baldwin 
13235033c43bSJohn Baldwin 	/* These two flits are actually a CPL_TLS_TX_SCMD_FMT. */
13245033c43bSJohn Baldwin 	hmac_ctrl = ccr_hmac_ctrl(AES_GMAC_HASH_LEN, hash_size_in_response);
13255033c43bSJohn Baldwin 	crwr->sec_cpl.seqno_numivs = htobe32(
13265033c43bSJohn Baldwin 	    V_SCMD_SEQ_NO_CTRL(0) |
1327d09389fdSJohn Baldwin 	    V_SCMD_PROTO_VERSION(SCMD_PROTO_VERSION_GENERIC) |
13285033c43bSJohn Baldwin 	    V_SCMD_ENC_DEC_CTRL(op_type) |
13295033c43bSJohn Baldwin 	    V_SCMD_CIPH_AUTH_SEQ_CTRL(op_type == CHCR_ENCRYPT_OP ? 1 : 0) |
1330d09389fdSJohn Baldwin 	    V_SCMD_CIPH_MODE(SCMD_CIPH_MODE_AES_GCM) |
1331d09389fdSJohn Baldwin 	    V_SCMD_AUTH_MODE(SCMD_AUTH_MODE_GHASH) |
13325033c43bSJohn Baldwin 	    V_SCMD_HMAC_CTRL(hmac_ctrl) |
13335033c43bSJohn Baldwin 	    V_SCMD_IV_SIZE(iv_len / 2) |
13345033c43bSJohn Baldwin 	    V_SCMD_NUM_IVS(0));
13355033c43bSJohn Baldwin 	crwr->sec_cpl.ivgen_hdrlen = htobe32(
13365033c43bSJohn Baldwin 	    V_SCMD_IV_GEN_CTRL(0) |
13375033c43bSJohn Baldwin 	    V_SCMD_MORE_FRAGS(0) | V_SCMD_LAST_FRAG(0) | V_SCMD_MAC_ONLY(0) |
13385929c9fbSJohn Baldwin 	    V_SCMD_AADIVDROP(0) | V_SCMD_HDR_LEN(dsgl_len));
13395033c43bSJohn Baldwin 
1340762f1dcbSJohn Baldwin 	crwr->key_ctx.ctx_hdr = s->cipher.key_ctx_hdr;
1341762f1dcbSJohn Baldwin 	memcpy(crwr->key_ctx.key, s->cipher.enckey, s->cipher.key_len);
1342762f1dcbSJohn Baldwin 	dst = crwr->key_ctx.key + roundup2(s->cipher.key_len, 16);
13435033c43bSJohn Baldwin 	memcpy(dst, s->gmac.ghash_h, GMAC_BLOCK_LEN);
13445033c43bSJohn Baldwin 
13455033c43bSJohn Baldwin 	dst = (char *)(crwr + 1) + kctx_len;
134694578db2SJohn Baldwin 	ccr_write_phys_dsgl(s, dst, dsgl_nsegs);
13475033c43bSJohn Baldwin 	dst += sizeof(struct cpl_rx_phys_dsgl) + dsgl_len;
13485033c43bSJohn Baldwin 	memcpy(dst, iv, iv_len);
13495033c43bSJohn Baldwin 	dst += iv_len;
13505033c43bSJohn Baldwin 	if (imm_len != 0) {
1351c0341432SJohn Baldwin 		if (crp->crp_aad_length != 0) {
13526deb4131SJohn Baldwin 			if (crp->crp_aad != NULL)
13536deb4131SJohn Baldwin 				memcpy(dst, crp->crp_aad, crp->crp_aad_length);
13546deb4131SJohn Baldwin 			else
1355c0341432SJohn Baldwin 				crypto_copydata(crp, crp->crp_aad_start,
1356c0341432SJohn Baldwin 				    crp->crp_aad_length, dst);
1357c0341432SJohn Baldwin 			dst += crp->crp_aad_length;
13585033c43bSJohn Baldwin 		}
1359c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_payload_start,
1360c0341432SJohn Baldwin 		    crp->crp_payload_length, dst);
1361c0341432SJohn Baldwin 		dst += crp->crp_payload_length;
13625033c43bSJohn Baldwin 		if (op_type == CHCR_DECRYPT_OP)
1363c0341432SJohn Baldwin 			crypto_copydata(crp, crp->crp_digest_start,
1364c0341432SJohn Baldwin 			    hash_size_in_response, dst);
13655033c43bSJohn Baldwin 	} else
136694578db2SJohn Baldwin 		ccr_write_ulptx_sgl(s, dst, sgl_nsegs);
13675033c43bSJohn Baldwin 
13685033c43bSJohn Baldwin 	/* XXX: TODO backpressure */
13695033c43bSJohn Baldwin 	t4_wrq_tx(sc->adapter, wr);
13705033c43bSJohn Baldwin 
13711a4a7e98SJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
13725033c43bSJohn Baldwin 	return (0);
13735033c43bSJohn Baldwin }
13745033c43bSJohn Baldwin 
13755033c43bSJohn Baldwin static int
ccr_gcm_done(struct ccr_softc * sc,struct ccr_session * s,struct cryptop * crp,const struct cpl_fw6_pld * cpl,int error)13765033c43bSJohn Baldwin ccr_gcm_done(struct ccr_softc *sc, struct ccr_session *s,
13775033c43bSJohn Baldwin     struct cryptop *crp, const struct cpl_fw6_pld *cpl, int error)
13785033c43bSJohn Baldwin {
13795033c43bSJohn Baldwin 
13805033c43bSJohn Baldwin 	/*
13815033c43bSJohn Baldwin 	 * The updated IV to permit chained requests is at
13825033c43bSJohn Baldwin 	 * cpl->data[2], but OCF doesn't permit chained requests.
13835033c43bSJohn Baldwin 	 *
13845033c43bSJohn Baldwin 	 * Note that the hardware should always verify the GMAC hash.
13855033c43bSJohn Baldwin 	 */
13865033c43bSJohn Baldwin 	return (error);
13875033c43bSJohn Baldwin }
13885033c43bSJohn Baldwin 
1389e148e407SJohn Baldwin static int
ccr_ccm_hmac_ctrl(unsigned int authsize)1390e148e407SJohn Baldwin ccr_ccm_hmac_ctrl(unsigned int authsize)
1391e148e407SJohn Baldwin {
1392e148e407SJohn Baldwin 	switch (authsize) {
1393e148e407SJohn Baldwin 	case 4:
1394e148e407SJohn Baldwin 		return (SCMD_HMAC_CTRL_PL1);
1395e148e407SJohn Baldwin 	case 6:
1396e148e407SJohn Baldwin 		return (SCMD_HMAC_CTRL_PL2);
1397e148e407SJohn Baldwin 	case 8:
1398e148e407SJohn Baldwin 		return (SCMD_HMAC_CTRL_DIV2);
1399e148e407SJohn Baldwin 	case 10:
1400e148e407SJohn Baldwin 		return (SCMD_HMAC_CTRL_TRUNC_RFC4366);
1401e148e407SJohn Baldwin 	case 12:
1402e148e407SJohn Baldwin 		return (SCMD_HMAC_CTRL_IPSEC_96BIT);
1403e148e407SJohn Baldwin 	case 14:
1404e148e407SJohn Baldwin 		return (SCMD_HMAC_CTRL_PL3);
1405e148e407SJohn Baldwin 	case 16:
1406e148e407SJohn Baldwin 		return (SCMD_HMAC_CTRL_NO_TRUNC);
1407e148e407SJohn Baldwin 	default:
1408e148e407SJohn Baldwin 		__assert_unreachable();
1409e148e407SJohn Baldwin 	}
1410e148e407SJohn Baldwin }
1411e148e407SJohn Baldwin 
14125033c43bSJohn Baldwin static void
generate_ccm_b0(struct cryptop * crp,u_int hash_size_in_response,const char * iv,char * b0)1413c0341432SJohn Baldwin generate_ccm_b0(struct cryptop *crp, u_int hash_size_in_response,
1414c0341432SJohn Baldwin     const char *iv, char *b0)
14156b0451d6SJohn Baldwin {
14163e6a97b3SJohn Baldwin 	u_int i, payload_len, L;
14176b0451d6SJohn Baldwin 
14186b0451d6SJohn Baldwin 	/* NB: L is already set in the first byte of the IV. */
14196b0451d6SJohn Baldwin 	memcpy(b0, iv, CCM_B0_SIZE);
14203e6a97b3SJohn Baldwin 	L = iv[0] + 1;
14216b0451d6SJohn Baldwin 
14226b0451d6SJohn Baldwin 	/* Set length of hash in bits 3 - 5. */
14236b0451d6SJohn Baldwin 	b0[0] |= (((hash_size_in_response - 2) / 2) << 3);
14246b0451d6SJohn Baldwin 
14256b0451d6SJohn Baldwin 	/* Store the payload length as a big-endian value. */
1426c0341432SJohn Baldwin 	payload_len = crp->crp_payload_length;
14273e6a97b3SJohn Baldwin 	for (i = 0; i < L; i++) {
14286b0451d6SJohn Baldwin 		b0[CCM_CBC_BLOCK_LEN - 1 - i] = payload_len;
14296b0451d6SJohn Baldwin 		payload_len >>= 8;
14306b0451d6SJohn Baldwin 	}
14316b0451d6SJohn Baldwin 
14326b0451d6SJohn Baldwin 	/*
14336b0451d6SJohn Baldwin 	 * If there is AAD in the request, set bit 6 in the flags
14346b0451d6SJohn Baldwin 	 * field and store the AAD length as a big-endian value at the
14356b0451d6SJohn Baldwin 	 * start of block 1.  This only assumes a 16-bit AAD length
14366b0451d6SJohn Baldwin 	 * since T6 doesn't support large AAD sizes.
14376b0451d6SJohn Baldwin 	 */
1438c0341432SJohn Baldwin 	if (crp->crp_aad_length != 0) {
14396b0451d6SJohn Baldwin 		b0[0] |= (1 << 6);
1440c0341432SJohn Baldwin 		*(uint16_t *)(b0 + CCM_B0_SIZE) = htobe16(crp->crp_aad_length);
14416b0451d6SJohn Baldwin 	}
14426b0451d6SJohn Baldwin }
14436b0451d6SJohn Baldwin 
14446b0451d6SJohn Baldwin static int
ccr_ccm(struct ccr_softc * sc,struct ccr_session * s,struct cryptop * crp)1445c0341432SJohn Baldwin ccr_ccm(struct ccr_softc *sc, struct ccr_session *s, struct cryptop *crp)
14466b0451d6SJohn Baldwin {
14476b0451d6SJohn Baldwin 	char iv[CHCR_MAX_CRYPTO_IV_LEN];
14483e6a97b3SJohn Baldwin 	const struct crypto_session_params *csp;
14496b0451d6SJohn Baldwin 	struct ulptx_idata *idata;
14506b0451d6SJohn Baldwin 	struct chcr_wr *crwr;
14516b0451d6SJohn Baldwin 	struct wrqe *wr;
14526b0451d6SJohn Baldwin 	char *dst;
14536b0451d6SJohn Baldwin 	u_int iv_len, kctx_len, op_type, transhdr_len, wr_len;
14546b0451d6SJohn Baldwin 	u_int aad_len, b0_len, hash_size_in_response, imm_len;
14556b0451d6SJohn Baldwin 	u_int aad_start, aad_stop, cipher_start, cipher_stop, auth_insert;
14566b0451d6SJohn Baldwin 	u_int hmac_ctrl, input_len;
14576b0451d6SJohn Baldwin 	int dsgl_nsegs, dsgl_len;
14586b0451d6SJohn Baldwin 	int sgl_nsegs, sgl_len;
14596b0451d6SJohn Baldwin 	int error;
14606b0451d6SJohn Baldwin 
14613e6a97b3SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
14623e6a97b3SJohn Baldwin 
1463762f1dcbSJohn Baldwin 	if (s->cipher.key_len == 0)
14646b0451d6SJohn Baldwin 		return (EINVAL);
14656b0451d6SJohn Baldwin 
14666b0451d6SJohn Baldwin 	/*
14676b0451d6SJohn Baldwin 	 * The crypto engine doesn't handle CCM requests with an empty
14686b0451d6SJohn Baldwin 	 * payload, so handle those in software instead.
14696b0451d6SJohn Baldwin 	 */
1470c0341432SJohn Baldwin 	if (crp->crp_payload_length == 0)
14716b0451d6SJohn Baldwin 		return (EMSGSIZE);
14726b0451d6SJohn Baldwin 
14733e6a97b3SJohn Baldwin 	/* The length has to fit within the length field in block 0. */
14743e6a97b3SJohn Baldwin 	if (crp->crp_payload_length > ccm_max_payload_length(csp))
14753e6a97b3SJohn Baldwin 		return (EMSGSIZE);
14763e6a97b3SJohn Baldwin 
14776b0451d6SJohn Baldwin 	/*
14786b0451d6SJohn Baldwin 	 * CCM always includes block 0 in the AAD before AAD from the
14796b0451d6SJohn Baldwin 	 * request.
14806b0451d6SJohn Baldwin 	 */
14816b0451d6SJohn Baldwin 	b0_len = CCM_B0_SIZE;
1482c0341432SJohn Baldwin 	if (crp->crp_aad_length != 0)
14836b0451d6SJohn Baldwin 		b0_len += CCM_AAD_FIELD_SIZE;
1484c0341432SJohn Baldwin 	aad_len = b0_len + crp->crp_aad_length;
14856b0451d6SJohn Baldwin 
14866b0451d6SJohn Baldwin 	/*
1487c0341432SJohn Baldwin 	 * CCM requests should always provide an explicit IV (really
1488c0341432SJohn Baldwin 	 * the nonce).
1489c0341432SJohn Baldwin 	 */
1490c0341432SJohn Baldwin 	if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
1491c0341432SJohn Baldwin 		return (EINVAL);
1492c0341432SJohn Baldwin 
1493c0341432SJohn Baldwin 	/*
14943e6a97b3SJohn Baldwin 	 * The IV in the work request is 16 bytes and not just the
14953e6a97b3SJohn Baldwin 	 * nonce.
14966b0451d6SJohn Baldwin 	 */
14976b0451d6SJohn Baldwin 	iv_len = AES_BLOCK_LEN;
14986b0451d6SJohn Baldwin 
14996b0451d6SJohn Baldwin 	if (iv_len + aad_len > MAX_AAD_LEN)
15006b0451d6SJohn Baldwin 		return (EMSGSIZE);
15016b0451d6SJohn Baldwin 
15026b0451d6SJohn Baldwin 	hash_size_in_response = s->ccm_mac.hash_len;
1503c0341432SJohn Baldwin 	if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
15046b0451d6SJohn Baldwin 		op_type = CHCR_ENCRYPT_OP;
15056b0451d6SJohn Baldwin 	else
15066b0451d6SJohn Baldwin 		op_type = CHCR_DECRYPT_OP;
15076b0451d6SJohn Baldwin 
15086b0451d6SJohn Baldwin 	/*
15096b0451d6SJohn Baldwin 	 * The output buffer consists of the cipher text followed by
15106b0451d6SJohn Baldwin 	 * the tag when encrypting.  For decryption it only contains
15116b0451d6SJohn Baldwin 	 * the plain text.
15126b0451d6SJohn Baldwin 	 *
15136b0451d6SJohn Baldwin 	 * Due to a firmware bug, the output buffer must include a
15146b0451d6SJohn Baldwin 	 * dummy output buffer for the IV and AAD prior to the real
15156b0451d6SJohn Baldwin 	 * output buffer.
15166b0451d6SJohn Baldwin 	 */
15176b0451d6SJohn Baldwin 	if (op_type == CHCR_ENCRYPT_OP) {
1518c0341432SJohn Baldwin 		if (iv_len + aad_len + crp->crp_payload_length +
1519c0341432SJohn Baldwin 		    hash_size_in_response > MAX_REQUEST_SIZE)
15206b0451d6SJohn Baldwin 			return (EFBIG);
15216b0451d6SJohn Baldwin 	} else {
1522c0341432SJohn Baldwin 		if (iv_len + aad_len + crp->crp_payload_length >
1523c0341432SJohn Baldwin 		    MAX_REQUEST_SIZE)
15246b0451d6SJohn Baldwin 			return (EFBIG);
15256b0451d6SJohn Baldwin 	}
152694578db2SJohn Baldwin 	sglist_reset(s->sg_dsgl);
152794578db2SJohn Baldwin 	error = sglist_append_sglist(s->sg_dsgl, sc->sg_iv_aad, 0, iv_len +
15286b0451d6SJohn Baldwin 	    aad_len);
15296b0451d6SJohn Baldwin 	if (error)
15306b0451d6SJohn Baldwin 		return (error);
15312adc3c94SJohn Baldwin 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp))
153294578db2SJohn Baldwin 		error = sglist_append_sglist(s->sg_dsgl, s->sg_output,
15332adc3c94SJohn Baldwin 		    crp->crp_payload_output_start, crp->crp_payload_length);
15342adc3c94SJohn Baldwin 	else
153594578db2SJohn Baldwin 		error = sglist_append_sglist(s->sg_dsgl, s->sg_input,
1536c0341432SJohn Baldwin 		    crp->crp_payload_start, crp->crp_payload_length);
15376b0451d6SJohn Baldwin 	if (error)
15386b0451d6SJohn Baldwin 		return (error);
15396b0451d6SJohn Baldwin 	if (op_type == CHCR_ENCRYPT_OP) {
15402adc3c94SJohn Baldwin 		if (CRYPTO_HAS_OUTPUT_BUFFER(crp))
154194578db2SJohn Baldwin 			error = sglist_append_sglist(s->sg_dsgl, s->sg_output,
15422adc3c94SJohn Baldwin 			    crp->crp_digest_start, hash_size_in_response);
15432adc3c94SJohn Baldwin 		else
154494578db2SJohn Baldwin 			error = sglist_append_sglist(s->sg_dsgl, s->sg_input,
1545c0341432SJohn Baldwin 			    crp->crp_digest_start, hash_size_in_response);
15466b0451d6SJohn Baldwin 		if (error)
15476b0451d6SJohn Baldwin 			return (error);
15486b0451d6SJohn Baldwin 	}
154994578db2SJohn Baldwin 	dsgl_nsegs = ccr_count_sgl(s->sg_dsgl, DSGL_SGE_MAXLEN);
15506b0451d6SJohn Baldwin 	if (dsgl_nsegs > MAX_RX_PHYS_DSGL_SGE)
15516b0451d6SJohn Baldwin 		return (EFBIG);
15526b0451d6SJohn Baldwin 	dsgl_len = ccr_phys_dsgl_len(dsgl_nsegs);
15536b0451d6SJohn Baldwin 
15546b0451d6SJohn Baldwin 	/*
15556b0451d6SJohn Baldwin 	 * The 'key' part of the key context consists of two copies of
15566b0451d6SJohn Baldwin 	 * the AES key.
15576b0451d6SJohn Baldwin 	 */
1558762f1dcbSJohn Baldwin 	kctx_len = roundup2(s->cipher.key_len, 16) * 2;
15596b0451d6SJohn Baldwin 	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dsgl_len);
15606b0451d6SJohn Baldwin 
15616b0451d6SJohn Baldwin 	/*
15626b0451d6SJohn Baldwin 	 * The input buffer consists of the IV, AAD (including block
15636b0451d6SJohn Baldwin 	 * 0), and then the cipher/plain text.  For decryption
15646b0451d6SJohn Baldwin 	 * requests the hash is appended after the cipher text.
15656b0451d6SJohn Baldwin 	 *
15666b0451d6SJohn Baldwin 	 * The IV is always stored at the start of the input buffer
15676b0451d6SJohn Baldwin 	 * even though it may be duplicated in the payload.  The
15686b0451d6SJohn Baldwin 	 * crypto engine doesn't work properly if the IV offset points
15696b0451d6SJohn Baldwin 	 * inside of the AAD region, so a second copy is always
15706b0451d6SJohn Baldwin 	 * required.
15716b0451d6SJohn Baldwin 	 */
1572c0341432SJohn Baldwin 	input_len = aad_len + crp->crp_payload_length;
15736b0451d6SJohn Baldwin 	if (op_type == CHCR_DECRYPT_OP)
15746b0451d6SJohn Baldwin 		input_len += hash_size_in_response;
15756b0451d6SJohn Baldwin 	if (input_len > MAX_REQUEST_SIZE)
15766b0451d6SJohn Baldwin 		return (EFBIG);
15776b0451d6SJohn Baldwin 	if (ccr_use_imm_data(transhdr_len, iv_len + input_len)) {
15786b0451d6SJohn Baldwin 		imm_len = input_len;
15796b0451d6SJohn Baldwin 		sgl_nsegs = 0;
15806b0451d6SJohn Baldwin 		sgl_len = 0;
15816b0451d6SJohn Baldwin 	} else {
15826b0451d6SJohn Baldwin 		/* Block 0 is passed as immediate data. */
15836b0451d6SJohn Baldwin 		imm_len = b0_len;
15846b0451d6SJohn Baldwin 
158594578db2SJohn Baldwin 		sglist_reset(s->sg_ulptx);
1586c0341432SJohn Baldwin 		if (crp->crp_aad_length != 0) {
15876deb4131SJohn Baldwin 			if (crp->crp_aad != NULL)
158894578db2SJohn Baldwin 				error = sglist_append(s->sg_ulptx,
15896deb4131SJohn Baldwin 				    crp->crp_aad, crp->crp_aad_length);
15906deb4131SJohn Baldwin 			else
159194578db2SJohn Baldwin 				error = sglist_append_sglist(s->sg_ulptx,
159294578db2SJohn Baldwin 				    s->sg_input, crp->crp_aad_start,
15936deb4131SJohn Baldwin 				    crp->crp_aad_length);
15946b0451d6SJohn Baldwin 			if (error)
15956b0451d6SJohn Baldwin 				return (error);
15966b0451d6SJohn Baldwin 		}
159794578db2SJohn Baldwin 		error = sglist_append_sglist(s->sg_ulptx, s->sg_input,
1598c0341432SJohn Baldwin 		    crp->crp_payload_start, crp->crp_payload_length);
15996b0451d6SJohn Baldwin 		if (error)
16006b0451d6SJohn Baldwin 			return (error);
16016b0451d6SJohn Baldwin 		if (op_type == CHCR_DECRYPT_OP) {
160294578db2SJohn Baldwin 			error = sglist_append_sglist(s->sg_ulptx, s->sg_input,
1603c0341432SJohn Baldwin 			    crp->crp_digest_start, hash_size_in_response);
16046b0451d6SJohn Baldwin 			if (error)
16056b0451d6SJohn Baldwin 				return (error);
16066b0451d6SJohn Baldwin 		}
160794578db2SJohn Baldwin 		sgl_nsegs = s->sg_ulptx->sg_nseg;
16086b0451d6SJohn Baldwin 		sgl_len = ccr_ulptx_sgl_len(sgl_nsegs);
16096b0451d6SJohn Baldwin 	}
16106b0451d6SJohn Baldwin 
16116b0451d6SJohn Baldwin 	aad_start = iv_len + 1;
16126b0451d6SJohn Baldwin 	aad_stop = aad_start + aad_len - 1;
16136b0451d6SJohn Baldwin 	cipher_start = aad_stop + 1;
16146b0451d6SJohn Baldwin 	if (op_type == CHCR_DECRYPT_OP)
16156b0451d6SJohn Baldwin 		cipher_stop = hash_size_in_response;
16166b0451d6SJohn Baldwin 	else
16176b0451d6SJohn Baldwin 		cipher_stop = 0;
16186b0451d6SJohn Baldwin 	if (op_type == CHCR_DECRYPT_OP)
16196b0451d6SJohn Baldwin 		auth_insert = hash_size_in_response;
16206b0451d6SJohn Baldwin 	else
16216b0451d6SJohn Baldwin 		auth_insert = 0;
16226b0451d6SJohn Baldwin 
16236b0451d6SJohn Baldwin 	wr_len = roundup2(transhdr_len, 16) + iv_len + roundup2(imm_len, 16) +
16246b0451d6SJohn Baldwin 	    sgl_len;
16256b0451d6SJohn Baldwin 	if (wr_len > SGE_MAX_WR_LEN)
16266b0451d6SJohn Baldwin 		return (EFBIG);
162794fad5ffSJohn Baldwin 	wr = alloc_wrqe(wr_len, s->port->txq);
16286b0451d6SJohn Baldwin 	if (wr == NULL) {
162994578db2SJohn Baldwin 		counter_u64_add(sc->stats_wr_nomem, 1);
16306b0451d6SJohn Baldwin 		return (ENOMEM);
16316b0451d6SJohn Baldwin 	}
16326b0451d6SJohn Baldwin 	crwr = wrtod(wr);
16336b0451d6SJohn Baldwin 	memset(crwr, 0, wr_len);
16346b0451d6SJohn Baldwin 
16356b0451d6SJohn Baldwin 	/*
1636c0341432SJohn Baldwin 	 * Read the nonce from the request.  Use the nonce to generate
1637c0341432SJohn Baldwin 	 * the full IV with the counter set to 0.
16386b0451d6SJohn Baldwin 	 */
16396b0451d6SJohn Baldwin 	memset(iv, 0, iv_len);
16403e6a97b3SJohn Baldwin 	iv[0] = (15 - csp->csp_ivlen) - 1;
1641cb128893SJohn Baldwin 	crypto_read_iv(crp, iv + 1);
16426b0451d6SJohn Baldwin 
164394fad5ffSJohn Baldwin 	ccr_populate_wreq(sc, s, crwr, kctx_len, wr_len, imm_len, sgl_len, 0,
16446b0451d6SJohn Baldwin 	    crp);
16456b0451d6SJohn Baldwin 
16466b0451d6SJohn Baldwin 	crwr->sec_cpl.op_ivinsrtofst = htobe32(
16476b0451d6SJohn Baldwin 	    V_CPL_TX_SEC_PDU_OPCODE(CPL_TX_SEC_PDU) |
16488f885fd1SJohn Baldwin 	    V_CPL_TX_SEC_PDU_RXCHID(s->port->rx_channel_id) |
16496b0451d6SJohn Baldwin 	    V_CPL_TX_SEC_PDU_ACKFOLLOWS(0) | V_CPL_TX_SEC_PDU_ULPTXLPBK(1) |
16506b0451d6SJohn Baldwin 	    V_CPL_TX_SEC_PDU_CPLLEN(2) | V_CPL_TX_SEC_PDU_PLACEHOLDER(0) |
16516b0451d6SJohn Baldwin 	    V_CPL_TX_SEC_PDU_IVINSRTOFST(1));
16526b0451d6SJohn Baldwin 
16536b0451d6SJohn Baldwin 	crwr->sec_cpl.pldlen = htobe32(iv_len + input_len);
16546b0451d6SJohn Baldwin 
16556b0451d6SJohn Baldwin 	/*
16566b0451d6SJohn Baldwin 	 * NB: cipherstop is explicitly set to 0.  See comments above
16576b0451d6SJohn Baldwin 	 * in ccr_gcm().
16586b0451d6SJohn Baldwin 	 */
16596b0451d6SJohn Baldwin 	crwr->sec_cpl.aadstart_cipherstop_hi = htobe32(
16606b0451d6SJohn Baldwin 	    V_CPL_TX_SEC_PDU_AADSTART(aad_start) |
16616b0451d6SJohn Baldwin 	    V_CPL_TX_SEC_PDU_AADSTOP(aad_stop) |
16626b0451d6SJohn Baldwin 	    V_CPL_TX_SEC_PDU_CIPHERSTART(cipher_start) |
16636b0451d6SJohn Baldwin 	    V_CPL_TX_SEC_PDU_CIPHERSTOP_HI(0));
16646b0451d6SJohn Baldwin 	crwr->sec_cpl.cipherstop_lo_authinsert = htobe32(
16656b0451d6SJohn Baldwin 	    V_CPL_TX_SEC_PDU_CIPHERSTOP_LO(0) |
16666b0451d6SJohn Baldwin 	    V_CPL_TX_SEC_PDU_AUTHSTART(cipher_start) |
16676b0451d6SJohn Baldwin 	    V_CPL_TX_SEC_PDU_AUTHSTOP(cipher_stop) |
16686b0451d6SJohn Baldwin 	    V_CPL_TX_SEC_PDU_AUTHINSERT(auth_insert));
16696b0451d6SJohn Baldwin 
16706b0451d6SJohn Baldwin 	/* These two flits are actually a CPL_TLS_TX_SCMD_FMT. */
1671e148e407SJohn Baldwin 	hmac_ctrl = ccr_ccm_hmac_ctrl(hash_size_in_response);
16726b0451d6SJohn Baldwin 	crwr->sec_cpl.seqno_numivs = htobe32(
16736b0451d6SJohn Baldwin 	    V_SCMD_SEQ_NO_CTRL(0) |
16746b0451d6SJohn Baldwin 	    V_SCMD_PROTO_VERSION(SCMD_PROTO_VERSION_GENERIC) |
16756b0451d6SJohn Baldwin 	    V_SCMD_ENC_DEC_CTRL(op_type) |
16766b0451d6SJohn Baldwin 	    V_SCMD_CIPH_AUTH_SEQ_CTRL(op_type == CHCR_ENCRYPT_OP ? 0 : 1) |
16776b0451d6SJohn Baldwin 	    V_SCMD_CIPH_MODE(SCMD_CIPH_MODE_AES_CCM) |
16786b0451d6SJohn Baldwin 	    V_SCMD_AUTH_MODE(SCMD_AUTH_MODE_CBCMAC) |
16796b0451d6SJohn Baldwin 	    V_SCMD_HMAC_CTRL(hmac_ctrl) |
16806b0451d6SJohn Baldwin 	    V_SCMD_IV_SIZE(iv_len / 2) |
16816b0451d6SJohn Baldwin 	    V_SCMD_NUM_IVS(0));
16826b0451d6SJohn Baldwin 	crwr->sec_cpl.ivgen_hdrlen = htobe32(
16836b0451d6SJohn Baldwin 	    V_SCMD_IV_GEN_CTRL(0) |
16846b0451d6SJohn Baldwin 	    V_SCMD_MORE_FRAGS(0) | V_SCMD_LAST_FRAG(0) | V_SCMD_MAC_ONLY(0) |
16856b0451d6SJohn Baldwin 	    V_SCMD_AADIVDROP(0) | V_SCMD_HDR_LEN(dsgl_len));
16866b0451d6SJohn Baldwin 
1687762f1dcbSJohn Baldwin 	crwr->key_ctx.ctx_hdr = s->cipher.key_ctx_hdr;
1688762f1dcbSJohn Baldwin 	memcpy(crwr->key_ctx.key, s->cipher.enckey, s->cipher.key_len);
1689762f1dcbSJohn Baldwin 	memcpy(crwr->key_ctx.key + roundup(s->cipher.key_len, 16),
1690762f1dcbSJohn Baldwin 	    s->cipher.enckey, s->cipher.key_len);
16916b0451d6SJohn Baldwin 
16926b0451d6SJohn Baldwin 	dst = (char *)(crwr + 1) + kctx_len;
169394578db2SJohn Baldwin 	ccr_write_phys_dsgl(s, dst, dsgl_nsegs);
16946b0451d6SJohn Baldwin 	dst += sizeof(struct cpl_rx_phys_dsgl) + dsgl_len;
16956b0451d6SJohn Baldwin 	memcpy(dst, iv, iv_len);
16966b0451d6SJohn Baldwin 	dst += iv_len;
1697c0341432SJohn Baldwin 	generate_ccm_b0(crp, hash_size_in_response, iv, dst);
16986b0451d6SJohn Baldwin 	if (sgl_nsegs == 0) {
16996b0451d6SJohn Baldwin 		dst += b0_len;
1700c0341432SJohn Baldwin 		if (crp->crp_aad_length != 0) {
17016deb4131SJohn Baldwin 			if (crp->crp_aad != NULL)
17026deb4131SJohn Baldwin 				memcpy(dst, crp->crp_aad, crp->crp_aad_length);
17036deb4131SJohn Baldwin 			else
1704c0341432SJohn Baldwin 				crypto_copydata(crp, crp->crp_aad_start,
1705c0341432SJohn Baldwin 				    crp->crp_aad_length, dst);
1706c0341432SJohn Baldwin 			dst += crp->crp_aad_length;
17076b0451d6SJohn Baldwin 		}
1708c0341432SJohn Baldwin 		crypto_copydata(crp, crp->crp_payload_start,
1709c0341432SJohn Baldwin 		    crp->crp_payload_length, dst);
1710c0341432SJohn Baldwin 		dst += crp->crp_payload_length;
17116b0451d6SJohn Baldwin 		if (op_type == CHCR_DECRYPT_OP)
1712c0341432SJohn Baldwin 			crypto_copydata(crp, crp->crp_digest_start,
1713c0341432SJohn Baldwin 			    hash_size_in_response, dst);
17146b0451d6SJohn Baldwin 	} else {
17156b0451d6SJohn Baldwin 		dst += CCM_B0_SIZE;
17166b0451d6SJohn Baldwin 		if (b0_len > CCM_B0_SIZE) {
17176b0451d6SJohn Baldwin 			/*
17186b0451d6SJohn Baldwin 			 * If there is AAD, insert padding including a
17196b0451d6SJohn Baldwin 			 * ULP_TX_SC_NOOP so that the ULP_TX_SC_DSGL
17206b0451d6SJohn Baldwin 			 * is 16-byte aligned.
17216b0451d6SJohn Baldwin 			 */
17226b0451d6SJohn Baldwin 			KASSERT(b0_len - CCM_B0_SIZE == CCM_AAD_FIELD_SIZE,
17236b0451d6SJohn Baldwin 			    ("b0_len mismatch"));
17246b0451d6SJohn Baldwin 			memset(dst + CCM_AAD_FIELD_SIZE, 0,
17256b0451d6SJohn Baldwin 			    8 - CCM_AAD_FIELD_SIZE);
17266b0451d6SJohn Baldwin 			idata = (void *)(dst + 8);
17276b0451d6SJohn Baldwin 			idata->cmd_more = htobe32(V_ULPTX_CMD(ULP_TX_SC_NOOP));
17286b0451d6SJohn Baldwin 			idata->len = htobe32(0);
17296b0451d6SJohn Baldwin 			dst = (void *)(idata + 1);
17306b0451d6SJohn Baldwin 		}
173194578db2SJohn Baldwin 		ccr_write_ulptx_sgl(s, dst, sgl_nsegs);
17326b0451d6SJohn Baldwin 	}
17336b0451d6SJohn Baldwin 
17346b0451d6SJohn Baldwin 	/* XXX: TODO backpressure */
17356b0451d6SJohn Baldwin 	t4_wrq_tx(sc->adapter, wr);
17366b0451d6SJohn Baldwin 
17371a4a7e98SJohn Baldwin 	explicit_bzero(iv, sizeof(iv));
17386b0451d6SJohn Baldwin 	return (0);
17396b0451d6SJohn Baldwin }
17406b0451d6SJohn Baldwin 
17416b0451d6SJohn Baldwin static int
ccr_ccm_done(struct ccr_softc * sc,struct ccr_session * s,struct cryptop * crp,const struct cpl_fw6_pld * cpl,int error)17426b0451d6SJohn Baldwin ccr_ccm_done(struct ccr_softc *sc, struct ccr_session *s,
17436b0451d6SJohn Baldwin     struct cryptop *crp, const struct cpl_fw6_pld *cpl, int error)
17446b0451d6SJohn Baldwin {
17456b0451d6SJohn Baldwin 
17466b0451d6SJohn Baldwin 	/*
17476b0451d6SJohn Baldwin 	 * The updated IV to permit chained requests is at
17486b0451d6SJohn Baldwin 	 * cpl->data[2], but OCF doesn't permit chained requests.
17496b0451d6SJohn Baldwin 	 *
17506b0451d6SJohn Baldwin 	 * Note that the hardware should always verify the CBC MAC
17516b0451d6SJohn Baldwin 	 * hash.
17526b0451d6SJohn Baldwin 	 */
17536b0451d6SJohn Baldwin 	return (error);
17546b0451d6SJohn Baldwin }
17556b0451d6SJohn Baldwin 
17566b0451d6SJohn Baldwin /*
1757e43cf698SJohn Baldwin  * Use the software session for requests not supported by the crypto
1758e43cf698SJohn Baldwin  * engine (e.g. CCM and GCM requests with an empty payload).
17596b0451d6SJohn Baldwin  */
17604361c4ebSJohn Baldwin static int
ccr_soft_done(struct cryptop * crp)1761e43cf698SJohn Baldwin ccr_soft_done(struct cryptop *crp)
17624361c4ebSJohn Baldwin {
1763e43cf698SJohn Baldwin 	struct cryptop *orig;
1764e43cf698SJohn Baldwin 
1765e43cf698SJohn Baldwin 	orig = crp->crp_opaque;
1766e43cf698SJohn Baldwin 	orig->crp_etype = crp->crp_etype;
1767e43cf698SJohn Baldwin 	crypto_freereq(crp);
1768e43cf698SJohn Baldwin 	crypto_done(orig);
1769e43cf698SJohn Baldwin 	return (0);
17704361c4ebSJohn Baldwin }
17714361c4ebSJohn Baldwin 
17724361c4ebSJohn Baldwin static void
ccr_soft(struct ccr_session * s,struct cryptop * crp)1773e43cf698SJohn Baldwin ccr_soft(struct ccr_session *s, struct cryptop *crp)
17746b0451d6SJohn Baldwin {
1775e43cf698SJohn Baldwin 	struct cryptop *new;
1776e43cf698SJohn Baldwin 	int error;
17776b0451d6SJohn Baldwin 
1778e43cf698SJohn Baldwin 	new = crypto_clonereq(crp, s->sw_session, M_NOWAIT);
1779e43cf698SJohn Baldwin 	if (new == NULL) {
1780e43cf698SJohn Baldwin 		crp->crp_etype = ENOMEM;
1781e43cf698SJohn Baldwin 		crypto_done(crp);
1782e43cf698SJohn Baldwin 		return;
17833e6a97b3SJohn Baldwin 	}
17843e6a97b3SJohn Baldwin 
1785e43cf698SJohn Baldwin 	/*
1786e43cf698SJohn Baldwin 	 * XXX: This only really needs CRYPTO_ASYNC_ORDERED if the
1787e43cf698SJohn Baldwin 	 * original request was dispatched that way.  There is no way
1788e43cf698SJohn Baldwin 	 * to know that though since crypto_dispatch_async() discards
1789e43cf698SJohn Baldwin 	 * the flag for async backends (such as ccr(4)).
1790e43cf698SJohn Baldwin 	 */
1791e43cf698SJohn Baldwin 	new->crp_opaque = crp;
1792e43cf698SJohn Baldwin 	new->crp_callback = ccr_soft_done;
1793e43cf698SJohn Baldwin 	error = crypto_dispatch_async(new, CRYPTO_ASYNC_ORDERED);
1794e43cf698SJohn Baldwin 	if (error != 0) {
17956b0451d6SJohn Baldwin 		crp->crp_etype = error;
17966b0451d6SJohn Baldwin 		crypto_done(crp);
17976b0451d6SJohn Baldwin 	}
1798e43cf698SJohn Baldwin }
17996b0451d6SJohn Baldwin 
18006b0451d6SJohn Baldwin static void
ccr_identify(driver_t * driver,device_t parent)18015033c43bSJohn Baldwin ccr_identify(driver_t *driver, device_t parent)
18025033c43bSJohn Baldwin {
18035033c43bSJohn Baldwin 	struct adapter *sc;
18045033c43bSJohn Baldwin 
18055033c43bSJohn Baldwin 	sc = device_get_softc(parent);
18065033c43bSJohn Baldwin 	if (sc->cryptocaps & FW_CAPS_CONFIG_CRYPTO_LOOKASIDE &&
1807*b670c9baSAhmad Khalifa 	    device_find_child(parent, "ccr", DEVICE_UNIT_ANY) == NULL)
18085b56413dSWarner Losh 		device_add_child(parent, "ccr", DEVICE_UNIT_ANY);
18095033c43bSJohn Baldwin }
18105033c43bSJohn Baldwin 
18115033c43bSJohn Baldwin static int
ccr_probe(device_t dev)18125033c43bSJohn Baldwin ccr_probe(device_t dev)
18135033c43bSJohn Baldwin {
18145033c43bSJohn Baldwin 
18155033c43bSJohn Baldwin 	device_set_desc(dev, "Chelsio Crypto Accelerator");
18165033c43bSJohn Baldwin 	return (BUS_PROBE_DEFAULT);
18175033c43bSJohn Baldwin }
18185033c43bSJohn Baldwin 
18195033c43bSJohn Baldwin static void
ccr_sysctls(struct ccr_softc * sc)18205033c43bSJohn Baldwin ccr_sysctls(struct ccr_softc *sc)
18215033c43bSJohn Baldwin {
1822a727d953SNavdeep Parhar 	struct sysctl_ctx_list *ctx = &sc->ctx;
182394fad5ffSJohn Baldwin 	struct sysctl_oid *oid, *port_oid;
18245033c43bSJohn Baldwin 	struct sysctl_oid_list *children;
182594fad5ffSJohn Baldwin 	char buf[16];
182694fad5ffSJohn Baldwin 	int i;
18275033c43bSJohn Baldwin 
18285033c43bSJohn Baldwin 	/*
18295033c43bSJohn Baldwin 	 * dev.ccr.X.
18305033c43bSJohn Baldwin 	 */
18315033c43bSJohn Baldwin 	oid = device_get_sysctl_tree(sc->dev);
18325033c43bSJohn Baldwin 	children = SYSCTL_CHILDREN(oid);
18335033c43bSJohn Baldwin 
183494fad5ffSJohn Baldwin 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "port_mask", CTLFLAG_RW,
183594fad5ffSJohn Baldwin 	    &sc->port_mask, 0, "Mask of enabled ports");
183694fad5ffSJohn Baldwin 
18375033c43bSJohn Baldwin 	/*
18385033c43bSJohn Baldwin 	 * dev.ccr.X.stats.
18395033c43bSJohn Baldwin 	 */
18407029da5cSPawel Biernacki 	oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats",
18417029da5cSPawel Biernacki 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "statistics");
18425033c43bSJohn Baldwin 	children = SYSCTL_CHILDREN(oid);
18435033c43bSJohn Baldwin 
184494578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "hash", CTLFLAG_RD,
184594578db2SJohn Baldwin 	    &sc->stats_hash, "Hash requests submitted");
184694578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "hmac", CTLFLAG_RD,
184794578db2SJohn Baldwin 	    &sc->stats_hmac, "HMAC requests submitted");
184894578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "cipher_encrypt",
1849762f1dcbSJohn Baldwin 	    CTLFLAG_RD, &sc->stats_cipher_encrypt,
18505033c43bSJohn Baldwin 	    "Cipher encryption requests submitted");
185194578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "cipher_decrypt",
1852762f1dcbSJohn Baldwin 	    CTLFLAG_RD, &sc->stats_cipher_decrypt,
18535033c43bSJohn Baldwin 	    "Cipher decryption requests submitted");
185494578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "eta_encrypt",
185594578db2SJohn Baldwin 	    CTLFLAG_RD, &sc->stats_eta_encrypt,
18565033c43bSJohn Baldwin 	    "Combined AES+HMAC encryption requests submitted");
185794578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "eta_decrypt",
185894578db2SJohn Baldwin 	    CTLFLAG_RD, &sc->stats_eta_decrypt,
18595033c43bSJohn Baldwin 	    "Combined AES+HMAC decryption requests submitted");
186094578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "gcm_encrypt",
186194578db2SJohn Baldwin 	    CTLFLAG_RD, &sc->stats_gcm_encrypt,
186294578db2SJohn Baldwin 	    "AES-GCM encryption requests submitted");
186394578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "gcm_decrypt",
186494578db2SJohn Baldwin 	    CTLFLAG_RD, &sc->stats_gcm_decrypt,
186594578db2SJohn Baldwin 	    "AES-GCM decryption requests submitted");
186694578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "ccm_encrypt",
186794578db2SJohn Baldwin 	    CTLFLAG_RD, &sc->stats_ccm_encrypt,
186894578db2SJohn Baldwin 	    "AES-CCM encryption requests submitted");
186994578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "ccm_decrypt",
187094578db2SJohn Baldwin 	    CTLFLAG_RD, &sc->stats_ccm_decrypt,
187194578db2SJohn Baldwin 	    "AES-CCM decryption requests submitted");
187294578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "wr_nomem", CTLFLAG_RD,
187394578db2SJohn Baldwin 	    &sc->stats_wr_nomem, "Work request memory allocation failures");
187494578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "inflight", CTLFLAG_RD,
187594578db2SJohn Baldwin 	    &sc->stats_inflight, "Requests currently pending");
187694578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "mac_error", CTLFLAG_RD,
187794578db2SJohn Baldwin 	    &sc->stats_mac_error, "MAC errors");
187894578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "pad_error", CTLFLAG_RD,
187994578db2SJohn Baldwin 	    &sc->stats_pad_error, "Padding errors");
188094578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "sglist_error",
188194578db2SJohn Baldwin 	    CTLFLAG_RD, &sc->stats_sglist_error,
18822bd1e600SJohn Baldwin 	    "Requests for which DMA mapping failed");
188394578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "process_error",
188494578db2SJohn Baldwin 	    CTLFLAG_RD, &sc->stats_process_error,
188594578db2SJohn Baldwin 	    "Requests failed during queueing");
188694578db2SJohn Baldwin 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "sw_fallback",
188794578db2SJohn Baldwin 	    CTLFLAG_RD, &sc->stats_sw_fallback,
188804043b3dSJohn Baldwin 	    "Requests processed by falling back to software");
188994fad5ffSJohn Baldwin 
189094fad5ffSJohn Baldwin 	/*
189194fad5ffSJohn Baldwin 	 * dev.ccr.X.stats.port
189294fad5ffSJohn Baldwin 	 */
189394fad5ffSJohn Baldwin 	port_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "port",
189494fad5ffSJohn Baldwin 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Per-port statistics");
189594fad5ffSJohn Baldwin 
189694fad5ffSJohn Baldwin 	for (i = 0; i < nitems(sc->ports); i++) {
189794fad5ffSJohn Baldwin 		if (sc->ports[i].rxq == NULL)
189894fad5ffSJohn Baldwin 			continue;
189994fad5ffSJohn Baldwin 
190094fad5ffSJohn Baldwin 		/*
190194fad5ffSJohn Baldwin 		 * dev.ccr.X.stats.port.Y
190294fad5ffSJohn Baldwin 		 */
190394fad5ffSJohn Baldwin 		snprintf(buf, sizeof(buf), "%d", i);
190494fad5ffSJohn Baldwin 		oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(port_oid), OID_AUTO,
190594fad5ffSJohn Baldwin 		    buf, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, buf);
190694fad5ffSJohn Baldwin 		children = SYSCTL_CHILDREN(oid);
190794fad5ffSJohn Baldwin 
190894fad5ffSJohn Baldwin 		SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "active_sessions",
190994fad5ffSJohn Baldwin 		    CTLFLAG_RD, &sc->ports[i].active_sessions, 0,
191094fad5ffSJohn Baldwin 		    "Count of active sessions");
19119c5137beSJohn Baldwin 		SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "queued",
19129c5137beSJohn Baldwin 		    CTLFLAG_RD, &sc->ports[i].stats_queued, "Requests queued");
19139c5137beSJohn Baldwin 		SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "completed",
19149c5137beSJohn Baldwin 		    CTLFLAG_RD, &sc->ports[i].stats_completed,
19159c5137beSJohn Baldwin 		    "Requests completed");
191694fad5ffSJohn Baldwin 	}
191794fad5ffSJohn Baldwin }
191894fad5ffSJohn Baldwin 
191994fad5ffSJohn Baldwin static void
ccr_init_port(struct ccr_softc * sc,int port)192094fad5ffSJohn Baldwin ccr_init_port(struct ccr_softc *sc, int port)
192194fad5ffSJohn Baldwin {
19228f885fd1SJohn Baldwin 	struct port_info *pi;
192394fad5ffSJohn Baldwin 
19248f885fd1SJohn Baldwin 	pi = sc->adapter->port[port];
192594fad5ffSJohn Baldwin 	sc->ports[port].txq = &sc->adapter->sge.ctrlq[port];
19268f885fd1SJohn Baldwin 	sc->ports[port].rxq = &sc->adapter->sge.rxq[pi->vi->first_rxq];
1927480ff89cSNavdeep Parhar 	sc->ports[port].rx_channel_id = pi->rx_chan;
19288f885fd1SJohn Baldwin 	sc->ports[port].tx_channel_id = pi->tx_chan;
19299c5137beSJohn Baldwin 	sc->ports[port].stats_queued = counter_u64_alloc(M_WAITOK);
19309c5137beSJohn Baldwin 	sc->ports[port].stats_completed = counter_u64_alloc(M_WAITOK);
193194fad5ffSJohn Baldwin 	_Static_assert(sizeof(sc->port_mask) * NBBY >= MAX_NPORTS - 1,
193294fad5ffSJohn Baldwin 	    "Too many ports to fit in port_mask");
19335fe0cd65SJohn Baldwin 
19345fe0cd65SJohn Baldwin 	/*
19355fe0cd65SJohn Baldwin 	 * Completions for crypto requests on port 1 can sometimes
19365fe0cd65SJohn Baldwin 	 * return a stale cookie value due to a firmware bug.  Disable
19375fe0cd65SJohn Baldwin 	 * requests on port 1 by default on affected firmware.
19385fe0cd65SJohn Baldwin 	 */
19395fe0cd65SJohn Baldwin 	if (sc->adapter->params.fw_vers >= FW_VERSION32(1, 25, 4, 0) ||
19405fe0cd65SJohn Baldwin 	    port == 0)
194194fad5ffSJohn Baldwin 		sc->port_mask |= 1u << port;
19425033c43bSJohn Baldwin }
19435033c43bSJohn Baldwin 
19445033c43bSJohn Baldwin static int
ccr_attach(device_t dev)19455033c43bSJohn Baldwin ccr_attach(device_t dev)
19465033c43bSJohn Baldwin {
19475033c43bSJohn Baldwin 	struct ccr_softc *sc;
19485033c43bSJohn Baldwin 	int32_t cid;
194994fad5ffSJohn Baldwin 	int i;
19505033c43bSJohn Baldwin 
19515033c43bSJohn Baldwin 	sc = device_get_softc(dev);
19525033c43bSJohn Baldwin 	sc->dev = dev;
1953a727d953SNavdeep Parhar 	sysctl_ctx_init(&sc->ctx);
19545033c43bSJohn Baldwin 	sc->adapter = device_get_softc(device_get_parent(dev));
195594fad5ffSJohn Baldwin 	for_each_port(sc->adapter, i) {
195694fad5ffSJohn Baldwin 		ccr_init_port(sc, i);
195794fad5ffSJohn Baldwin 	}
19581b0909d5SConrad Meyer 	cid = crypto_get_driverid(dev, sizeof(struct ccr_session),
19591b0909d5SConrad Meyer 	    CRYPTOCAP_F_HARDWARE);
19605033c43bSJohn Baldwin 	if (cid < 0) {
19615033c43bSJohn Baldwin 		device_printf(dev, "could not get crypto driver id\n");
19625033c43bSJohn Baldwin 		return (ENXIO);
19635033c43bSJohn Baldwin 	}
19645033c43bSJohn Baldwin 	sc->cid = cid;
19655033c43bSJohn Baldwin 
19668f885fd1SJohn Baldwin 	/*
19678f885fd1SJohn Baldwin 	 * The FID must be the first RXQ for port 0 regardless of
19688f885fd1SJohn Baldwin 	 * which port is used to service the request.
19698f885fd1SJohn Baldwin 	 */
19708f885fd1SJohn Baldwin 	sc->first_rxq_id = sc->adapter->sge.rxq[0].iq.abs_id;
19718f885fd1SJohn Baldwin 
19725033c43bSJohn Baldwin 	mtx_init(&sc->lock, "ccr", NULL, MTX_DEF);
19735929c9fbSJohn Baldwin 	sc->iv_aad_buf = malloc(MAX_AAD_LEN, M_CCR, M_WAITOK);
19745929c9fbSJohn Baldwin 	sc->sg_iv_aad = sglist_build(sc->iv_aad_buf, MAX_AAD_LEN, M_WAITOK);
1975762f1dcbSJohn Baldwin 	sc->stats_cipher_encrypt = counter_u64_alloc(M_WAITOK);
1976762f1dcbSJohn Baldwin 	sc->stats_cipher_decrypt = counter_u64_alloc(M_WAITOK);
197794578db2SJohn Baldwin 	sc->stats_hash = counter_u64_alloc(M_WAITOK);
197894578db2SJohn Baldwin 	sc->stats_hmac = counter_u64_alloc(M_WAITOK);
197994578db2SJohn Baldwin 	sc->stats_eta_encrypt = counter_u64_alloc(M_WAITOK);
198094578db2SJohn Baldwin 	sc->stats_eta_decrypt = counter_u64_alloc(M_WAITOK);
198194578db2SJohn Baldwin 	sc->stats_gcm_encrypt = counter_u64_alloc(M_WAITOK);
198294578db2SJohn Baldwin 	sc->stats_gcm_decrypt = counter_u64_alloc(M_WAITOK);
198394578db2SJohn Baldwin 	sc->stats_ccm_encrypt = counter_u64_alloc(M_WAITOK);
198494578db2SJohn Baldwin 	sc->stats_ccm_decrypt = counter_u64_alloc(M_WAITOK);
198594578db2SJohn Baldwin 	sc->stats_wr_nomem = counter_u64_alloc(M_WAITOK);
198694578db2SJohn Baldwin 	sc->stats_inflight = counter_u64_alloc(M_WAITOK);
198794578db2SJohn Baldwin 	sc->stats_mac_error = counter_u64_alloc(M_WAITOK);
198894578db2SJohn Baldwin 	sc->stats_pad_error = counter_u64_alloc(M_WAITOK);
198994578db2SJohn Baldwin 	sc->stats_sglist_error = counter_u64_alloc(M_WAITOK);
199094578db2SJohn Baldwin 	sc->stats_process_error = counter_u64_alloc(M_WAITOK);
199194578db2SJohn Baldwin 	sc->stats_sw_fallback = counter_u64_alloc(M_WAITOK);
19925033c43bSJohn Baldwin 	ccr_sysctls(sc);
19935033c43bSJohn Baldwin 
19945033c43bSJohn Baldwin 	return (0);
19955033c43bSJohn Baldwin }
19965033c43bSJohn Baldwin 
19979c5137beSJohn Baldwin static void
ccr_free_port(struct ccr_softc * sc,int port)19989c5137beSJohn Baldwin ccr_free_port(struct ccr_softc *sc, int port)
19999c5137beSJohn Baldwin {
20009c5137beSJohn Baldwin 
20019c5137beSJohn Baldwin 	counter_u64_free(sc->ports[port].stats_queued);
20029c5137beSJohn Baldwin 	counter_u64_free(sc->ports[port].stats_completed);
20039c5137beSJohn Baldwin }
20049c5137beSJohn Baldwin 
20055033c43bSJohn Baldwin static int
ccr_detach(device_t dev)20065033c43bSJohn Baldwin ccr_detach(device_t dev)
20075033c43bSJohn Baldwin {
20085033c43bSJohn Baldwin 	struct ccr_softc *sc;
20099c5137beSJohn Baldwin 	int i;
20105033c43bSJohn Baldwin 
20115033c43bSJohn Baldwin 	sc = device_get_softc(dev);
20125033c43bSJohn Baldwin 
20135033c43bSJohn Baldwin 	mtx_lock(&sc->lock);
20145033c43bSJohn Baldwin 	sc->detaching = true;
20155033c43bSJohn Baldwin 	mtx_unlock(&sc->lock);
20165033c43bSJohn Baldwin 
20175033c43bSJohn Baldwin 	crypto_unregister_all(sc->cid);
20181b0909d5SConrad Meyer 
2019a727d953SNavdeep Parhar 	sysctl_ctx_free(&sc->ctx);
20205033c43bSJohn Baldwin 	mtx_destroy(&sc->lock);
2021762f1dcbSJohn Baldwin 	counter_u64_free(sc->stats_cipher_encrypt);
2022762f1dcbSJohn Baldwin 	counter_u64_free(sc->stats_cipher_decrypt);
202394578db2SJohn Baldwin 	counter_u64_free(sc->stats_hash);
202494578db2SJohn Baldwin 	counter_u64_free(sc->stats_hmac);
202594578db2SJohn Baldwin 	counter_u64_free(sc->stats_eta_encrypt);
202694578db2SJohn Baldwin 	counter_u64_free(sc->stats_eta_decrypt);
202794578db2SJohn Baldwin 	counter_u64_free(sc->stats_gcm_encrypt);
202894578db2SJohn Baldwin 	counter_u64_free(sc->stats_gcm_decrypt);
202994578db2SJohn Baldwin 	counter_u64_free(sc->stats_ccm_encrypt);
203094578db2SJohn Baldwin 	counter_u64_free(sc->stats_ccm_decrypt);
203194578db2SJohn Baldwin 	counter_u64_free(sc->stats_wr_nomem);
203294578db2SJohn Baldwin 	counter_u64_free(sc->stats_inflight);
203394578db2SJohn Baldwin 	counter_u64_free(sc->stats_mac_error);
203494578db2SJohn Baldwin 	counter_u64_free(sc->stats_pad_error);
203594578db2SJohn Baldwin 	counter_u64_free(sc->stats_sglist_error);
203694578db2SJohn Baldwin 	counter_u64_free(sc->stats_process_error);
203794578db2SJohn Baldwin 	counter_u64_free(sc->stats_sw_fallback);
20389c5137beSJohn Baldwin 	for_each_port(sc->adapter, i) {
20399c5137beSJohn Baldwin 		ccr_free_port(sc, i);
20409c5137beSJohn Baldwin 	}
20415929c9fbSJohn Baldwin 	sglist_free(sc->sg_iv_aad);
20425929c9fbSJohn Baldwin 	free(sc->iv_aad_buf, M_CCR);
20435033c43bSJohn Baldwin 	return (0);
20445033c43bSJohn Baldwin }
20455033c43bSJohn Baldwin 
20465033c43bSJohn Baldwin static void
ccr_init_hash_digest(struct ccr_session * s)2047c0341432SJohn Baldwin ccr_init_hash_digest(struct ccr_session *s)
2048567a3784SJohn Baldwin {
2049567a3784SJohn Baldwin 	union authctx auth_ctx;
2050d8787d4fSMark Johnston 	const struct auth_hash *axf;
2051567a3784SJohn Baldwin 
2052567a3784SJohn Baldwin 	axf = s->hmac.auth_hash;
2053567a3784SJohn Baldwin 	axf->Init(&auth_ctx);
2054c0341432SJohn Baldwin 	t4_copy_partial_hash(axf->type, &auth_ctx, s->hmac.pads);
20555033c43bSJohn Baldwin }
20565033c43bSJohn Baldwin 
2057c0341432SJohn Baldwin static bool
ccr_aes_check_keylen(int alg,int klen)20585033c43bSJohn Baldwin ccr_aes_check_keylen(int alg, int klen)
20595033c43bSJohn Baldwin {
20605033c43bSJohn Baldwin 
2061c0341432SJohn Baldwin 	switch (klen * 8) {
20625033c43bSJohn Baldwin 	case 128:
20635033c43bSJohn Baldwin 	case 192:
20645033c43bSJohn Baldwin 		if (alg == CRYPTO_AES_XTS)
2065c0341432SJohn Baldwin 			return (false);
20665033c43bSJohn Baldwin 		break;
20675033c43bSJohn Baldwin 	case 256:
20685033c43bSJohn Baldwin 		break;
20695033c43bSJohn Baldwin 	case 512:
20705033c43bSJohn Baldwin 		if (alg != CRYPTO_AES_XTS)
2071c0341432SJohn Baldwin 			return (false);
20725033c43bSJohn Baldwin 		break;
20735033c43bSJohn Baldwin 	default:
2074c0341432SJohn Baldwin 		return (false);
20755033c43bSJohn Baldwin 	}
2076c0341432SJohn Baldwin 	return (true);
20775033c43bSJohn Baldwin }
20785033c43bSJohn Baldwin 
20795033c43bSJohn Baldwin static void
ccr_aes_setkey(struct ccr_session * s,const void * key,int klen)2080c0341432SJohn Baldwin ccr_aes_setkey(struct ccr_session *s, const void *key, int klen)
20815033c43bSJohn Baldwin {
20825033c43bSJohn Baldwin 	unsigned int ck_size, iopad_size, kctx_flits, kctx_len, kbits, mk_size;
20835033c43bSJohn Baldwin 	unsigned int opad_present;
20845033c43bSJohn Baldwin 
2085762f1dcbSJohn Baldwin 	if (s->cipher.cipher_mode == SCMD_CIPH_MODE_AES_XTS)
2086c0341432SJohn Baldwin 		kbits = (klen / 2) * 8;
20875033c43bSJohn Baldwin 	else
2088c0341432SJohn Baldwin 		kbits = klen * 8;
20895033c43bSJohn Baldwin 	switch (kbits) {
20905033c43bSJohn Baldwin 	case 128:
20915033c43bSJohn Baldwin 		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
20925033c43bSJohn Baldwin 		break;
20935033c43bSJohn Baldwin 	case 192:
20945033c43bSJohn Baldwin 		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192;
20955033c43bSJohn Baldwin 		break;
20965033c43bSJohn Baldwin 	case 256:
20975033c43bSJohn Baldwin 		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
20985033c43bSJohn Baldwin 		break;
20995033c43bSJohn Baldwin 	default:
21005033c43bSJohn Baldwin 		panic("should not get here");
21015033c43bSJohn Baldwin 	}
21025033c43bSJohn Baldwin 
2103762f1dcbSJohn Baldwin 	s->cipher.key_len = klen;
2104762f1dcbSJohn Baldwin 	memcpy(s->cipher.enckey, key, s->cipher.key_len);
2105762f1dcbSJohn Baldwin 	switch (s->cipher.cipher_mode) {
2106c0341432SJohn Baldwin 	case SCMD_CIPH_MODE_AES_CBC:
2107c0341432SJohn Baldwin 	case SCMD_CIPH_MODE_AES_XTS:
2108762f1dcbSJohn Baldwin 		t4_aes_getdeckey(s->cipher.deckey, key, kbits);
21095033c43bSJohn Baldwin 		break;
21105033c43bSJohn Baldwin 	}
21115033c43bSJohn Baldwin 
2112762f1dcbSJohn Baldwin 	kctx_len = roundup2(s->cipher.key_len, 16);
21135033c43bSJohn Baldwin 	switch (s->mode) {
2114c0341432SJohn Baldwin 	case ETA:
21155033c43bSJohn Baldwin 		mk_size = s->hmac.mk_size;
21165033c43bSJohn Baldwin 		opad_present = 1;
21175033c43bSJohn Baldwin 		iopad_size = roundup2(s->hmac.partial_digest_len, 16);
21185033c43bSJohn Baldwin 		kctx_len += iopad_size * 2;
21195033c43bSJohn Baldwin 		break;
21205033c43bSJohn Baldwin 	case GCM:
21215033c43bSJohn Baldwin 		mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_128;
21225033c43bSJohn Baldwin 		opad_present = 0;
21235033c43bSJohn Baldwin 		kctx_len += GMAC_BLOCK_LEN;
21245033c43bSJohn Baldwin 		break;
21256b0451d6SJohn Baldwin 	case CCM:
21266b0451d6SJohn Baldwin 		switch (kbits) {
21276b0451d6SJohn Baldwin 		case 128:
21286b0451d6SJohn Baldwin 			mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_128;
21296b0451d6SJohn Baldwin 			break;
21306b0451d6SJohn Baldwin 		case 192:
21316b0451d6SJohn Baldwin 			mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_192;
21326b0451d6SJohn Baldwin 			break;
21336b0451d6SJohn Baldwin 		case 256:
21346b0451d6SJohn Baldwin 			mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256;
21356b0451d6SJohn Baldwin 			break;
21366b0451d6SJohn Baldwin 		default:
21376b0451d6SJohn Baldwin 			panic("should not get here");
21386b0451d6SJohn Baldwin 		}
21396b0451d6SJohn Baldwin 		opad_present = 0;
21406b0451d6SJohn Baldwin 		kctx_len *= 2;
21416b0451d6SJohn Baldwin 		break;
21425033c43bSJohn Baldwin 	default:
21435033c43bSJohn Baldwin 		mk_size = CHCR_KEYCTX_NO_KEY;
21445033c43bSJohn Baldwin 		opad_present = 0;
21455033c43bSJohn Baldwin 		break;
21465033c43bSJohn Baldwin 	}
21475033c43bSJohn Baldwin 	kctx_flits = (sizeof(struct _key_ctx) + kctx_len) / 16;
2148762f1dcbSJohn Baldwin 	s->cipher.key_ctx_hdr = htobe32(V_KEY_CONTEXT_CTX_LEN(kctx_flits) |
2149762f1dcbSJohn Baldwin 	    V_KEY_CONTEXT_DUAL_CK(s->cipher.cipher_mode ==
2150c0341432SJohn Baldwin 	    SCMD_CIPH_MODE_AES_XTS) |
21515033c43bSJohn Baldwin 	    V_KEY_CONTEXT_OPAD_PRESENT(opad_present) |
21525033c43bSJohn Baldwin 	    V_KEY_CONTEXT_SALT_PRESENT(1) | V_KEY_CONTEXT_CK_SIZE(ck_size) |
21535033c43bSJohn Baldwin 	    V_KEY_CONTEXT_MK_SIZE(mk_size) | V_KEY_CONTEXT_VALID(1));
21545033c43bSJohn Baldwin }
21555033c43bSJohn Baldwin 
2156c0341432SJohn Baldwin static bool
ccr_auth_supported(const struct crypto_session_params * csp)2157c0341432SJohn Baldwin ccr_auth_supported(const struct crypto_session_params *csp)
21585033c43bSJohn Baldwin {
21595033c43bSJohn Baldwin 
2160c0341432SJohn Baldwin 	switch (csp->csp_auth_alg) {
2161567a3784SJohn Baldwin 	case CRYPTO_SHA1:
2162567a3784SJohn Baldwin 	case CRYPTO_SHA2_224:
2163567a3784SJohn Baldwin 	case CRYPTO_SHA2_256:
2164567a3784SJohn Baldwin 	case CRYPTO_SHA2_384:
2165567a3784SJohn Baldwin 	case CRYPTO_SHA2_512:
21665033c43bSJohn Baldwin 	case CRYPTO_SHA1_HMAC:
21671146377bSJohn Baldwin 	case CRYPTO_SHA2_224_HMAC:
21685033c43bSJohn Baldwin 	case CRYPTO_SHA2_256_HMAC:
21695033c43bSJohn Baldwin 	case CRYPTO_SHA2_384_HMAC:
21705033c43bSJohn Baldwin 	case CRYPTO_SHA2_512_HMAC:
2171c0341432SJohn Baldwin 		break;
2172c0341432SJohn Baldwin 	default:
2173c0341432SJohn Baldwin 		return (false);
2174c0341432SJohn Baldwin 	}
2175c0341432SJohn Baldwin 	return (true);
2176c0341432SJohn Baldwin }
2177c0341432SJohn Baldwin 
2178c0341432SJohn Baldwin static bool
ccr_cipher_supported(const struct crypto_session_params * csp)2179c0341432SJohn Baldwin ccr_cipher_supported(const struct crypto_session_params *csp)
2180c0341432SJohn Baldwin {
2181c0341432SJohn Baldwin 
2182c0341432SJohn Baldwin 	switch (csp->csp_cipher_alg) {
2183c0341432SJohn Baldwin 	case CRYPTO_AES_CBC:
2184c0341432SJohn Baldwin 		if (csp->csp_ivlen != AES_BLOCK_LEN)
2185c0341432SJohn Baldwin 			return (false);
2186c0341432SJohn Baldwin 		break;
2187c0341432SJohn Baldwin 	case CRYPTO_AES_ICM:
2188c0341432SJohn Baldwin 		if (csp->csp_ivlen != AES_BLOCK_LEN)
2189c0341432SJohn Baldwin 			return (false);
2190c0341432SJohn Baldwin 		break;
2191c0341432SJohn Baldwin 	case CRYPTO_AES_XTS:
2192c0341432SJohn Baldwin 		if (csp->csp_ivlen != AES_XTS_IV_LEN)
2193c0341432SJohn Baldwin 			return (false);
2194c0341432SJohn Baldwin 		break;
2195c0341432SJohn Baldwin 	default:
2196c0341432SJohn Baldwin 		return (false);
2197c0341432SJohn Baldwin 	}
2198c0341432SJohn Baldwin 	return (ccr_aes_check_keylen(csp->csp_cipher_alg,
2199c0341432SJohn Baldwin 	    csp->csp_cipher_klen));
2200c0341432SJohn Baldwin }
2201c0341432SJohn Baldwin 
2202c0341432SJohn Baldwin static int
ccr_cipher_mode(const struct crypto_session_params * csp)2203c0341432SJohn Baldwin ccr_cipher_mode(const struct crypto_session_params *csp)
2204c0341432SJohn Baldwin {
2205c0341432SJohn Baldwin 
2206c0341432SJohn Baldwin 	switch (csp->csp_cipher_alg) {
2207c0341432SJohn Baldwin 	case CRYPTO_AES_CBC:
2208c0341432SJohn Baldwin 		return (SCMD_CIPH_MODE_AES_CBC);
2209c0341432SJohn Baldwin 	case CRYPTO_AES_ICM:
2210c0341432SJohn Baldwin 		return (SCMD_CIPH_MODE_AES_CTR);
2211c0341432SJohn Baldwin 	case CRYPTO_AES_NIST_GCM_16:
2212c0341432SJohn Baldwin 		return (SCMD_CIPH_MODE_AES_GCM);
2213c0341432SJohn Baldwin 	case CRYPTO_AES_XTS:
2214c0341432SJohn Baldwin 		return (SCMD_CIPH_MODE_AES_XTS);
2215c0341432SJohn Baldwin 	case CRYPTO_AES_CCM_16:
2216c0341432SJohn Baldwin 		return (SCMD_CIPH_MODE_AES_CCM);
2217c0341432SJohn Baldwin 	default:
2218c0341432SJohn Baldwin 		return (SCMD_CIPH_MODE_NOP);
2219c0341432SJohn Baldwin 	}
2220c0341432SJohn Baldwin }
2221c0341432SJohn Baldwin 
2222c0341432SJohn Baldwin static int
ccr_probesession(device_t dev,const struct crypto_session_params * csp)2223c0341432SJohn Baldwin ccr_probesession(device_t dev, const struct crypto_session_params *csp)
2224c0341432SJohn Baldwin {
2225c0341432SJohn Baldwin 	unsigned int cipher_mode;
2226c0341432SJohn Baldwin 
22276deb4131SJohn Baldwin 	if ((csp->csp_flags & ~(CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD)) !=
22286deb4131SJohn Baldwin 	    0)
22295033c43bSJohn Baldwin 		return (EINVAL);
2230c0341432SJohn Baldwin 	switch (csp->csp_mode) {
2231c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
2232c0341432SJohn Baldwin 		if (!ccr_auth_supported(csp))
2233c0341432SJohn Baldwin 			return (EINVAL);
2234c0341432SJohn Baldwin 		break;
2235c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
2236c0341432SJohn Baldwin 		if (!ccr_cipher_supported(csp))
2237c0341432SJohn Baldwin 			return (EINVAL);
2238c0341432SJohn Baldwin 		break;
2239c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
2240c0341432SJohn Baldwin 		switch (csp->csp_cipher_alg) {
2241c0341432SJohn Baldwin 		case CRYPTO_AES_NIST_GCM_16:
2242c0341432SJohn Baldwin 		case CRYPTO_AES_CCM_16:
2243c0341432SJohn Baldwin 			break;
2244c0341432SJohn Baldwin 		default:
2245c0341432SJohn Baldwin 			return (EINVAL);
2246c0341432SJohn Baldwin 		}
2247c0341432SJohn Baldwin 		break;
2248c0341432SJohn Baldwin 	case CSP_MODE_ETA:
2249c0341432SJohn Baldwin 		if (!ccr_auth_supported(csp) || !ccr_cipher_supported(csp))
2250c0341432SJohn Baldwin 			return (EINVAL);
2251c0341432SJohn Baldwin 		break;
2252c0341432SJohn Baldwin 	default:
2253c0341432SJohn Baldwin 		return (EINVAL);
2254c0341432SJohn Baldwin 	}
2255c0341432SJohn Baldwin 
2256c0341432SJohn Baldwin 	if (csp->csp_cipher_klen != 0) {
2257c0341432SJohn Baldwin 		cipher_mode = ccr_cipher_mode(csp);
2258c0341432SJohn Baldwin 		if (cipher_mode == SCMD_CIPH_MODE_NOP)
2259c0341432SJohn Baldwin 			return (EINVAL);
2260c0341432SJohn Baldwin 	}
2261c0341432SJohn Baldwin 
2262c0341432SJohn Baldwin 	return (CRYPTODEV_PROBE_HARDWARE);
2263c0341432SJohn Baldwin }
2264c0341432SJohn Baldwin 
226594fad5ffSJohn Baldwin /*
226694fad5ffSJohn Baldwin  * Select an available port with the lowest number of active sessions.
226794fad5ffSJohn Baldwin  */
226894fad5ffSJohn Baldwin static struct ccr_port *
ccr_choose_port(struct ccr_softc * sc)226994fad5ffSJohn Baldwin ccr_choose_port(struct ccr_softc *sc)
227094fad5ffSJohn Baldwin {
227194fad5ffSJohn Baldwin 	struct ccr_port *best, *p;
227294fad5ffSJohn Baldwin 	int i;
227394fad5ffSJohn Baldwin 
227494fad5ffSJohn Baldwin 	mtx_assert(&sc->lock, MA_OWNED);
227594fad5ffSJohn Baldwin 	best = NULL;
227694fad5ffSJohn Baldwin 	for (i = 0; i < nitems(sc->ports); i++) {
227794fad5ffSJohn Baldwin 		p = &sc->ports[i];
227894fad5ffSJohn Baldwin 
227994fad5ffSJohn Baldwin 		/* Ignore non-existent ports. */
228094fad5ffSJohn Baldwin 		if (p->rxq == NULL)
228194fad5ffSJohn Baldwin 			continue;
228294fad5ffSJohn Baldwin 
228394fad5ffSJohn Baldwin 		/*
228494fad5ffSJohn Baldwin 		 * XXX: Ignore ports whose queues aren't initialized.
228594fad5ffSJohn Baldwin 		 * This is racy as the rxq can be destroyed by the
228694fad5ffSJohn Baldwin 		 * associated VI detaching.  Eventually ccr should use
228794fad5ffSJohn Baldwin 		 * dedicated queues.
228894fad5ffSJohn Baldwin 		 */
228994fad5ffSJohn Baldwin 		if (p->rxq->iq.adapter == NULL || p->txq->adapter == NULL)
229094fad5ffSJohn Baldwin 			continue;
229194fad5ffSJohn Baldwin 
229294fad5ffSJohn Baldwin 		if ((sc->port_mask & (1u << i)) == 0)
229394fad5ffSJohn Baldwin 			continue;
229494fad5ffSJohn Baldwin 
229594fad5ffSJohn Baldwin 		if (best == NULL ||
229694fad5ffSJohn Baldwin 		    p->active_sessions < best->active_sessions)
229794fad5ffSJohn Baldwin 			best = p;
229894fad5ffSJohn Baldwin 	}
229994fad5ffSJohn Baldwin 	return (best);
230094fad5ffSJohn Baldwin }
230194fad5ffSJohn Baldwin 
230294578db2SJohn Baldwin static void
ccr_delete_session(struct ccr_session * s)230394578db2SJohn Baldwin ccr_delete_session(struct ccr_session *s)
230494578db2SJohn Baldwin {
2305e43cf698SJohn Baldwin 	crypto_freesession(s->sw_session);
230694578db2SJohn Baldwin 	sglist_free(s->sg_input);
230794578db2SJohn Baldwin 	sglist_free(s->sg_output);
230894578db2SJohn Baldwin 	sglist_free(s->sg_ulptx);
230994578db2SJohn Baldwin 	sglist_free(s->sg_dsgl);
231094578db2SJohn Baldwin 	mtx_destroy(&s->lock);
231194578db2SJohn Baldwin }
231294578db2SJohn Baldwin 
2313c0341432SJohn Baldwin static int
ccr_newsession(device_t dev,crypto_session_t cses,const struct crypto_session_params * csp)2314c0341432SJohn Baldwin ccr_newsession(device_t dev, crypto_session_t cses,
2315c0341432SJohn Baldwin     const struct crypto_session_params *csp)
2316c0341432SJohn Baldwin {
2317c0341432SJohn Baldwin 	struct ccr_softc *sc;
2318c0341432SJohn Baldwin 	struct ccr_session *s;
2319d8787d4fSMark Johnston 	const struct auth_hash *auth_hash;
2320c0341432SJohn Baldwin 	unsigned int auth_mode, cipher_mode, mk_size;
2321c0341432SJohn Baldwin 	unsigned int partial_digest_len;
2322e43cf698SJohn Baldwin 	int error;
2323c0341432SJohn Baldwin 
2324c0341432SJohn Baldwin 	switch (csp->csp_auth_alg) {
2325567a3784SJohn Baldwin 	case CRYPTO_SHA1:
23265033c43bSJohn Baldwin 	case CRYPTO_SHA1_HMAC:
23275033c43bSJohn Baldwin 		auth_hash = &auth_hash_hmac_sha1;
2328d09389fdSJohn Baldwin 		auth_mode = SCMD_AUTH_MODE_SHA1;
23295033c43bSJohn Baldwin 		mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_160;
23305033c43bSJohn Baldwin 		partial_digest_len = SHA1_HASH_LEN;
23315033c43bSJohn Baldwin 		break;
2332567a3784SJohn Baldwin 	case CRYPTO_SHA2_224:
23331146377bSJohn Baldwin 	case CRYPTO_SHA2_224_HMAC:
23341146377bSJohn Baldwin 		auth_hash = &auth_hash_hmac_sha2_224;
2335d09389fdSJohn Baldwin 		auth_mode = SCMD_AUTH_MODE_SHA224;
23361146377bSJohn Baldwin 		mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256;
23371146377bSJohn Baldwin 		partial_digest_len = SHA2_256_HASH_LEN;
23381146377bSJohn Baldwin 		break;
2339567a3784SJohn Baldwin 	case CRYPTO_SHA2_256:
23405033c43bSJohn Baldwin 	case CRYPTO_SHA2_256_HMAC:
23415033c43bSJohn Baldwin 		auth_hash = &auth_hash_hmac_sha2_256;
2342d09389fdSJohn Baldwin 		auth_mode = SCMD_AUTH_MODE_SHA256;
23435033c43bSJohn Baldwin 		mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256;
23445033c43bSJohn Baldwin 		partial_digest_len = SHA2_256_HASH_LEN;
23455033c43bSJohn Baldwin 		break;
2346567a3784SJohn Baldwin 	case CRYPTO_SHA2_384:
23475033c43bSJohn Baldwin 	case CRYPTO_SHA2_384_HMAC:
23485033c43bSJohn Baldwin 		auth_hash = &auth_hash_hmac_sha2_384;
2349d09389fdSJohn Baldwin 		auth_mode = SCMD_AUTH_MODE_SHA512_384;
23505033c43bSJohn Baldwin 		mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_512;
23515033c43bSJohn Baldwin 		partial_digest_len = SHA2_512_HASH_LEN;
23525033c43bSJohn Baldwin 		break;
2353567a3784SJohn Baldwin 	case CRYPTO_SHA2_512:
23545033c43bSJohn Baldwin 	case CRYPTO_SHA2_512_HMAC:
23555033c43bSJohn Baldwin 		auth_hash = &auth_hash_hmac_sha2_512;
2356d09389fdSJohn Baldwin 		auth_mode = SCMD_AUTH_MODE_SHA512_512;
23575033c43bSJohn Baldwin 		mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_512;
23585033c43bSJohn Baldwin 		partial_digest_len = SHA2_512_HASH_LEN;
23595033c43bSJohn Baldwin 		break;
2360c0341432SJohn Baldwin 	default:
2361c0341432SJohn Baldwin 		auth_hash = NULL;
2362c0341432SJohn Baldwin 		auth_mode = SCMD_AUTH_MODE_NOP;
2363c0341432SJohn Baldwin 		mk_size = 0;
2364c0341432SJohn Baldwin 		partial_digest_len = 0;
23656b0451d6SJohn Baldwin 		break;
23665033c43bSJohn Baldwin 	}
2367c0341432SJohn Baldwin 
2368c0341432SJohn Baldwin 	cipher_mode = ccr_cipher_mode(csp);
2369c0341432SJohn Baldwin 
2370c0341432SJohn Baldwin #ifdef INVARIANTS
2371c0341432SJohn Baldwin 	switch (csp->csp_mode) {
2372c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
2373c0341432SJohn Baldwin 		if (cipher_mode == SCMD_CIPH_MODE_NOP ||
2374c0341432SJohn Baldwin 		    cipher_mode == SCMD_CIPH_MODE_AES_GCM ||
2375c0341432SJohn Baldwin 		    cipher_mode == SCMD_CIPH_MODE_AES_CCM)
2376c0341432SJohn Baldwin 			panic("invalid cipher algo");
2377567a3784SJohn Baldwin 		break;
2378c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
2379c0341432SJohn Baldwin 		if (auth_mode == SCMD_AUTH_MODE_NOP)
2380c0341432SJohn Baldwin 			panic("invalid auth algo");
23815033c43bSJohn Baldwin 		break;
2382c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
2383c0341432SJohn Baldwin 		if (cipher_mode != SCMD_CIPH_MODE_AES_GCM &&
2384c0341432SJohn Baldwin 		    cipher_mode != SCMD_CIPH_MODE_AES_CCM)
2385c0341432SJohn Baldwin 			panic("invalid aead cipher algo");
2386c0341432SJohn Baldwin 		if (auth_mode != SCMD_AUTH_MODE_NOP)
2387c0341432SJohn Baldwin 			panic("invalid aead auth aglo");
23885033c43bSJohn Baldwin 		break;
2389c0341432SJohn Baldwin 	case CSP_MODE_ETA:
2390c0341432SJohn Baldwin 		if (cipher_mode == SCMD_CIPH_MODE_NOP ||
2391c0341432SJohn Baldwin 		    cipher_mode == SCMD_CIPH_MODE_AES_GCM ||
2392c0341432SJohn Baldwin 		    cipher_mode == SCMD_CIPH_MODE_AES_CCM)
2393c0341432SJohn Baldwin 			panic("invalid cipher algo");
2394c0341432SJohn Baldwin 		if (auth_mode == SCMD_AUTH_MODE_NOP)
2395c0341432SJohn Baldwin 			panic("invalid auth algo");
23965033c43bSJohn Baldwin 		break;
23975033c43bSJohn Baldwin 	default:
2398c0341432SJohn Baldwin 		panic("invalid csp mode");
23995033c43bSJohn Baldwin 	}
2400c0341432SJohn Baldwin #endif
24015033c43bSJohn Baldwin 
240294578db2SJohn Baldwin 	s = crypto_get_driver_session(cses);
240394578db2SJohn Baldwin 	mtx_init(&s->lock, "ccr session", NULL, MTX_DEF);
240494578db2SJohn Baldwin 	s->sg_input = sglist_alloc(TX_SGL_SEGS, M_NOWAIT);
240594578db2SJohn Baldwin 	s->sg_output = sglist_alloc(TX_SGL_SEGS, M_NOWAIT);
240694578db2SJohn Baldwin 	s->sg_ulptx = sglist_alloc(TX_SGL_SEGS, M_NOWAIT);
240794578db2SJohn Baldwin 	s->sg_dsgl = sglist_alloc(MAX_RX_PHYS_DSGL_SGE, M_NOWAIT);
240894578db2SJohn Baldwin 	if (s->sg_input == NULL || s->sg_output == NULL ||
240994578db2SJohn Baldwin 	    s->sg_ulptx == NULL || s->sg_dsgl == NULL) {
241094578db2SJohn Baldwin 		ccr_delete_session(s);
241194578db2SJohn Baldwin 		return (ENOMEM);
241294578db2SJohn Baldwin 	}
241394578db2SJohn Baldwin 
2414e43cf698SJohn Baldwin 	if (csp->csp_mode == CSP_MODE_AEAD) {
2415e43cf698SJohn Baldwin 		error = crypto_newsession(&s->sw_session, csp,
2416e43cf698SJohn Baldwin 		    CRYPTOCAP_F_SOFTWARE);
2417e43cf698SJohn Baldwin 		if (error) {
2418e43cf698SJohn Baldwin 			ccr_delete_session(s);
2419e43cf698SJohn Baldwin 			return (error);
2420e43cf698SJohn Baldwin 		}
2421e43cf698SJohn Baldwin 	}
2422e43cf698SJohn Baldwin 
24235033c43bSJohn Baldwin 	sc = device_get_softc(dev);
24247063b997SJohn Baldwin 	s->sc = sc;
2425475d54faSJohn Baldwin 
24265033c43bSJohn Baldwin 	mtx_lock(&sc->lock);
24275033c43bSJohn Baldwin 	if (sc->detaching) {
24285033c43bSJohn Baldwin 		mtx_unlock(&sc->lock);
242994578db2SJohn Baldwin 		ccr_delete_session(s);
24305033c43bSJohn Baldwin 		return (ENXIO);
24315033c43bSJohn Baldwin 	}
24325033c43bSJohn Baldwin 
243394fad5ffSJohn Baldwin 	s->port = ccr_choose_port(sc);
243494fad5ffSJohn Baldwin 	if (s->port == NULL) {
243594fad5ffSJohn Baldwin 		mtx_unlock(&sc->lock);
243694578db2SJohn Baldwin 		ccr_delete_session(s);
243794fad5ffSJohn Baldwin 		return (ENXIO);
243894fad5ffSJohn Baldwin 	}
24395033c43bSJohn Baldwin 
2440c0341432SJohn Baldwin 	switch (csp->csp_mode) {
2441c0341432SJohn Baldwin 	case CSP_MODE_AEAD:
2442c0341432SJohn Baldwin 		if (cipher_mode == SCMD_CIPH_MODE_AES_CCM)
24436b0451d6SJohn Baldwin 			s->mode = CCM;
2444c0341432SJohn Baldwin 		else
2445c0341432SJohn Baldwin 			s->mode = GCM;
2446c0341432SJohn Baldwin 		break;
2447c0341432SJohn Baldwin 	case CSP_MODE_ETA:
2448c0341432SJohn Baldwin 		s->mode = ETA;
2449c0341432SJohn Baldwin 		break;
2450c0341432SJohn Baldwin 	case CSP_MODE_DIGEST:
2451c0341432SJohn Baldwin 		if (csp->csp_auth_klen != 0)
24525033c43bSJohn Baldwin 			s->mode = HMAC;
2453567a3784SJohn Baldwin 		else
2454567a3784SJohn Baldwin 			s->mode = HASH;
2455c0341432SJohn Baldwin 		break;
2456c0341432SJohn Baldwin 	case CSP_MODE_CIPHER:
2457762f1dcbSJohn Baldwin 		s->mode = CIPHER;
2458c0341432SJohn Baldwin 		break;
24595033c43bSJohn Baldwin 	}
2460c0341432SJohn Baldwin 
2461c0341432SJohn Baldwin 	if (s->mode == GCM) {
2462c0341432SJohn Baldwin 		if (csp->csp_auth_mlen == 0)
24635033c43bSJohn Baldwin 			s->gmac.hash_len = AES_GMAC_HASH_LEN;
24645033c43bSJohn Baldwin 		else
2465c0341432SJohn Baldwin 			s->gmac.hash_len = csp->csp_auth_mlen;
2466c0341432SJohn Baldwin 		t4_init_gmac_hash(csp->csp_cipher_key, csp->csp_cipher_klen,
2467a1b2b6e1SJohn Baldwin 		    s->gmac.ghash_h);
2468c0341432SJohn Baldwin 	} else if (s->mode == CCM) {
2469c0341432SJohn Baldwin 		if (csp->csp_auth_mlen == 0)
24706b0451d6SJohn Baldwin 			s->ccm_mac.hash_len = AES_CBC_MAC_HASH_LEN;
24716b0451d6SJohn Baldwin 		else
2472c0341432SJohn Baldwin 			s->ccm_mac.hash_len = csp->csp_auth_mlen;
2473c0341432SJohn Baldwin 	} else if (auth_mode != SCMD_AUTH_MODE_NOP) {
24745033c43bSJohn Baldwin 		s->hmac.auth_hash = auth_hash;
24755033c43bSJohn Baldwin 		s->hmac.auth_mode = auth_mode;
24765033c43bSJohn Baldwin 		s->hmac.mk_size = mk_size;
24775033c43bSJohn Baldwin 		s->hmac.partial_digest_len = partial_digest_len;
2478c0341432SJohn Baldwin 		if (csp->csp_auth_mlen == 0)
24795033c43bSJohn Baldwin 			s->hmac.hash_len = auth_hash->hashsize;
24805033c43bSJohn Baldwin 		else
2481c0341432SJohn Baldwin 			s->hmac.hash_len = csp->csp_auth_mlen;
2482c0341432SJohn Baldwin 		if (csp->csp_auth_key != NULL)
2483a1b2b6e1SJohn Baldwin 			t4_init_hmac_digest(auth_hash, partial_digest_len,
2484c0341432SJohn Baldwin 			    csp->csp_auth_key, csp->csp_auth_klen,
2485c0341432SJohn Baldwin 			    s->hmac.pads);
2486567a3784SJohn Baldwin 		else
2487c0341432SJohn Baldwin 			ccr_init_hash_digest(s);
24885033c43bSJohn Baldwin 	}
2489c0341432SJohn Baldwin 	if (cipher_mode != SCMD_CIPH_MODE_NOP) {
2490762f1dcbSJohn Baldwin 		s->cipher.cipher_mode = cipher_mode;
2491762f1dcbSJohn Baldwin 		s->cipher.iv_len = csp->csp_ivlen;
2492c0341432SJohn Baldwin 		if (csp->csp_cipher_key != NULL)
2493c0341432SJohn Baldwin 			ccr_aes_setkey(s, csp->csp_cipher_key,
2494c0341432SJohn Baldwin 			    csp->csp_cipher_klen);
24955033c43bSJohn Baldwin 	}
24965033c43bSJohn Baldwin 
249794fad5ffSJohn Baldwin 	s->port->active_sessions++;
24985033c43bSJohn Baldwin 	mtx_unlock(&sc->lock);
24995033c43bSJohn Baldwin 	return (0);
25005033c43bSJohn Baldwin }
25015033c43bSJohn Baldwin 
25021b0909d5SConrad Meyer static void
ccr_freesession(device_t dev,crypto_session_t cses)25031b0909d5SConrad Meyer ccr_freesession(device_t dev, crypto_session_t cses)
25045033c43bSJohn Baldwin {
25055033c43bSJohn Baldwin 	struct ccr_softc *sc;
25061b0909d5SConrad Meyer 	struct ccr_session *s;
25075033c43bSJohn Baldwin 
25085033c43bSJohn Baldwin 	sc = device_get_softc(dev);
25091b0909d5SConrad Meyer 	s = crypto_get_driver_session(cses);
251094578db2SJohn Baldwin #ifdef INVARIANTS
25111b0909d5SConrad Meyer 	if (s->pending != 0)
25125033c43bSJohn Baldwin 		device_printf(dev,
25131b0909d5SConrad Meyer 		    "session %p freed with %d pending requests\n", s,
25141b0909d5SConrad Meyer 		    s->pending);
251594578db2SJohn Baldwin #endif
251694578db2SJohn Baldwin 	mtx_lock(&sc->lock);
251794fad5ffSJohn Baldwin 	s->port->active_sessions--;
25185033c43bSJohn Baldwin 	mtx_unlock(&sc->lock);
251994578db2SJohn Baldwin 	ccr_delete_session(s);
25205033c43bSJohn Baldwin }
25215033c43bSJohn Baldwin 
25225033c43bSJohn Baldwin static int
ccr_process(device_t dev,struct cryptop * crp,int hint)25235033c43bSJohn Baldwin ccr_process(device_t dev, struct cryptop *crp, int hint)
25245033c43bSJohn Baldwin {
2525c0341432SJohn Baldwin 	const struct crypto_session_params *csp;
25265033c43bSJohn Baldwin 	struct ccr_softc *sc;
25275033c43bSJohn Baldwin 	struct ccr_session *s;
25285033c43bSJohn Baldwin 	int error;
25295033c43bSJohn Baldwin 
2530c0341432SJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
25311b0909d5SConrad Meyer 	s = crypto_get_driver_session(crp->crp_session);
25325033c43bSJohn Baldwin 	sc = device_get_softc(dev);
25335033c43bSJohn Baldwin 
253494578db2SJohn Baldwin 	mtx_lock(&s->lock);
253594578db2SJohn Baldwin 	error = ccr_populate_sglist(s->sg_input, &crp->crp_buf);
25362adc3c94SJohn Baldwin 	if (error == 0 && CRYPTO_HAS_OUTPUT_BUFFER(crp))
253794578db2SJohn Baldwin 		error = ccr_populate_sglist(s->sg_output, &crp->crp_obuf);
25385033c43bSJohn Baldwin 	if (error) {
253994578db2SJohn Baldwin 		counter_u64_add(sc->stats_sglist_error, 1);
25405033c43bSJohn Baldwin 		goto out;
25415033c43bSJohn Baldwin 	}
25425033c43bSJohn Baldwin 
25435033c43bSJohn Baldwin 	switch (s->mode) {
2544567a3784SJohn Baldwin 	case HASH:
2545567a3784SJohn Baldwin 		error = ccr_hash(sc, s, crp);
2546567a3784SJohn Baldwin 		if (error == 0)
254794578db2SJohn Baldwin 			counter_u64_add(sc->stats_hash, 1);
2548567a3784SJohn Baldwin 		break;
25495033c43bSJohn Baldwin 	case HMAC:
2550c0341432SJohn Baldwin 		if (crp->crp_auth_key != NULL)
2551a1b2b6e1SJohn Baldwin 			t4_init_hmac_digest(s->hmac.auth_hash,
2552c0341432SJohn Baldwin 			    s->hmac.partial_digest_len, crp->crp_auth_key,
2553c0341432SJohn Baldwin 			    csp->csp_auth_klen, s->hmac.pads);
2554567a3784SJohn Baldwin 		error = ccr_hash(sc, s, crp);
25555033c43bSJohn Baldwin 		if (error == 0)
255694578db2SJohn Baldwin 			counter_u64_add(sc->stats_hmac, 1);
25575033c43bSJohn Baldwin 		break;
2558762f1dcbSJohn Baldwin 	case CIPHER:
2559c0341432SJohn Baldwin 		if (crp->crp_cipher_key != NULL)
2560c0341432SJohn Baldwin 			ccr_aes_setkey(s, crp->crp_cipher_key,
2561c0341432SJohn Baldwin 			    csp->csp_cipher_klen);
2562762f1dcbSJohn Baldwin 		error = ccr_cipher(sc, s, crp);
25635033c43bSJohn Baldwin 		if (error == 0) {
2564c0341432SJohn Baldwin 			if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
2565762f1dcbSJohn Baldwin 				counter_u64_add(sc->stats_cipher_encrypt, 1);
25665033c43bSJohn Baldwin 			else
2567762f1dcbSJohn Baldwin 				counter_u64_add(sc->stats_cipher_decrypt, 1);
25685033c43bSJohn Baldwin 		}
25695033c43bSJohn Baldwin 		break;
2570c0341432SJohn Baldwin 	case ETA:
2571c0341432SJohn Baldwin 		if (crp->crp_auth_key != NULL)
2572a1b2b6e1SJohn Baldwin 			t4_init_hmac_digest(s->hmac.auth_hash,
2573c0341432SJohn Baldwin 			    s->hmac.partial_digest_len, crp->crp_auth_key,
2574c0341432SJohn Baldwin 			    csp->csp_auth_klen, s->hmac.pads);
2575c0341432SJohn Baldwin 		if (crp->crp_cipher_key != NULL)
2576c0341432SJohn Baldwin 			ccr_aes_setkey(s, crp->crp_cipher_key,
2577c0341432SJohn Baldwin 			    csp->csp_cipher_klen);
2578c0341432SJohn Baldwin 		error = ccr_eta(sc, s, crp);
25795033c43bSJohn Baldwin 		if (error == 0) {
2580c0341432SJohn Baldwin 			if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
258194578db2SJohn Baldwin 				counter_u64_add(sc->stats_eta_encrypt, 1);
25825033c43bSJohn Baldwin 			else
258394578db2SJohn Baldwin 				counter_u64_add(sc->stats_eta_decrypt, 1);
25845033c43bSJohn Baldwin 		}
25855033c43bSJohn Baldwin 		break;
25865033c43bSJohn Baldwin 	case GCM:
2587c0341432SJohn Baldwin 		if (crp->crp_cipher_key != NULL) {
2588c0341432SJohn Baldwin 			t4_init_gmac_hash(crp->crp_cipher_key,
2589c0341432SJohn Baldwin 			    csp->csp_cipher_klen, s->gmac.ghash_h);
2590c0341432SJohn Baldwin 			ccr_aes_setkey(s, crp->crp_cipher_key,
2591c0341432SJohn Baldwin 			    csp->csp_cipher_klen);
25925033c43bSJohn Baldwin 		}
2593c0341432SJohn Baldwin 		error = ccr_gcm(sc, s, crp);
25940e993396SJohn Baldwin 		if (error == EMSGSIZE || error == EFBIG) {
259594578db2SJohn Baldwin 			counter_u64_add(sc->stats_sw_fallback, 1);
259694578db2SJohn Baldwin 			mtx_unlock(&s->lock);
2597e43cf698SJohn Baldwin 			ccr_soft(s, crp);
259804043b3dSJohn Baldwin 			return (0);
259904043b3dSJohn Baldwin 		}
26005033c43bSJohn Baldwin 		if (error == 0) {
2601c0341432SJohn Baldwin 			if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
260294578db2SJohn Baldwin 				counter_u64_add(sc->stats_gcm_encrypt, 1);
26035033c43bSJohn Baldwin 			else
260494578db2SJohn Baldwin 				counter_u64_add(sc->stats_gcm_decrypt, 1);
26055033c43bSJohn Baldwin 		}
26065033c43bSJohn Baldwin 		break;
26076b0451d6SJohn Baldwin 	case CCM:
2608c0341432SJohn Baldwin 		if (crp->crp_cipher_key != NULL) {
2609c0341432SJohn Baldwin 			ccr_aes_setkey(s, crp->crp_cipher_key,
2610c0341432SJohn Baldwin 			    csp->csp_cipher_klen);
26116b0451d6SJohn Baldwin 		}
2612c0341432SJohn Baldwin 		error = ccr_ccm(sc, s, crp);
26130e993396SJohn Baldwin 		if (error == EMSGSIZE || error == EFBIG) {
261494578db2SJohn Baldwin 			counter_u64_add(sc->stats_sw_fallback, 1);
261594578db2SJohn Baldwin 			mtx_unlock(&s->lock);
2616e43cf698SJohn Baldwin 			ccr_soft(s, crp);
26176b0451d6SJohn Baldwin 			return (0);
26186b0451d6SJohn Baldwin 		}
26196b0451d6SJohn Baldwin 		if (error == 0) {
2620c0341432SJohn Baldwin 			if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
262194578db2SJohn Baldwin 				counter_u64_add(sc->stats_ccm_encrypt, 1);
26226b0451d6SJohn Baldwin 			else
262394578db2SJohn Baldwin 				counter_u64_add(sc->stats_ccm_decrypt, 1);
26246b0451d6SJohn Baldwin 		}
26256b0451d6SJohn Baldwin 		break;
26265033c43bSJohn Baldwin 	}
26275033c43bSJohn Baldwin 
26285033c43bSJohn Baldwin 	if (error == 0) {
262994578db2SJohn Baldwin #ifdef INVARIANTS
26305033c43bSJohn Baldwin 		s->pending++;
263194578db2SJohn Baldwin #endif
263294578db2SJohn Baldwin 		counter_u64_add(sc->stats_inflight, 1);
26339c5137beSJohn Baldwin 		counter_u64_add(s->port->stats_queued, 1);
26345033c43bSJohn Baldwin 	} else
263594578db2SJohn Baldwin 		counter_u64_add(sc->stats_process_error, 1);
26365033c43bSJohn Baldwin 
26375033c43bSJohn Baldwin out:
263894578db2SJohn Baldwin 	mtx_unlock(&s->lock);
26395033c43bSJohn Baldwin 
26405033c43bSJohn Baldwin 	if (error) {
26415033c43bSJohn Baldwin 		crp->crp_etype = error;
26425033c43bSJohn Baldwin 		crypto_done(crp);
26435033c43bSJohn Baldwin 	}
26445033c43bSJohn Baldwin 
26455033c43bSJohn Baldwin 	return (0);
26465033c43bSJohn Baldwin }
26475033c43bSJohn Baldwin 
26485033c43bSJohn Baldwin static int
do_cpl6_fw_pld(struct sge_iq * iq,const struct rss_header * rss,struct mbuf * m)26495033c43bSJohn Baldwin do_cpl6_fw_pld(struct sge_iq *iq, const struct rss_header *rss,
26505033c43bSJohn Baldwin     struct mbuf *m)
26515033c43bSJohn Baldwin {
26527063b997SJohn Baldwin 	struct ccr_softc *sc;
26535033c43bSJohn Baldwin 	struct ccr_session *s;
26545033c43bSJohn Baldwin 	const struct cpl_fw6_pld *cpl;
26555033c43bSJohn Baldwin 	struct cryptop *crp;
26561b0909d5SConrad Meyer 	uint32_t status;
26575033c43bSJohn Baldwin 	int error;
26585033c43bSJohn Baldwin 
26595033c43bSJohn Baldwin 	if (m != NULL)
26605033c43bSJohn Baldwin 		cpl = mtod(m, const void *);
26615033c43bSJohn Baldwin 	else
26625033c43bSJohn Baldwin 		cpl = (const void *)(rss + 1);
26635033c43bSJohn Baldwin 
26645033c43bSJohn Baldwin 	crp = (struct cryptop *)(uintptr_t)be64toh(cpl->data[1]);
26651b0909d5SConrad Meyer 	s = crypto_get_driver_session(crp->crp_session);
26665033c43bSJohn Baldwin 	status = be64toh(cpl->data[0]);
26675033c43bSJohn Baldwin 	if (CHK_MAC_ERR_BIT(status) || CHK_PAD_ERR_BIT(status))
26685033c43bSJohn Baldwin 		error = EBADMSG;
26695033c43bSJohn Baldwin 	else
26705033c43bSJohn Baldwin 		error = 0;
26715033c43bSJohn Baldwin 
26727063b997SJohn Baldwin 	sc = s->sc;
267394578db2SJohn Baldwin #ifdef INVARIANTS
267494578db2SJohn Baldwin 	mtx_lock(&s->lock);
26755033c43bSJohn Baldwin 	s->pending--;
267694578db2SJohn Baldwin 	mtx_unlock(&s->lock);
267794578db2SJohn Baldwin #endif
267894578db2SJohn Baldwin 	counter_u64_add(sc->stats_inflight, -1);
26799c5137beSJohn Baldwin 	counter_u64_add(s->port->stats_completed, 1);
26805033c43bSJohn Baldwin 
26815033c43bSJohn Baldwin 	switch (s->mode) {
2682567a3784SJohn Baldwin 	case HASH:
26835033c43bSJohn Baldwin 	case HMAC:
2684567a3784SJohn Baldwin 		error = ccr_hash_done(sc, s, crp, cpl, error);
26855033c43bSJohn Baldwin 		break;
2686762f1dcbSJohn Baldwin 	case CIPHER:
2687762f1dcbSJohn Baldwin 		error = ccr_cipher_done(sc, s, crp, cpl, error);
26885033c43bSJohn Baldwin 		break;
2689c0341432SJohn Baldwin 	case ETA:
2690c0341432SJohn Baldwin 		error = ccr_eta_done(sc, s, crp, cpl, error);
26915033c43bSJohn Baldwin 		break;
26925033c43bSJohn Baldwin 	case GCM:
26935033c43bSJohn Baldwin 		error = ccr_gcm_done(sc, s, crp, cpl, error);
26945033c43bSJohn Baldwin 		break;
26956b0451d6SJohn Baldwin 	case CCM:
26966b0451d6SJohn Baldwin 		error = ccr_ccm_done(sc, s, crp, cpl, error);
26976b0451d6SJohn Baldwin 		break;
26985033c43bSJohn Baldwin 	}
26995033c43bSJohn Baldwin 
27005033c43bSJohn Baldwin 	if (error == EBADMSG) {
27015033c43bSJohn Baldwin 		if (CHK_MAC_ERR_BIT(status))
270294578db2SJohn Baldwin 			counter_u64_add(sc->stats_mac_error, 1);
27035033c43bSJohn Baldwin 		if (CHK_PAD_ERR_BIT(status))
270494578db2SJohn Baldwin 			counter_u64_add(sc->stats_pad_error, 1);
27055033c43bSJohn Baldwin 	}
27065033c43bSJohn Baldwin 	crp->crp_etype = error;
27075033c43bSJohn Baldwin 	crypto_done(crp);
27085033c43bSJohn Baldwin 	m_freem(m);
27095033c43bSJohn Baldwin 	return (0);
27105033c43bSJohn Baldwin }
27115033c43bSJohn Baldwin 
27125033c43bSJohn Baldwin static int
ccr_modevent(module_t mod,int cmd,void * arg)27135033c43bSJohn Baldwin ccr_modevent(module_t mod, int cmd, void *arg)
27145033c43bSJohn Baldwin {
27155033c43bSJohn Baldwin 
27165033c43bSJohn Baldwin 	switch (cmd) {
27175033c43bSJohn Baldwin 	case MOD_LOAD:
27185033c43bSJohn Baldwin 		t4_register_cpl_handler(CPL_FW6_PLD, do_cpl6_fw_pld);
27195033c43bSJohn Baldwin 		return (0);
27205033c43bSJohn Baldwin 	case MOD_UNLOAD:
27215033c43bSJohn Baldwin 		t4_register_cpl_handler(CPL_FW6_PLD, NULL);
27225033c43bSJohn Baldwin 		return (0);
27235033c43bSJohn Baldwin 	default:
27245033c43bSJohn Baldwin 		return (EOPNOTSUPP);
27255033c43bSJohn Baldwin 	}
27265033c43bSJohn Baldwin }
27275033c43bSJohn Baldwin 
27285033c43bSJohn Baldwin static device_method_t ccr_methods[] = {
27295033c43bSJohn Baldwin 	DEVMETHOD(device_identify,	ccr_identify),
27305033c43bSJohn Baldwin 	DEVMETHOD(device_probe,		ccr_probe),
27315033c43bSJohn Baldwin 	DEVMETHOD(device_attach,	ccr_attach),
27325033c43bSJohn Baldwin 	DEVMETHOD(device_detach,	ccr_detach),
27335033c43bSJohn Baldwin 
2734c0341432SJohn Baldwin 	DEVMETHOD(cryptodev_probesession, ccr_probesession),
27355033c43bSJohn Baldwin 	DEVMETHOD(cryptodev_newsession,	ccr_newsession),
27365033c43bSJohn Baldwin 	DEVMETHOD(cryptodev_freesession, ccr_freesession),
27375033c43bSJohn Baldwin 	DEVMETHOD(cryptodev_process,	ccr_process),
27385033c43bSJohn Baldwin 
27395033c43bSJohn Baldwin 	DEVMETHOD_END
27405033c43bSJohn Baldwin };
27415033c43bSJohn Baldwin 
27425033c43bSJohn Baldwin static driver_t ccr_driver = {
27435033c43bSJohn Baldwin 	"ccr",
27445033c43bSJohn Baldwin 	ccr_methods,
27455033c43bSJohn Baldwin 	sizeof(struct ccr_softc)
27465033c43bSJohn Baldwin };
27475033c43bSJohn Baldwin 
2748478c66fdSJohn Baldwin DRIVER_MODULE(ccr, t6nex, ccr_driver, ccr_modevent, NULL);
27495033c43bSJohn Baldwin MODULE_VERSION(ccr, 1);
27505033c43bSJohn Baldwin MODULE_DEPEND(ccr, crypto, 1, 1, 1);
27515033c43bSJohn Baldwin MODULE_DEPEND(ccr, t6nex, 1, 1, 1);
2752