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