1 /*-
2 * Copyright (c) 2018 Conrad Meyer <[email protected]>
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
blake2_identify(driver_t * drv,device_t parent)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
blake2_probe(device_t dev)71 blake2_probe(device_t dev)
72 {
73 device_set_desc(dev, "Blake2");
74 return (0);
75 }
76
77 static int
blake2_attach(device_t dev)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
blake2_detach(device_t dev)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
blake2_probesession(device_t dev,const struct crypto_session_params * csp)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
blake2_newsession(device_t dev,crypto_session_t cses,const struct crypto_session_params * csp)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
blake2_process(device_t dev,struct cryptop * crp,int hint __unused)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
blake2_check_klen(const struct crypto_session_params * csp,unsigned klen)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
blake2_cipher_setup(struct blake2_session * ses,const struct crypto_session_params * csp)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
blake2b_applicator(void * state,const void * buf,u_int len)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
blake2s_applicator(void * state,const void * buf,u_int len)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
blake2_cipher_process(struct blake2_session * ses,struct cryptop * crp)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