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: stable/12/sys/mips/nlm/dev/sec/nlmseclib.c 326259 2017-11-27 15:07:26Z pfg $");
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)95 nlm_crypto_form_srcdst_segs(struct xlp_sec_command *cmd)
96 {
97 	unsigned int srcseg = 0, dstseg = 0;
98 	struct cryptodesc *cipdesc = NULL;
99 	struct cryptop *crp = NULL;
100 
101 	crp = cmd->crp;
102 	cipdesc = cmd->enccrd;
103 
104 	if (cipdesc != NULL) {
105 		/* IV is given as ONE segment to avoid copy */
106 		if (cipdesc->crd_flags & CRD_F_IV_EXPLICIT) {
107 			srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg,
108 			    cmd->iv, cmd->ivlen);
109 			dstseg = nlm_crypto_fill_dst_seg(cmd->paramp, dstseg,
110 			    cmd->iv, cmd->ivlen);
111 		}
112 	}
113 
114 	if (crp->crp_flags & CRYPTO_F_IMBUF) {
115 		struct mbuf *m = NULL;
116 
117 		m  = (struct mbuf *)crp->crp_buf;
118 		while (m != NULL) {
119 			srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg,
120 			    mtod(m,caddr_t), m->m_len);
121 			if (cipdesc != NULL) {
122 				dstseg = nlm_crypto_fill_dst_seg(cmd->paramp,
123 				    dstseg, mtod(m,caddr_t), m->m_len);
124 			}
125 			m = m->m_next;
126 		}
127 	} else if (crp->crp_flags & CRYPTO_F_IOV) {
128 		struct uio *uio = NULL;
129 		struct iovec *iov = NULL;
130 	        int iol = 0;
131 
132 		uio = (struct uio *)crp->crp_buf;
133 		iov = (struct iovec *)uio->uio_iov;
134 		iol = uio->uio_iovcnt;
135 
136 		while (iol > 0) {
137 			srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg,
138 			    (caddr_t)iov->iov_base, iov->iov_len);
139 			if (cipdesc != NULL) {
140 				dstseg = nlm_crypto_fill_dst_seg(cmd->paramp,
141 				    dstseg, (caddr_t)iov->iov_base,
142 				    iov->iov_len);
143 			}
144 			iov++;
145 			iol--;
146 		}
147 	} else {
148 		srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg,
149 		    ((caddr_t)crp->crp_buf), crp->crp_ilen);
150 		if (cipdesc != NULL) {
151 			dstseg = nlm_crypto_fill_dst_seg(cmd->paramp, dstseg,
152 			    ((caddr_t)crp->crp_buf), crp->crp_ilen);
153 		}
154 	}
155 	return (0);
156 }
157 
158 int
nlm_crypto_do_cipher(struct xlp_sec_softc * sc,struct xlp_sec_command * cmd)159 nlm_crypto_do_cipher(struct xlp_sec_softc *sc, struct xlp_sec_command *cmd)
160 {
161 	struct cryptodesc *cipdesc = NULL;
162 	unsigned char *cipkey = NULL;
163 	int ret = 0;
164 
165 	cipdesc = cmd->enccrd;
166 	cipkey = (unsigned char *)cipdesc->crd_key;
167 	if (cmd->cipheralg == NLM_CIPHER_3DES) {
168 		if (!(cipdesc->crd_flags & CRD_F_ENCRYPT)) {
169                         uint64_t *k, *tkey;
170 			k = (uint64_t *)cipdesc->crd_key;
171 			tkey = (uint64_t *)cmd->des3key;
172 			tkey[2] = k[0];
173 			tkey[1] = k[1];
174 			tkey[0] = k[2];
175 			cipkey = (unsigned char *)tkey;
176 		}
177 	}
178 	nlm_crypto_fill_pkt_ctrl(cmd->ctrlp, 0, NLM_HASH_BYPASS, 0,
179 	    cmd->cipheralg, cmd->ciphermode, cipkey,
180 	    (cipdesc->crd_klen >> 3), NULL, 0);
181 
182 	nlm_crypto_fill_cipher_pkt_param(cmd->ctrlp, cmd->paramp,
183 	    (cipdesc->crd_flags & CRD_F_ENCRYPT) ? 1 : 0, cmd->ivoff,
184 	    cmd->ivlen, cmd->cipheroff, cmd->cipherlen);
185 	nlm_crypto_form_srcdst_segs(cmd);
186 
187 	ret = nlm_crypto_complete_sec_request(sc, cmd);
188 	return (ret);
189 }
190 
191 int
nlm_crypto_do_digest(struct xlp_sec_softc * sc,struct xlp_sec_command * cmd)192 nlm_crypto_do_digest(struct xlp_sec_softc *sc, struct xlp_sec_command *cmd)
193 {
194 	struct cryptodesc *digdesc = NULL;
195 	int ret=0;
196 
197 	digdesc = cmd->maccrd;
198 
199 	nlm_crypto_fill_pkt_ctrl(cmd->ctrlp, (digdesc->crd_klen) ? 1 : 0,
200 	    cmd->hashalg, cmd->hashmode, NLM_CIPHER_BYPASS, 0,
201 	    NULL, 0, digdesc->crd_key, digdesc->crd_klen >> 3);
202 
203 	nlm_crypto_fill_auth_pkt_param(cmd->ctrlp, cmd->paramp,
204 	    cmd->hashoff, cmd->hashlen, cmd->hmacpad,
205 	    (unsigned char *)cmd->hashdest);
206 
207 	nlm_crypto_form_srcdst_segs(cmd);
208 
209 	ret = nlm_crypto_complete_sec_request(sc, cmd);
210 
211 	return (ret);
212 }
213 
214 int
nlm_crypto_do_cipher_digest(struct xlp_sec_softc * sc,struct xlp_sec_command * cmd)215 nlm_crypto_do_cipher_digest(struct xlp_sec_softc *sc,
216     struct xlp_sec_command *cmd)
217 {
218 	struct cryptodesc *cipdesc=NULL, *digdesc=NULL;
219 	unsigned char *cipkey = NULL;
220 	int ret=0;
221 
222 	cipdesc = cmd->enccrd;
223 	digdesc = cmd->maccrd;
224 
225 	cipkey = (unsigned char *)cipdesc->crd_key;
226 	if (cmd->cipheralg == NLM_CIPHER_3DES) {
227 		if (!(cipdesc->crd_flags & CRD_F_ENCRYPT)) {
228 			uint64_t *k, *tkey;
229 			k = (uint64_t *)cipdesc->crd_key;
230 			tkey = (uint64_t *)cmd->des3key;
231 			tkey[2] = k[0];
232 			tkey[1] = k[1];
233 			tkey[0] = k[2];
234 			cipkey = (unsigned char *)tkey;
235 		}
236 	}
237 	nlm_crypto_fill_pkt_ctrl(cmd->ctrlp, (digdesc->crd_klen) ? 1 : 0,
238 	    cmd->hashalg, cmd->hashmode, cmd->cipheralg, cmd->ciphermode,
239 	    cipkey, (cipdesc->crd_klen >> 3),
240 	    digdesc->crd_key, (digdesc->crd_klen >> 3));
241 
242 	nlm_crypto_fill_cipher_auth_pkt_param(cmd->ctrlp, cmd->paramp,
243 	    (cipdesc->crd_flags & CRD_F_ENCRYPT) ? 1 : 0, cmd->hashsrc,
244 	    cmd->ivoff, cmd->ivlen, cmd->hashoff, cmd->hashlen,
245 	    cmd->hmacpad, cmd->cipheroff, cmd->cipherlen,
246 	    (unsigned char *)cmd->hashdest);
247 
248 	nlm_crypto_form_srcdst_segs(cmd);
249 
250 	ret = nlm_crypto_complete_sec_request(sc, cmd);
251 	return (ret);
252 }
253 
254 int
nlm_get_digest_param(struct xlp_sec_command * cmd)255 nlm_get_digest_param(struct xlp_sec_command *cmd)
256 {
257 	switch(cmd->maccrd->crd_alg) {
258 	case CRYPTO_MD5:
259 		cmd->hashalg  = NLM_HASH_MD5;
260 		cmd->hashmode = NLM_HASH_MODE_SHA1;
261 		break;
262 	case CRYPTO_SHA1:
263 		cmd->hashalg  = NLM_HASH_SHA;
264 		cmd->hashmode = NLM_HASH_MODE_SHA1;
265 		break;
266 	case CRYPTO_MD5_HMAC:
267 		cmd->hashalg  = NLM_HASH_MD5;
268 		cmd->hashmode = NLM_HASH_MODE_SHA1;
269 		break;
270 	case CRYPTO_SHA1_HMAC:
271 		cmd->hashalg  = NLM_HASH_SHA;
272 		cmd->hashmode = NLM_HASH_MODE_SHA1;
273 		break;
274 	default:
275 		/* Not supported */
276 		return (-1);
277 	}
278 	return (0);
279 }
280 int
nlm_get_cipher_param(struct xlp_sec_command * cmd)281 nlm_get_cipher_param(struct xlp_sec_command *cmd)
282 {
283 	switch(cmd->enccrd->crd_alg) {
284 	case CRYPTO_DES_CBC:
285 		cmd->cipheralg  = NLM_CIPHER_DES;
286 		cmd->ciphermode = NLM_CIPHER_MODE_CBC;
287 		cmd->ivlen	= XLP_SEC_DES_IV_LENGTH;
288 		break;
289 	case CRYPTO_3DES_CBC:
290 		cmd->cipheralg  = NLM_CIPHER_3DES;
291 		cmd->ciphermode = NLM_CIPHER_MODE_CBC;
292 		cmd->ivlen	= XLP_SEC_DES_IV_LENGTH;
293 		break;
294 	case CRYPTO_AES_CBC:
295 		cmd->cipheralg  = NLM_CIPHER_AES128;
296 		cmd->ciphermode = NLM_CIPHER_MODE_CBC;
297 		cmd->ivlen	= XLP_SEC_AES_IV_LENGTH;
298 		break;
299 	case CRYPTO_ARC4:
300 		cmd->cipheralg  = NLM_CIPHER_ARC4;
301 		cmd->ciphermode = NLM_CIPHER_MODE_ECB;
302 		cmd->ivlen	= XLP_SEC_ARC4_IV_LENGTH;
303 		break;
304 	default:
305 		/* Not supported */
306 		return (-1);
307 	}
308 	return (0);
309 }
310