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
61static int
62nlm_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
94int
95nlm_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
158int
159nlm_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
191int
192nlm_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
214int
215nlm_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
254int
255nlm_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}
280int
281nlm_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