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 case CRYPTO_BUF_SINGLE_MBUF:
116 {
117 struct mbuf *m = NULL;
118
119 m = crp->crp_buf.cb_mbuf;
120 while (m != NULL) {
121 srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg,
122 mtod(m,caddr_t), m->m_len);
123 if (csp->csp_mode != CSP_MODE_DIGEST) {
124 dstseg = nlm_crypto_fill_dst_seg(cmd->paramp,
125 dstseg, mtod(m,caddr_t), m->m_len);
126 }
127 if (crp->crp_buf.cb_type == CRYPTO_BUF_SINGLE_MBUF)
128 break;
129 m = m->m_next;
130 }
131 break;
132 }
133 case CRYPTO_BUF_UIO:
134 {
135 struct uio *uio = NULL;
136 struct iovec *iov = NULL;
137 int iol = 0;
138
139 uio = crp->crp_buf.cb_uio;
140 iov = uio->uio_iov;
141 iol = uio->uio_iovcnt;
142
143 while (iol > 0) {
144 srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg,
145 (caddr_t)iov->iov_base, iov->iov_len);
146 if (csp->csp_mode != CSP_MODE_DIGEST) {
147 dstseg = nlm_crypto_fill_dst_seg(cmd->paramp,
148 dstseg, (caddr_t)iov->iov_base,
149 iov->iov_len);
150 }
151 iov++;
152 iol--;
153 }
154 }
155 case CRYPTO_BUF_CONTIG:
156 srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg,
157 crp->crp_buf.cb_buf, crp->crp_buf.cb_buf_len);
158 if (csp->csp_mode != CSP_MODE_DIGEST) {
159 dstseg = nlm_crypto_fill_dst_seg(cmd->paramp, dstseg,
160 crp->crp_buf.cb_buf, crp->crp_buf.cb_buf_len);
161 }
162 break;
163 default:
164 __assert_unreachable();
165 }
166 return (0);
167 }
168
169 int
nlm_crypto_do_cipher(struct xlp_sec_softc * sc,struct xlp_sec_command * cmd,const struct crypto_session_params * csp)170 nlm_crypto_do_cipher(struct xlp_sec_softc *sc, struct xlp_sec_command *cmd,
171 const struct crypto_session_params *csp)
172 {
173 const unsigned char *cipkey = NULL;
174 int ret = 0;
175
176 if (cmd->crp->crp_cipher_key != NULL)
177 cipkey = cmd->crp->crp_cipher_key;
178 else
179 cipkey = csp->csp_cipher_key;
180 nlm_crypto_fill_pkt_ctrl(cmd->ctrlp, 0, NLM_HASH_BYPASS, 0,
181 cmd->cipheralg, cmd->ciphermode, cipkey,
182 csp->csp_cipher_klen, NULL, 0);
183
184 nlm_crypto_fill_cipher_pkt_param(cmd->ctrlp, cmd->paramp,
185 CRYPTO_OP_IS_ENCRYPT(cmd->crp->crp_op) ? 1 : 0, cmd->ivoff,
186 cmd->ivlen, cmd->cipheroff, cmd->cipherlen);
187 nlm_crypto_form_srcdst_segs(cmd, csp);
188
189 ret = nlm_crypto_complete_sec_request(sc, cmd);
190 return (ret);
191 }
192
193 int
nlm_crypto_do_digest(struct xlp_sec_softc * sc,struct xlp_sec_command * cmd,const struct crypto_session_params * csp)194 nlm_crypto_do_digest(struct xlp_sec_softc *sc, struct xlp_sec_command *cmd,
195 const struct crypto_session_params *csp)
196 {
197 const char *key;
198 int ret=0;
199
200 if (cmd->crp->crp_auth_key != NULL)
201 key = cmd->crp->crp_auth_key;
202 else
203 key = csp->csp_auth_key;
204 nlm_crypto_fill_pkt_ctrl(cmd->ctrlp, csp->csp_auth_klen ? 1 : 0,
205 cmd->hashalg, cmd->hashmode, NLM_CIPHER_BYPASS, 0,
206 NULL, 0, key, csp->csp_auth_klen);
207
208 nlm_crypto_fill_auth_pkt_param(cmd->ctrlp, cmd->paramp,
209 cmd->hashoff, cmd->hashlen, cmd->hmacpad,
210 (unsigned char *)cmd->hashdest);
211
212 nlm_crypto_form_srcdst_segs(cmd, csp);
213
214 ret = nlm_crypto_complete_sec_request(sc, cmd);
215
216 return (ret);
217 }
218
219 int
nlm_crypto_do_cipher_digest(struct xlp_sec_softc * sc,struct xlp_sec_command * cmd,const struct crypto_session_params * csp)220 nlm_crypto_do_cipher_digest(struct xlp_sec_softc *sc,
221 struct xlp_sec_command *cmd, const struct crypto_session_params *csp)
222 {
223 const unsigned char *cipkey = NULL;
224 const char *authkey;
225 int ret=0;
226
227 if (cmd->crp->crp_cipher_key != NULL)
228 cipkey = cmd->crp->crp_cipher_key;
229 else
230 cipkey = csp->csp_cipher_key;
231 if (cmd->crp->crp_auth_key != NULL)
232 authkey = cmd->crp->crp_auth_key;
233 else
234 authkey = csp->csp_auth_key;
235 nlm_crypto_fill_pkt_ctrl(cmd->ctrlp, csp->csp_auth_klen ? 1 : 0,
236 cmd->hashalg, cmd->hashmode, cmd->cipheralg, cmd->ciphermode,
237 cipkey, csp->csp_cipher_klen,
238 authkey, csp->csp_auth_klen);
239
240 nlm_crypto_fill_cipher_auth_pkt_param(cmd->ctrlp, cmd->paramp,
241 CRYPTO_OP_IS_ENCRYPT(cmd->crp->crp_op) ? 1 : 0, cmd->hashsrc,
242 cmd->ivoff, cmd->ivlen, cmd->hashoff, cmd->hashlen,
243 cmd->hmacpad, cmd->cipheroff, cmd->cipherlen,
244 (unsigned char *)cmd->hashdest);
245
246 nlm_crypto_form_srcdst_segs(cmd, csp);
247
248 ret = nlm_crypto_complete_sec_request(sc, cmd);
249 return (ret);
250 }
251
252 int
nlm_get_digest_param(struct xlp_sec_command * cmd,const struct crypto_session_params * csp)253 nlm_get_digest_param(struct xlp_sec_command *cmd,
254 const struct crypto_session_params *csp)
255 {
256 switch(csp->csp_auth_alg) {
257 case CRYPTO_SHA1:
258 cmd->hashalg = NLM_HASH_SHA;
259 cmd->hashmode = NLM_HASH_MODE_SHA1;
260 break;
261 case CRYPTO_SHA1_HMAC:
262 cmd->hashalg = NLM_HASH_SHA;
263 cmd->hashmode = NLM_HASH_MODE_SHA1;
264 break;
265 default:
266 /* Not supported */
267 return (-1);
268 }
269 return (0);
270 }
271 int
nlm_get_cipher_param(struct xlp_sec_command * cmd,const struct crypto_session_params * csp)272 nlm_get_cipher_param(struct xlp_sec_command *cmd,
273 const struct crypto_session_params *csp)
274 {
275 switch(csp->csp_cipher_alg) {
276 case CRYPTO_AES_CBC:
277 cmd->cipheralg = NLM_CIPHER_AES128;
278 cmd->ciphermode = NLM_CIPHER_MODE_CBC;
279 cmd->ivlen = XLP_SEC_AES_IV_LENGTH;
280 break;
281 default:
282 /* Not supported */
283 return (-1);
284 }
285 return (0);
286 }
287