1*73bb2479SJustin Hibbits /*
2*73bb2479SJustin Hibbits * Copyright (c) 2026 Justin Hibbits <jhibbits@FreeBSD.org>
3*73bb2479SJustin Hibbits *
4*73bb2479SJustin Hibbits * SPDX-License-Identifier: BSD-2-Clause
5*73bb2479SJustin Hibbits */
6*73bb2479SJustin Hibbits
7*73bb2479SJustin Hibbits #include <sys/param.h>
8*73bb2479SJustin Hibbits #include <sys/bus.h>
9*73bb2479SJustin Hibbits #include <sys/callout.h>
10*73bb2479SJustin Hibbits #include <sys/kernel.h>
11*73bb2479SJustin Hibbits #include <sys/lock.h>
12*73bb2479SJustin Hibbits #include <sys/malloc.h>
13*73bb2479SJustin Hibbits #include <sys/module.h>
14*73bb2479SJustin Hibbits #include <sys/mutex.h>
15*73bb2479SJustin Hibbits #include <sys/queue.h>
16*73bb2479SJustin Hibbits #include <sys/rman.h>
17*73bb2479SJustin Hibbits #include <sys/smp.h>
18*73bb2479SJustin Hibbits
19*73bb2479SJustin Hibbits #include <machine/atomic.h>
20*73bb2479SJustin Hibbits #include <machine/bus.h>
21*73bb2479SJustin Hibbits #include <machine/resource.h>
22*73bb2479SJustin Hibbits
23*73bb2479SJustin Hibbits #include <vm/vm.h>
24*73bb2479SJustin Hibbits #include <vm/pmap.h>
25*73bb2479SJustin Hibbits
26*73bb2479SJustin Hibbits #include <sys/endian.h>
27*73bb2479SJustin Hibbits
28*73bb2479SJustin Hibbits #include <dev/ofw/ofw_bus.h>
29*73bb2479SJustin Hibbits #include <dev/ofw/ofw_bus_subr.h>
30*73bb2479SJustin Hibbits #include <opencrypto/cryptodev.h>
31*73bb2479SJustin Hibbits #include <opencrypto/xform_auth.h>
32*73bb2479SJustin Hibbits
33*73bb2479SJustin Hibbits #include "sec_var.h"
34*73bb2479SJustin Hibbits #include "cryptodev_if.h"
35*73bb2479SJustin Hibbits
36*73bb2479SJustin Hibbits /*
37*73bb2479SJustin Hibbits * Most of this work is based on the T2080 Security (SEC) Reference Manual.
38*73bb2479SJustin Hibbits *
39*73bb2479SJustin Hibbits * The driver uses the Job Ring interface for all jobs. The QI interface can be
40*73bb2479SJustin Hibbits * added if IPSec, OVPN, or kTLS acceleration is added.
41*73bb2479SJustin Hibbits */
42*73bb2479SJustin Hibbits
43*73bb2479SJustin Hibbits /* From T2080 Security Reference Manual */
44*73bb2479SJustin Hibbits #define SEC_MAX_SHDESC_WORDS 62
45*73bb2479SJustin Hibbits
46*73bb2479SJustin Hibbits #define SEC_MAX_JR 4 /* T2080 exposes four Job Rings */
47*73bb2479SJustin Hibbits
48*73bb2479SJustin Hibbits /* CCSR register offsets. */
49*73bb2479SJustin Hibbits #define SEC_MCFGR 0x0004
50*73bb2479SJustin Hibbits #define MCFGR_SWRST 0x80000000 /* Software reset */
51*73bb2479SJustin Hibbits #define MCFGR_WDE 0x40000000 /* DECO watchdog enable */
52*73bb2479SJustin Hibbits #define MCFGR_WDF 0x20000000 /* Watchdog fast (test only) */
53*73bb2479SJustin Hibbits #define MCFGR_DMARST 0x10000000 /* DMA reset (with SWRST) */
54*73bb2479SJustin Hibbits #define MCFGR_WRHD 0x08000000 /* Write handoff disable */
55*73bb2479SJustin Hibbits #define MCFGR_DJPC 0x00200000 /* Disable job perf ctrs */
56*73bb2479SJustin Hibbits #define MCFGR_DBPC 0x00100000 /* Disable byte perf ctrs */
57*73bb2479SJustin Hibbits #define MCFGR_PS 0x00010000 /* Large pointers */
58*73bb2479SJustin Hibbits #define MCFGR_ARCACHE_M 0x0000f000 /* AXI read cache attrs */
59*73bb2479SJustin Hibbits #define MCFGR_AWCACHE_M 0x00000f00 /* AXI write cache attrs */
60*73bb2479SJustin Hibbits #define MCFGR_AXIPRI 0x00000008 /* AXI master priority */
61*73bb2479SJustin Hibbits #define MCFGR_LARGE_BURST 0x00000004 /* Enable 256B bursts */
62*73bb2479SJustin Hibbits #define SEC_SCFGR 0x000c
63*73bb2479SJustin Hibbits #define SCFGR_VIRT_EN 0x00008000 /* Virtualization enabled */
64*73bb2479SJustin Hibbits
65*73bb2479SJustin Hibbits #define SEC_RDSTA 0x06c0 /* RNG DRNG Status */
66*73bb2479SJustin Hibbits #define RDSTA_IF0 0x00000001 /* State handle 0 up */
67*73bb2479SJustin Hibbits #define RDSTA_IF1 0x00000002 /* State handle 1 up */
68*73bb2479SJustin Hibbits #define RDSTA_ERRCODE_M 0x000f0000
69*73bb2479SJustin Hibbits #define RDSTA_ERRCODE_S 16
70*73bb2479SJustin Hibbits #define RDSTA_CE 0x00100000 /* Catastrophic error */
71*73bb2479SJustin Hibbits
72*73bb2479SJustin Hibbits /* DECO direct-access registers */
73*73bb2479SJustin Hibbits #define SEC_DECORR 0x009c /* DECO Request Register */
74*73bb2479SJustin Hibbits #define DECORR_DEN0 0x00010000 /* DECO0 enable (RO, bit 16) */
75*73bb2479SJustin Hibbits #define DECORR_RQD0 0x00000001 /* DECO0 request */
76*73bb2479SJustin Hibbits #define SEC_D0LIODNR_MS 0x00a0
77*73bb2479SJustin Hibbits #define SEC_D0LIODNR_LS 0x00a4
78*73bb2479SJustin Hibbits #define SEC_D0JQCR_MS 0x8800 /* JQCR upper: WHL/FOUR/SOB */
79*73bb2479SJustin Hibbits #define DAJQCR_MS_WHL 0x20000000 /* Whole descriptor loaded */
80*73bb2479SJustin Hibbits #define DAJQCR_MS_FOUR 0x10000000 /* >= 4 words in first burst */
81*73bb2479SJustin Hibbits #define DAJQCR_MS_SOB 0x00010000 /* Shared/burst loaded */
82*73bb2479SJustin Hibbits #define DAJQCR_MS_SRC_M 0x00000700 /* Job source */
83*73bb2479SJustin Hibbits #define DAJQCR_MS_SRC_S 8
84*73bb2479SJustin Hibbits #define SEC_D0JQCR_LS 0x8804
85*73bb2479SJustin Hibbits #define SEC_D0DAR_MS 0x8808 /* Descriptor address, upper */
86*73bb2479SJustin Hibbits #define SEC_D0DAR_LS 0x880c
87*73bb2479SJustin Hibbits #define SEC_D0DESB(n) (0x8a00 + (n) * 4) /* n = 0..63 */
88*73bb2479SJustin Hibbits #define SEC_D0DDR 0x8e04 /* Debug status */
89*73bb2479SJustin Hibbits #define DADDR_VALID 0x80000000 /* Job currently running */
90*73bb2479SJustin Hibbits #define DADDR_DECO_STATE_M 0x00f00000 /* Main state machine */
91*73bb2479SJustin Hibbits #define DADDR_DECO_STATE_S 20
92*73bb2479SJustin Hibbits
93*73bb2479SJustin Hibbits /* Fault-address registers. */
94*73bb2479SJustin Hibbits #define SEC_FAR_HI 0x0fc0 /* Fault Address, upper */
95*73bb2479SJustin Hibbits #define SEC_FAR_LO 0x0fc4 /* Fault Address, lower */
96*73bb2479SJustin Hibbits #define SEC_FALR 0x0fc8 /* Fault Address LIODN */
97*73bb2479SJustin Hibbits #define SEC_FADR 0x0fcc /* Fault Address Detail */
98*73bb2479SJustin Hibbits #define FADR_FERR_M 0xc0000000 /* AXI error response */
99*73bb2479SJustin Hibbits #define FADR_FERR_S 30
100*73bb2479SJustin Hibbits #define FADR_FSZ_EXT_M 0x00070000 /* Transfer size high 3 bits */
101*73bb2479SJustin Hibbits #define FADR_FSZ_EXT_S 16
102*73bb2479SJustin Hibbits #define FADR_DTYP 0x00008000 /* 0=message, 1=control */
103*73bb2479SJustin Hibbits #define FADR_JSRC_M 0x00007000 /* Job source */
104*73bb2479SJustin Hibbits #define FADR_JSRC_S 12
105*73bb2479SJustin Hibbits #define FADR_BLKID_M 0x00000f00 /* SEC internal block ID */
106*73bb2479SJustin Hibbits #define FADR_BLKID_S 8
107*73bb2479SJustin Hibbits #define FADR_TYP 0x00000080 /* 0=read, 1=write */
108*73bb2479SJustin Hibbits #define FADR_FSZ_M 0x0000007f /* Transfer size low 7 bits */
109*73bb2479SJustin Hibbits
110*73bb2479SJustin Hibbits #define SEC_RD4(sc, off) bus_read_4((sc)->sc_rres, (off))
111*73bb2479SJustin Hibbits #define SEC_WR4(sc, off, v) bus_write_4((sc)->sc_rres, (off), (v))
112*73bb2479SJustin Hibbits
113*73bb2479SJustin Hibbits /* Descriptor command components */
114*73bb2479SJustin Hibbits /* SEQ commands are intended for network protocols */
115*73bb2479SJustin Hibbits #define CMD_DESC(n) ((n) << 27)
116*73bb2479SJustin Hibbits #define CMD_KEY 0x00 /* Pointer/key follows descriptor */
117*73bb2479SJustin Hibbits #define CMD_SEQ_KEY 0x01
118*73bb2479SJustin Hibbits #define KEY_CLASS_M 0x06000000
119*73bb2479SJustin Hibbits #define KEY_CLASS_1 0x02000000
120*73bb2479SJustin Hibbits #define KEY_CLASS_2 0x04000000
121*73bb2479SJustin Hibbits #define KEY_SGF 0x01000000 /* KEY - Pointer to SGT */
122*73bb2479SJustin Hibbits #define KEY_VLF 0x01000000 /* SK - variable length */
123*73bb2479SJustin Hibbits #define KEY_IMM 0x00800000 /* KEY - Key follows descriptor */
124*73bb2479SJustin Hibbits #define KEY_AIDF 0x00800000 /* SK - Already in Input FIFO */
125*73bb2479SJustin Hibbits #define KEY_ENC 0x00400000 /* Key is encrypted */
126*73bb2479SJustin Hibbits #define KEY_NWB 0x00200000 /* No write back */
127*73bb2479SJustin Hibbits #define KEY_EKT 0x00100000 /* Encrypted Key Type:
128*73bb2479SJustin Hibbits * 0 - AES-CCB
129*73bb2479SJustin Hibbits * 1 - AES-CCM
130*73bb2479SJustin Hibbits */
131*73bb2479SJustin Hibbits #define KEY_KDEST_M 0x00030000 /* Key Destination */
132*73bb2479SJustin Hibbits #define KEY_KDEST_REG 0x00000000 /* Dest is Key register */
133*73bb2479SJustin Hibbits #define KEY_KDEST_PKHA 0x00010000 /* Dest is PKHA E-memory */
134*73bb2479SJustin Hibbits #define KEY_KDEST_AFHA 0x00020000 /* Dest is AFHA S-Box */
135*73bb2479SJustin Hibbits #define KEY_KDEST_MDHA_SPLIT 0x00030000 /* Key is MDHA split key */
136*73bb2479SJustin Hibbits #define KEY_TK 0x00008000 /* Trusted Key */
137*73bb2479SJustin Hibbits #define KEY_LENGTH_M 0x000003ff /* Key length */
138*73bb2479SJustin Hibbits #define CMD_LOAD 0x02
139*73bb2479SJustin Hibbits #define CMD_SEQ_LOAD 0x03
140*73bb2479SJustin Hibbits #define LOAD_CLASS_M 0x06000000
141*73bb2479SJustin Hibbits #define LOAD_CLASS_1 0x02000000
142*73bb2479SJustin Hibbits #define LOAD_CLASS_2 0x04000000
143*73bb2479SJustin Hibbits #define LOAD_CLASS_3 0x06000000
144*73bb2479SJustin Hibbits #define LOAD_SGF 0x01000000 /* LOAD - Pointer to SGT */
145*73bb2479SJustin Hibbits #define LOAD_VLF 0x01000000 /* SL - variable length */
146*73bb2479SJustin Hibbits #define LOAD_IMM 0x00800000 /* LOAD - Data follows descriptor */
147*73bb2479SJustin Hibbits #define LOAD_DST_M 0x007f0000 /* Destination register */
148*73bb2479SJustin Hibbits #define LOAD_DST_S 16
149*73bb2479SJustin Hibbits #define LOAD_KSR 0x00010000 /* Key Size Register (C1/C2) */
150*73bb2479SJustin Hibbits #define LOAD_DSR 0x00020000 /* Data Size Register (C1/C2) */
151*73bb2479SJustin Hibbits #define LOAD_ICVS 0x00030000 /* ICV Size Register (C1/C2) */
152*73bb2479SJustin Hibbits #define LOAD_LSR 0x00040000 /* LIODN Status Register (C3) */
153*73bb2479SJustin Hibbits #define LOAD_DCTRL2 0x00050000 /* DECO Control Register 2(C3) */
154*73bb2479SJustin Hibbits #define LOAD_CCTRL 0x00060000 /* CHA Control Register (C1) */
155*73bb2479SJustin Hibbits #define LOAD_DCTRL 0x00060000 /* DECO Control Register (C3) */
156*73bb2479SJustin Hibbits #define LOAD_ICTRL 0x00070000 /* IRQ Control Register (C0) */
157*73bb2479SJustin Hibbits #define LOAD_DPOVRD 0x00070000 /* DECO Protocol Override (C3) */
158*73bb2479SJustin Hibbits #define LOAD_CLRW 0x00080000 /* Clear Written Register (C0) */
159*73bb2479SJustin Hibbits #define LOAD_MATH0W 0x00080000 /* DECO Math Register 0 (C3) */
160*73bb2479SJustin Hibbits #define LOAD_MATH1W 0x00090000 /* DECO Math Register 1 (C3) */
161*73bb2479SJustin Hibbits #define LOAD_MATH2W 0x000a0000 /* DECO Math Register 2 (C3) */
162*73bb2479SJustin Hibbits #define LOAD_CISEL 0x000a0000 /* CHA Instance Select Reg (C0) */
163*73bb2479SJustin Hibbits #define LOAD_AADSZ 0x000b0000 /* AAD Size Register (C1) */
164*73bb2479SJustin Hibbits #define LOAD_MAT3W 0x000b0000 /* DECO Math Register 3 (C3) */
165*73bb2479SJustin Hibbits #define LOAD_C1VSZ 0x000c0000 /* Class 1 IV SIze Register (C1) */
166*73bb2479SJustin Hibbits #define LOAD_ALTDS1 0x000f0000 /* Alternate Data Size C1 (C1) */
167*73bb2479SJustin Hibbits #define LOAD_PKASZ 0x00100000 /* PKHA A Size Register (C1) */
168*73bb2479SJustin Hibbits #define LOAD_PKBSZ 0x00110000 /* PKHA B Size Register (C1) */
169*73bb2479SJustin Hibbits #define LOAD_PKNSZ 0x00120000 /* PKHA N Size Register (C1) */
170*73bb2479SJustin Hibbits #define LOAD_PKESZ 0x00130000 /* PKHA E Size Register (C1) */
171*73bb2479SJustin Hibbits #define LOAD_CTX 0x00200000 /* Context Register (C1/C2) */
172*73bb2479SJustin Hibbits #define LOAD_KEY 0x00400000 /* Key Register (C1/C2) */
173*73bb2479SJustin Hibbits #define LOAD_DESC_BUF 0x00400000 /* DECO Descriptor Buffer (C3) */
174*73bb2479SJustin Hibbits #define LOAD_NFSL 0x00700000 /* NFIFO and size registers (C0) */
175*73bb2479SJustin Hibbits #define LOAD_NFSM 0x00710000 /* NFIFO and size registers (C0) */
176*73bb2479SJustin Hibbits #define LOAD_NFL 0x00720000 /* NFIFO (C0) */
177*73bb2479SJustin Hibbits #define LOAD_NFM 0x00730000 /* NFIFO (C0) */
178*73bb2479SJustin Hibbits #define LOAD_SL 0x00740000 /* Size register(s) (C0) */
179*73bb2479SJustin Hibbits #define LOAD_SM 0x00750000 /* Size register(s) (C0) */
180*73bb2479SJustin Hibbits #define LOAD_IDFNS 0x00760000 /* Input Data FIFO Nibble Shift (C0) */
181*73bb2479SJustin Hibbits #define LOAD_ODFNS 0x00770000 /* Output Data FIFO Nibble Shift (C0) */
182*73bb2479SJustin Hibbits #define LOAD_AUXDATA 0x00780000 /* Aux Data FIFO (C0) */
183*73bb2479SJustin Hibbits #define LOAD_NFIFO 0x007a0000 /* NFIFO (C0) */
184*73bb2479SJustin Hibbits #define LOAD_IFIFO 0x007c0000 /* Input Data FIFO (C0) */
185*73bb2479SJustin Hibbits #define LOAD_OFIFO 0x007e0000 /* Output Data FIFO (C0) */
186*73bb2479SJustin Hibbits #define LOAD_LENGTH_M 0x000000ff /* Data length (8 bits) */
187*73bb2479SJustin Hibbits #define LOAD_OFFSET_S 8 /* OFFSET field shift (bits 8-15) */
188*73bb2479SJustin Hibbits #define CMD_FIFO_LOAD 0x04
189*73bb2479SJustin Hibbits #define CMD_SEQ_FIFO_LOAD 0x05
190*73bb2479SJustin Hibbits #define CMD_STORE 0x0a
191*73bb2479SJustin Hibbits #define CMD_SEQ_STORE 0x0b
192*73bb2479SJustin Hibbits #define CMD_FIFO_STORE 0x0c
193*73bb2479SJustin Hibbits #define CMD_SEQ_FIFO_STORE 0x0d
194*73bb2479SJustin Hibbits #define CMD_MOVE 0x0e
195*73bb2479SJustin Hibbits #define CMD_MOVE_LEN 0x0f
196*73bb2479SJustin Hibbits #define CMD_OPERATION 0x10
197*73bb2479SJustin Hibbits #define OPTYPE_M 0x07000000
198*73bb2479SJustin Hibbits #define OPTYPE_S 24
199*73bb2479SJustin Hibbits #define OPTYPE_CLASS1_ALG 0x02000000
200*73bb2479SJustin Hibbits #define OPTYPE_CLASS2_ALG 0x04000000
201*73bb2479SJustin Hibbits #define ALG_S 16
202*73bb2479SJustin Hibbits #define CMD_ALGORITHM(m, n) ((m) | ((n) << ALG_S))
203*73bb2479SJustin Hibbits /* Class 1 algorithms */
204*73bb2479SJustin Hibbits #define ALG_AES CMD_ALGORITHM(OPTYPE_CLASS1_ALG, 0x10)
205*73bb2479SJustin Hibbits #define ALG_DES CMD_ALGORITHM(OPTYPE_CLASS1_ALG, 0x20)
206*73bb2479SJustin Hibbits #define ALG_3DES CMD_ALGORITHM(OPTYPE_CLASS1_ALG, 0x21)
207*73bb2479SJustin Hibbits #define ALG_ARC4 CMD_ALGORITHM(OPTYPE_CLASS1_ALG, 0x30)
208*73bb2479SJustin Hibbits #define ALG_RNG CMD_ALGORITHM(OPTYPE_CLASS1_ALG, 0x50)
209*73bb2479SJustin Hibbits #define ALG_SNOW3G_F8 CMD_ALGORITHM(OPTYPE_CLASS1_ALG, 0x60)
210*73bb2479SJustin Hibbits #define ALG_KASUMI CMD_ALGORITHM(OPTYPE_CLASS1_ALG, 0x70)
211*73bb2479SJustin Hibbits #define ALG_ZUC_ENC CMD_ALGORITHM(OPTYPE_CLASS1_ALG, 0xb0)
212*73bb2479SJustin Hibbits /* Class 2 algorithms */
213*73bb2479SJustin Hibbits #define ALG_MD5 CMD_ALGORITHM(OPTYPE_CLASS2_ALG, 0x40)
214*73bb2479SJustin Hibbits #define ALG_SHA1 CMD_ALGORITHM(OPTYPE_CLASS2_ALG, 0x41)
215*73bb2479SJustin Hibbits #define ALG_SHA224 CMD_ALGORITHM(OPTYPE_CLASS2_ALG, 0x42)
216*73bb2479SJustin Hibbits #define ALG_SHA256 CMD_ALGORITHM(OPTYPE_CLASS2_ALG, 0x43)
217*73bb2479SJustin Hibbits #define ALG_SHA384 CMD_ALGORITHM(OPTYPE_CLASS2_ALG, 0x44)
218*73bb2479SJustin Hibbits #define ALG_SHA512 CMD_ALGORITHM(OPTYPE_CLASS2_ALG, 0x45)
219*73bb2479SJustin Hibbits #define ALG_CRC CMD_ALGORITHM(OPTYPE_CLASS2_ALG, 0x90)
220*73bb2479SJustin Hibbits #define ALG_SNOW3G_F9 CMD_ALGORITHM(OPTYPE_CLASS2_ALG, 0xa0)
221*73bb2479SJustin Hibbits #define ALG_ZUC_AUTH CMD_ALGORITHM(OPTYPE_CLASS2_ALG, 0xc0)
222*73bb2479SJustin Hibbits /* AAI (Additional Algorithm Information) codes. */
223*73bb2479SJustin Hibbits #define AAI_S 4
224*73bb2479SJustin Hibbits /* AES modes */
225*73bb2479SJustin Hibbits #define AAI_AES_CTR (0x00 << AAI_S)
226*73bb2479SJustin Hibbits #define AAI_AES_CBC (0x10 << AAI_S)
227*73bb2479SJustin Hibbits #define AAI_AES_ECB (0x20 << AAI_S)
228*73bb2479SJustin Hibbits #define AAI_AES_CFB (0x30 << AAI_S)
229*73bb2479SJustin Hibbits #define AAI_AES_OFB (0x40 << AAI_S)
230*73bb2479SJustin Hibbits #define AAI_AES_XTS (0x50 << AAI_S)
231*73bb2479SJustin Hibbits #define AAI_AES_CMAC (0x60 << AAI_S)
232*73bb2479SJustin Hibbits #define AAI_AES_XCBC_MAC (0x70 << AAI_S)
233*73bb2479SJustin Hibbits #define AAI_AES_CCM (0x80 << AAI_S)
234*73bb2479SJustin Hibbits #define AAI_AES_GCM (0x90 << AAI_S)
235*73bb2479SJustin Hibbits #define AAI_AES_DK (0x100 << AAI_S) /* Decrypt-key derive */
236*73bb2479SJustin Hibbits /* DES/3DES modes */
237*73bb2479SJustin Hibbits #define AAI_DES_CBC (0x10 << AAI_S)
238*73bb2479SJustin Hibbits #define AAI_DES_ECB (0x20 << AAI_S)
239*73bb2479SJustin Hibbits /* MDHA modes */
240*73bb2479SJustin Hibbits #define AAI_HASH (0x00 << AAI_S)
241*73bb2479SJustin Hibbits #define AAI_HMAC (0x01 << AAI_S)
242*73bb2479SJustin Hibbits #define AAI_HMAC_PRECOMP (0x04 << AAI_S) /* Precomputed IPAD/OPAD */
243*73bb2479SJustin Hibbits /* Algorithm State field (bits 2-3): what phase to run */
244*73bb2479SJustin Hibbits #define AS_S 2
245*73bb2479SJustin Hibbits #define AS_UPDATE (0x0 << AS_S)
246*73bb2479SJustin Hibbits #define AS_INIT (0x1 << AS_S)
247*73bb2479SJustin Hibbits #define AS_FINAL (0x2 << AS_S)
248*73bb2479SJustin Hibbits #define AS_INIT_FINAL (0x3 << AS_S)
249*73bb2479SJustin Hibbits /* RNG-specific: State-Handle field. */
250*73bb2479SJustin Hibbits #define OP_RNG_SH_S 4
251*73bb2479SJustin Hibbits #define OP_RNG_SH(n) ((n) << OP_RNG_SH_S)
252*73bb2479SJustin Hibbits /* Direction / ICV */
253*73bb2479SJustin Hibbits #define OP_ICV 0x00000002
254*73bb2479SJustin Hibbits #define OP_ENC 0x00000001
255*73bb2479SJustin Hibbits
256*73bb2479SJustin Hibbits /* SEQ FIFO LOAD command bits. */
257*73bb2479SJustin Hibbits #define FIFOLD_CLASS_1 0x02000000 /* CLASS = 01b (Class 1) */
258*73bb2479SJustin Hibbits #define FIFOLD_CLASS_2 0x04000000 /* CLASS = 10b (Class 2) */
259*73bb2479SJustin Hibbits #define FIFOLD_CLASS_BOTH 0x06000000 /* CLASS = 11b (snooping) */
260*73bb2479SJustin Hibbits #define FIFOLD_VLF 0x01000000 /* Variable-length flag */
261*73bb2479SJustin Hibbits /*
262*73bb2479SJustin Hibbits * Input data type: top 3 bits = type,
263*73bb2479SJustin Hibbits * bottom 3 bits = LC2/LC1/FC1 flags.
264*73bb2479SJustin Hibbits */
265*73bb2479SJustin Hibbits #define FIFOLD_TYPE_S 16
266*73bb2479SJustin Hibbits #define FIFOLD_TYPE_MSG (0x10 << FIFOLD_TYPE_S) /* 010_000 */
267*73bb2479SJustin Hibbits /* Class 1 output fed straight into Class 2, i.e. MAC over ciphertext. */
268*73bb2479SJustin Hibbits #define FIFOLD_TYPE_MSG_C1OUT (0x18 << FIFOLD_TYPE_S) /* 011_000 */
269*73bb2479SJustin Hibbits #define FIFOLD_TYPE_IV (0x20 << FIFOLD_TYPE_S) /* 100_000 */
270*73bb2479SJustin Hibbits #define FIFOLD_TYPE_AAD (0x30 << FIFOLD_TYPE_S) /* 110_000 */
271*73bb2479SJustin Hibbits #define FIFOLD_TYPE_ICV (0x38 << FIFOLD_TYPE_S) /* 111_000 */
272*73bb2479SJustin Hibbits #define FIFOLD_FC1 (0x01 << FIFOLD_TYPE_S) /* Flush class 1 */
273*73bb2479SJustin Hibbits #define FIFOLD_LC1 (0x02 << FIFOLD_TYPE_S) /* Last for Class 1 */
274*73bb2479SJustin Hibbits #define FIFOLD_LC2 (0x04 << FIFOLD_TYPE_S) /* Last for Class 2 */
275*73bb2479SJustin Hibbits /* Length moves to a 32-bit word after the command. */
276*73bb2479SJustin Hibbits #define FIFO_EXT 0x00400000
277*73bb2479SJustin Hibbits
278*73bb2479SJustin Hibbits /* SEQ FIFO STORE command bits. */
279*73bb2479SJustin Hibbits #define FIFOST_VLF 0x01000000
280*73bb2479SJustin Hibbits #define FIFOST_TYPE_S 16
281*73bb2479SJustin Hibbits #define FIFOST_TYPE_MSG_DATA (0x30 << FIFOST_TYPE_S)
282*73bb2479SJustin Hibbits
283*73bb2479SJustin Hibbits #define CMD_SIGNATURE 0x12
284*73bb2479SJustin Hibbits #define CMD_JUMP 0x14
285*73bb2479SJustin Hibbits #define CMD_MATH 0x15
286*73bb2479SJustin Hibbits #define MATH_FN_ADD (0x0 << 20) /* SRC0 + SRC1 */
287*73bb2479SJustin Hibbits #define MATH_SRC0_SIL (0x8 << 16) /* Sequence In Length */
288*73bb2479SJustin Hibbits #define MATH_SRC1_ZERO (0xF << 12) /* Constant zero */
289*73bb2479SJustin Hibbits #define MATH_DEST_VSIL (0xA << 8) /* Variable SIL */
290*73bb2479SJustin Hibbits #define MATH_DEST_VSOL (0xB << 8) /* Variable SOL */
291*73bb2479SJustin Hibbits #define MATH_LEN_4 0x4
292*73bb2479SJustin Hibbits /* J - Job Descriptor, S - Shared Descriptor */
293*73bb2479SJustin Hibbits #define CMD_DESC_HEADER 0x16
294*73bb2479SJustin Hibbits #define HEADER_EXT 0x04000000 /* Has Extension (J) */
295*73bb2479SJustin Hibbits #define HEADER_RSL 0x02000000 /* Require SEQ LIODN (J) */
296*73bb2479SJustin Hibbits #define HEADER_DNR 0x01000000 /* Do Not Run (J/S) */
297*73bb2479SJustin Hibbits #define HEADER_ONE 0x00800000 /* Must be 1 (J/S) */
298*73bb2479SJustin Hibbits #define HEADER_START_INDEX(n) ((n) << 16) /* Start Index (J/S) */
299*73bb2479SJustin Hibbits #define HEADER_SHR_DESC_L(n) ((n) << 16) /* Shared Desc len (J) */
300*73bb2479SJustin Hibbits /* Bit 16 must be 0 */
301*73bb2479SJustin Hibbits #define HEADER_TDES_M 0x00006000 /* Trusted Descriptor Mask (J) */
302*73bb2479SJustin Hibbits #define HEADER_TDES 0x00004000 /* Trusted Descriptor (J) */
303*73bb2479SJustin Hibbits #define HEADER_TDES_CAND 0x00006000 /* Candidate Trust Desc (J) */
304*73bb2479SJustin Hibbits #define HEADER_SHR 0x00001000 /* Has Shared Descriptor (J) */
305*73bb2479SJustin Hibbits #define HEADER_REO 0x00000800 /* Reverse Execution Order (J) */
306*73bb2479SJustin Hibbits #define HEADER_SHARE_M 0x00000700 /* Share State (J/S) */
307*73bb2479SJustin Hibbits #define HEADER_SHARE_WAIT 0x00000100 /* Wait to share (J/S) */
308*73bb2479SJustin Hibbits #define HEADER_SHARE_SERIAL 0x00000200 /* Serialize (J/S) */
309*73bb2479SJustin Hibbits #define HEADER_SHARE_ALWAYS 0x00000300 /* Always share (stateless) (J/S) */
310*73bb2479SJustin Hibbits #define HEADER_SHARE_DEFER 0x00000400 /* Defer to shared desc (J) */
311*73bb2479SJustin Hibbits #define HEADER_DESCLEN_M 0x0000007f /* Descriptor length */
312*73bb2479SJustin Hibbits #define HEADER_DESCLEN_S 0
313*73bb2479SJustin Hibbits #define HEADER_EXT_FTD 0x00000100 /* Fake Trusted Descriptor */
314*73bb2479SJustin Hibbits #define HEADER_EXT_DSELVALID 0x00000080 /* DECO_SELECT field valid */
315*73bb2479SJustin Hibbits #define HEADER_EXT_DSEL_M 0x0000000f /* DECO Select */
316*73bb2479SJustin Hibbits #define CMD_SHARED_HEADER 0x17
317*73bb2479SJustin Hibbits #define HEADER_RIF 0x02000000 /* Read Input Frame */
318*73bb2479SJustin Hibbits #define HEADER_CIF 0x00002000 /* Clear Input FIFO */
319*73bb2479SJustin Hibbits #define HEADER_SC 0x00001000 /* Save Context */
320*73bb2479SJustin Hibbits #define HEADER_PD 0x00000800 /* Propagate DNR */
321*73bb2479SJustin Hibbits #define CMD_MATHI 0x1d
322*73bb2479SJustin Hibbits #define CMD_SEQ_IN_PTR 0x1e
323*73bb2479SJustin Hibbits #define SEQ_SGF 0x01000000 /* Pointer is SGT (bit 7 NXP) */
324*73bb2479SJustin Hibbits #define SEQ_EXT 0x00400000 /* 32-bit extended length (bit 9 NXP) */
325*73bb2479SJustin Hibbits #define CMD_SEQ_OUT_PTR 0x1f
326*73bb2479SJustin Hibbits
327*73bb2479SJustin Hibbits /* Shared descriptor container. */
328*73bb2479SJustin Hibbits struct sec_context {
329*73bb2479SJustin Hibbits uint32_t shd[SEC_MAX_SHDESC_WORDS];
330*73bb2479SJustin Hibbits };
331*73bb2479SJustin Hibbits
332*73bb2479SJustin Hibbits
333*73bb2479SJustin Hibbits /*
334*73bb2479SJustin Hibbits * Session state: one shared descriptor per direction. The shared
335*73bb2479SJustin Hibbits * descriptor holds just KEY + OPERATION; the per-job JD adds LOAD-IV
336*73bb2479SJustin Hibbits * and SEQ_IN_PTR / SEQ_OUT_PTR inline.
337*73bb2479SJustin Hibbits */
338*73bb2479SJustin Hibbits #define SEC_MAX_SPLIT_KEY 128 /* SHA-512 AES-ECB encrypted */
339*73bb2479SJustin Hibbits
340*73bb2479SJustin Hibbits #define SEC_CCM_AAD_MAX 0xfeff
341*73bb2479SJustin Hibbits
342*73bb2479SJustin Hibbits struct sec_session {
343*73bb2479SJustin Hibbits struct sec_softc *sess_sc;
344*73bb2479SJustin Hibbits struct sec_context ctx[2]; /* [0]=dec, [1]=enc */
345*73bb2479SJustin Hibbits uint32_t sdlen[2]; /* words per direction */
346*73bb2479SJustin Hibbits uint8_t digestlen; /* HMAC output size (0 if none) */
347*73bb2479SJustin Hibbits uint8_t skeylen; /* HMAC split key size (0 if none) */
348*73bb2479SJustin Hibbits uint8_t skey[SEC_MAX_SPLIT_KEY];
349*73bb2479SJustin Hibbits };
350*73bb2479SJustin Hibbits
351*73bb2479SJustin Hibbits static device_probe_t sec_probe;
352*73bb2479SJustin Hibbits static device_attach_t sec_attach;
353*73bb2479SJustin Hibbits static device_detach_t sec_detach;
354*73bb2479SJustin Hibbits static cryptodev_probesession_t sec_probe_session;
355*73bb2479SJustin Hibbits static cryptodev_newsession_t sec_new_session;
356*73bb2479SJustin Hibbits static cryptodev_freesession_t sec_free_session;
357*73bb2479SJustin Hibbits static cryptodev_process_t sec_process;
358*73bb2479SJustin Hibbits
359*73bb2479SJustin Hibbits static void sec_intr(void *);
360*73bb2479SJustin Hibbits
361*73bb2479SJustin Hibbits /* Register-level bring-up. Filled in from the SEC reference manual. */
362*73bb2479SJustin Hibbits static int sec_reset(struct sec_softc *);
363*73bb2479SJustin Hibbits static int sec_rng_init(struct sec_softc *);
364*73bb2479SJustin Hibbits
365*73bb2479SJustin Hibbits static struct ofw_compat_data compats[] = {
366*73bb2479SJustin Hibbits { "fsl,sec-v5.2", 52 },
367*73bb2479SJustin Hibbits { "fsl,sec-v5.0", 50 },
368*73bb2479SJustin Hibbits { "fsl,sec-v4.0", 40 },
369*73bb2479SJustin Hibbits { NULL, 0 }
370*73bb2479SJustin Hibbits };
371*73bb2479SJustin Hibbits
372*73bb2479SJustin Hibbits static device_method_t sec_methods[] = {
373*73bb2479SJustin Hibbits /* Device methods */
374*73bb2479SJustin Hibbits DEVMETHOD(device_probe, sec_probe),
375*73bb2479SJustin Hibbits DEVMETHOD(device_attach, sec_attach),
376*73bb2479SJustin Hibbits DEVMETHOD(device_detach, sec_detach),
377*73bb2479SJustin Hibbits
378*73bb2479SJustin Hibbits /* Cryptodev methods */
379*73bb2479SJustin Hibbits DEVMETHOD(cryptodev_probesession, sec_probe_session),
380*73bb2479SJustin Hibbits DEVMETHOD(cryptodev_newsession, sec_new_session),
381*73bb2479SJustin Hibbits DEVMETHOD(cryptodev_freesession, sec_free_session),
382*73bb2479SJustin Hibbits DEVMETHOD(cryptodev_process, sec_process),
383*73bb2479SJustin Hibbits
384*73bb2479SJustin Hibbits DEVMETHOD_END
385*73bb2479SJustin Hibbits };
386*73bb2479SJustin Hibbits
387*73bb2479SJustin Hibbits static DEFINE_CLASS_0(sec, sec_driver, sec_methods, sizeof(struct sec_softc));
388*73bb2479SJustin Hibbits DRIVER_MODULE(sec, simplebus, sec_driver, NULL, NULL);
389*73bb2479SJustin Hibbits MODULE_DEPEND(sec, crypto, 1, 1, 1);
390*73bb2479SJustin Hibbits
391*73bb2479SJustin Hibbits MALLOC_DEFINE(M_SEC, "sec", "SEC driver");
392*73bb2479SJustin Hibbits
393*73bb2479SJustin Hibbits static int
sec_probe(device_t dev)394*73bb2479SJustin Hibbits sec_probe(device_t dev)
395*73bb2479SJustin Hibbits {
396*73bb2479SJustin Hibbits const struct ofw_compat_data *cd;
397*73bb2479SJustin Hibbits
398*73bb2479SJustin Hibbits cd = ofw_bus_search_compatible(dev, compats);
399*73bb2479SJustin Hibbits if (cd->ocd_data == 0)
400*73bb2479SJustin Hibbits return (ENXIO);
401*73bb2479SJustin Hibbits
402*73bb2479SJustin Hibbits device_set_descf(dev, "Freescale Security Engine v%d.%d",
403*73bb2479SJustin Hibbits (int)cd->ocd_data / 10, (int)cd->ocd_data % 10);
404*73bb2479SJustin Hibbits
405*73bb2479SJustin Hibbits return (BUS_PROBE_DEFAULT);
406*73bb2479SJustin Hibbits }
407*73bb2479SJustin Hibbits
408*73bb2479SJustin Hibbits static int
sec_attach(device_t dev)409*73bb2479SJustin Hibbits sec_attach(device_t dev)
410*73bb2479SJustin Hibbits {
411*73bb2479SJustin Hibbits struct sec_softc *sc = device_get_softc(dev);
412*73bb2479SJustin Hibbits const struct ofw_compat_data *cd;
413*73bb2479SJustin Hibbits
414*73bb2479SJustin Hibbits sc->sc_dev = dev;
415*73bb2479SJustin Hibbits sc->sc_cid = -1;
416*73bb2479SJustin Hibbits
417*73bb2479SJustin Hibbits cd = ofw_bus_search_compatible(dev, compats);
418*73bb2479SJustin Hibbits sc->sc_version = cd->ocd_data;
419*73bb2479SJustin Hibbits
420*73bb2479SJustin Hibbits sc->sc_rrid = 0;
421*73bb2479SJustin Hibbits sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid,
422*73bb2479SJustin Hibbits RF_ACTIVE);
423*73bb2479SJustin Hibbits if (sc->sc_rres == NULL) {
424*73bb2479SJustin Hibbits device_printf(dev, "could not allocate register resource\n");
425*73bb2479SJustin Hibbits goto fail;
426*73bb2479SJustin Hibbits }
427*73bb2479SJustin Hibbits
428*73bb2479SJustin Hibbits /* TODO: Error IRQ handling. */
429*73bb2479SJustin Hibbits sc->sc_irid = 0;
430*73bb2479SJustin Hibbits sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
431*73bb2479SJustin Hibbits RF_ACTIVE | RF_SHAREABLE);
432*73bb2479SJustin Hibbits if (sc->sc_ires == NULL) {
433*73bb2479SJustin Hibbits device_printf(dev, "could not allocate error interrupt\n");
434*73bb2479SJustin Hibbits goto fail;
435*73bb2479SJustin Hibbits }
436*73bb2479SJustin Hibbits
437*73bb2479SJustin Hibbits if (bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
438*73bb2479SJustin Hibbits BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
439*73bb2479SJustin Hibbits SEC_MAX_SIZE, SEC_MAX_SEGMENTS, SEC_MAX_SIZE, BUS_DMA_ALLOCNOW,
440*73bb2479SJustin Hibbits NULL, NULL, &sc->sc_dmatag) != 0) {
441*73bb2479SJustin Hibbits device_printf(dev, "could not create DMA tag\n");
442*73bb2479SJustin Hibbits goto fail;
443*73bb2479SJustin Hibbits }
444*73bb2479SJustin Hibbits
445*73bb2479SJustin Hibbits if (sec_reset(sc) != 0) {
446*73bb2479SJustin Hibbits device_printf(dev, "SEC reset failed\n");
447*73bb2479SJustin Hibbits goto fail;
448*73bb2479SJustin Hibbits }
449*73bb2479SJustin Hibbits if (sec_rng_init(sc) != 0) {
450*73bb2479SJustin Hibbits device_printf(dev, "SEC RNG instantiation failed\n");
451*73bb2479SJustin Hibbits goto fail;
452*73bb2479SJustin Hibbits }
453*73bb2479SJustin Hibbits if (sec_init_rings(sc) == 0) {
454*73bb2479SJustin Hibbits device_printf(dev, "SEC job ring init failed\n");
455*73bb2479SJustin Hibbits goto fail;
456*73bb2479SJustin Hibbits }
457*73bb2479SJustin Hibbits
458*73bb2479SJustin Hibbits /*
459*73bb2479SJustin Hibbits * Clear any fault-address latch left over from the bootloader before
460*73bb2479SJustin Hibbits * enabling the error IRQ. FADR, FAR_HI/LO, and FALR must all be read
461*73bb2479SJustin Hibbits * before they're all cleared, per the RM.
462*73bb2479SJustin Hibbits */
463*73bb2479SJustin Hibbits (void)SEC_RD4(sc, SEC_FADR);
464*73bb2479SJustin Hibbits (void)SEC_RD4(sc, SEC_FAR_HI);
465*73bb2479SJustin Hibbits (void)SEC_RD4(sc, SEC_FAR_LO);
466*73bb2479SJustin Hibbits (void)SEC_RD4(sc, SEC_FALR);
467*73bb2479SJustin Hibbits
468*73bb2479SJustin Hibbits if (bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_MISC | INTR_MPSAFE,
469*73bb2479SJustin Hibbits NULL, sec_intr, sc, &sc->sc_icookie) != 0) {
470*73bb2479SJustin Hibbits device_printf(dev, "could not install error interrupt\n");
471*73bb2479SJustin Hibbits goto fail;
472*73bb2479SJustin Hibbits }
473*73bb2479SJustin Hibbits
474*73bb2479SJustin Hibbits sc->sc_cid = crypto_get_driverid(dev, sizeof(struct sec_session),
475*73bb2479SJustin Hibbits CRYPTOCAP_F_HARDWARE);
476*73bb2479SJustin Hibbits if (sc->sc_cid < 0) {
477*73bb2479SJustin Hibbits device_printf(dev, "could not get crypto driver id\n");
478*73bb2479SJustin Hibbits goto fail;
479*73bb2479SJustin Hibbits }
480*73bb2479SJustin Hibbits
481*73bb2479SJustin Hibbits return (0);
482*73bb2479SJustin Hibbits
483*73bb2479SJustin Hibbits fail:
484*73bb2479SJustin Hibbits sec_detach(dev);
485*73bb2479SJustin Hibbits return (ENXIO);
486*73bb2479SJustin Hibbits }
487*73bb2479SJustin Hibbits
488*73bb2479SJustin Hibbits static int
sec_detach(device_t dev)489*73bb2479SJustin Hibbits sec_detach(device_t dev)
490*73bb2479SJustin Hibbits {
491*73bb2479SJustin Hibbits struct sec_softc *sc = device_get_softc(dev);
492*73bb2479SJustin Hibbits u_int i;
493*73bb2479SJustin Hibbits
494*73bb2479SJustin Hibbits if (sc->sc_cid >= 0)
495*73bb2479SJustin Hibbits crypto_unregister_all(sc->sc_cid);
496*73bb2479SJustin Hibbits
497*73bb2479SJustin Hibbits /* Silence the rings before halting them. */
498*73bb2479SJustin Hibbits for (i = 0; i < sc->sc_njr; i++) {
499*73bb2479SJustin Hibbits struct sec_jr *jr = &sc->sc_jr[i];
500*73bb2479SJustin Hibbits
501*73bb2479SJustin Hibbits if (jr->jr_icookie != NULL)
502*73bb2479SJustin Hibbits bus_teardown_intr(dev, jr->jr_ires, jr->jr_icookie);
503*73bb2479SJustin Hibbits if (jr->jr_ires != NULL)
504*73bb2479SJustin Hibbits bus_release_resource(dev, SYS_RES_IRQ, jr->jr_irid,
505*73bb2479SJustin Hibbits jr->jr_ires);
506*73bb2479SJustin Hibbits sec_jr_teardown(sc, jr);
507*73bb2479SJustin Hibbits }
508*73bb2479SJustin Hibbits free(sc->sc_jr, M_SEC);
509*73bb2479SJustin Hibbits
510*73bb2479SJustin Hibbits if (sc->sc_dmatag != NULL)
511*73bb2479SJustin Hibbits bus_dma_tag_destroy(sc->sc_dmatag);
512*73bb2479SJustin Hibbits if (sc->sc_icookie != NULL)
513*73bb2479SJustin Hibbits bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
514*73bb2479SJustin Hibbits if (sc->sc_ires != NULL)
515*73bb2479SJustin Hibbits bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
516*73bb2479SJustin Hibbits sc->sc_ires);
517*73bb2479SJustin Hibbits if (sc->sc_rres != NULL)
518*73bb2479SJustin Hibbits bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid,
519*73bb2479SJustin Hibbits sc->sc_rres);
520*73bb2479SJustin Hibbits
521*73bb2479SJustin Hibbits return (0);
522*73bb2479SJustin Hibbits }
523*73bb2479SJustin Hibbits
524*73bb2479SJustin Hibbits static const char *sec_ferr_str[] = {
525*73bb2479SJustin Hibbits "OKAY", "reserved", "SLVERR", "DECERR",
526*73bb2479SJustin Hibbits };
527*73bb2479SJustin Hibbits
528*73bb2479SJustin Hibbits static const char *sec_jsrc_str[] = {
529*73bb2479SJustin Hibbits "JR0", "JR1", "JR2", "JR3", "RTIC", "QI", "rsvd6", "rsvd7",
530*73bb2479SJustin Hibbits };
531*73bb2479SJustin Hibbits
532*73bb2479SJustin Hibbits static void
sec_intr(void * arg)533*73bb2479SJustin Hibbits sec_intr(void *arg)
534*73bb2479SJustin Hibbits {
535*73bb2479SJustin Hibbits struct sec_softc *sc = arg;
536*73bb2479SJustin Hibbits uint32_t fadr, falr;
537*73bb2479SJustin Hibbits uint64_t far;
538*73bb2479SJustin Hibbits
539*73bb2479SJustin Hibbits fadr = SEC_RD4(sc, SEC_FADR);
540*73bb2479SJustin Hibbits if ((fadr & FADR_FERR_M) != 0) {
541*73bb2479SJustin Hibbits /*
542*73bb2479SJustin Hibbits * All fault registers are latched by hardware until all are
543*73bb2479SJustin Hibbits * read, in any order.
544*73bb2479SJustin Hibbits */
545*73bb2479SJustin Hibbits far = (uint64_t)SEC_RD4(sc, SEC_FAR_HI) << 32;
546*73bb2479SJustin Hibbits far |= SEC_RD4(sc, SEC_FAR_LO);
547*73bb2479SJustin Hibbits falr = SEC_RD4(sc, SEC_FALR);
548*73bb2479SJustin Hibbits
549*73bb2479SJustin Hibbits device_printf(sc->sc_dev,
550*73bb2479SJustin Hibbits "bus fault: FADR=%#x FAR=%#jx FALR=%#x "
551*73bb2479SJustin Hibbits "(%s, %s, src=%s, blkid=%#x, %s, size=%u)\n",
552*73bb2479SJustin Hibbits fadr, (uintmax_t)far, falr,
553*73bb2479SJustin Hibbits sec_ferr_str[(fadr & FADR_FERR_M) >> FADR_FERR_S],
554*73bb2479SJustin Hibbits (fadr & FADR_DTYP) ? "control" : "message",
555*73bb2479SJustin Hibbits sec_jsrc_str[(fadr & FADR_JSRC_M) >> FADR_JSRC_S],
556*73bb2479SJustin Hibbits (fadr & FADR_BLKID_M) >> FADR_BLKID_S,
557*73bb2479SJustin Hibbits (fadr & FADR_TYP) ? "write" : "read",
558*73bb2479SJustin Hibbits (unsigned)(((fadr & FADR_FSZ_EXT_M) >>
559*73bb2479SJustin Hibbits (FADR_FSZ_EXT_S - 7)) | (fadr & FADR_FSZ_M)));
560*73bb2479SJustin Hibbits }
561*73bb2479SJustin Hibbits
562*73bb2479SJustin Hibbits }
563*73bb2479SJustin Hibbits
564*73bb2479SJustin Hibbits /*
565*73bb2479SJustin Hibbits * Decode a SEC job termination status word.
566*73bb2479SJustin Hibbits *
567*73bb2479SJustin Hibbits * Bits 0-3 (MSB) are the "source" of the report; the remaining bits are
568*73bb2479SJustin Hibbits * source-specific. Zero means clean completion.
569*73bb2479SJustin Hibbits *
570*73bb2479SJustin Hibbits * Two cases we care to distinguish:
571*73bb2479SJustin Hibbits * - CCB (source 2), ERRID field bits 28-31
572*73bb2479SJustin Hibbits * value 0xA is "ICV check failed" -> EBADMSG.
573*73bb2479SJustin Hibbits * - DECO (source 4), Error Code bits 24-31
574*73bb2479SJustin Hibbits * values F0h/F1h/FFh are informational warnings (IPsec TTL,
575*73bb2479SJustin Hibbits * 3GPP HFN, output-length rollover). The job actually completed,
576*73bb2479SJustin Hibbits * so map those to success.
577*73bb2479SJustin Hibbits *
578*73bb2479SJustin Hibbits * Everything else is logged and reported as EIO. Real per-code
579*73bb2479SJustin Hibbits * decoding of DECO/QI errors can be layered on as we hit them.
580*73bb2479SJustin Hibbits */
581*73bb2479SJustin Hibbits #define SEC_STAT_SOURCE(s) (((s) >> 28) & 0xf)
582*73bb2479SJustin Hibbits #define SEC_SRC_NONE 0x0
583*73bb2479SJustin Hibbits #define SEC_SRC_CCB 0x2
584*73bb2479SJustin Hibbits #define SEC_SRC_DECO 0x4
585*73bb2479SJustin Hibbits #define SEC_SRC_QI 0x5
586*73bb2479SJustin Hibbits #define SEC_SRC_JR 0x6
587*73bb2479SJustin Hibbits #define SEC_CCB_ERR_ICV_FAIL 0x0a
588*73bb2479SJustin Hibbits #define SEC_DECO_ERR_WARN_MIN 0xf0
589*73bb2479SJustin Hibbits
590*73bb2479SJustin Hibbits static int
sec_decode_status(struct sec_softc * sc,uint32_t status)591*73bb2479SJustin Hibbits sec_decode_status(struct sec_softc *sc, uint32_t status)
592*73bb2479SJustin Hibbits {
593*73bb2479SJustin Hibbits uint32_t source;
594*73bb2479SJustin Hibbits
595*73bb2479SJustin Hibbits if (status == 0)
596*73bb2479SJustin Hibbits return (0);
597*73bb2479SJustin Hibbits
598*73bb2479SJustin Hibbits source = SEC_STAT_SOURCE(status);
599*73bb2479SJustin Hibbits
600*73bb2479SJustin Hibbits switch (source) {
601*73bb2479SJustin Hibbits case SEC_SRC_CCB:
602*73bb2479SJustin Hibbits if ((status & 0xf) == SEC_CCB_ERR_ICV_FAIL)
603*73bb2479SJustin Hibbits return (EBADMSG);
604*73bb2479SJustin Hibbits break;
605*73bb2479SJustin Hibbits case SEC_SRC_DECO:
606*73bb2479SJustin Hibbits if ((status & 0xff) >= SEC_DECO_ERR_WARN_MIN)
607*73bb2479SJustin Hibbits return (0);
608*73bb2479SJustin Hibbits break;
609*73bb2479SJustin Hibbits }
610*73bb2479SJustin Hibbits
611*73bb2479SJustin Hibbits device_printf(sc->sc_dev,
612*73bb2479SJustin Hibbits "job termination status %#x (source %#x)\n", status, source);
613*73bb2479SJustin Hibbits return (EIO);
614*73bb2479SJustin Hibbits }
615*73bb2479SJustin Hibbits
616*73bb2479SJustin Hibbits /*
617*73bb2479SJustin Hibbits * Complete one job that SEC has finished processing.
618*73bb2479SJustin Hibbits */
619*73bb2479SJustin Hibbits void
sec_complete_one(struct sec_softc * sc,uint64_t desc_pa,uint32_t status)620*73bb2479SJustin Hibbits sec_complete_one(struct sec_softc *sc, uint64_t desc_pa, uint32_t status)
621*73bb2479SJustin Hibbits {
622*73bb2479SJustin Hibbits struct sec_job *job;
623*73bb2479SJustin Hibbits struct cryptop *crp;
624*73bb2479SJustin Hibbits const struct crypto_session_params *csp;
625*73bb2479SJustin Hibbits uint8_t expected[SEC_MAX_DIGEST];
626*73bb2479SJustin Hibbits int dlen;
627*73bb2479SJustin Hibbits
628*73bb2479SJustin Hibbits job = (struct sec_job *)PHYS_TO_DMAP((vm_paddr_t)desc_pa);
629*73bb2479SJustin Hibbits crp = job->crp;
630*73bb2479SJustin Hibbits
631*73bb2479SJustin Hibbits crp->crp_etype = sec_decode_status(sc, status);
632*73bb2479SJustin Hibbits
633*73bb2479SJustin Hibbits bus_dmamap_sync(sc->sc_dmatag, job->map,
634*73bb2479SJustin Hibbits BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
635*73bb2479SJustin Hibbits bus_dmamap_unload(sc->sc_dmatag, job->map);
636*73bb2479SJustin Hibbits bus_dmamap_destroy(sc->sc_dmatag, job->map);
637*73bb2479SJustin Hibbits
638*73bb2479SJustin Hibbits if (crp->crp_etype == 0) {
639*73bb2479SJustin Hibbits csp = crypto_get_params(crp->crp_session);
640*73bb2479SJustin Hibbits dlen = csp->csp_auth_mlen != 0 ? csp->csp_auth_mlen :
641*73bb2479SJustin Hibbits job->sess->digestlen;
642*73bb2479SJustin Hibbits switch (csp->csp_mode) {
643*73bb2479SJustin Hibbits case CSP_MODE_DIGEST:
644*73bb2479SJustin Hibbits if ((crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) != 0) {
645*73bb2479SJustin Hibbits crypto_copydata(crp, crp->crp_digest_start,
646*73bb2479SJustin Hibbits dlen, expected);
647*73bb2479SJustin Hibbits if (timingsafe_bcmp(job->digest, expected,
648*73bb2479SJustin Hibbits dlen) != 0)
649*73bb2479SJustin Hibbits crp->crp_etype = EBADMSG;
650*73bb2479SJustin Hibbits } else {
651*73bb2479SJustin Hibbits crypto_copyback(crp, crp->crp_digest_start,
652*73bb2479SJustin Hibbits dlen, job->digest);
653*73bb2479SJustin Hibbits }
654*73bb2479SJustin Hibbits break;
655*73bb2479SJustin Hibbits case CSP_MODE_ETA:
656*73bb2479SJustin Hibbits if ((crp->crp_op & CRYPTO_OP_ENCRYPT) != 0) {
657*73bb2479SJustin Hibbits crypto_copyback(crp, crp->crp_digest_start,
658*73bb2479SJustin Hibbits dlen, job->digest);
659*73bb2479SJustin Hibbits break;
660*73bb2479SJustin Hibbits }
661*73bb2479SJustin Hibbits crypto_copydata(crp, crp->crp_digest_start, dlen,
662*73bb2479SJustin Hibbits expected);
663*73bb2479SJustin Hibbits if (timingsafe_bcmp(job->digest, expected, dlen) != 0)
664*73bb2479SJustin Hibbits crp->crp_etype = EBADMSG;
665*73bb2479SJustin Hibbits break;
666*73bb2479SJustin Hibbits case CSP_MODE_AEAD:
667*73bb2479SJustin Hibbits if ((crp->crp_op & CRYPTO_OP_ENCRYPT) != 0)
668*73bb2479SJustin Hibbits crypto_copyback(crp, crp->crp_digest_start,
669*73bb2479SJustin Hibbits dlen, job->digest);
670*73bb2479SJustin Hibbits break;
671*73bb2479SJustin Hibbits }
672*73bb2479SJustin Hibbits }
673*73bb2479SJustin Hibbits
674*73bb2479SJustin Hibbits crypto_done(crp);
675*73bb2479SJustin Hibbits free(job, M_SEC);
676*73bb2479SJustin Hibbits }
677*73bb2479SJustin Hibbits
678*73bb2479SJustin Hibbits static bool
check_cipher(const struct crypto_session_params * csp)679*73bb2479SJustin Hibbits check_cipher(const struct crypto_session_params *csp)
680*73bb2479SJustin Hibbits {
681*73bb2479SJustin Hibbits
682*73bb2479SJustin Hibbits switch (csp->csp_cipher_alg) {
683*73bb2479SJustin Hibbits case CRYPTO_AES_CBC:
684*73bb2479SJustin Hibbits case CRYPTO_AES_ICM:
685*73bb2479SJustin Hibbits if (csp->csp_ivlen != AES_BLOCK_LEN)
686*73bb2479SJustin Hibbits return (false);
687*73bb2479SJustin Hibbits return (csp->csp_cipher_klen == 16 ||
688*73bb2479SJustin Hibbits csp->csp_cipher_klen == 24 ||
689*73bb2479SJustin Hibbits csp->csp_cipher_klen == 32);
690*73bb2479SJustin Hibbits case CRYPTO_AES_XTS:
691*73bb2479SJustin Hibbits if (csp->csp_ivlen != AES_XTS_IV_LEN)
692*73bb2479SJustin Hibbits return (false);
693*73bb2479SJustin Hibbits return (csp->csp_cipher_klen == 32 ||
694*73bb2479SJustin Hibbits csp->csp_cipher_klen == 64);
695*73bb2479SJustin Hibbits default:
696*73bb2479SJustin Hibbits return (false);
697*73bb2479SJustin Hibbits }
698*73bb2479SJustin Hibbits }
699*73bb2479SJustin Hibbits
700*73bb2479SJustin Hibbits static bool
check_aead(const struct crypto_session_params * csp)701*73bb2479SJustin Hibbits check_aead(const struct crypto_session_params *csp)
702*73bb2479SJustin Hibbits {
703*73bb2479SJustin Hibbits
704*73bb2479SJustin Hibbits switch (csp->csp_cipher_alg) {
705*73bb2479SJustin Hibbits case CRYPTO_AES_NIST_GCM_16:
706*73bb2479SJustin Hibbits if (csp->csp_auth_mlen != 0 &&
707*73bb2479SJustin Hibbits csp->csp_auth_mlen != AES_GMAC_HASH_LEN)
708*73bb2479SJustin Hibbits return (false);
709*73bb2479SJustin Hibbits return (csp->csp_cipher_klen == 16 ||
710*73bb2479SJustin Hibbits csp->csp_cipher_klen == 24 ||
711*73bb2479SJustin Hibbits csp->csp_cipher_klen == 32);
712*73bb2479SJustin Hibbits case CRYPTO_AES_CCM_16:
713*73bb2479SJustin Hibbits return (csp->csp_cipher_klen == 16 ||
714*73bb2479SJustin Hibbits csp->csp_cipher_klen == 24 ||
715*73bb2479SJustin Hibbits csp->csp_cipher_klen == 32);
716*73bb2479SJustin Hibbits default:
717*73bb2479SJustin Hibbits return (false);
718*73bb2479SJustin Hibbits }
719*73bb2479SJustin Hibbits }
720*73bb2479SJustin Hibbits
721*73bb2479SJustin Hibbits /*
722*73bb2479SJustin Hibbits * Map an opencrypto auth_alg to its SEC selector and digest length.
723*73bb2479SJustin Hibbits * skeylen is zero for a plain hash, which is what tells the two apart.
724*73bb2479SJustin Hibbits */
725*73bb2479SJustin Hibbits static bool
sec_hash_params(int auth_alg,uint32_t * alg,uint8_t * dlen,uint8_t * skeylen)726*73bb2479SJustin Hibbits sec_hash_params(int auth_alg, uint32_t *alg, uint8_t *dlen, uint8_t *skeylen)
727*73bb2479SJustin Hibbits {
728*73bb2479SJustin Hibbits
729*73bb2479SJustin Hibbits switch (auth_alg) {
730*73bb2479SJustin Hibbits case CRYPTO_SHA1_HMAC:
731*73bb2479SJustin Hibbits *alg = ALG_SHA1; *dlen = 20; *skeylen = 40; return (true);
732*73bb2479SJustin Hibbits case CRYPTO_SHA2_224_HMAC:
733*73bb2479SJustin Hibbits *alg = ALG_SHA224; *dlen = 28; *skeylen = 64; return (true);
734*73bb2479SJustin Hibbits case CRYPTO_SHA2_256_HMAC:
735*73bb2479SJustin Hibbits *alg = ALG_SHA256; *dlen = 32; *skeylen = 64; return (true);
736*73bb2479SJustin Hibbits case CRYPTO_SHA2_384_HMAC:
737*73bb2479SJustin Hibbits *alg = ALG_SHA384; *dlen = 48; *skeylen = 128; return (true);
738*73bb2479SJustin Hibbits case CRYPTO_SHA2_512_HMAC:
739*73bb2479SJustin Hibbits *alg = ALG_SHA512; *dlen = 64; *skeylen = 128; return (true);
740*73bb2479SJustin Hibbits case CRYPTO_SHA1:
741*73bb2479SJustin Hibbits *alg = ALG_SHA1; *dlen = 20; *skeylen = 0; return (true);
742*73bb2479SJustin Hibbits case CRYPTO_SHA2_224:
743*73bb2479SJustin Hibbits *alg = ALG_SHA224; *dlen = 28; *skeylen = 0; return (true);
744*73bb2479SJustin Hibbits case CRYPTO_SHA2_256:
745*73bb2479SJustin Hibbits *alg = ALG_SHA256; *dlen = 32; *skeylen = 0; return (true);
746*73bb2479SJustin Hibbits case CRYPTO_SHA2_384:
747*73bb2479SJustin Hibbits *alg = ALG_SHA384; *dlen = 48; *skeylen = 0; return (true);
748*73bb2479SJustin Hibbits case CRYPTO_SHA2_512:
749*73bb2479SJustin Hibbits *alg = ALG_SHA512; *dlen = 64; *skeylen = 0; return (true);
750*73bb2479SJustin Hibbits }
751*73bb2479SJustin Hibbits return (false);
752*73bb2479SJustin Hibbits }
753*73bb2479SJustin Hibbits
754*73bb2479SJustin Hibbits static bool
check_digest(const struct crypto_session_params * csp)755*73bb2479SJustin Hibbits check_digest(const struct crypto_session_params *csp)
756*73bb2479SJustin Hibbits {
757*73bb2479SJustin Hibbits uint32_t alg;
758*73bb2479SJustin Hibbits uint8_t dlen, skeylen;
759*73bb2479SJustin Hibbits
760*73bb2479SJustin Hibbits /* GMAC is AESA rather than MDHA, so it has its own constraints. */
761*73bb2479SJustin Hibbits if (csp->csp_auth_alg == CRYPTO_AES_NIST_GMAC) {
762*73bb2479SJustin Hibbits if (csp->csp_ivlen != AES_GCM_IV_LEN)
763*73bb2479SJustin Hibbits return (false);
764*73bb2479SJustin Hibbits if (csp->csp_auth_mlen > AES_GMAC_HASH_LEN)
765*73bb2479SJustin Hibbits return (false);
766*73bb2479SJustin Hibbits return (csp->csp_auth_klen == 16 ||
767*73bb2479SJustin Hibbits csp->csp_auth_klen == 24 ||
768*73bb2479SJustin Hibbits csp->csp_auth_klen == 32);
769*73bb2479SJustin Hibbits }
770*73bb2479SJustin Hibbits
771*73bb2479SJustin Hibbits if (!sec_hash_params(csp->csp_auth_alg, &alg, &dlen, &skeylen))
772*73bb2479SJustin Hibbits return (false);
773*73bb2479SJustin Hibbits /* Keyed variants require a key; plain hashes must not carry one. */
774*73bb2479SJustin Hibbits if ((skeylen != 0) != (csp->csp_auth_klen != 0))
775*73bb2479SJustin Hibbits return (false);
776*73bb2479SJustin Hibbits return (csp->csp_auth_mlen <= dlen);
777*73bb2479SJustin Hibbits }
778*73bb2479SJustin Hibbits
779*73bb2479SJustin Hibbits static bool
check_eta(const struct crypto_session_params * csp)780*73bb2479SJustin Hibbits check_eta(const struct crypto_session_params *csp)
781*73bb2479SJustin Hibbits {
782*73bb2479SJustin Hibbits
783*73bb2479SJustin Hibbits /*
784*73bb2479SJustin Hibbits * ESN appends four bytes from crp_esn to the MAC input, which the
785*73bb2479SJustin Hibbits * descriptor has no way to splice in, so refuse rather than
786*73bb2479SJustin Hibbits * authenticate the wrong span.
787*73bb2479SJustin Hibbits */
788*73bb2479SJustin Hibbits if ((csp->csp_flags & CSP_F_ESN) != 0)
789*73bb2479SJustin Hibbits return (false);
790*73bb2479SJustin Hibbits /*
791*73bb2479SJustin Hibbits * XTS carries its tweak in the class 1 context and pairs with no
792*73bb2479SJustin Hibbits * MAC; its shared descriptor is shaped differently.
793*73bb2479SJustin Hibbits */
794*73bb2479SJustin Hibbits if (csp->csp_cipher_alg == CRYPTO_AES_XTS)
795*73bb2479SJustin Hibbits return (false);
796*73bb2479SJustin Hibbits /* The MAC half has to be keyed; a bare hash authenticates nothing. */
797*73bb2479SJustin Hibbits if (csp->csp_auth_klen == 0)
798*73bb2479SJustin Hibbits return (false);
799*73bb2479SJustin Hibbits return (check_cipher(csp) && check_digest(csp));
800*73bb2479SJustin Hibbits }
801*73bb2479SJustin Hibbits
802*73bb2479SJustin Hibbits /*
803*73bb2479SJustin Hibbits * Software split-key generator: computes the HMAC ipad/opad hash-state
804*73bb2479SJustin Hibbits * halves in software and packs them big-endian for SEC's Class 2 KEY
805*73bb2479SJustin Hibbits * register.
806*73bb2479SJustin Hibbits *
807*73bb2479SJustin Hibbits * Runs the CPU through one SHA block per pad (two total). Much cheaper than
808*73bb2479SJustin Hibbits * the round trip through the job ring for setup.
809*73bb2479SJustin Hibbits */
810*73bb2479SJustin Hibbits static void
sec_pack_state32(uint8_t * dst,const uint32_t * src,unsigned int nbytes)811*73bb2479SJustin Hibbits sec_pack_state32(uint8_t *dst, const uint32_t *src, unsigned int nbytes)
812*73bb2479SJustin Hibbits {
813*73bb2479SJustin Hibbits unsigned int i;
814*73bb2479SJustin Hibbits
815*73bb2479SJustin Hibbits for (i = 0; i < nbytes; i += 4)
816*73bb2479SJustin Hibbits be32enc(dst + i, src[i / 4]);
817*73bb2479SJustin Hibbits }
818*73bb2479SJustin Hibbits
819*73bb2479SJustin Hibbits static void
sec_pack_state64(uint8_t * dst,const uint64_t * src,unsigned int nbytes)820*73bb2479SJustin Hibbits sec_pack_state64(uint8_t *dst, const uint64_t *src, unsigned int nbytes)
821*73bb2479SJustin Hibbits {
822*73bb2479SJustin Hibbits unsigned int i;
823*73bb2479SJustin Hibbits
824*73bb2479SJustin Hibbits for (i = 0; i < nbytes; i += 8)
825*73bb2479SJustin Hibbits be64enc(dst + i, src[i / 8]);
826*73bb2479SJustin Hibbits }
827*73bb2479SJustin Hibbits
828*73bb2479SJustin Hibbits static void
sec_sw_gen_split_key(const struct crypto_session_params * csp,uint8_t * out,size_t out_len)829*73bb2479SJustin Hibbits sec_sw_gen_split_key(const struct crypto_session_params *csp,
830*73bb2479SJustin Hibbits uint8_t *out, size_t out_len)
831*73bb2479SJustin Hibbits {
832*73bb2479SJustin Hibbits union authctx ictx, octx;
833*73bb2479SJustin Hibbits const struct auth_hash *axf;
834*73bb2479SJustin Hibbits uint8_t half;
835*73bb2479SJustin Hibbits
836*73bb2479SJustin Hibbits axf = crypto_auth_hash(csp);
837*73bb2479SJustin Hibbits hmac_init_ipad(axf, csp->csp_auth_key, csp->csp_auth_klen, &ictx);
838*73bb2479SJustin Hibbits hmac_init_opad(axf, csp->csp_auth_key, csp->csp_auth_klen, &octx);
839*73bb2479SJustin Hibbits
840*73bb2479SJustin Hibbits KASSERT(out_len % 2 == 0, ("split key len must be even"));
841*73bb2479SJustin Hibbits half = out_len / 2;
842*73bb2479SJustin Hibbits
843*73bb2479SJustin Hibbits switch (csp->csp_auth_alg) {
844*73bb2479SJustin Hibbits case CRYPTO_SHA1_HMAC:
845*73bb2479SJustin Hibbits sec_pack_state32(out, ictx.sha1ctx.h.b32, half);
846*73bb2479SJustin Hibbits sec_pack_state32(out + half, octx.sha1ctx.h.b32, half);
847*73bb2479SJustin Hibbits break;
848*73bb2479SJustin Hibbits case CRYPTO_SHA2_224_HMAC:
849*73bb2479SJustin Hibbits sec_pack_state32(out, ictx.sha224ctx.state, half);
850*73bb2479SJustin Hibbits sec_pack_state32(out + half, octx.sha224ctx.state, half);
851*73bb2479SJustin Hibbits break;
852*73bb2479SJustin Hibbits case CRYPTO_SHA2_256_HMAC:
853*73bb2479SJustin Hibbits sec_pack_state32(out, ictx.sha256ctx.state, half);
854*73bb2479SJustin Hibbits sec_pack_state32(out + half, octx.sha256ctx.state, half);
855*73bb2479SJustin Hibbits break;
856*73bb2479SJustin Hibbits case CRYPTO_SHA2_384_HMAC:
857*73bb2479SJustin Hibbits sec_pack_state64(out, ictx.sha384ctx.state, half);
858*73bb2479SJustin Hibbits sec_pack_state64(out + half, octx.sha384ctx.state, half);
859*73bb2479SJustin Hibbits break;
860*73bb2479SJustin Hibbits case CRYPTO_SHA2_512_HMAC:
861*73bb2479SJustin Hibbits sec_pack_state64(out, ictx.sha512ctx.state, half);
862*73bb2479SJustin Hibbits sec_pack_state64(out + half, octx.sha512ctx.state, half);
863*73bb2479SJustin Hibbits break;
864*73bb2479SJustin Hibbits }
865*73bb2479SJustin Hibbits
866*73bb2479SJustin Hibbits explicit_bzero(&ictx, sizeof(ictx));
867*73bb2479SJustin Hibbits explicit_bzero(&octx, sizeof(octx));
868*73bb2479SJustin Hibbits }
869*73bb2479SJustin Hibbits
870*73bb2479SJustin Hibbits /*
871*73bb2479SJustin Hibbits * Descriptor builder. Word 0 is the HEADER and is filled in last, since its
872*73bb2479SJustin Hibbits * length field is only known once the body has been emitted.
873*73bb2479SJustin Hibbits */
874*73bb2479SJustin Hibbits struct sec_desc_builder {
875*73bb2479SJustin Hibbits uint32_t *desc;
876*73bb2479SJustin Hibbits unsigned int idx; /* next word to write */
877*73bb2479SJustin Hibbits unsigned int max;
878*73bb2479SJustin Hibbits int err;
879*73bb2479SJustin Hibbits };
880*73bb2479SJustin Hibbits
881*73bb2479SJustin Hibbits static inline void
sec_desc_init(struct sec_desc_builder * b,uint32_t * desc,unsigned int max)882*73bb2479SJustin Hibbits sec_desc_init(struct sec_desc_builder *b, uint32_t *desc, unsigned int max)
883*73bb2479SJustin Hibbits {
884*73bb2479SJustin Hibbits
885*73bb2479SJustin Hibbits b->desc = desc;
886*73bb2479SJustin Hibbits b->idx = 1; /* reserve word 0 for the HEADER */
887*73bb2479SJustin Hibbits b->max = max;
888*73bb2479SJustin Hibbits b->err = 0;
889*73bb2479SJustin Hibbits }
890*73bb2479SJustin Hibbits
891*73bb2479SJustin Hibbits static inline void
sec_desc_word(struct sec_desc_builder * b,uint32_t w)892*73bb2479SJustin Hibbits sec_desc_word(struct sec_desc_builder *b, uint32_t w)
893*73bb2479SJustin Hibbits {
894*73bb2479SJustin Hibbits
895*73bb2479SJustin Hibbits if (b->err != 0)
896*73bb2479SJustin Hibbits return;
897*73bb2479SJustin Hibbits if (b->idx >= b->max) {
898*73bb2479SJustin Hibbits b->err = ENOSPC;
899*73bb2479SJustin Hibbits return;
900*73bb2479SJustin Hibbits }
901*73bb2479SJustin Hibbits b->desc[b->idx++] = w;
902*73bb2479SJustin Hibbits }
903*73bb2479SJustin Hibbits
904*73bb2479SJustin Hibbits /* Emit a KEY command with the key inline after it. */
905*73bb2479SJustin Hibbits static inline void
sec_desc_key_imm(struct sec_desc_builder * b,uint32_t class,const void * key,unsigned int keylen)906*73bb2479SJustin Hibbits sec_desc_key_imm(struct sec_desc_builder *b, uint32_t class,
907*73bb2479SJustin Hibbits const void *key, unsigned int keylen)
908*73bb2479SJustin Hibbits {
909*73bb2479SJustin Hibbits unsigned int nwords = howmany(keylen, sizeof(uint32_t));
910*73bb2479SJustin Hibbits
911*73bb2479SJustin Hibbits if (b->err != 0)
912*73bb2479SJustin Hibbits return;
913*73bb2479SJustin Hibbits if (b->idx + 1 + nwords > b->max) {
914*73bb2479SJustin Hibbits b->err = ENOSPC;
915*73bb2479SJustin Hibbits return;
916*73bb2479SJustin Hibbits }
917*73bb2479SJustin Hibbits b->desc[b->idx++] = CMD_DESC(CMD_KEY) | class | KEY_IMM |
918*73bb2479SJustin Hibbits (keylen & KEY_LENGTH_M);
919*73bb2479SJustin Hibbits memcpy(&b->desc[b->idx], key, keylen);
920*73bb2479SJustin Hibbits b->idx += nwords;
921*73bb2479SJustin Hibbits }
922*73bb2479SJustin Hibbits
923*73bb2479SJustin Hibbits static int
sec_desc_finalize_shared(struct sec_desc_builder * b,uint32_t flags,uint32_t * sdlenp)924*73bb2479SJustin Hibbits sec_desc_finalize_shared(struct sec_desc_builder *b, uint32_t flags,
925*73bb2479SJustin Hibbits uint32_t *sdlenp)
926*73bb2479SJustin Hibbits {
927*73bb2479SJustin Hibbits
928*73bb2479SJustin Hibbits if (b->err != 0)
929*73bb2479SJustin Hibbits return (b->err);
930*73bb2479SJustin Hibbits if (b->idx > SEC_MAX_SHDESC_WORDS)
931*73bb2479SJustin Hibbits return (ENOSPC);
932*73bb2479SJustin Hibbits b->desc[0] = CMD_DESC(CMD_SHARED_HEADER) | HEADER_ONE |
933*73bb2479SJustin Hibbits (flags & (HEADER_SHARE_M | HEADER_SC)) |
934*73bb2479SJustin Hibbits (b->idx & HEADER_DESCLEN_M);
935*73bb2479SJustin Hibbits *sdlenp = b->idx;
936*73bb2479SJustin Hibbits return (0);
937*73bb2479SJustin Hibbits }
938*73bb2479SJustin Hibbits
939*73bb2479SJustin Hibbits static int
sec_desc_finalize_job(struct sec_desc_builder * b,uint32_t word,uint32_t * dlenp)940*73bb2479SJustin Hibbits sec_desc_finalize_job(struct sec_desc_builder *b, uint32_t word,
941*73bb2479SJustin Hibbits uint32_t *dlenp)
942*73bb2479SJustin Hibbits {
943*73bb2479SJustin Hibbits
944*73bb2479SJustin Hibbits if (b->err != 0)
945*73bb2479SJustin Hibbits return (b->err);
946*73bb2479SJustin Hibbits if (b->idx > SEC_MAX_DESC_WORDS)
947*73bb2479SJustin Hibbits return (ENOSPC);
948*73bb2479SJustin Hibbits b->desc[0] = CMD_DESC(CMD_DESC_HEADER) | HEADER_ONE |
949*73bb2479SJustin Hibbits word | (b->idx & HEADER_DESCLEN_M);
950*73bb2479SJustin Hibbits *dlenp = b->idx;
951*73bb2479SJustin Hibbits return (0);
952*73bb2479SJustin Hibbits }
953*73bb2479SJustin Hibbits
954*73bb2479SJustin Hibbits
955*73bb2479SJustin Hibbits /*
956*73bb2479SJustin Hibbits * Job descriptor builder conveniences.
957*73bb2479SJustin Hibbits */
958*73bb2479SJustin Hibbits
959*73bb2479SJustin Hibbits static inline void
sec_jd_ptr(struct sec_desc_builder * b,vm_paddr_t pa)960*73bb2479SJustin Hibbits sec_jd_ptr(struct sec_desc_builder *b, vm_paddr_t pa)
961*73bb2479SJustin Hibbits {
962*73bb2479SJustin Hibbits sec_desc_word(b, (uint32_t)(pa >> 32));
963*73bb2479SJustin Hibbits sec_desc_word(b, (uint32_t)pa);
964*73bb2479SJustin Hibbits }
965*73bb2479SJustin Hibbits
966*73bb2479SJustin Hibbits /* Build a SEQ_IN/SEQ_OUT descriptor command. */
967*73bb2479SJustin Hibbits static inline void
sec_jd_seq(struct sec_desc_builder * b,bool inout,uint32_t flags,vm_paddr_t ptr,uint32_t len)968*73bb2479SJustin Hibbits sec_jd_seq(struct sec_desc_builder *b, bool inout, uint32_t flags,
969*73bb2479SJustin Hibbits vm_paddr_t ptr, uint32_t len)
970*73bb2479SJustin Hibbits {
971*73bb2479SJustin Hibbits sec_desc_word(b,
972*73bb2479SJustin Hibbits CMD_DESC(inout ? CMD_SEQ_OUT_PTR : CMD_SEQ_IN_PTR) | flags);
973*73bb2479SJustin Hibbits sec_jd_ptr(b, ptr);
974*73bb2479SJustin Hibbits sec_desc_word(b, len);
975*73bb2479SJustin Hibbits }
976*73bb2479SJustin Hibbits
977*73bb2479SJustin Hibbits static inline void
sec_jd_load(struct sec_desc_builder * b,bool seq,uint32_t class,uint32_t flags,uint32_t dst,uint32_t off,uint32_t len,vm_paddr_t ptr)978*73bb2479SJustin Hibbits sec_jd_load(struct sec_desc_builder *b, bool seq, uint32_t class,
979*73bb2479SJustin Hibbits uint32_t flags, uint32_t dst, uint32_t off, uint32_t len, vm_paddr_t ptr)
980*73bb2479SJustin Hibbits {
981*73bb2479SJustin Hibbits uint32_t cmd = seq ? CMD_SEQ_LOAD : CMD_LOAD;
982*73bb2479SJustin Hibbits
983*73bb2479SJustin Hibbits sec_desc_word(b, CMD_DESC(cmd) | class | flags | dst |
984*73bb2479SJustin Hibbits (off << LOAD_OFFSET_S) | (len & LOAD_LENGTH_M));
985*73bb2479SJustin Hibbits if (!seq)
986*73bb2479SJustin Hibbits sec_jd_ptr(b, ptr);
987*73bb2479SJustin Hibbits }
988*73bb2479SJustin Hibbits
989*73bb2479SJustin Hibbits static inline void
sec_jd_store(struct sec_desc_builder * b,bool seq,uint32_t class,uint32_t src,uint32_t off,uint32_t len,vm_paddr_t ptr)990*73bb2479SJustin Hibbits sec_jd_store(struct sec_desc_builder *b, bool seq, uint32_t class, uint32_t src,
991*73bb2479SJustin Hibbits uint32_t off, uint32_t len, vm_paddr_t ptr)
992*73bb2479SJustin Hibbits {
993*73bb2479SJustin Hibbits uint32_t cmd = seq ? CMD_SEQ_STORE : CMD_STORE;
994*73bb2479SJustin Hibbits
995*73bb2479SJustin Hibbits sec_desc_word(b, CMD_DESC(cmd) | class | src |
996*73bb2479SJustin Hibbits (off << LOAD_OFFSET_S) | (len & LOAD_LENGTH_M));
997*73bb2479SJustin Hibbits if (!seq)
998*73bb2479SJustin Hibbits sec_jd_ptr(b, ptr);
999*73bb2479SJustin Hibbits }
1000*73bb2479SJustin Hibbits
1001*73bb2479SJustin Hibbits static inline void
sec_jd_fifo(struct sec_desc_builder * b,uint32_t cmd,uint32_t len)1002*73bb2479SJustin Hibbits sec_jd_fifo(struct sec_desc_builder *b, uint32_t cmd, uint32_t len)
1003*73bb2479SJustin Hibbits {
1004*73bb2479SJustin Hibbits
1005*73bb2479SJustin Hibbits if (len > 0xffff) {
1006*73bb2479SJustin Hibbits sec_desc_word(b, cmd | FIFO_EXT);
1007*73bb2479SJustin Hibbits sec_desc_word(b, len);
1008*73bb2479SJustin Hibbits } else {
1009*73bb2479SJustin Hibbits sec_desc_word(b, cmd | len);
1010*73bb2479SJustin Hibbits }
1011*73bb2479SJustin Hibbits }
1012*73bb2479SJustin Hibbits
1013*73bb2479SJustin Hibbits /*
1014*73bb2479SJustin Hibbits * AES-XTS Class 1 context layout (byte offsets into the CTX register).
1015*73bb2479SJustin Hibbits * The 16-byte tweak is split either side of the sector-size field.
1016*73bb2479SJustin Hibbits */
1017*73bb2479SJustin Hibbits #define SEC_XTS_CTX_TWEAK_LO 0x20
1018*73bb2479SJustin Hibbits #define SEC_XTS_CTX_SECTOR 0x28
1019*73bb2479SJustin Hibbits #define SEC_XTS_CTX_TWEAK_HI 0x30
1020*73bb2479SJustin Hibbits
1021*73bb2479SJustin Hibbits /*
1022*73bb2479SJustin Hibbits * Sector size tells the hardware how often to re-derive the tweak.
1023*73bb2479SJustin Hibbits * opencrypto's XTS runs one continuous tweak over the whole request, so
1024*73bb2479SJustin Hibbits * this only needs to exceed any payload we accept; sec_jd_build_cipher
1025*73bb2479SJustin Hibbits * rejects requests that would cross the boundary.
1026*73bb2479SJustin Hibbits */
1027*73bb2479SJustin Hibbits #define SEC_XTS_SECTOR_SIZE 0x8000
1028*73bb2479SJustin Hibbits
1029*73bb2479SJustin Hibbits /*
1030*73bb2479SJustin Hibbits * Build the CCM context block and formatted-AAD length prefix.
1031*73bb2479SJustin Hibbits *
1032*73bb2479SJustin Hibbits * The hardware wants B0 in context dwords 0-1 and the initial counter
1033*73bb2479SJustin Hibbits * CTR0 in dwords 2-3, with dwords 4-6 zeroed because AS is
1034*73bb2479SJustin Hibbits * INITIALIZE/FINALIZE. Both blocks are laid out per RFC 3610: with a
1035*73bb2479SJustin Hibbits * nonce of n bytes, the length field occupies the trailing L = 15 - n
1036*73bb2479SJustin Hibbits * bytes and the flags byte carries L-1 plus, for B0, the encoded tag
1037*73bb2479SJustin Hibbits * size and an AAD-present flag.
1038*73bb2479SJustin Hibbits *
1039*73bb2479SJustin Hibbits * The AAD itself is prefixed with its length and then zero-padded to a
1040*73bb2479SJustin Hibbits * 16-byte boundary by the hardware, which pads AAD and IV FIFO loads
1041*73bb2479SJustin Hibbits * when the flush-class-1 bit is set.
1042*73bb2479SJustin Hibbits */
1043*73bb2479SJustin Hibbits static int
sec_ccm_prep(struct sec_job * job,const struct crypto_session_params * csp)1044*73bb2479SJustin Hibbits sec_ccm_prep(struct sec_job *job, const struct crypto_session_params *csp)
1045*73bb2479SJustin Hibbits {
1046*73bb2479SJustin Hibbits uint8_t *b0 = job->ccm_ctx;
1047*73bb2479SJustin Hibbits uint8_t *ctr0 = job->ccm_ctx + 16;
1048*73bb2479SJustin Hibbits uint32_t aadlen = job->crp->crp_aad_length;
1049*73bb2479SJustin Hibbits uint64_t paylen = job->crp->crp_payload_length;
1050*73bb2479SJustin Hibbits u_int i, lfield = 15 - csp->csp_ivlen;
1051*73bb2479SJustin Hibbits
1052*73bb2479SJustin Hibbits if (aadlen > SEC_CCM_AAD_MAX)
1053*73bb2479SJustin Hibbits return (EOPNOTSUPP);
1054*73bb2479SJustin Hibbits /*
1055*73bb2479SJustin Hibbits * B0 carries the payload length in its trailing lfield bytes, so
1056*73bb2479SJustin Hibbits * the nonce is what really caps the payload: a 13-byte nonce
1057*73bb2479SJustin Hibbits * leaves two bytes and stops at 64 KB, while the usual 12-byte one
1058*73bb2479SJustin Hibbits * leaves three and reaches 16 MB.
1059*73bb2479SJustin Hibbits */
1060*73bb2479SJustin Hibbits if (lfield < sizeof(paylen) && paylen >= (uint64_t)1 << (8 * lfield))
1061*73bb2479SJustin Hibbits return (EOPNOTSUPP);
1062*73bb2479SJustin Hibbits
1063*73bb2479SJustin Hibbits memset(job->ccm_ctx, 0, sizeof(job->ccm_ctx));
1064*73bb2479SJustin Hibbits
1065*73bb2479SJustin Hibbits b0[0] = (aadlen > 0 ? 0x40 : 0x00) |
1066*73bb2479SJustin Hibbits (((job->sess->digestlen - 2) / 2) << 3) | (lfield - 1);
1067*73bb2479SJustin Hibbits memcpy(b0 + 1, job->iv, csp->csp_ivlen);
1068*73bb2479SJustin Hibbits for (i = 0; i < lfield; i++)
1069*73bb2479SJustin Hibbits b0[15 - i] = (paylen >> (8 * i)) & 0xff;
1070*73bb2479SJustin Hibbits
1071*73bb2479SJustin Hibbits ctr0[0] = lfield - 1;
1072*73bb2479SJustin Hibbits memcpy(ctr0 + 1, job->iv, csp->csp_ivlen);
1073*73bb2479SJustin Hibbits
1074*73bb2479SJustin Hibbits be16enc(job->ccm_alen, aadlen);
1075*73bb2479SJustin Hibbits return (0);
1076*73bb2479SJustin Hibbits }
1077*73bb2479SJustin Hibbits
1078*73bb2479SJustin Hibbits /*
1079*73bb2479SJustin Hibbits * Bytes of IV the input sequence carries. XTS is the odd one out:
1080*73bb2479SJustin Hibbits * opencrypto's IV is just the 8-byte block number, but the hardware
1081*73bb2479SJustin Hibbits * loads both halves of the 16-byte tweak from the sequence.
1082*73bb2479SJustin Hibbits */
1083*73bb2479SJustin Hibbits static uint32_t
sec_cipher_ivlen(const struct crypto_session_params * csp)1084*73bb2479SJustin Hibbits sec_cipher_ivlen(const struct crypto_session_params *csp)
1085*73bb2479SJustin Hibbits {
1086*73bb2479SJustin Hibbits
1087*73bb2479SJustin Hibbits if (csp->csp_cipher_alg == CRYPTO_AES_XTS)
1088*73bb2479SJustin Hibbits return (AES_BLOCK_LEN);
1089*73bb2479SJustin Hibbits return (csp->csp_ivlen);
1090*73bb2479SJustin Hibbits }
1091*73bb2479SJustin Hibbits
1092*73bb2479SJustin Hibbits /*
1093*73bb2479SJustin Hibbits * Expand opencrypto's 8-byte XTS IV in place into the 16-byte tweak the
1094*73bb2479SJustin Hibbits * hardware expects. The IV holds a block number in host order
1095*73bb2479SJustin Hibbits * (xform_aes_xts.c:aes_xts_reinit) and the tweak is that number's
1096*73bb2479SJustin Hibbits * little-endian encoding followed by zeroes.
1097*73bb2479SJustin Hibbits */
1098*73bb2479SJustin Hibbits static void
sec_xts_tweak(uint8_t * iv)1099*73bb2479SJustin Hibbits sec_xts_tweak(uint8_t *iv)
1100*73bb2479SJustin Hibbits {
1101*73bb2479SJustin Hibbits uint64_t blocknum;
1102*73bb2479SJustin Hibbits
1103*73bb2479SJustin Hibbits memcpy(&blocknum, iv, sizeof(blocknum));
1104*73bb2479SJustin Hibbits le64enc(iv, blocknum);
1105*73bb2479SJustin Hibbits memset(iv + sizeof(blocknum), 0, AES_BLOCK_LEN - sizeof(blocknum));
1106*73bb2479SJustin Hibbits }
1107*73bb2479SJustin Hibbits
1108*73bb2479SJustin Hibbits static uint32_t
sec_cipher_ctx_offset(uint32_t cipher_alg)1109*73bb2479SJustin Hibbits sec_cipher_ctx_offset(uint32_t cipher_alg)
1110*73bb2479SJustin Hibbits {
1111*73bb2479SJustin Hibbits switch (cipher_alg) {
1112*73bb2479SJustin Hibbits case CRYPTO_AES_ICM:
1113*73bb2479SJustin Hibbits return (16);
1114*73bb2479SJustin Hibbits };
1115*73bb2479SJustin Hibbits
1116*73bb2479SJustin Hibbits return (0);
1117*73bb2479SJustin Hibbits }
1118*73bb2479SJustin Hibbits
1119*73bb2479SJustin Hibbits /* Per-mode shared-descriptor builders. */
1120*73bb2479SJustin Hibbits /*
1121*73bb2479SJustin Hibbits * Cipher shared descriptor has the following format:
1122*73bb2479SJustin Hibbits * [0] - Header
1123*73bb2479SJustin Hibbits * [1..klen] - KEY descriptor + key
1124*73bb2479SJustin Hibbits * [XTS:..5] -- XTS specific
1125*73bb2479SJustin Hibbits * [0..2] - LOAD XTS context
1126*73bb2479SJustin Hibbits * [3..4] - LOAD XTS tweak
1127*73bb2479SJustin Hibbits * [!XTS:1] -- Load IV into Context register
1128*73bb2479SJustin Hibbits * [] - Operation
1129*73bb2479SJustin Hibbits * [] - MATH - Move SIL register to VSIL for FIFO IN
1130*73bb2479SJustin Hibbits * [] - MATH - Move SOL register to VSOL for FIFO OUT
1131*73bb2479SJustin Hibbits * [] - FIFO LOAD
1132*73bb2479SJustin Hibbits * [] - FIFO STORE
1133*73bb2479SJustin Hibbits */
1134*73bb2479SJustin Hibbits static int
sec_shd_build_cipher(struct sec_session * sess,const struct crypto_session_params * csp,int enc,uint32_t * sdlenp)1135*73bb2479SJustin Hibbits sec_shd_build_cipher(struct sec_session *sess,
1136*73bb2479SJustin Hibbits const struct crypto_session_params *csp, int enc, uint32_t *sdlenp)
1137*73bb2479SJustin Hibbits {
1138*73bb2479SJustin Hibbits struct sec_desc_builder b;
1139*73bb2479SJustin Hibbits uint32_t flags, op;
1140*73bb2479SJustin Hibbits uint32_t ctx_offset;
1141*73bb2479SJustin Hibbits
1142*73bb2479SJustin Hibbits switch (csp->csp_cipher_alg) {
1143*73bb2479SJustin Hibbits case CRYPTO_AES_CBC:
1144*73bb2479SJustin Hibbits op = CMD_DESC(CMD_OPERATION) | ALG_AES |
1145*73bb2479SJustin Hibbits AAI_AES_CBC | AS_INIT_FINAL;
1146*73bb2479SJustin Hibbits break;
1147*73bb2479SJustin Hibbits case CRYPTO_AES_ICM:
1148*73bb2479SJustin Hibbits op = CMD_DESC(CMD_OPERATION) | ALG_AES |
1149*73bb2479SJustin Hibbits AAI_AES_CTR | AS_INIT_FINAL;
1150*73bb2479SJustin Hibbits break;
1151*73bb2479SJustin Hibbits case CRYPTO_AES_XTS:
1152*73bb2479SJustin Hibbits op = CMD_DESC(CMD_OPERATION) | ALG_AES |
1153*73bb2479SJustin Hibbits AAI_AES_XTS | AS_INIT_FINAL;
1154*73bb2479SJustin Hibbits break;
1155*73bb2479SJustin Hibbits default:
1156*73bb2479SJustin Hibbits return (EOPNOTSUPP);
1157*73bb2479SJustin Hibbits }
1158*73bb2479SJustin Hibbits
1159*73bb2479SJustin Hibbits ctx_offset = sec_cipher_ctx_offset(csp->csp_cipher_alg);
1160*73bb2479SJustin Hibbits
1161*73bb2479SJustin Hibbits if (enc)
1162*73bb2479SJustin Hibbits op |= OP_ENC;
1163*73bb2479SJustin Hibbits
1164*73bb2479SJustin Hibbits sec_desc_init(&b, sess->ctx[enc].shd, SEC_MAX_SHDESC_WORDS);
1165*73bb2479SJustin Hibbits
1166*73bb2479SJustin Hibbits if (csp->csp_cipher_klen > 0)
1167*73bb2479SJustin Hibbits sec_desc_key_imm(&b, KEY_CLASS_1, csp->csp_cipher_key,
1168*73bb2479SJustin Hibbits csp->csp_cipher_klen);
1169*73bb2479SJustin Hibbits
1170*73bb2479SJustin Hibbits if (csp->csp_cipher_alg == CRYPTO_AES_XTS) {
1171*73bb2479SJustin Hibbits sec_jd_load(&b, false, LOAD_CLASS_1, LOAD_IMM, LOAD_CTX,
1172*73bb2479SJustin Hibbits SEC_XTS_CTX_SECTOR, 8, SEC_XTS_SECTOR_SIZE);
1173*73bb2479SJustin Hibbits
1174*73bb2479SJustin Hibbits sec_jd_load(&b, true, LOAD_CLASS_1, 0, LOAD_CTX,
1175*73bb2479SJustin Hibbits SEC_XTS_CTX_TWEAK_LO, 8, 0);
1176*73bb2479SJustin Hibbits sec_jd_load(&b, true, LOAD_CLASS_1, 0, LOAD_CTX,
1177*73bb2479SJustin Hibbits SEC_XTS_CTX_TWEAK_HI, 8, 0);
1178*73bb2479SJustin Hibbits } else {
1179*73bb2479SJustin Hibbits sec_jd_load(&b, true, LOAD_CLASS_1, 0, LOAD_CTX, ctx_offset,
1180*73bb2479SJustin Hibbits csp->csp_ivlen, 0);
1181*73bb2479SJustin Hibbits }
1182*73bb2479SJustin Hibbits
1183*73bb2479SJustin Hibbits sec_desc_word(&b, op);
1184*73bb2479SJustin Hibbits
1185*73bb2479SJustin Hibbits /*
1186*73bb2479SJustin Hibbits * Copy SIL into VSIL and VSOL so the following VLF-flagged FIFO
1187*73bb2479SJustin Hibbits * commands know how many bytes to move. VLF reads the VS*L
1188*73bb2479SJustin Hibbits * registers, so we need to get the values from the SEQ registers
1189*73bb2479SJustin Hibbits * the SEQ IN/OUT PTR descriptors populate.
1190*73bb2479SJustin Hibbits */
1191*73bb2479SJustin Hibbits sec_desc_word(&b, CMD_DESC(CMD_MATH) | MATH_FN_ADD | MATH_SRC0_SIL |
1192*73bb2479SJustin Hibbits MATH_SRC1_ZERO | MATH_DEST_VSIL | MATH_LEN_4);
1193*73bb2479SJustin Hibbits sec_desc_word(&b, CMD_DESC(CMD_MATH) | MATH_FN_ADD | MATH_SRC0_SIL |
1194*73bb2479SJustin Hibbits MATH_SRC1_ZERO | MATH_DEST_VSOL | MATH_LEN_4);
1195*73bb2479SJustin Hibbits
1196*73bb2479SJustin Hibbits sec_desc_word(&b, CMD_DESC(CMD_SEQ_FIFO_LOAD) | FIFOLD_CLASS_1 |
1197*73bb2479SJustin Hibbits FIFOLD_VLF | FIFOLD_TYPE_MSG | FIFOLD_LC1);
1198*73bb2479SJustin Hibbits
1199*73bb2479SJustin Hibbits sec_desc_word(&b, CMD_DESC(CMD_SEQ_FIFO_STORE) | FIFOST_VLF |
1200*73bb2479SJustin Hibbits FIFOST_TYPE_MSG_DATA);
1201*73bb2479SJustin Hibbits
1202*73bb2479SJustin Hibbits /* XTS keeps its tweak in the context, so the CCB has to save it. */
1203*73bb2479SJustin Hibbits flags = HEADER_SHARE_SERIAL;
1204*73bb2479SJustin Hibbits if (csp->csp_cipher_alg == CRYPTO_AES_XTS)
1205*73bb2479SJustin Hibbits flags |= HEADER_SC;
1206*73bb2479SJustin Hibbits
1207*73bb2479SJustin Hibbits return (sec_desc_finalize_shared(&b, flags, sdlenp));
1208*73bb2479SJustin Hibbits }
1209*73bb2479SJustin Hibbits
1210*73bb2479SJustin Hibbits /*
1211*73bb2479SJustin Hibbits * Digest shared descriptor. The split key is computed in software at
1212*73bb2479SJustin Hibbits * session setup, so MDHA is told it is precomputed and skips the
1213*73bb2479SJustin Hibbits * ipad/opad expansion.
1214*73bb2479SJustin Hibbits */
1215*73bb2479SJustin Hibbits static int
sec_shd_build_digest(struct sec_session * sess,const struct crypto_session_params * csp,int enc,uint32_t * sdlenp)1216*73bb2479SJustin Hibbits sec_shd_build_digest(struct sec_session *sess,
1217*73bb2479SJustin Hibbits const struct crypto_session_params *csp, int enc, uint32_t *sdlenp)
1218*73bb2479SJustin Hibbits {
1219*73bb2479SJustin Hibbits struct sec_desc_builder b;
1220*73bb2479SJustin Hibbits uint32_t alg;
1221*73bb2479SJustin Hibbits uint8_t dlen, skeylen;
1222*73bb2479SJustin Hibbits
1223*73bb2479SJustin Hibbits /*
1224*73bb2479SJustin Hibbits * GMAC runs on AESA, not MDHA: the shared descriptor is just the
1225*73bb2479SJustin Hibbits * class 1 key, and the JD drives it as GCM with no message.
1226*73bb2479SJustin Hibbits */
1227*73bb2479SJustin Hibbits if (csp->csp_auth_alg == CRYPTO_AES_NIST_GMAC) {
1228*73bb2479SJustin Hibbits sess->digestlen = csp->csp_auth_mlen != 0 ?
1229*73bb2479SJustin Hibbits csp->csp_auth_mlen : AES_GMAC_HASH_LEN;
1230*73bb2479SJustin Hibbits sec_desc_init(&b, sess->ctx[enc].shd, SEC_MAX_SHDESC_WORDS);
1231*73bb2479SJustin Hibbits sec_desc_key_imm(&b, KEY_CLASS_1, csp->csp_auth_key,
1232*73bb2479SJustin Hibbits csp->csp_auth_klen);
1233*73bb2479SJustin Hibbits return (sec_desc_finalize_shared(&b, HEADER_SHARE_SERIAL,
1234*73bb2479SJustin Hibbits sdlenp));
1235*73bb2479SJustin Hibbits }
1236*73bb2479SJustin Hibbits
1237*73bb2479SJustin Hibbits if (!sec_hash_params(csp->csp_auth_alg, &alg, &dlen, &skeylen))
1238*73bb2479SJustin Hibbits return (EOPNOTSUPP);
1239*73bb2479SJustin Hibbits sess->digestlen = dlen;
1240*73bb2479SJustin Hibbits
1241*73bb2479SJustin Hibbits sec_desc_init(&b, sess->ctx[enc].shd, SEC_MAX_SHDESC_WORDS);
1242*73bb2479SJustin Hibbits
1243*73bb2479SJustin Hibbits /*
1244*73bb2479SJustin Hibbits * A plain hash takes no key at all; the keyed variants load the
1245*73bb2479SJustin Hibbits * precomputed ipad || opad blob as an MDHA split key, which is
1246*73bb2479SJustin Hibbits * what AAI_HMAC_PRECOMP tells MDHA to expect.
1247*73bb2479SJustin Hibbits */
1248*73bb2479SJustin Hibbits if (skeylen != 0) {
1249*73bb2479SJustin Hibbits unsigned int nwords = howmany(skeylen, 4);
1250*73bb2479SJustin Hibbits
1251*73bb2479SJustin Hibbits b.desc[b.idx++] = CMD_DESC(CMD_KEY) | KEY_CLASS_2 |
1252*73bb2479SJustin Hibbits KEY_KDEST_MDHA_SPLIT | KEY_IMM |
1253*73bb2479SJustin Hibbits (skeylen & KEY_LENGTH_M);
1254*73bb2479SJustin Hibbits memcpy(&b.desc[b.idx], sess->skey, skeylen);
1255*73bb2479SJustin Hibbits if (skeylen % 4 != 0)
1256*73bb2479SJustin Hibbits memset((uint8_t *)&b.desc[b.idx] + skeylen, 0,
1257*73bb2479SJustin Hibbits nwords * 4 - skeylen);
1258*73bb2479SJustin Hibbits b.idx += nwords;
1259*73bb2479SJustin Hibbits }
1260*73bb2479SJustin Hibbits
1261*73bb2479SJustin Hibbits sec_desc_word(&b, CMD_DESC(CMD_OPERATION) | alg |
1262*73bb2479SJustin Hibbits (skeylen != 0 ? AAI_HMAC_PRECOMP : AAI_HASH) | AS_INIT_FINAL);
1263*73bb2479SJustin Hibbits
1264*73bb2479SJustin Hibbits /* VLF FIFO_LOAD needs VSIL, which SEQ_IN_PTR doesn't populate. */
1265*73bb2479SJustin Hibbits sec_desc_word(&b, CMD_DESC(CMD_MATH) | MATH_FN_ADD | MATH_SRC0_SIL |
1266*73bb2479SJustin Hibbits MATH_SRC1_ZERO | MATH_DEST_VSIL | MATH_LEN_4);
1267*73bb2479SJustin Hibbits
1268*73bb2479SJustin Hibbits sec_desc_word(&b, CMD_DESC(CMD_SEQ_FIFO_LOAD) | FIFOLD_CLASS_2 |
1269*73bb2479SJustin Hibbits FIFOLD_VLF | FIFOLD_TYPE_MSG | FIFOLD_LC2);
1270*73bb2479SJustin Hibbits
1271*73bb2479SJustin Hibbits /*
1272*73bb2479SJustin Hibbits * Drain the completed hash from the Class 2 CCB Context register.
1273*73bb2479SJustin Hibbits * SEQ_STORE with class 2 + SRC=CTX (0x20) blocks until MDHA is
1274*73bb2479SJustin Hibbits * done.
1275*73bb2479SJustin Hibbits */
1276*73bb2479SJustin Hibbits sec_jd_store(&b, true, LOAD_CLASS_2, LOAD_CTX, 0, dlen, 0);
1277*73bb2479SJustin Hibbits
1278*73bb2479SJustin Hibbits return (sec_desc_finalize_shared(&b, HEADER_SHARE_SERIAL, sdlenp));
1279*73bb2479SJustin Hibbits }
1280*73bb2479SJustin Hibbits
1281*73bb2479SJustin Hibbits /*
1282*73bb2479SJustin Hibbits * AEAD shared descriptor. AAD and payload lengths vary per job, so
1283*73bb2479SJustin Hibbits * everything but the key lives in the JD. Execution order is not
1284*73bb2479SJustin Hibbits * reversed here: the key has to be loaded before the JD drives data.
1285*73bb2479SJustin Hibbits *
1286*73bb2479SJustin Hibbits * When ICV is set the ENC bit must be clear, which is the only
1287*73bb2479SJustin Hibbits * difference between the two direction slots.
1288*73bb2479SJustin Hibbits */
1289*73bb2479SJustin Hibbits static int
sec_shd_build_aead(struct sec_session * sess,const struct crypto_session_params * csp,int enc,uint32_t * sdlenp)1290*73bb2479SJustin Hibbits sec_shd_build_aead(struct sec_session *sess,
1291*73bb2479SJustin Hibbits const struct crypto_session_params *csp, int enc, uint32_t *sdlenp)
1292*73bb2479SJustin Hibbits {
1293*73bb2479SJustin Hibbits struct sec_desc_builder b;
1294*73bb2479SJustin Hibbits
1295*73bb2479SJustin Hibbits switch (csp->csp_cipher_alg) {
1296*73bb2479SJustin Hibbits case CRYPTO_AES_NIST_GCM_16:
1297*73bb2479SJustin Hibbits case CRYPTO_AES_CCM_16:
1298*73bb2479SJustin Hibbits break;
1299*73bb2479SJustin Hibbits default:
1300*73bb2479SJustin Hibbits return (EOPNOTSUPP);
1301*73bb2479SJustin Hibbits }
1302*73bb2479SJustin Hibbits (void)enc;
1303*73bb2479SJustin Hibbits
1304*73bb2479SJustin Hibbits /* Cache tag length once (both directions share). */
1305*73bb2479SJustin Hibbits sess->digestlen = csp->csp_auth_mlen != 0 ? csp->csp_auth_mlen : 16;
1306*73bb2479SJustin Hibbits
1307*73bb2479SJustin Hibbits /*
1308*73bb2479SJustin Hibbits * SHD holds just the AES key.
1309*73bb2479SJustin Hibbits */
1310*73bb2479SJustin Hibbits sec_desc_init(&b, sess->ctx[enc].shd, SEC_MAX_SHDESC_WORDS);
1311*73bb2479SJustin Hibbits if (csp->csp_cipher_klen > 0)
1312*73bb2479SJustin Hibbits sec_desc_key_imm(&b, KEY_CLASS_1, csp->csp_cipher_key,
1313*73bb2479SJustin Hibbits csp->csp_cipher_klen);
1314*73bb2479SJustin Hibbits return (sec_desc_finalize_shared(&b, HEADER_SHARE_SERIAL, sdlenp));
1315*73bb2479SJustin Hibbits }
1316*73bb2479SJustin Hibbits
1317*73bb2479SJustin Hibbits /*
1318*73bb2479SJustin Hibbits * Shared descriptor for encrypt-then-auth: both keys and both mode
1319*73bb2479SJustin Hibbits * registers, nothing else.
1320*73bb2479SJustin Hibbits */
1321*73bb2479SJustin Hibbits static int
sec_shd_build_eta(struct sec_session * sess,const struct crypto_session_params * csp,int enc,uint32_t * sdlenp)1322*73bb2479SJustin Hibbits sec_shd_build_eta(struct sec_session *sess,
1323*73bb2479SJustin Hibbits const struct crypto_session_params *csp, int enc, uint32_t *sdlenp)
1324*73bb2479SJustin Hibbits {
1325*73bb2479SJustin Hibbits struct sec_desc_builder b;
1326*73bb2479SJustin Hibbits uint32_t alg, op;
1327*73bb2479SJustin Hibbits uint8_t dlen, skeylen;
1328*73bb2479SJustin Hibbits
1329*73bb2479SJustin Hibbits if (!sec_hash_params(csp->csp_auth_alg, &alg, &dlen, &skeylen))
1330*73bb2479SJustin Hibbits return (EOPNOTSUPP);
1331*73bb2479SJustin Hibbits sess->digestlen = csp->csp_auth_mlen != 0 ? csp->csp_auth_mlen : dlen;
1332*73bb2479SJustin Hibbits
1333*73bb2479SJustin Hibbits switch (csp->csp_cipher_alg) {
1334*73bb2479SJustin Hibbits case CRYPTO_AES_CBC:
1335*73bb2479SJustin Hibbits op = CMD_DESC(CMD_OPERATION) | ALG_AES | AAI_AES_CBC |
1336*73bb2479SJustin Hibbits AS_INIT_FINAL;
1337*73bb2479SJustin Hibbits break;
1338*73bb2479SJustin Hibbits case CRYPTO_AES_ICM:
1339*73bb2479SJustin Hibbits op = CMD_DESC(CMD_OPERATION) | ALG_AES | AAI_AES_CTR |
1340*73bb2479SJustin Hibbits AS_INIT_FINAL;
1341*73bb2479SJustin Hibbits break;
1342*73bb2479SJustin Hibbits default:
1343*73bb2479SJustin Hibbits return (EOPNOTSUPP);
1344*73bb2479SJustin Hibbits }
1345*73bb2479SJustin Hibbits if (enc)
1346*73bb2479SJustin Hibbits op |= OP_ENC;
1347*73bb2479SJustin Hibbits
1348*73bb2479SJustin Hibbits sec_desc_init(&b, sess->ctx[enc].shd, SEC_MAX_SHDESC_WORDS);
1349*73bb2479SJustin Hibbits
1350*73bb2479SJustin Hibbits sec_desc_key_imm(&b, KEY_CLASS_1, csp->csp_cipher_key,
1351*73bb2479SJustin Hibbits csp->csp_cipher_klen);
1352*73bb2479SJustin Hibbits
1353*73bb2479SJustin Hibbits /* Class 2 takes the precomputed ipad/opad blob, as for plain HMAC. */
1354*73bb2479SJustin Hibbits {
1355*73bb2479SJustin Hibbits unsigned int nwords = howmany(skeylen, 4);
1356*73bb2479SJustin Hibbits
1357*73bb2479SJustin Hibbits b.desc[b.idx++] = CMD_DESC(CMD_KEY) | KEY_CLASS_2 |
1358*73bb2479SJustin Hibbits KEY_KDEST_MDHA_SPLIT | KEY_IMM | (skeylen & KEY_LENGTH_M);
1359*73bb2479SJustin Hibbits memcpy(&b.desc[b.idx], sess->skey, skeylen);
1360*73bb2479SJustin Hibbits if (skeylen % 4 != 0)
1361*73bb2479SJustin Hibbits memset((uint8_t *)&b.desc[b.idx] + skeylen, 0,
1362*73bb2479SJustin Hibbits nwords * 4 - skeylen);
1363*73bb2479SJustin Hibbits b.idx += nwords;
1364*73bb2479SJustin Hibbits }
1365*73bb2479SJustin Hibbits
1366*73bb2479SJustin Hibbits sec_desc_word(&b, CMD_DESC(CMD_OPERATION) | alg | AAI_HMAC_PRECOMP |
1367*73bb2479SJustin Hibbits AS_INIT_FINAL);
1368*73bb2479SJustin Hibbits sec_desc_word(&b, op);
1369*73bb2479SJustin Hibbits
1370*73bb2479SJustin Hibbits return (sec_desc_finalize_shared(&b, HEADER_SHARE_SERIAL, sdlenp));
1371*73bb2479SJustin Hibbits }
1372*73bb2479SJustin Hibbits
1373*73bb2479SJustin Hibbits static int
sec_probe_session(device_t dev,const struct crypto_session_params * csp)1374*73bb2479SJustin Hibbits sec_probe_session(device_t dev, const struct crypto_session_params *csp)
1375*73bb2479SJustin Hibbits {
1376*73bb2479SJustin Hibbits
1377*73bb2479SJustin Hibbits switch (csp->csp_mode) {
1378*73bb2479SJustin Hibbits case CSP_MODE_CIPHER:
1379*73bb2479SJustin Hibbits if (!check_cipher(csp))
1380*73bb2479SJustin Hibbits return (EINVAL);
1381*73bb2479SJustin Hibbits break;
1382*73bb2479SJustin Hibbits case CSP_MODE_DIGEST:
1383*73bb2479SJustin Hibbits if (!check_digest(csp))
1384*73bb2479SJustin Hibbits return (EINVAL);
1385*73bb2479SJustin Hibbits break;
1386*73bb2479SJustin Hibbits case CSP_MODE_AEAD:
1387*73bb2479SJustin Hibbits if (!check_aead(csp))
1388*73bb2479SJustin Hibbits return (EINVAL);
1389*73bb2479SJustin Hibbits break;
1390*73bb2479SJustin Hibbits case CSP_MODE_ETA:
1391*73bb2479SJustin Hibbits if (!check_eta(csp))
1392*73bb2479SJustin Hibbits return (EINVAL);
1393*73bb2479SJustin Hibbits break;
1394*73bb2479SJustin Hibbits default:
1395*73bb2479SJustin Hibbits return (EINVAL);
1396*73bb2479SJustin Hibbits }
1397*73bb2479SJustin Hibbits return (CRYPTODEV_PROBE_HARDWARE);
1398*73bb2479SJustin Hibbits }
1399*73bb2479SJustin Hibbits
1400*73bb2479SJustin Hibbits static int
sec_new_session(device_t dev,crypto_session_t session,const struct crypto_session_params * csp)1401*73bb2479SJustin Hibbits sec_new_session(device_t dev, crypto_session_t session,
1402*73bb2479SJustin Hibbits const struct crypto_session_params *csp)
1403*73bb2479SJustin Hibbits {
1404*73bb2479SJustin Hibbits struct sec_softc *sc = device_get_softc(dev);
1405*73bb2479SJustin Hibbits struct sec_session *sess;
1406*73bb2479SJustin Hibbits uint32_t sdlen;
1407*73bb2479SJustin Hibbits int enc, error;
1408*73bb2479SJustin Hibbits
1409*73bb2479SJustin Hibbits sess = crypto_get_driver_session(session);
1410*73bb2479SJustin Hibbits sess->sess_sc = sc;
1411*73bb2479SJustin Hibbits
1412*73bb2479SJustin Hibbits if ((csp->csp_mode == CSP_MODE_DIGEST ||
1413*73bb2479SJustin Hibbits csp->csp_mode == CSP_MODE_ETA) && csp->csp_auth_klen > 0 &&
1414*73bb2479SJustin Hibbits csp->csp_auth_alg != CRYPTO_AES_NIST_GMAC) {
1415*73bb2479SJustin Hibbits uint32_t alg;
1416*73bb2479SJustin Hibbits uint8_t dlen, skeylen;
1417*73bb2479SJustin Hibbits
1418*73bb2479SJustin Hibbits if (!sec_hash_params(csp->csp_auth_alg, &alg, &dlen, &skeylen))
1419*73bb2479SJustin Hibbits return (EOPNOTSUPP);
1420*73bb2479SJustin Hibbits (void)alg;
1421*73bb2479SJustin Hibbits sec_sw_gen_split_key(csp, sess->skey, skeylen);
1422*73bb2479SJustin Hibbits sess->skeylen = skeylen;
1423*73bb2479SJustin Hibbits }
1424*73bb2479SJustin Hibbits
1425*73bb2479SJustin Hibbits for (enc = 0; enc <= 1; enc++) {
1426*73bb2479SJustin Hibbits switch (csp->csp_mode) {
1427*73bb2479SJustin Hibbits case CSP_MODE_CIPHER:
1428*73bb2479SJustin Hibbits error = sec_shd_build_cipher(sess, csp, enc, &sdlen);
1429*73bb2479SJustin Hibbits break;
1430*73bb2479SJustin Hibbits case CSP_MODE_DIGEST:
1431*73bb2479SJustin Hibbits error = sec_shd_build_digest(sess, csp, enc, &sdlen);
1432*73bb2479SJustin Hibbits break;
1433*73bb2479SJustin Hibbits case CSP_MODE_AEAD:
1434*73bb2479SJustin Hibbits error = sec_shd_build_aead(sess, csp, enc, &sdlen);
1435*73bb2479SJustin Hibbits break;
1436*73bb2479SJustin Hibbits case CSP_MODE_ETA:
1437*73bb2479SJustin Hibbits error = sec_shd_build_eta(sess, csp, enc, &sdlen);
1438*73bb2479SJustin Hibbits break;
1439*73bb2479SJustin Hibbits default:
1440*73bb2479SJustin Hibbits return (EINVAL);
1441*73bb2479SJustin Hibbits }
1442*73bb2479SJustin Hibbits if (error != 0)
1443*73bb2479SJustin Hibbits return (error);
1444*73bb2479SJustin Hibbits sess->sdlen[enc] = sdlen;
1445*73bb2479SJustin Hibbits }
1446*73bb2479SJustin Hibbits return (0);
1447*73bb2479SJustin Hibbits }
1448*73bb2479SJustin Hibbits
1449*73bb2479SJustin Hibbits static void
sec_free_session(device_t dev,crypto_session_t session)1450*73bb2479SJustin Hibbits sec_free_session(device_t dev, crypto_session_t session)
1451*73bb2479SJustin Hibbits {
1452*73bb2479SJustin Hibbits /* Nothing to do here. */
1453*73bb2479SJustin Hibbits }
1454*73bb2479SJustin Hibbits
1455*73bb2479SJustin Hibbits static void
sec_load_cb(void * arg,bus_dma_segment_t * segs,int nsegs,int error)1456*73bb2479SJustin Hibbits sec_load_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
1457*73bb2479SJustin Hibbits {
1458*73bb2479SJustin Hibbits struct sec_job *job = arg;
1459*73bb2479SJustin Hibbits
1460*73bb2479SJustin Hibbits if (error != 0) {
1461*73bb2479SJustin Hibbits job->nsegs = 0;
1462*73bb2479SJustin Hibbits return;
1463*73bb2479SJustin Hibbits }
1464*73bb2479SJustin Hibbits KASSERT(nsegs <= SEC_MAX_SEGMENTS,
1465*73bb2479SJustin Hibbits ("SEC job segment overflow: %d > %d", nsegs, SEC_MAX_SEGMENTS));
1466*73bb2479SJustin Hibbits memcpy(job->segs, segs, nsegs * sizeof(segs[0]));
1467*73bb2479SJustin Hibbits job->nsegs = nsegs;
1468*73bb2479SJustin Hibbits }
1469*73bb2479SJustin Hibbits
1470*73bb2479SJustin Hibbits /*
1471*73bb2479SJustin Hibbits * Append the segments covering [start, start + len) of the mapped buffer.
1472*73bb2479SJustin Hibbits * Returns the next free index, or -1 if the table would overflow or the
1473*73bb2479SJustin Hibbits * range runs past the mapping.
1474*73bb2479SJustin Hibbits */
1475*73bb2479SJustin Hibbits static int
dpaa_sgte_append(struct sec_job * job,struct dpaa_sgte * sgt,int i,int max,uint32_t start,uint32_t len)1476*73bb2479SJustin Hibbits dpaa_sgte_append(struct sec_job *job, struct dpaa_sgte *sgt, int i, int max,
1477*73bb2479SJustin Hibbits uint32_t start, uint32_t len)
1478*73bb2479SJustin Hibbits {
1479*73bb2479SJustin Hibbits int s;
1480*73bb2479SJustin Hibbits
1481*73bb2479SJustin Hibbits for (s = 0; s < job->nsegs && len > 0; s++) {
1482*73bb2479SJustin Hibbits bus_addr_t addr = job->segs[s].ds_addr;
1483*73bb2479SJustin Hibbits bus_size_t seglen = job->segs[s].ds_len;
1484*73bb2479SJustin Hibbits uint32_t take;
1485*73bb2479SJustin Hibbits
1486*73bb2479SJustin Hibbits if (start >= seglen) {
1487*73bb2479SJustin Hibbits start -= seglen;
1488*73bb2479SJustin Hibbits continue;
1489*73bb2479SJustin Hibbits }
1490*73bb2479SJustin Hibbits addr += start;
1491*73bb2479SJustin Hibbits seglen -= start;
1492*73bb2479SJustin Hibbits start = 0;
1493*73bb2479SJustin Hibbits
1494*73bb2479SJustin Hibbits take = seglen > len ? len : seglen;
1495*73bb2479SJustin Hibbits len -= take;
1496*73bb2479SJustin Hibbits
1497*73bb2479SJustin Hibbits if (i >= max)
1498*73bb2479SJustin Hibbits return (-1);
1499*73bb2479SJustin Hibbits sgt[i].addr = addr;
1500*73bb2479SJustin Hibbits sgt[i].extension = 0;
1501*73bb2479SJustin Hibbits sgt[i].final = 0;
1502*73bb2479SJustin Hibbits sgt[i].length = take;
1503*73bb2479SJustin Hibbits sgt[i].bpid = 0;
1504*73bb2479SJustin Hibbits sgt[i].offset = 0;
1505*73bb2479SJustin Hibbits i++;
1506*73bb2479SJustin Hibbits }
1507*73bb2479SJustin Hibbits if (len != 0)
1508*73bb2479SJustin Hibbits return (-1);
1509*73bb2479SJustin Hibbits return (i);
1510*73bb2479SJustin Hibbits }
1511*73bb2479SJustin Hibbits
1512*73bb2479SJustin Hibbits /*
1513*73bb2479SJustin Hibbits * Populate the SGTs from the DMA-loaded segment list. Entry order is
1514*73bb2479SJustin Hibbits * what the descriptor's SEQ commands consume, so it is fixed per mode:
1515*73bb2479SJustin Hibbits * CIPHER:
1516*73bb2479SJustin Hibbits * in_sgt[0] = job->iv
1517*73bb2479SJustin Hibbits * in_sgt[1..n] = payload segments
1518*73bb2479SJustin Hibbits * out_sgt[0..n-1] = payload segments (in-place)
1519*73bb2479SJustin Hibbits * DIGEST (HMAC, no IV):
1520*73bb2479SJustin Hibbits * in_sgt[0..n-1] = payload segments
1521*73bb2479SJustin Hibbits * out_sgt unused (JD points SEQ_OUT_PTR directly at job->digest).
1522*73bb2479SJustin Hibbits * AEAD and ETA:
1523*73bb2479SJustin Hibbits * in_sgt[0] = job->iv, or job->ccm_ctx for CCM
1524*73bb2479SJustin Hibbits * in_sgt[1..A] = AAD (crp_aad, or crp_buf at crp_aad_start)
1525*73bb2479SJustin Hibbits * in_sgt[A+1..N] = payload segments
1526*73bb2479SJustin Hibbits * in_sgt[N+1..] = (decrypt only) received tag from crp_buf
1527*73bb2479SJustin Hibbits * out_sgt[0..] = payload segments (in-place); the tag goes to
1528*73bb2479SJustin Hibbits * job->digest via a separate STORE.
1529*73bb2479SJustin Hibbits * The final SGT entry in each populated table gets F=1.
1530*73bb2479SJustin Hibbits */
1531*73bb2479SJustin Hibbits static int
sec_job_build_sgts(struct sec_job * job,const struct crypto_session_params * csp)1532*73bb2479SJustin Hibbits sec_job_build_sgts(struct sec_job *job, const struct crypto_session_params *csp)
1533*73bb2479SJustin Hibbits {
1534*73bb2479SJustin Hibbits struct cryptop *crp = job->crp;
1535*73bb2479SJustin Hibbits uint32_t skip = crp->crp_payload_start;
1536*73bb2479SJustin Hibbits uint32_t left = crp->crp_payload_length;
1537*73bb2479SJustin Hibbits int i, out_i;
1538*73bb2479SJustin Hibbits int iv_slot = csp->csp_ivlen > 0 ? 1 : 0;
1539*73bb2479SJustin Hibbits
1540*73bb2479SJustin Hibbits if (csp->csp_mode == CSP_MODE_AEAD ||
1541*73bb2479SJustin Hibbits csp->csp_mode == CSP_MODE_ETA) {
1542*73bb2479SJustin Hibbits const int inmax = 1 + SEC_MAX_SEGMENTS;
1543*73bb2479SJustin Hibbits bool encrypt = (crp->crp_op & CRYPTO_OP_ENCRYPT) != 0;
1544*73bb2479SJustin Hibbits bool ccm = csp->csp_mode == CSP_MODE_AEAD &&
1545*73bb2479SJustin Hibbits csp->csp_cipher_alg == CRYPTO_AES_CCM_16;
1546*73bb2479SJustin Hibbits int in_i = 0, npay, pay_i;
1547*73bb2479SJustin Hibbits
1548*73bb2479SJustin Hibbits /* IV, or for CCM the B0 || CTR0 context block. */
1549*73bb2479SJustin Hibbits if (ccm) {
1550*73bb2479SJustin Hibbits job->in_sgt[in_i].addr =
1551*73bb2479SJustin Hibbits pmap_kextract((vm_offset_t)job->ccm_ctx);
1552*73bb2479SJustin Hibbits job->in_sgt[in_i].length = SEC_CCM_CTX_LEN;
1553*73bb2479SJustin Hibbits } else {
1554*73bb2479SJustin Hibbits job->in_sgt[in_i].addr =
1555*73bb2479SJustin Hibbits pmap_kextract((vm_offset_t)job->iv);
1556*73bb2479SJustin Hibbits job->in_sgt[in_i].length = csp->csp_ivlen;
1557*73bb2479SJustin Hibbits }
1558*73bb2479SJustin Hibbits job->in_sgt[in_i].extension = 0;
1559*73bb2479SJustin Hibbits job->in_sgt[in_i].final = 0;
1560*73bb2479SJustin Hibbits job->in_sgt[in_i].bpid = 0;
1561*73bb2479SJustin Hibbits job->in_sgt[in_i].offset = 0;
1562*73bb2479SJustin Hibbits in_i++;
1563*73bb2479SJustin Hibbits
1564*73bb2479SJustin Hibbits if (crp->crp_aad_length > 0) {
1565*73bb2479SJustin Hibbits /* CCM feeds the AAD length ahead of the AAD. */
1566*73bb2479SJustin Hibbits if (ccm) {
1567*73bb2479SJustin Hibbits job->in_sgt[in_i].addr = pmap_kextract(
1568*73bb2479SJustin Hibbits (vm_offset_t)job->ccm_alen);
1569*73bb2479SJustin Hibbits job->in_sgt[in_i].extension = 0;
1570*73bb2479SJustin Hibbits job->in_sgt[in_i].final = 0;
1571*73bb2479SJustin Hibbits job->in_sgt[in_i].length =
1572*73bb2479SJustin Hibbits sizeof(job->ccm_alen);
1573*73bb2479SJustin Hibbits job->in_sgt[in_i].bpid = 0;
1574*73bb2479SJustin Hibbits job->in_sgt[in_i].offset = 0;
1575*73bb2479SJustin Hibbits in_i++;
1576*73bb2479SJustin Hibbits }
1577*73bb2479SJustin Hibbits if (crp->crp_aad != NULL) {
1578*73bb2479SJustin Hibbits /*
1579*73bb2479SJustin Hibbits * A dedicated AAD buffer is not part of the
1580*73bb2479SJustin Hibbits * crp mapping; it is small enough that one
1581*73bb2479SJustin Hibbits * entry always covers it.
1582*73bb2479SJustin Hibbits */
1583*73bb2479SJustin Hibbits job->in_sgt[in_i].addr = pmap_kextract(
1584*73bb2479SJustin Hibbits (vm_offset_t)crp->crp_aad);
1585*73bb2479SJustin Hibbits job->in_sgt[in_i].extension = 0;
1586*73bb2479SJustin Hibbits job->in_sgt[in_i].final = 0;
1587*73bb2479SJustin Hibbits job->in_sgt[in_i].length = crp->crp_aad_length;
1588*73bb2479SJustin Hibbits job->in_sgt[in_i].bpid = 0;
1589*73bb2479SJustin Hibbits job->in_sgt[in_i].offset = 0;
1590*73bb2479SJustin Hibbits in_i++;
1591*73bb2479SJustin Hibbits } else {
1592*73bb2479SJustin Hibbits in_i = dpaa_sgte_append(job, job->in_sgt, in_i,
1593*73bb2479SJustin Hibbits inmax, crp->crp_aad_start,
1594*73bb2479SJustin Hibbits crp->crp_aad_length);
1595*73bb2479SJustin Hibbits if (in_i < 0)
1596*73bb2479SJustin Hibbits return (E2BIG);
1597*73bb2479SJustin Hibbits }
1598*73bb2479SJustin Hibbits }
1599*73bb2479SJustin Hibbits
1600*73bb2479SJustin Hibbits pay_i = in_i;
1601*73bb2479SJustin Hibbits in_i = dpaa_sgte_append(job, job->in_sgt, in_i, inmax, skip,
1602*73bb2479SJustin Hibbits left);
1603*73bb2479SJustin Hibbits if (in_i < 0)
1604*73bb2479SJustin Hibbits return (E2BIG);
1605*73bb2479SJustin Hibbits npay = in_i - pay_i;
1606*73bb2479SJustin Hibbits if (npay == 0)
1607*73bb2479SJustin Hibbits return (EINVAL);
1608*73bb2479SJustin Hibbits
1609*73bb2479SJustin Hibbits /*
1610*73bb2479SJustin Hibbits * AEAD decrypt hands the received tag to the CHA for its
1611*73bb2479SJustin Hibbits * own compare; ETA drains the MAC to job->digest instead
1612*73bb2479SJustin Hibbits * and compares in software, so it needs no entry here.
1613*73bb2479SJustin Hibbits */
1614*73bb2479SJustin Hibbits if (!encrypt && csp->csp_mode == CSP_MODE_AEAD) {
1615*73bb2479SJustin Hibbits in_i = dpaa_sgte_append(job, job->in_sgt, in_i, inmax,
1616*73bb2479SJustin Hibbits crp->crp_digest_start, job->sess->digestlen);
1617*73bb2479SJustin Hibbits if (in_i < 0)
1618*73bb2479SJustin Hibbits return (E2BIG);
1619*73bb2479SJustin Hibbits }
1620*73bb2479SJustin Hibbits job->in_sgt[in_i - 1].final = 1;
1621*73bb2479SJustin Hibbits
1622*73bb2479SJustin Hibbits /* Output mirrors the payload segments, in place. */
1623*73bb2479SJustin Hibbits memcpy(job->out_sgt, &job->in_sgt[pay_i],
1624*73bb2479SJustin Hibbits npay * sizeof(job->out_sgt[0]));
1625*73bb2479SJustin Hibbits job->out_sgt[npay - 1].final = 1;
1626*73bb2479SJustin Hibbits return (0);
1627*73bb2479SJustin Hibbits }
1628*73bb2479SJustin Hibbits
1629*73bb2479SJustin Hibbits if (iv_slot) {
1630*73bb2479SJustin Hibbits job->in_sgt[0].addr = pmap_kextract((vm_offset_t)job->iv);
1631*73bb2479SJustin Hibbits job->in_sgt[0].extension = 0;
1632*73bb2479SJustin Hibbits job->in_sgt[0].final = 0;
1633*73bb2479SJustin Hibbits job->in_sgt[0].length = sec_cipher_ivlen(csp);
1634*73bb2479SJustin Hibbits job->in_sgt[0].bpid = 0;
1635*73bb2479SJustin Hibbits job->in_sgt[0].offset = 0;
1636*73bb2479SJustin Hibbits }
1637*73bb2479SJustin Hibbits
1638*73bb2479SJustin Hibbits out_i = 0;
1639*73bb2479SJustin Hibbits for (i = 0; i < job->nsegs && left > 0; i++) {
1640*73bb2479SJustin Hibbits bus_addr_t addr = job->segs[i].ds_addr;
1641*73bb2479SJustin Hibbits bus_size_t len = job->segs[i].ds_len;
1642*73bb2479SJustin Hibbits uint32_t take;
1643*73bb2479SJustin Hibbits
1644*73bb2479SJustin Hibbits if (skip >= len) {
1645*73bb2479SJustin Hibbits skip -= len;
1646*73bb2479SJustin Hibbits continue;
1647*73bb2479SJustin Hibbits }
1648*73bb2479SJustin Hibbits addr += skip;
1649*73bb2479SJustin Hibbits len -= skip;
1650*73bb2479SJustin Hibbits skip = 0;
1651*73bb2479SJustin Hibbits
1652*73bb2479SJustin Hibbits take = (len > left) ? left : len;
1653*73bb2479SJustin Hibbits left -= take;
1654*73bb2479SJustin Hibbits
1655*73bb2479SJustin Hibbits if (out_i >= SEC_MAX_SEGMENTS)
1656*73bb2479SJustin Hibbits return (E2BIG);
1657*73bb2479SJustin Hibbits
1658*73bb2479SJustin Hibbits job->in_sgt[iv_slot + out_i].addr = addr;
1659*73bb2479SJustin Hibbits job->in_sgt[iv_slot + out_i].extension = 0;
1660*73bb2479SJustin Hibbits job->in_sgt[iv_slot + out_i].final = 0;
1661*73bb2479SJustin Hibbits job->in_sgt[iv_slot + out_i].length = take;
1662*73bb2479SJustin Hibbits job->in_sgt[iv_slot + out_i].bpid = 0;
1663*73bb2479SJustin Hibbits job->in_sgt[iv_slot + out_i].offset = 0;
1664*73bb2479SJustin Hibbits
1665*73bb2479SJustin Hibbits if (iv_slot)
1666*73bb2479SJustin Hibbits job->out_sgt[out_i] = job->in_sgt[iv_slot + out_i];
1667*73bb2479SJustin Hibbits out_i++;
1668*73bb2479SJustin Hibbits }
1669*73bb2479SJustin Hibbits if (left != 0)
1670*73bb2479SJustin Hibbits return (EINVAL);
1671*73bb2479SJustin Hibbits if (out_i == 0)
1672*73bb2479SJustin Hibbits return (EINVAL);
1673*73bb2479SJustin Hibbits
1674*73bb2479SJustin Hibbits job->in_sgt[iv_slot + out_i - 1].final = 1;
1675*73bb2479SJustin Hibbits if (iv_slot)
1676*73bb2479SJustin Hibbits job->out_sgt[out_i - 1].final = 1;
1677*73bb2479SJustin Hibbits return (0);
1678*73bb2479SJustin Hibbits }
1679*73bb2479SJustin Hibbits
1680*73bb2479SJustin Hibbits /*
1681*73bb2479SJustin Hibbits * JD for the cipher modes. The shared descriptor runs the pipeline, so
1682*73bb2479SJustin Hibbits * the JD only points at the SGTs.
1683*73bb2479SJustin Hibbits *
1684*73bb2479SJustin Hibbits * Both sequences use SGF and EXT unconditionally. Always using a table
1685*73bb2479SJustin Hibbits * keeps the builder from caring how many segments there are, and the
1686*73bb2479SJustin Hibbits * 16-bit length in the command word is too small for the payloads geli
1687*73bb2479SJustin Hibbits * and kTLS hand down.
1688*73bb2479SJustin Hibbits */
1689*73bb2479SJustin Hibbits static int
sec_jd_build_cipher(struct sec_job * job,const struct crypto_session_params * csp)1690*73bb2479SJustin Hibbits sec_jd_build_cipher(struct sec_job *job,
1691*73bb2479SJustin Hibbits const struct crypto_session_params *csp)
1692*73bb2479SJustin Hibbits {
1693*73bb2479SJustin Hibbits struct sec_desc_builder b;
1694*73bb2479SJustin Hibbits struct sec_session *sess = job->sess;
1695*73bb2479SJustin Hibbits int enc = CRYPTO_OP_IS_ENCRYPT(job->crp->crp_op);
1696*73bb2479SJustin Hibbits uint32_t sdlen = sess->sdlen[enc];
1697*73bb2479SJustin Hibbits uint32_t desclen;
1698*73bb2479SJustin Hibbits uint32_t in_len = sec_cipher_ivlen(csp) + job->crp->crp_payload_length;
1699*73bb2479SJustin Hibbits vm_paddr_t shd_pa, in_sgt_pa, out_sgt_pa;
1700*73bb2479SJustin Hibbits
1701*73bb2479SJustin Hibbits /*
1702*73bb2479SJustin Hibbits * The hardware restarts the tweak every SEC_XTS_SECTOR_SIZE bytes;
1703*73bb2479SJustin Hibbits * opencrypto expects one continuous tweak, so anything that would
1704*73bb2479SJustin Hibbits * cross the boundary has to go back to software.
1705*73bb2479SJustin Hibbits */
1706*73bb2479SJustin Hibbits if (csp->csp_cipher_alg == CRYPTO_AES_XTS &&
1707*73bb2479SJustin Hibbits job->crp->crp_payload_length > SEC_XTS_SECTOR_SIZE)
1708*73bb2479SJustin Hibbits return (EOPNOTSUPP);
1709*73bb2479SJustin Hibbits
1710*73bb2479SJustin Hibbits shd_pa = pmap_kextract((vm_offset_t)sess->ctx[enc].shd);
1711*73bb2479SJustin Hibbits in_sgt_pa = pmap_kextract((vm_offset_t)job->in_sgt);
1712*73bb2479SJustin Hibbits out_sgt_pa = pmap_kextract((vm_offset_t)job->out_sgt);
1713*73bb2479SJustin Hibbits
1714*73bb2479SJustin Hibbits sec_desc_init(&b, job->jd, SEC_MAX_DESC_WORDS);
1715*73bb2479SJustin Hibbits sec_jd_ptr(&b, shd_pa);
1716*73bb2479SJustin Hibbits
1717*73bb2479SJustin Hibbits sec_jd_seq(&b, true, SEQ_SGF | SEQ_EXT, out_sgt_pa,
1718*73bb2479SJustin Hibbits job->crp->crp_payload_length);
1719*73bb2479SJustin Hibbits
1720*73bb2479SJustin Hibbits sec_jd_seq(&b, false, SEQ_SGF | SEQ_EXT, in_sgt_pa, in_len);
1721*73bb2479SJustin Hibbits
1722*73bb2479SJustin Hibbits /*
1723*73bb2479SJustin Hibbits * HEADER_REO (Reverse Execution Order) makes SEC run the JD
1724*73bb2479SJustin Hibbits * commands FIRST (SEQ_OUT_PTR / SEQ_IN_PTR set up the input and
1725*73bb2479SJustin Hibbits * output sequences), then fall into the shared descriptor. The
1726*73bb2479SJustin Hibbits * shared descriptor's SEQ_LOAD / SEQ_FIFO_LOAD / SEQ_FIFO_STORE
1727*73bb2479SJustin Hibbits * commands depend on those sequences being programmed. Without
1728*73bb2479SJustin Hibbits * this bit the shared desc runs first and SEQ_LOAD hits an
1729*73bb2479SJustin Hibbits * uninitialized input sequence, and DECO reports an invalid
1730*73bb2479SJustin Hibbits * sequence command (error 0x10).
1731*73bb2479SJustin Hibbits */
1732*73bb2479SJustin Hibbits return (sec_desc_finalize_job(&b, HEADER_SHR |
1733*73bb2479SJustin Hibbits HEADER_REO | HEADER_SHR_DESC_L(sdlen) | HEADER_SHARE_DEFER,
1734*73bb2479SJustin Hibbits &desclen));
1735*73bb2479SJustin Hibbits }
1736*73bb2479SJustin Hibbits
1737*73bb2479SJustin Hibbits /*
1738*73bb2479SJustin Hibbits * JD for the digest modes. There is no IV to prepend and the output is
1739*73bb2479SJustin Hibbits * a small fixed buffer, so SEQ_OUT_PTR addresses it directly.
1740*73bb2479SJustin Hibbits */
1741*73bb2479SJustin Hibbits static int
sec_jd_build_digest(struct sec_job * job)1742*73bb2479SJustin Hibbits sec_jd_build_digest(struct sec_job *job)
1743*73bb2479SJustin Hibbits {
1744*73bb2479SJustin Hibbits struct sec_desc_builder b;
1745*73bb2479SJustin Hibbits struct sec_session *sess = job->sess;
1746*73bb2479SJustin Hibbits uint32_t sdlen = sess->sdlen[0];
1747*73bb2479SJustin Hibbits uint32_t desclen;
1748*73bb2479SJustin Hibbits vm_paddr_t shd_pa, in_sgt_pa, digest_pa;
1749*73bb2479SJustin Hibbits
1750*73bb2479SJustin Hibbits shd_pa = pmap_kextract((vm_offset_t)sess->ctx[0].shd);
1751*73bb2479SJustin Hibbits in_sgt_pa = pmap_kextract((vm_offset_t)job->in_sgt);
1752*73bb2479SJustin Hibbits digest_pa = pmap_kextract((vm_offset_t)job->digest);
1753*73bb2479SJustin Hibbits
1754*73bb2479SJustin Hibbits sec_desc_init(&b, job->jd, SEC_MAX_DESC_WORDS);
1755*73bb2479SJustin Hibbits sec_jd_ptr(&b, shd_pa);
1756*73bb2479SJustin Hibbits
1757*73bb2479SJustin Hibbits sec_jd_seq(&b, true, SEQ_EXT, digest_pa, sess->digestlen);
1758*73bb2479SJustin Hibbits sec_jd_seq(&b, false, SEQ_SGF | SEQ_EXT, in_sgt_pa,
1759*73bb2479SJustin Hibbits job->crp->crp_payload_length);
1760*73bb2479SJustin Hibbits
1761*73bb2479SJustin Hibbits return (sec_desc_finalize_job(&b,
1762*73bb2479SJustin Hibbits HEADER_SHR | HEADER_REO | HEADER_SHR_DESC_L(sdlen) |
1763*73bb2479SJustin Hibbits HEADER_SHARE_DEFER, &desclen));
1764*73bb2479SJustin Hibbits }
1765*73bb2479SJustin Hibbits
1766*73bb2479SJustin Hibbits /*
1767*73bb2479SJustin Hibbits * JD for AEAD (AES-GCM).
1768*73bb2479SJustin Hibbits *
1769*73bb2479SJustin Hibbits * The shared descriptor holds only the class 1 key and runs first, so
1770*73bb2479SJustin Hibbits * the job descriptor sets up both sequences and drives all of the data.
1771*73bb2479SJustin Hibbits * The data size counts the IV and AAD rounded up to 16 bytes even though
1772*73bb2479SJustin Hibbits * the FIFO loads supply them unpadded; SEC pads them internally.
1773*73bb2479SJustin Hibbits *
1774*73bb2479SJustin Hibbits * [0] - Header
1775*73bb2479SJustin Hibbits * [1..2] - Shared descriptor pointer
1776*73bb2479SJustin Hibbits * [3..6] - SEQ OUT PTR - ciphertext only, the tag leaves via STORE
1777*73bb2479SJustin Hibbits * [7..10] - SEQ IN PTR - iv + aad + payload, and the tag when decrypting
1778*73bb2479SJustin Hibbits * [11] - Operation
1779*73bb2479SJustin Hibbits * [12] - LOAD Class 1 Data Size, which starts processing
1780*73bb2479SJustin Hibbits * [13] - FIFO LOAD IV
1781*73bb2479SJustin Hibbits * [14] - FIFO LOAD AAD
1782*73bb2479SJustin Hibbits * [15] - FIFO STORE ciphertext
1783*73bb2479SJustin Hibbits * [16] - FIFO LOAD message
1784*73bb2479SJustin Hibbits * [encrypt:17..19] - STORE the computed tag to job->digest
1785*73bb2479SJustin Hibbits * [decrypt:17] - FIFO LOAD received ICV
1786*73bb2479SJustin Hibbits */
1787*73bb2479SJustin Hibbits static int
sec_jd_build_aead(struct sec_job * job)1788*73bb2479SJustin Hibbits sec_jd_build_aead(struct sec_job *job)
1789*73bb2479SJustin Hibbits {
1790*73bb2479SJustin Hibbits struct sec_desc_builder b;
1791*73bb2479SJustin Hibbits struct sec_session *sess = job->sess;
1792*73bb2479SJustin Hibbits const struct crypto_session_params *csp;
1793*73bb2479SJustin Hibbits uint32_t sdlen = sess->sdlen[0];
1794*73bb2479SJustin Hibbits uint32_t desclen;
1795*73bb2479SJustin Hibbits vm_paddr_t shd_pa, in_sgt_pa, out_sgt_pa;
1796*73bb2479SJustin Hibbits uint32_t ivlen, aadlen, paylen, taglen;
1797*73bb2479SJustin Hibbits uint32_t padded_iv, padded_aad, dsr_val;
1798*73bb2479SJustin Hibbits uint32_t in_len, out_len;
1799*73bb2479SJustin Hibbits vm_paddr_t digest_pa;
1800*73bb2479SJustin Hibbits int enc;
1801*73bb2479SJustin Hibbits
1802*73bb2479SJustin Hibbits csp = crypto_get_params(job->crp->crp_session);
1803*73bb2479SJustin Hibbits enc = (job->crp->crp_op & CRYPTO_OP_ENCRYPT) != 0;
1804*73bb2479SJustin Hibbits ivlen = csp->csp_ivlen;
1805*73bb2479SJustin Hibbits aadlen = job->crp->crp_aad_length;
1806*73bb2479SJustin Hibbits paylen = job->crp->crp_payload_length;
1807*73bb2479SJustin Hibbits taglen = sess->digestlen;
1808*73bb2479SJustin Hibbits
1809*73bb2479SJustin Hibbits padded_iv = roundup(ivlen, 16);
1810*73bb2479SJustin Hibbits padded_aad = roundup(aadlen, 16);
1811*73bb2479SJustin Hibbits dsr_val = padded_iv + padded_aad + paylen;
1812*73bb2479SJustin Hibbits in_len = ivlen + aadlen + paylen + (enc ? 0 : taglen);
1813*73bb2479SJustin Hibbits /* Output sequence is ciphertext only; tag goes via direct STORE. */
1814*73bb2479SJustin Hibbits out_len = paylen;
1815*73bb2479SJustin Hibbits digest_pa = pmap_kextract((vm_offset_t)job->digest);
1816*73bb2479SJustin Hibbits
1817*73bb2479SJustin Hibbits shd_pa = pmap_kextract((vm_offset_t)sess->ctx[enc].shd);
1818*73bb2479SJustin Hibbits in_sgt_pa = pmap_kextract((vm_offset_t)job->in_sgt);
1819*73bb2479SJustin Hibbits out_sgt_pa = pmap_kextract((vm_offset_t)job->out_sgt);
1820*73bb2479SJustin Hibbits
1821*73bb2479SJustin Hibbits sec_desc_init(&b, job->jd, SEC_MAX_DESC_WORDS);
1822*73bb2479SJustin Hibbits sec_jd_ptr(&b, shd_pa);
1823*73bb2479SJustin Hibbits
1824*73bb2479SJustin Hibbits sec_jd_seq(&b, true, SEQ_SGF | SEQ_EXT, out_sgt_pa, out_len);
1825*73bb2479SJustin Hibbits sec_jd_seq(&b, false, SEQ_SGF | SEQ_EXT, in_sgt_pa, in_len);
1826*73bb2479SJustin Hibbits
1827*73bb2479SJustin Hibbits /*
1828*73bb2479SJustin Hibbits * Writing the data size starts processing, so OPERATION has to arm
1829*73bb2479SJustin Hibbits * the CHA in GCM mode before the DSR load below.
1830*73bb2479SJustin Hibbits */
1831*73bb2479SJustin Hibbits sec_desc_word(&b, CMD_DESC(CMD_OPERATION) | ALG_AES | AAI_AES_GCM |
1832*73bb2479SJustin Hibbits AS_INIT_FINAL | (enc ? OP_ENC : OP_ICV));
1833*73bb2479SJustin Hibbits
1834*73bb2479SJustin Hibbits sec_jd_load(&b, false, LOAD_CLASS_1, LOAD_IMM, LOAD_DSR, 0, 8,
1835*73bb2479SJustin Hibbits (uint64_t)dsr_val << 32);
1836*73bb2479SJustin Hibbits
1837*73bb2479SJustin Hibbits /* IV: FC1 so SEC pads to 16 without ending class 1 input. */
1838*73bb2479SJustin Hibbits sec_jd_fifo(&b, CMD_DESC(CMD_SEQ_FIFO_LOAD) | FIFOLD_CLASS_1 |
1839*73bb2479SJustin Hibbits FIFOLD_TYPE_IV | FIFOLD_FC1, ivlen);
1840*73bb2479SJustin Hibbits /*
1841*73bb2479SJustin Hibbits * Always emit an AAD FIFO_LOAD (even with length 0) so SEC gets
1842*73bb2479SJustin Hibbits * an explicit "AAD phase done" signal via FC1.
1843*73bb2479SJustin Hibbits */
1844*73bb2479SJustin Hibbits sec_jd_fifo(&b, CMD_DESC(CMD_SEQ_FIFO_LOAD) | FIFOLD_CLASS_1 |
1845*73bb2479SJustin Hibbits FIFOLD_TYPE_AAD | FIFOLD_FC1, aadlen);
1846*73bb2479SJustin Hibbits sec_jd_fifo(&b, CMD_DESC(CMD_SEQ_FIFO_STORE) |
1847*73bb2479SJustin Hibbits FIFOST_TYPE_MSG_DATA, paylen);
1848*73bb2479SJustin Hibbits
1849*73bb2479SJustin Hibbits /* MSG: LC1 for encrypt (last class-1 input), FC1 for decrypt. */
1850*73bb2479SJustin Hibbits sec_jd_fifo(&b, CMD_DESC(CMD_SEQ_FIFO_LOAD) | FIFOLD_CLASS_1 |
1851*73bb2479SJustin Hibbits FIFOLD_TYPE_MSG | (enc ? FIFOLD_LC1 : FIFOLD_FC1), paylen);
1852*73bb2479SJustin Hibbits if (enc)
1853*73bb2479SJustin Hibbits sec_jd_store(&b, false, LOAD_CLASS_1, LOAD_CTX, 0, taglen,
1854*73bb2479SJustin Hibbits digest_pa);
1855*73bb2479SJustin Hibbits else
1856*73bb2479SJustin Hibbits sec_jd_fifo(&b, CMD_DESC(CMD_SEQ_FIFO_LOAD) |
1857*73bb2479SJustin Hibbits FIFOLD_CLASS_1 | FIFOLD_TYPE_ICV | FIFOLD_LC1, taglen);
1858*73bb2479SJustin Hibbits
1859*73bb2479SJustin Hibbits /* SHR=1, NO REO, so the shd (KEY only) runs first, then the JD. */
1860*73bb2479SJustin Hibbits return (sec_desc_finalize_job(&b, HEADER_SHR |
1861*73bb2479SJustin Hibbits HEADER_SHR_DESC_L(sdlen) | HEADER_SHARE_SERIAL, &desclen));
1862*73bb2479SJustin Hibbits }
1863*73bb2479SJustin Hibbits
1864*73bb2479SJustin Hibbits /*
1865*73bb2479SJustin Hibbits * JD for AES-CCM.
1866*73bb2479SJustin Hibbits */
1867*73bb2479SJustin Hibbits static int
sec_jd_build_ccm(struct sec_job * job)1868*73bb2479SJustin Hibbits sec_jd_build_ccm(struct sec_job *job)
1869*73bb2479SJustin Hibbits {
1870*73bb2479SJustin Hibbits struct sec_desc_builder b;
1871*73bb2479SJustin Hibbits struct sec_session *sess = job->sess;
1872*73bb2479SJustin Hibbits uint32_t sdlen = sess->sdlen[0];
1873*73bb2479SJustin Hibbits uint32_t desclen, aadlen, paylen, taglen, in_len;
1874*73bb2479SJustin Hibbits vm_paddr_t shd_pa, in_sgt_pa, out_sgt_pa, digest_pa;
1875*73bb2479SJustin Hibbits int enc;
1876*73bb2479SJustin Hibbits
1877*73bb2479SJustin Hibbits enc = (job->crp->crp_op & CRYPTO_OP_ENCRYPT) != 0;
1878*73bb2479SJustin Hibbits aadlen = job->crp->crp_aad_length;
1879*73bb2479SJustin Hibbits paylen = job->crp->crp_payload_length;
1880*73bb2479SJustin Hibbits taglen = sess->digestlen;
1881*73bb2479SJustin Hibbits
1882*73bb2479SJustin Hibbits in_len = SEC_CCM_CTX_LEN + paylen + (enc ? 0 : taglen);
1883*73bb2479SJustin Hibbits if (aadlen > 0)
1884*73bb2479SJustin Hibbits in_len += sizeof(job->ccm_alen) + aadlen;
1885*73bb2479SJustin Hibbits
1886*73bb2479SJustin Hibbits shd_pa = pmap_kextract((vm_offset_t)sess->ctx[enc].shd);
1887*73bb2479SJustin Hibbits in_sgt_pa = pmap_kextract((vm_offset_t)job->in_sgt);
1888*73bb2479SJustin Hibbits out_sgt_pa = pmap_kextract((vm_offset_t)job->out_sgt);
1889*73bb2479SJustin Hibbits digest_pa = pmap_kextract((vm_offset_t)job->digest);
1890*73bb2479SJustin Hibbits
1891*73bb2479SJustin Hibbits sec_desc_init(&b, job->jd, SEC_MAX_DESC_WORDS);
1892*73bb2479SJustin Hibbits sec_jd_ptr(&b, shd_pa);
1893*73bb2479SJustin Hibbits
1894*73bb2479SJustin Hibbits sec_jd_seq(&b, true, SEQ_SGF | SEQ_EXT, out_sgt_pa, paylen);
1895*73bb2479SJustin Hibbits sec_jd_seq(&b, false, SEQ_SGF | SEQ_EXT, in_sgt_pa, in_len);
1896*73bb2479SJustin Hibbits
1897*73bb2479SJustin Hibbits /* B0 || CTR0 || zeroed result dwords, from the head of the input. */
1898*73bb2479SJustin Hibbits sec_desc_word(&b, CMD_DESC(CMD_SEQ_LOAD) | LOAD_CLASS_1 | LOAD_CTX |
1899*73bb2479SJustin Hibbits (SEC_CCM_CTX_LEN & LOAD_LENGTH_M));
1900*73bb2479SJustin Hibbits
1901*73bb2479SJustin Hibbits sec_desc_word(&b, CMD_DESC(CMD_OPERATION) | ALG_AES | AAI_AES_CCM |
1902*73bb2479SJustin Hibbits AS_INIT_FINAL | (enc ? OP_ENC : OP_ICV));
1903*73bb2479SJustin Hibbits
1904*73bb2479SJustin Hibbits /* Writing the data size starts the operation. */
1905*73bb2479SJustin Hibbits sec_jd_load(&b, false, LOAD_CLASS_1, LOAD_IMM, LOAD_DSR, 0, 8,
1906*73bb2479SJustin Hibbits (uint64_t)paylen << 32);
1907*73bb2479SJustin Hibbits
1908*73bb2479SJustin Hibbits /* Length-prefixed AAD; the hardware pads it out to 16 bytes. */
1909*73bb2479SJustin Hibbits if (aadlen > 0)
1910*73bb2479SJustin Hibbits sec_jd_fifo(&b, CMD_DESC(CMD_SEQ_FIFO_LOAD) |
1911*73bb2479SJustin Hibbits FIFOLD_CLASS_1 | FIFOLD_TYPE_AAD | FIFOLD_FC1,
1912*73bb2479SJustin Hibbits sizeof(job->ccm_alen) + aadlen);
1913*73bb2479SJustin Hibbits
1914*73bb2479SJustin Hibbits /* Arm the drain before the message, as for GCM. */
1915*73bb2479SJustin Hibbits sec_jd_fifo(&b, CMD_DESC(CMD_SEQ_FIFO_STORE) |
1916*73bb2479SJustin Hibbits FIFOST_TYPE_MSG_DATA, paylen);
1917*73bb2479SJustin Hibbits
1918*73bb2479SJustin Hibbits sec_jd_fifo(&b, CMD_DESC(CMD_SEQ_FIFO_LOAD) | FIFOLD_CLASS_1 |
1919*73bb2479SJustin Hibbits FIFOLD_TYPE_MSG | (enc ? FIFOLD_LC1 : FIFOLD_FC1), paylen);
1920*73bb2479SJustin Hibbits
1921*73bb2479SJustin Hibbits if (enc)
1922*73bb2479SJustin Hibbits sec_jd_store(&b, false, LOAD_CLASS_1, LOAD_CTX, 32, taglen,
1923*73bb2479SJustin Hibbits digest_pa);
1924*73bb2479SJustin Hibbits else
1925*73bb2479SJustin Hibbits sec_jd_fifo(&b, CMD_DESC(CMD_SEQ_FIFO_LOAD) |
1926*73bb2479SJustin Hibbits FIFOLD_CLASS_1 | FIFOLD_TYPE_ICV | FIFOLD_LC1, taglen);
1927*73bb2479SJustin Hibbits
1928*73bb2479SJustin Hibbits return (sec_desc_finalize_job(&b, HEADER_SHR |
1929*73bb2479SJustin Hibbits HEADER_SHR_DESC_L(sdlen) | HEADER_SHARE_SERIAL, &desclen));
1930*73bb2479SJustin Hibbits }
1931*73bb2479SJustin Hibbits
1932*73bb2479SJustin Hibbits /*
1933*73bb2479SJustin Hibbits * JD for encrypt-then-auth.
1934*73bb2479SJustin Hibbits */
1935*73bb2479SJustin Hibbits static int
sec_jd_build_eta(struct sec_job * job)1936*73bb2479SJustin Hibbits sec_jd_build_eta(struct sec_job *job)
1937*73bb2479SJustin Hibbits {
1938*73bb2479SJustin Hibbits struct sec_desc_builder b;
1939*73bb2479SJustin Hibbits struct sec_session *sess = job->sess;
1940*73bb2479SJustin Hibbits const struct crypto_session_params *csp;
1941*73bb2479SJustin Hibbits uint32_t sdlen, desclen, aadlen, paylen, ivlen, in_len;
1942*73bb2479SJustin Hibbits uint32_t ctx_offset;
1943*73bb2479SJustin Hibbits vm_paddr_t shd_pa, in_sgt_pa, out_sgt_pa, digest_pa;
1944*73bb2479SJustin Hibbits int enc;
1945*73bb2479SJustin Hibbits
1946*73bb2479SJustin Hibbits csp = crypto_get_params(job->crp->crp_session);
1947*73bb2479SJustin Hibbits enc = CRYPTO_OP_IS_ENCRYPT(job->crp->crp_op);
1948*73bb2479SJustin Hibbits sdlen = sess->sdlen[enc];
1949*73bb2479SJustin Hibbits ivlen = csp->csp_ivlen;
1950*73bb2479SJustin Hibbits aadlen = job->crp->crp_aad_length;
1951*73bb2479SJustin Hibbits paylen = job->crp->crp_payload_length;
1952*73bb2479SJustin Hibbits
1953*73bb2479SJustin Hibbits in_len = ivlen + aadlen + paylen;
1954*73bb2479SJustin Hibbits
1955*73bb2479SJustin Hibbits shd_pa = pmap_kextract((vm_offset_t)sess->ctx[enc].shd);
1956*73bb2479SJustin Hibbits in_sgt_pa = pmap_kextract((vm_offset_t)job->in_sgt);
1957*73bb2479SJustin Hibbits out_sgt_pa = pmap_kextract((vm_offset_t)job->out_sgt);
1958*73bb2479SJustin Hibbits digest_pa = pmap_kextract((vm_offset_t)job->digest);
1959*73bb2479SJustin Hibbits
1960*73bb2479SJustin Hibbits sec_desc_init(&b, job->jd, SEC_MAX_DESC_WORDS);
1961*73bb2479SJustin Hibbits sec_jd_ptr(&b, shd_pa);
1962*73bb2479SJustin Hibbits
1963*73bb2479SJustin Hibbits sec_jd_seq(&b, true, SEQ_SGF | SEQ_EXT, out_sgt_pa, paylen);
1964*73bb2479SJustin Hibbits sec_jd_seq(&b, false, SEQ_SGF | SEQ_EXT, in_sgt_pa, in_len);
1965*73bb2479SJustin Hibbits
1966*73bb2479SJustin Hibbits ctx_offset = sec_cipher_ctx_offset(csp->csp_cipher_alg);
1967*73bb2479SJustin Hibbits
1968*73bb2479SJustin Hibbits /* IV into the class 1 context; also drops SIL by ivlen. */
1969*73bb2479SJustin Hibbits sec_jd_load(&b, true, LOAD_CLASS_1, 0, LOAD_CTX, ctx_offset,
1970*73bb2479SJustin Hibbits ivlen, 0);
1971*73bb2479SJustin Hibbits
1972*73bb2479SJustin Hibbits /* AAD is authenticated only, so class 2 alone. */
1973*73bb2479SJustin Hibbits if (aadlen > 0)
1974*73bb2479SJustin Hibbits sec_jd_fifo(&b, CMD_DESC(CMD_SEQ_FIFO_LOAD) |
1975*73bb2479SJustin Hibbits FIFOLD_CLASS_2 | FIFOLD_TYPE_MSG, aadlen);
1976*73bb2479SJustin Hibbits
1977*73bb2479SJustin Hibbits /* Arm the ciphertext drain before feeding the message. */
1978*73bb2479SJustin Hibbits sec_jd_fifo(&b, CMD_DESC(CMD_SEQ_FIFO_STORE) |
1979*73bb2479SJustin Hibbits FIFOST_TYPE_MSG_DATA, paylen);
1980*73bb2479SJustin Hibbits
1981*73bb2479SJustin Hibbits sec_jd_fifo(&b, CMD_DESC(CMD_SEQ_FIFO_LOAD) |
1982*73bb2479SJustin Hibbits FIFOLD_CLASS_BOTH | FIFOLD_LC1 | FIFOLD_LC2 |
1983*73bb2479SJustin Hibbits (enc ? FIFOLD_TYPE_MSG_C1OUT : FIFOLD_TYPE_MSG), paylen);
1984*73bb2479SJustin Hibbits
1985*73bb2479SJustin Hibbits /* Drain the MAC to job->digest; the caller compares or copies back. */
1986*73bb2479SJustin Hibbits sec_jd_store(&b, false, LOAD_CLASS_2, LOAD_CTX, 0,
1987*73bb2479SJustin Hibbits sess->digestlen, digest_pa);
1988*73bb2479SJustin Hibbits
1989*73bb2479SJustin Hibbits return (sec_desc_finalize_job(&b, HEADER_SHR |
1990*73bb2479SJustin Hibbits HEADER_SHR_DESC_L(sdlen) | HEADER_SHARE_SERIAL, &desclen));
1991*73bb2479SJustin Hibbits }
1992*73bb2479SJustin Hibbits
1993*73bb2479SJustin Hibbits /*
1994*73bb2479SJustin Hibbits * JD for AES-GMAC: GCM with nothing to encrypt.
1995*73bb2479SJustin Hibbits */
1996*73bb2479SJustin Hibbits static int
sec_jd_build_gmac(struct sec_job * job)1997*73bb2479SJustin Hibbits sec_jd_build_gmac(struct sec_job *job)
1998*73bb2479SJustin Hibbits {
1999*73bb2479SJustin Hibbits struct sec_desc_builder b;
2000*73bb2479SJustin Hibbits struct sec_session *sess = job->sess;
2001*73bb2479SJustin Hibbits const struct crypto_session_params *csp;
2002*73bb2479SJustin Hibbits uint32_t sdlen = sess->sdlen[0];
2003*73bb2479SJustin Hibbits uint32_t desclen, ivlen, datalen, dsr_val, in_len;
2004*73bb2479SJustin Hibbits vm_paddr_t shd_pa, in_sgt_pa, digest_pa;
2005*73bb2479SJustin Hibbits
2006*73bb2479SJustin Hibbits csp = crypto_get_params(job->crp->crp_session);
2007*73bb2479SJustin Hibbits ivlen = csp->csp_ivlen;
2008*73bb2479SJustin Hibbits datalen = job->crp->crp_payload_length;
2009*73bb2479SJustin Hibbits
2010*73bb2479SJustin Hibbits /*
2011*73bb2479SJustin Hibbits * The digest-mode SGT maps the payload only, so AAD has nowhere
2012*73bb2479SJustin Hibbits * to come from.
2013*73bb2479SJustin Hibbits */
2014*73bb2479SJustin Hibbits if (job->crp->crp_aad_length != 0)
2015*73bb2479SJustin Hibbits return (EOPNOTSUPP);
2016*73bb2479SJustin Hibbits
2017*73bb2479SJustin Hibbits dsr_val = roundup(ivlen, 16) + roundup(datalen, 16);
2018*73bb2479SJustin Hibbits in_len = ivlen + datalen;
2019*73bb2479SJustin Hibbits
2020*73bb2479SJustin Hibbits shd_pa = pmap_kextract((vm_offset_t)sess->ctx[0].shd);
2021*73bb2479SJustin Hibbits in_sgt_pa = pmap_kextract((vm_offset_t)job->in_sgt);
2022*73bb2479SJustin Hibbits digest_pa = pmap_kextract((vm_offset_t)job->digest);
2023*73bb2479SJustin Hibbits
2024*73bb2479SJustin Hibbits sec_desc_init(&b, job->jd, SEC_MAX_DESC_WORDS);
2025*73bb2479SJustin Hibbits sec_jd_ptr(&b, shd_pa);
2026*73bb2479SJustin Hibbits
2027*73bb2479SJustin Hibbits /* No output sequence: the tag leaves through an inline STORE. */
2028*73bb2479SJustin Hibbits sec_jd_seq(&b, false, SEQ_SGF | SEQ_EXT, in_sgt_pa, in_len);
2029*73bb2479SJustin Hibbits
2030*73bb2479SJustin Hibbits sec_desc_word(&b, CMD_DESC(CMD_OPERATION) | ALG_AES | AAI_AES_GCM |
2031*73bb2479SJustin Hibbits AS_INIT_FINAL | OP_ENC);
2032*73bb2479SJustin Hibbits
2033*73bb2479SJustin Hibbits sec_jd_load(&b, false, LOAD_CLASS_1, LOAD_IMM, LOAD_DSR, 0, 8,
2034*73bb2479SJustin Hibbits (uint64_t)dsr_val << 32);
2035*73bb2479SJustin Hibbits
2036*73bb2479SJustin Hibbits sec_jd_fifo(&b, CMD_DESC(CMD_SEQ_FIFO_LOAD) | FIFOLD_CLASS_1 |
2037*73bb2479SJustin Hibbits FIFOLD_TYPE_IV | FIFOLD_FC1, ivlen);
2038*73bb2479SJustin Hibbits sec_jd_fifo(&b, CMD_DESC(CMD_SEQ_FIFO_LOAD) | FIFOLD_CLASS_1 |
2039*73bb2479SJustin Hibbits FIFOLD_TYPE_AAD | FIFOLD_LC1, datalen);
2040*73bb2479SJustin Hibbits
2041*73bb2479SJustin Hibbits sec_jd_store(&b, false, LOAD_CLASS_1, LOAD_CTX, 0,
2042*73bb2479SJustin Hibbits sess->digestlen, digest_pa);
2043*73bb2479SJustin Hibbits
2044*73bb2479SJustin Hibbits return (sec_desc_finalize_job(&b, HEADER_SHR |
2045*73bb2479SJustin Hibbits HEADER_SHR_DESC_L(sdlen) | HEADER_SHARE_SERIAL, &desclen));
2046*73bb2479SJustin Hibbits }
2047*73bb2479SJustin Hibbits
2048*73bb2479SJustin Hibbits static int
sec_process(device_t dev,struct cryptop * crp,int hint)2049*73bb2479SJustin Hibbits sec_process(device_t dev, struct cryptop *crp, int hint)
2050*73bb2479SJustin Hibbits {
2051*73bb2479SJustin Hibbits struct sec_softc *sc = device_get_softc(dev);
2052*73bb2479SJustin Hibbits struct sec_session *sess = crypto_get_driver_session(crp->crp_session);
2053*73bb2479SJustin Hibbits const struct crypto_session_params *csp;
2054*73bb2479SJustin Hibbits struct sec_job *job;
2055*73bb2479SJustin Hibbits struct sec_jr *jr;
2056*73bb2479SJustin Hibbits int error;
2057*73bb2479SJustin Hibbits
2058*73bb2479SJustin Hibbits job = malloc(sizeof(*job), M_SEC, M_NOWAIT | M_ZERO);
2059*73bb2479SJustin Hibbits if (job == NULL) {
2060*73bb2479SJustin Hibbits crp->crp_etype = ENOMEM;
2061*73bb2479SJustin Hibbits crypto_done(crp);
2062*73bb2479SJustin Hibbits return (0);
2063*73bb2479SJustin Hibbits }
2064*73bb2479SJustin Hibbits job->crp = crp;
2065*73bb2479SJustin Hibbits job->sess = sess;
2066*73bb2479SJustin Hibbits
2067*73bb2479SJustin Hibbits error = bus_dmamap_create(sc->sc_dmatag, 0, &job->map);
2068*73bb2479SJustin Hibbits if (error != 0)
2069*73bb2479SJustin Hibbits goto fail_free;
2070*73bb2479SJustin Hibbits
2071*73bb2479SJustin Hibbits error = bus_dmamap_load_crp(sc->sc_dmatag, job->map, crp,
2072*73bb2479SJustin Hibbits sec_load_cb, job, BUS_DMA_NOWAIT);
2073*73bb2479SJustin Hibbits if (error != 0 || job->nsegs == 0) {
2074*73bb2479SJustin Hibbits if (error == 0)
2075*73bb2479SJustin Hibbits error = EIO;
2076*73bb2479SJustin Hibbits goto fail_destroy;
2077*73bb2479SJustin Hibbits }
2078*73bb2479SJustin Hibbits
2079*73bb2479SJustin Hibbits if (crp->crp_payload_length == 0) {
2080*73bb2479SJustin Hibbits error = EINVAL;
2081*73bb2479SJustin Hibbits goto fail_unload;
2082*73bb2479SJustin Hibbits }
2083*73bb2479SJustin Hibbits
2084*73bb2479SJustin Hibbits csp = crypto_get_params(crp->crp_session);
2085*73bb2479SJustin Hibbits if (csp->csp_ivlen > 0)
2086*73bb2479SJustin Hibbits crypto_read_iv(crp, job->iv);
2087*73bb2479SJustin Hibbits if (csp->csp_cipher_alg == CRYPTO_AES_XTS)
2088*73bb2479SJustin Hibbits sec_xts_tweak(job->iv);
2089*73bb2479SJustin Hibbits if (csp->csp_cipher_alg == CRYPTO_AES_CCM_16) {
2090*73bb2479SJustin Hibbits error = sec_ccm_prep(job, csp);
2091*73bb2479SJustin Hibbits if (error != 0)
2092*73bb2479SJustin Hibbits goto fail_unload;
2093*73bb2479SJustin Hibbits }
2094*73bb2479SJustin Hibbits
2095*73bb2479SJustin Hibbits error = sec_job_build_sgts(job, csp);
2096*73bb2479SJustin Hibbits if (error != 0)
2097*73bb2479SJustin Hibbits goto fail_unload;
2098*73bb2479SJustin Hibbits
2099*73bb2479SJustin Hibbits bus_dmamap_sync(sc->sc_dmatag, job->map,
2100*73bb2479SJustin Hibbits BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2101*73bb2479SJustin Hibbits
2102*73bb2479SJustin Hibbits switch (csp->csp_mode) {
2103*73bb2479SJustin Hibbits case CSP_MODE_DIGEST:
2104*73bb2479SJustin Hibbits if (csp->csp_auth_alg == CRYPTO_AES_NIST_GMAC)
2105*73bb2479SJustin Hibbits error = sec_jd_build_gmac(job);
2106*73bb2479SJustin Hibbits else
2107*73bb2479SJustin Hibbits error = sec_jd_build_digest(job);
2108*73bb2479SJustin Hibbits break;
2109*73bb2479SJustin Hibbits case CSP_MODE_AEAD:
2110*73bb2479SJustin Hibbits if (csp->csp_cipher_alg == CRYPTO_AES_CCM_16)
2111*73bb2479SJustin Hibbits error = sec_jd_build_ccm(job);
2112*73bb2479SJustin Hibbits else
2113*73bb2479SJustin Hibbits error = sec_jd_build_aead(job);
2114*73bb2479SJustin Hibbits break;
2115*73bb2479SJustin Hibbits case CSP_MODE_ETA:
2116*73bb2479SJustin Hibbits error = sec_jd_build_eta(job);
2117*73bb2479SJustin Hibbits break;
2118*73bb2479SJustin Hibbits default:
2119*73bb2479SJustin Hibbits error = sec_jd_build_cipher(job, csp);
2120*73bb2479SJustin Hibbits break;
2121*73bb2479SJustin Hibbits }
2122*73bb2479SJustin Hibbits if (error != 0)
2123*73bb2479SJustin Hibbits goto fail_unload;
2124*73bb2479SJustin Hibbits
2125*73bb2479SJustin Hibbits
2126*73bb2479SJustin Hibbits /*
2127*73bb2479SJustin Hibbits * Hand the job to a ring and return; sec_jr_intr() completes it.
2128*73bb2479SJustin Hibbits */
2129*73bb2479SJustin Hibbits jr = &sc->sc_jr[curcpu % sc->sc_njr];
2130*73bb2479SJustin Hibbits sec_jr_submit_job(sc, jr, job);
2131*73bb2479SJustin Hibbits return (0);
2132*73bb2479SJustin Hibbits
2133*73bb2479SJustin Hibbits fail_unload:
2134*73bb2479SJustin Hibbits bus_dmamap_sync(sc->sc_dmatag, job->map,
2135*73bb2479SJustin Hibbits BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2136*73bb2479SJustin Hibbits bus_dmamap_unload(sc->sc_dmatag, job->map);
2137*73bb2479SJustin Hibbits fail_destroy:
2138*73bb2479SJustin Hibbits bus_dmamap_destroy(sc->sc_dmatag, job->map);
2139*73bb2479SJustin Hibbits fail_free:
2140*73bb2479SJustin Hibbits free(job, M_SEC);
2141*73bb2479SJustin Hibbits /* ERESTART means opencrypto retries this crp, so don't complete it. */
2142*73bb2479SJustin Hibbits if (error == ERESTART)
2143*73bb2479SJustin Hibbits return (ERESTART);
2144*73bb2479SJustin Hibbits crp->crp_etype = error;
2145*73bb2479SJustin Hibbits crypto_done(crp);
2146*73bb2479SJustin Hibbits return (0);
2147*73bb2479SJustin Hibbits }
2148*73bb2479SJustin Hibbits
2149*73bb2479SJustin Hibbits static int
sec_reset(struct sec_softc * sc)2150*73bb2479SJustin Hibbits sec_reset(struct sec_softc *sc)
2151*73bb2479SJustin Hibbits {
2152*73bb2479SJustin Hibbits uint32_t mcfgr;
2153*73bb2479SJustin Hibbits int i;
2154*73bb2479SJustin Hibbits
2155*73bb2479SJustin Hibbits /*
2156*73bb2479SJustin Hibbits * Preserve cache-attribute fields (AWCACHE/ARCACHE) and burst
2157*73bb2479SJustin Hibbits * settings across the reset. The MCFGR write overwrites those
2158*73bb2479SJustin Hibbits * along with SWRST.
2159*73bb2479SJustin Hibbits */
2160*73bb2479SJustin Hibbits mcfgr = SEC_RD4(sc, SEC_MCFGR);
2161*73bb2479SJustin Hibbits SEC_WR4(sc, SEC_MCFGR, mcfgr | MCFGR_SWRST);
2162*73bb2479SJustin Hibbits
2163*73bb2479SJustin Hibbits /* Poll SWRST for self-clear. */
2164*73bb2479SJustin Hibbits for (i = 0; i < 10000; i++) {
2165*73bb2479SJustin Hibbits if ((SEC_RD4(sc, SEC_MCFGR) & MCFGR_SWRST) == 0)
2166*73bb2479SJustin Hibbits break;
2167*73bb2479SJustin Hibbits DELAY(10);
2168*73bb2479SJustin Hibbits }
2169*73bb2479SJustin Hibbits if ((SEC_RD4(sc, SEC_MCFGR) & MCFGR_SWRST) != 0) {
2170*73bb2479SJustin Hibbits device_printf(sc->sc_dev, "MCFGR.SWRST did not clear\n");
2171*73bb2479SJustin Hibbits return (EIO);
2172*73bb2479SJustin Hibbits }
2173*73bb2479SJustin Hibbits
2174*73bb2479SJustin Hibbits /*
2175*73bb2479SJustin Hibbits * Post-reset configuration: 40-bit pointers, DECO watchdog on,
2176*73bb2479SJustin Hibbits * large bursts. Preserve whatever cache attributes the bootloader
2177*73bb2479SJustin Hibbits * left in place.
2178*73bb2479SJustin Hibbits */
2179*73bb2479SJustin Hibbits mcfgr &= (MCFGR_ARCACHE_M | MCFGR_AWCACHE_M);
2180*73bb2479SJustin Hibbits mcfgr |= MCFGR_PS | MCFGR_WDE | MCFGR_LARGE_BURST;
2181*73bb2479SJustin Hibbits SEC_WR4(sc, SEC_MCFGR, mcfgr);
2182*73bb2479SJustin Hibbits
2183*73bb2479SJustin Hibbits return (0);
2184*73bb2479SJustin Hibbits }
2185*73bb2479SJustin Hibbits
2186*73bb2479SJustin Hibbits /*
2187*73bb2479SJustin Hibbits * Instantiate one RNG state handle via DECO0 direct access.
2188*73bb2479SJustin Hibbits */
2189*73bb2479SJustin Hibbits static int
sec_deco_rng_init(struct sec_softc * sc,int sh)2190*73bb2479SJustin Hibbits sec_deco_rng_init(struct sec_softc *sc, int sh)
2191*73bb2479SJustin Hibbits {
2192*73bb2479SJustin Hibbits uint32_t jd[2];
2193*73bb2479SJustin Hibbits uint32_t reg, decorr, scfgr;
2194*73bb2479SJustin Hibbits int i;
2195*73bb2479SJustin Hibbits
2196*73bb2479SJustin Hibbits jd[0] = CMD_DESC(CMD_DESC_HEADER) | HEADER_ONE |
2197*73bb2479SJustin Hibbits (2 & HEADER_DESCLEN_M);
2198*73bb2479SJustin Hibbits jd[1] = CMD_DESC(CMD_OPERATION) | ALG_RNG | AS_INIT | OP_RNG_SH(sh);
2199*73bb2479SJustin Hibbits
2200*73bb2479SJustin Hibbits /* Request DECO0 and wait for the grant (DEN0=1). */
2201*73bb2479SJustin Hibbits SEC_WR4(sc, SEC_DECORR, DECORR_RQD0);
2202*73bb2479SJustin Hibbits decorr = SEC_RD4(sc, SEC_DECORR);
2203*73bb2479SJustin Hibbits for (i = 0; i < 10000; i++) {
2204*73bb2479SJustin Hibbits decorr = SEC_RD4(sc, SEC_DECORR);
2205*73bb2479SJustin Hibbits if ((decorr & DECORR_DEN0) != 0)
2206*73bb2479SJustin Hibbits break;
2207*73bb2479SJustin Hibbits DELAY(10);
2208*73bb2479SJustin Hibbits }
2209*73bb2479SJustin Hibbits if ((decorr & DECORR_DEN0) == 0) {
2210*73bb2479SJustin Hibbits scfgr = SEC_RD4(sc, SEC_SCFGR);
2211*73bb2479SJustin Hibbits device_printf(sc->sc_dev,
2212*73bb2479SJustin Hibbits "DECO0 acquire timeout (DECORR=%#x SCFGR=%#x%s)\n",
2213*73bb2479SJustin Hibbits decorr, scfgr,
2214*73bb2479SJustin Hibbits (scfgr & SCFGR_VIRT_EN) ? " VIRT_EN" : "");
2215*73bb2479SJustin Hibbits SEC_WR4(sc, SEC_DECORR, 0);
2216*73bb2479SJustin Hibbits return (ETIMEDOUT);
2217*73bb2479SJustin Hibbits }
2218*73bb2479SJustin Hibbits
2219*73bb2479SJustin Hibbits SEC_WR4(sc, SEC_D0DESB(0), jd[0]);
2220*73bb2479SJustin Hibbits SEC_WR4(sc, SEC_D0DESB(1), jd[1]);
2221*73bb2479SJustin Hibbits
2222*73bb2479SJustin Hibbits SEC_WR4(sc, SEC_D0JQCR_MS, DAJQCR_MS_WHL);
2223*73bb2479SJustin Hibbits
2224*73bb2479SJustin Hibbits /* Wait for job completion */
2225*73bb2479SJustin Hibbits reg = 0;
2226*73bb2479SJustin Hibbits for (i = 0; i < 100000; i++) {
2227*73bb2479SJustin Hibbits reg = SEC_RD4(sc, SEC_D0DDR);
2228*73bb2479SJustin Hibbits if ((reg & DADDR_VALID) == 0)
2229*73bb2479SJustin Hibbits break;
2230*73bb2479SJustin Hibbits DELAY(10);
2231*73bb2479SJustin Hibbits }
2232*73bb2479SJustin Hibbits
2233*73bb2479SJustin Hibbits /* Release DECO0 either way. */
2234*73bb2479SJustin Hibbits SEC_WR4(sc, SEC_DECORR, 0);
2235*73bb2479SJustin Hibbits
2236*73bb2479SJustin Hibbits if ((reg & DADDR_VALID) != 0) {
2237*73bb2479SJustin Hibbits device_printf(sc->sc_dev,
2238*73bb2479SJustin Hibbits "RNG SH%d instantiate timeout (D0DDR=%#x)\n", sh, reg);
2239*73bb2479SJustin Hibbits return (ETIMEDOUT);
2240*73bb2479SJustin Hibbits }
2241*73bb2479SJustin Hibbits if (((reg & DADDR_DECO_STATE_M) >> DADDR_DECO_STATE_S) != 0) {
2242*73bb2479SJustin Hibbits device_printf(sc->sc_dev,
2243*73bb2479SJustin Hibbits "RNG SH%d instantiate error (D0DDR=%#x, DECO_STATE=%u)\n",
2244*73bb2479SJustin Hibbits sh, reg,
2245*73bb2479SJustin Hibbits (reg & DADDR_DECO_STATE_M) >> DADDR_DECO_STATE_S);
2246*73bb2479SJustin Hibbits return (EIO);
2247*73bb2479SJustin Hibbits }
2248*73bb2479SJustin Hibbits return (0);
2249*73bb2479SJustin Hibbits }
2250*73bb2479SJustin Hibbits
2251*73bb2479SJustin Hibbits static int
sec_rng_init(struct sec_softc * sc)2252*73bb2479SJustin Hibbits sec_rng_init(struct sec_softc *sc)
2253*73bb2479SJustin Hibbits {
2254*73bb2479SJustin Hibbits uint32_t rdsta;
2255*73bb2479SJustin Hibbits int error, sh;
2256*73bb2479SJustin Hibbits
2257*73bb2479SJustin Hibbits /*
2258*73bb2479SJustin Hibbits * SEC v4/v5 requires the DRNG state handles to be instantiated
2259*73bb2479SJustin Hibbits * before any class-1 (AES/DES/RNG) job will execute. This is typically
2260*73bb2479SJustin Hibbits * done by the bootloader, but finish what it didn't.
2261*73bb2479SJustin Hibbits */
2262*73bb2479SJustin Hibbits rdsta = SEC_RD4(sc, SEC_RDSTA);
2263*73bb2479SJustin Hibbits
2264*73bb2479SJustin Hibbits if ((rdsta & RDSTA_CE) != 0) {
2265*73bb2479SJustin Hibbits device_printf(sc->sc_dev,
2266*73bb2479SJustin Hibbits "RNG catastrophic error (RDSTA=%#x, ERRCODE=%u)\n",
2267*73bb2479SJustin Hibbits rdsta, (rdsta & RDSTA_ERRCODE_M) >> RDSTA_ERRCODE_S);
2268*73bb2479SJustin Hibbits return (EIO);
2269*73bb2479SJustin Hibbits }
2270*73bb2479SJustin Hibbits
2271*73bb2479SJustin Hibbits /* Instantiate anything the bootloader didn't. */
2272*73bb2479SJustin Hibbits for (sh = 0; sh <= 1; sh++) {
2273*73bb2479SJustin Hibbits uint32_t bit = (sh == 0) ? RDSTA_IF0 : RDSTA_IF1;
2274*73bb2479SJustin Hibbits
2275*73bb2479SJustin Hibbits if ((rdsta & bit) != 0)
2276*73bb2479SJustin Hibbits continue;
2277*73bb2479SJustin Hibbits error = sec_deco_rng_init(sc, sh);
2278*73bb2479SJustin Hibbits if (error != 0)
2279*73bb2479SJustin Hibbits return (error);
2280*73bb2479SJustin Hibbits }
2281*73bb2479SJustin Hibbits
2282*73bb2479SJustin Hibbits /* Verify the handles are now up. */
2283*73bb2479SJustin Hibbits rdsta = SEC_RD4(sc, SEC_RDSTA);
2284*73bb2479SJustin Hibbits if ((rdsta & (RDSTA_IF0 | RDSTA_IF1)) !=
2285*73bb2479SJustin Hibbits (RDSTA_IF0 | RDSTA_IF1)) {
2286*73bb2479SJustin Hibbits device_printf(sc->sc_dev,
2287*73bb2479SJustin Hibbits "RNG instantiation left RDSTA=%#x\n", rdsta);
2288*73bb2479SJustin Hibbits return (EIO);
2289*73bb2479SJustin Hibbits }
2290*73bb2479SJustin Hibbits return (0);
2291*73bb2479SJustin Hibbits }
2292