1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2003-2012 Broadcom Corporation
5 * All Rights Reserved
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/malloc.h>
40 #include <sys/mbuf.h>
41 #include <sys/lock.h>
42 #include <sys/mutex.h>
43 #include <sys/bus.h>
44 #include <sys/uio.h>
45 #include <machine/bus.h>
46 #include <machine/md_var.h>
47 #include <machine/cpuregs.h>
48
49 #include <vm/vm.h>
50 #include <vm/pmap.h>
51
52 #include <opencrypto/cryptodev.h>
53
54 #include <mips/nlm/hal/haldefs.h>
55 #include <mips/nlm/hal/cop2.h>
56 #include <mips/nlm/hal/fmn.h>
57 #include <mips/nlm/hal/mips-extns.h>
58 #include <mips/nlm/hal/nlmsaelib.h>
59 #include <mips/nlm/dev/sec/nlmseclib.h>
60
61 static int
nlm_crypto_complete_sec_request(struct xlp_sec_softc * sc,struct xlp_sec_command * cmd)62 nlm_crypto_complete_sec_request(struct xlp_sec_softc *sc,
63 struct xlp_sec_command *cmd)
64 {
65 unsigned int fbvc;
66 struct nlm_fmn_msg m;
67 int ret;
68
69 fbvc = nlm_cpuid() / CMS_MAX_VCPU_VC;
70 m.msg[0] = m.msg[1] = m.msg[2] = m.msg[3] = 0;
71
72 m.msg[0] = nlm_crypto_form_pkt_fmn_entry0(fbvc, 0, 0,
73 cmd->ctrlp->cipherkeylen, vtophys(cmd->ctrlp));
74
75 m.msg[1] = nlm_crypto_form_pkt_fmn_entry1(0, cmd->ctrlp->hashkeylen,
76 NLM_CRYPTO_PKT_DESC_SIZE(cmd->nsegs), vtophys(cmd->paramp));
77
78 /* Software scratch pad */
79 m.msg[2] = (uintptr_t)cmd;
80 sc->sec_msgsz = 3;
81
82 /* Send the message to sec/rsa engine vc */
83 ret = nlm_fmn_msgsend(sc->sec_vc_start, sc->sec_msgsz,
84 FMN_SWCODE_CRYPTO, &m);
85 if (ret != 0) {
86 #ifdef NLM_SEC_DEBUG
87 printf("%s: msgsnd failed (%x)\n", __func__, ret);
88 #endif
89 return (ERESTART);
90 }
91 return (0);
92 }
93
94 int
nlm_crypto_form_srcdst_segs(struct xlp_sec_command * cmd,const struct crypto_session_params * csp)95 nlm_crypto_form_srcdst_segs(struct xlp_sec_command *cmd,
96 const struct crypto_session_params *csp)
97 {
98 unsigned int srcseg = 0, dstseg = 0;
99 struct cryptop *crp = NULL;
100
101 crp = cmd->crp;
102
103 if (csp->csp_mode != CSP_MODE_DIGEST) {
104 /* IV is given as ONE segment to avoid copy */
105 if (crp->crp_flags & CRYPTO_F_IV_SEPARATE) {
106 srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg,
107 cmd->iv, cmd->ivlen);
108 dstseg = nlm_crypto_fill_dst_seg(cmd->paramp, dstseg,
109 cmd->iv, cmd->ivlen);
110 }
111 }
112
113 switch (crp->crp_buf.cb_type) {
114 case CRYPTO_BUF_MBUF:
115 {
116 struct mbuf *m = NULL;
117
118 m = crp->crp_buf.cb_mbuf;
119 while (m != NULL) {
120 srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg,
121 mtod(m,caddr_t), m->m_len);
122 if (csp->csp_mode != CSP_MODE_DIGEST) {
123 dstseg = nlm_crypto_fill_dst_seg(cmd->paramp,
124 dstseg, mtod(m,caddr_t), m->m_len);
125 }
126 m = m->m_next;
127 }
128 break;
129 }
130 case CRYPTO_BUF_UIO:
131 {
132 struct uio *uio = NULL;
133 struct iovec *iov = NULL;
134 int iol = 0;
135
136 uio = crp->crp_buf.cb_uio;
137 iov = uio->uio_iov;
138 iol = uio->uio_iovcnt;
139
140 while (iol > 0) {
141 srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg,
142 (caddr_t)iov->iov_base, iov->iov_len);
143 if (csp->csp_mode != CSP_MODE_DIGEST) {
144 dstseg = nlm_crypto_fill_dst_seg(cmd->paramp,
145 dstseg, (caddr_t)iov->iov_base,
146 iov->iov_len);
147 }
148 iov++;
149 iol--;
150 }
151 }
152 case CRYPTO_BUF_CONTIG:
153 srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg,
154 crp->crp_buf.cb_buf, crp->crp_buf.cb_buf_len);
155 if (csp->csp_mode != CSP_MODE_DIGEST) {
156 dstseg = nlm_crypto_fill_dst_seg(cmd->paramp, dstseg,
157 crp->crp_buf.cb_buf, crp->crp_buf.cb_buf_len);
158 }
159 break;
160 default:
161 __assert_unreachable();
162 }
163 return (0);
164 }
165
166 int
nlm_crypto_do_cipher(struct xlp_sec_softc * sc,struct xlp_sec_command * cmd,const struct crypto_session_params * csp)167 nlm_crypto_do_cipher(struct xlp_sec_softc *sc, struct xlp_sec_command *cmd,
168 const struct crypto_session_params *csp)
169 {
170 const unsigned char *cipkey = NULL;
171 int ret = 0;
172
173 if (cmd->crp->crp_cipher_key != NULL)
174 cipkey = cmd->crp->crp_cipher_key;
175 else
176 cipkey = csp->csp_cipher_key;
177 nlm_crypto_fill_pkt_ctrl(cmd->ctrlp, 0, NLM_HASH_BYPASS, 0,
178 cmd->cipheralg, cmd->ciphermode, cipkey,
179 csp->csp_cipher_klen, NULL, 0);
180
181 nlm_crypto_fill_cipher_pkt_param(cmd->ctrlp, cmd->paramp,
182 CRYPTO_OP_IS_ENCRYPT(cmd->crp->crp_op) ? 1 : 0, cmd->ivoff,
183 cmd->ivlen, cmd->cipheroff, cmd->cipherlen);
184 nlm_crypto_form_srcdst_segs(cmd, csp);
185
186 ret = nlm_crypto_complete_sec_request(sc, cmd);
187 return (ret);
188 }
189
190 int
nlm_crypto_do_digest(struct xlp_sec_softc * sc,struct xlp_sec_command * cmd,const struct crypto_session_params * csp)191 nlm_crypto_do_digest(struct xlp_sec_softc *sc, struct xlp_sec_command *cmd,
192 const struct crypto_session_params *csp)
193 {
194 const char *key;
195 int ret=0;
196
197 if (cmd->crp->crp_auth_key != NULL)
198 key = cmd->crp->crp_auth_key;
199 else
200 key = csp->csp_auth_key;
201 nlm_crypto_fill_pkt_ctrl(cmd->ctrlp, csp->csp_auth_klen ? 1 : 0,
202 cmd->hashalg, cmd->hashmode, NLM_CIPHER_BYPASS, 0,
203 NULL, 0, key, csp->csp_auth_klen);
204
205 nlm_crypto_fill_auth_pkt_param(cmd->ctrlp, cmd->paramp,
206 cmd->hashoff, cmd->hashlen, cmd->hmacpad,
207 (unsigned char *)cmd->hashdest);
208
209 nlm_crypto_form_srcdst_segs(cmd, csp);
210
211 ret = nlm_crypto_complete_sec_request(sc, cmd);
212
213 return (ret);
214 }
215
216 int
nlm_crypto_do_cipher_digest(struct xlp_sec_softc * sc,struct xlp_sec_command * cmd,const struct crypto_session_params * csp)217 nlm_crypto_do_cipher_digest(struct xlp_sec_softc *sc,
218 struct xlp_sec_command *cmd, const struct crypto_session_params *csp)
219 {
220 const unsigned char *cipkey = NULL;
221 const char *authkey;
222 int ret=0;
223
224 if (cmd->crp->crp_cipher_key != NULL)
225 cipkey = cmd->crp->crp_cipher_key;
226 else
227 cipkey = csp->csp_cipher_key;
228 if (cmd->crp->crp_auth_key != NULL)
229 authkey = cmd->crp->crp_auth_key;
230 else
231 authkey = csp->csp_auth_key;
232 nlm_crypto_fill_pkt_ctrl(cmd->ctrlp, csp->csp_auth_klen ? 1 : 0,
233 cmd->hashalg, cmd->hashmode, cmd->cipheralg, cmd->ciphermode,
234 cipkey, csp->csp_cipher_klen,
235 authkey, csp->csp_auth_klen);
236
237 nlm_crypto_fill_cipher_auth_pkt_param(cmd->ctrlp, cmd->paramp,
238 CRYPTO_OP_IS_ENCRYPT(cmd->crp->crp_op) ? 1 : 0, cmd->hashsrc,
239 cmd->ivoff, cmd->ivlen, cmd->hashoff, cmd->hashlen,
240 cmd->hmacpad, cmd->cipheroff, cmd->cipherlen,
241 (unsigned char *)cmd->hashdest);
242
243 nlm_crypto_form_srcdst_segs(cmd, csp);
244
245 ret = nlm_crypto_complete_sec_request(sc, cmd);
246 return (ret);
247 }
248
249 int
nlm_get_digest_param(struct xlp_sec_command * cmd,const struct crypto_session_params * csp)250 nlm_get_digest_param(struct xlp_sec_command *cmd,
251 const struct crypto_session_params *csp)
252 {
253 switch(csp->csp_auth_alg) {
254 case CRYPTO_SHA1:
255 cmd->hashalg = NLM_HASH_SHA;
256 cmd->hashmode = NLM_HASH_MODE_SHA1;
257 break;
258 case CRYPTO_SHA1_HMAC:
259 cmd->hashalg = NLM_HASH_SHA;
260 cmd->hashmode = NLM_HASH_MODE_SHA1;
261 break;
262 default:
263 /* Not supported */
264 return (-1);
265 }
266 return (0);
267 }
268 int
nlm_get_cipher_param(struct xlp_sec_command * cmd,const struct crypto_session_params * csp)269 nlm_get_cipher_param(struct xlp_sec_command *cmd,
270 const struct crypto_session_params *csp)
271 {
272 switch(csp->csp_cipher_alg) {
273 case CRYPTO_AES_CBC:
274 cmd->cipheralg = NLM_CIPHER_AES128;
275 cmd->ciphermode = NLM_CIPHER_MODE_CBC;
276 cmd->ivlen = XLP_SEC_AES_IV_LENGTH;
277 break;
278 default:
279 /* Not supported */
280 return (-1);
281 }
282 return (0);
283 }
284