xref: /freebsd-13.1/sys/mips/nlm/dev/sec/nlmseclib.c (revision 58d69f4e)
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