xref: /freebsd/sys/crypto/blake2/blake2_cryptodev.c (revision dc36d6f9bb1753f3808552f3afd30eda9a7b206a)
1 /*-
2  * Copyright (c) 2018 Conrad Meyer <cem@FreeBSD.org>
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  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 #include <sys/param.h>
29 #include <sys/bus.h>
30 #include <sys/kernel.h>
31 #include <sys/kobj.h>
32 #include <sys/malloc.h>
33 #include <sys/module.h>
34 #include <sys/mutex.h>
35 #include <sys/smp.h>
36 
37 #include <blake2.h>
38 
39 #include <opencrypto/cryptodev.h>
40 #include <cryptodev_if.h>
41 
42 #include <machine/fpu.h>
43 
44 struct blake2_session {
45 	size_t mlen;
46 };
47 CTASSERT((size_t)BLAKE2B_KEYBYTES > (size_t)BLAKE2S_KEYBYTES);
48 
49 struct blake2_softc {
50 	int32_t cid;
51 };
52 
53 static int blake2_cipher_setup(struct blake2_session *ses,
54     const struct crypto_session_params *csp);
55 static int blake2_cipher_process(struct blake2_session *ses,
56     struct cryptop *crp);
57 
58 MALLOC_DEFINE(M_BLAKE2, "blake2_data", "Blake2 Data");
59 
60 static void
61 blake2_identify(driver_t *drv, device_t parent)
62 {
63 
64 	/* NB: order 10 is so we get attached after h/w devices */
65 	if (device_find_child(parent, "blaketwo", -1) == NULL &&
66 	    BUS_ADD_CHILD(parent, 10, "blaketwo", -1) == 0)
67 		panic("blaketwo: could not attach");
68 }
69 
70 static int
71 blake2_probe(device_t dev)
72 {
73 	device_set_desc(dev, "Blake2");
74 	return (0);
75 }
76 
77 static int
78 blake2_attach(device_t dev)
79 {
80 	struct blake2_softc *sc;
81 
82 	sc = device_get_softc(dev);
83 
84 	sc->cid = crypto_get_driverid(dev, sizeof(struct blake2_session),
85 	    CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC |
86 	    CRYPTOCAP_F_ACCEL_SOFTWARE);
87 	if (sc->cid < 0) {
88 		device_printf(dev, "Could not get crypto driver id.\n");
89 		return (ENOMEM);
90 	}
91 
92 	return (0);
93 }
94 
95 static int
96 blake2_detach(device_t dev)
97 {
98 	struct blake2_softc *sc;
99 
100 	sc = device_get_softc(dev);
101 
102 	crypto_unregister_all(sc->cid);
103 
104 	return (0);
105 }
106 
107 static int
108 blake2_probesession(device_t dev, const struct crypto_session_params *csp)
109 {
110 
111 	if (csp->csp_flags != 0)
112 		return (EINVAL);
113 	switch (csp->csp_mode) {
114 	case CSP_MODE_DIGEST:
115 		switch (csp->csp_auth_alg) {
116 		case CRYPTO_BLAKE2B:
117 		case CRYPTO_BLAKE2S:
118 			break;
119 		default:
120 			return (EINVAL);
121 		}
122 		break;
123 	default:
124 		return (EINVAL);
125 	}
126 	return (CRYPTODEV_PROBE_ACCEL_SOFTWARE);
127 }
128 
129 static int
130 blake2_newsession(device_t dev, crypto_session_t cses,
131     const struct crypto_session_params *csp)
132 {
133 	struct blake2_session *ses;
134 	int error;
135 
136 	ses = crypto_get_driver_session(cses);
137 
138 	error = blake2_cipher_setup(ses, csp);
139 	if (error != 0) {
140 		CRYPTDEB("setup failed");
141 		return (error);
142 	}
143 
144 	return (0);
145 }
146 
147 static int
148 blake2_process(device_t dev, struct cryptop *crp, int hint __unused)
149 {
150 	struct blake2_session *ses;
151 	int error;
152 
153 	ses = crypto_get_driver_session(crp->crp_session);
154 	error = blake2_cipher_process(ses, crp);
155 
156 	crp->crp_etype = error;
157 	crypto_done(crp);
158 	return (0);
159 }
160 
161 static device_method_t blake2_methods[] = {
162 	DEVMETHOD(device_identify, blake2_identify),
163 	DEVMETHOD(device_probe, blake2_probe),
164 	DEVMETHOD(device_attach, blake2_attach),
165 	DEVMETHOD(device_detach, blake2_detach),
166 
167 	DEVMETHOD(cryptodev_probesession, blake2_probesession),
168 	DEVMETHOD(cryptodev_newsession, blake2_newsession),
169 	DEVMETHOD(cryptodev_process, blake2_process),
170 
171 	DEVMETHOD_END
172 };
173 
174 static driver_t blake2_driver = {
175 	"blaketwo",
176 	blake2_methods,
177 	sizeof(struct blake2_softc),
178 };
179 
180 DRIVER_MODULE(blake2, nexus, blake2_driver, 0, 0);
181 MODULE_VERSION(blake2, 1);
182 MODULE_DEPEND(blake2, crypto, 1, 1, 1);
183 
184 static bool
185 blake2_check_klen(const struct crypto_session_params *csp, unsigned klen)
186 {
187 
188 	if (csp->csp_auth_alg == CRYPTO_BLAKE2S)
189 		return (klen <= BLAKE2S_KEYBYTES);
190 	else
191 		return (klen <= BLAKE2B_KEYBYTES);
192 }
193 
194 static int
195 blake2_cipher_setup(struct blake2_session *ses,
196     const struct crypto_session_params *csp)
197 {
198 	int hashlen;
199 
200 	CTASSERT((size_t)BLAKE2S_OUTBYTES <= (size_t)BLAKE2B_OUTBYTES);
201 
202 	if (!blake2_check_klen(csp, csp->csp_auth_klen))
203 		return (EINVAL);
204 
205 	if (csp->csp_auth_mlen < 0)
206 		return (EINVAL);
207 
208 	switch (csp->csp_auth_alg) {
209 	case CRYPTO_BLAKE2S:
210 		hashlen = BLAKE2S_OUTBYTES;
211 		break;
212 	case CRYPTO_BLAKE2B:
213 		hashlen = BLAKE2B_OUTBYTES;
214 		break;
215 	default:
216 		return (EINVAL);
217 	}
218 
219 	if (csp->csp_auth_mlen > hashlen)
220 		return (EINVAL);
221 
222 	if (csp->csp_auth_mlen == 0)
223 		ses->mlen = hashlen;
224 	else
225 		ses->mlen = csp->csp_auth_mlen;
226 	return (0);
227 }
228 
229 static int
230 blake2b_applicator(void *state, const void *buf, u_int len)
231 {
232 	int rc;
233 
234 	rc = blake2b_update(state, buf, len);
235 	if (rc != 0)
236 		return (EINVAL);
237 	return (0);
238 }
239 
240 static int
241 blake2s_applicator(void *state, const void *buf, u_int len)
242 {
243 	int rc;
244 
245 	rc = blake2s_update(state, buf, len);
246 	if (rc != 0)
247 		return (EINVAL);
248 	return (0);
249 }
250 
251 static int
252 blake2_cipher_process(struct blake2_session *ses, struct cryptop *crp)
253 {
254 	union {
255 		blake2b_state sb;
256 		blake2s_state ss;
257 	} bctx;
258 	char res[BLAKE2B_OUTBYTES], res2[BLAKE2B_OUTBYTES];
259 	const struct crypto_session_params *csp;
260 	const void *key;
261 	int error, rc;
262 	unsigned klen;
263 
264 	csp = crypto_get_params(crp->crp_session);
265 	if (crp->crp_auth_key != NULL)
266 		key = crp->crp_auth_key;
267 	else
268 		key = csp->csp_auth_key;
269 	klen = csp->csp_auth_klen;
270 
271 	fpu_kern_enter(curthread, NULL, FPU_KERN_NORMAL | FPU_KERN_NOCTX);
272 
273 	switch (csp->csp_auth_alg) {
274 	case CRYPTO_BLAKE2B:
275 		if (klen > 0)
276 			rc = blake2b_init_key(&bctx.sb, ses->mlen, key, klen);
277 		else
278 			rc = blake2b_init(&bctx.sb, ses->mlen);
279 		if (rc != 0) {
280 			error = EINVAL;
281 			break;
282 		}
283 		error = crypto_apply(crp, crp->crp_payload_start,
284 		    crp->crp_payload_length, blake2b_applicator, &bctx.sb);
285 		if (error != 0)
286 			break;
287 		rc = blake2b_final(&bctx.sb, res, ses->mlen);
288 		if (rc != 0)
289 			error = EINVAL;
290 		break;
291 	case CRYPTO_BLAKE2S:
292 		if (klen > 0)
293 			rc = blake2s_init_key(&bctx.ss, ses->mlen, key, klen);
294 		else
295 			rc = blake2s_init(&bctx.ss, ses->mlen);
296 		if (rc != 0) {
297 			error = EINVAL;
298 			break;
299 		}
300 		error = crypto_apply(crp, crp->crp_payload_start,
301 		    crp->crp_payload_length, blake2s_applicator, &bctx.ss);
302 		if (error != 0)
303 			break;
304 		rc = blake2s_final(&bctx.ss, res, ses->mlen);
305 		if (rc != 0)
306 			error = EINVAL;
307 		break;
308 	default:
309 		__assert_unreachable();
310 	}
311 
312 	fpu_kern_leave(curthread, NULL);
313 
314 	if (error != 0)
315 		return (error);
316 
317 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
318 		crypto_copydata(crp, crp->crp_digest_start, ses->mlen, res2);
319 		if (timingsafe_bcmp(res, res2, ses->mlen) != 0)
320 			error = EBADMSG;
321 	} else
322 		crypto_copyback(crp, crp->crp_digest_start, ses->mlen, res);
323 
324 	return (error);
325 }
326