xref: /f-stack/freebsd/mips/nlm/dev/sec/nlmseclib.c (revision 22ce4aff)
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