]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/crypto/blake2/blake2_cryptodev.c
Import OpenCSD -- an ARM CoreSight(tm) Trace Decode Library.
[FreeBSD/FreeBSD.git] / sys / crypto / blake2 / blake2_cryptodev.c
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 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/bus.h>
32 #include <sys/kernel.h>
33 #include <sys/kobj.h>
34 #include <sys/lock.h>
35 #include <sys/module.h>
36 #include <sys/malloc.h>
37 #include <sys/rwlock.h>
38 #include <sys/smp.h>
39
40 #include <blake2.h>
41
42 #include <opencrypto/cryptodev.h>
43 #include <cryptodev_if.h>
44
45 #if defined(__amd64__)
46 #include <machine/fpu.h>
47 #elif defined(__i386__)
48 #include <machine/npx.h>
49 #endif
50
51 struct blake2_session {
52         int algo;
53         size_t klen;
54         size_t mlen;
55         uint8_t key[BLAKE2B_KEYBYTES];
56         bool used;
57         uint32_t id;
58         TAILQ_ENTRY(blake2_session) next;
59 };
60 CTASSERT((size_t)BLAKE2B_KEYBYTES > (size_t)BLAKE2S_KEYBYTES);
61
62 struct blake2_softc {
63         bool    dying;
64         int32_t cid;
65         uint32_t sid;
66         TAILQ_HEAD(blake2_sessions_head, blake2_session) sessions;
67         struct rwlock lock;
68 };
69
70 static struct mtx_padalign *ctx_mtx;
71 static struct fpu_kern_ctx **ctx_fpu;
72
73 #define ACQUIRE_CTX(i, ctx)                                     \
74         do {                                                    \
75                 (i) = PCPU_GET(cpuid);                          \
76                 mtx_lock(&ctx_mtx[(i)]);                        \
77                 (ctx) = ctx_fpu[(i)];                           \
78         } while (0)
79 #define RELEASE_CTX(i, ctx)                                     \
80         do {                                                    \
81                 mtx_unlock(&ctx_mtx[(i)]);                      \
82                 (i) = -1;                                       \
83                 (ctx) = NULL;                                   \
84         } while (0)
85
86 static int blake2_newsession(device_t, uint32_t *sidp, struct cryptoini *cri);
87 static int blake2_freesession(device_t, uint64_t tid);
88 static void blake2_freesession_locked(struct blake2_softc *sc,
89     struct blake2_session *ses);
90 static int blake2_cipher_setup(struct blake2_session *ses,
91     struct cryptoini *authini);
92 static int blake2_cipher_process(struct blake2_session *ses,
93     struct cryptop *crp);
94
95 MALLOC_DEFINE(M_BLAKE2, "blake2_data", "Blake2 Data");
96
97 static void
98 blake2_identify(driver_t *drv, device_t parent)
99 {
100
101         /* NB: order 10 is so we get attached after h/w devices */
102         if (device_find_child(parent, "blaketwo", -1) == NULL &&
103             BUS_ADD_CHILD(parent, 10, "blaketwo", -1) == 0)
104                 panic("blaketwo: could not attach");
105 }
106
107 static int
108 blake2_probe(device_t dev)
109 {
110         device_set_desc(dev, "Blake2");
111         return (0);
112 }
113
114 static void
115 blake2_cleanctx(void)
116 {
117         int i;
118
119         /* XXX - no way to return driverid */
120         CPU_FOREACH(i) {
121                 if (ctx_fpu[i] != NULL) {
122                         mtx_destroy(&ctx_mtx[i]);
123                         fpu_kern_free_ctx(ctx_fpu[i]);
124                 }
125                 ctx_fpu[i] = NULL;
126         }
127         free(ctx_mtx, M_BLAKE2);
128         ctx_mtx = NULL;
129         free(ctx_fpu, M_BLAKE2);
130         ctx_fpu = NULL;
131 }
132
133 static int
134 blake2_attach(device_t dev)
135 {
136         struct blake2_softc *sc;
137         int i;
138
139         sc = device_get_softc(dev);
140         sc->dying = false;
141         TAILQ_INIT(&sc->sessions);
142         sc->sid = 1;
143
144         sc->cid = crypto_get_driverid(dev, CRYPTOCAP_F_HARDWARE |
145             CRYPTOCAP_F_SYNC);
146         if (sc->cid < 0) {
147                 device_printf(dev, "Could not get crypto driver id.\n");
148                 return (ENOMEM);
149         }
150
151         ctx_mtx = malloc(sizeof(*ctx_mtx) * (mp_maxid + 1), M_BLAKE2,
152             M_WAITOK | M_ZERO);
153         ctx_fpu = malloc(sizeof(*ctx_fpu) * (mp_maxid + 1), M_BLAKE2,
154             M_WAITOK | M_ZERO);
155
156         CPU_FOREACH(i) {
157                 ctx_fpu[i] = fpu_kern_alloc_ctx(0);
158                 mtx_init(&ctx_mtx[i], "bl2fpumtx", NULL, MTX_DEF | MTX_NEW);
159         }
160
161         rw_init(&sc->lock, "blake2_lock");
162
163         crypto_register(sc->cid, CRYPTO_BLAKE2B, 0, 0);
164         crypto_register(sc->cid, CRYPTO_BLAKE2S, 0, 0);
165         return (0);
166 }
167
168 static int
169 blake2_detach(device_t dev)
170 {
171         struct blake2_softc *sc;
172         struct blake2_session *ses;
173
174         sc = device_get_softc(dev);
175
176         rw_wlock(&sc->lock);
177         TAILQ_FOREACH(ses, &sc->sessions, next) {
178                 if (ses->used) {
179                         rw_wunlock(&sc->lock);
180                         device_printf(dev,
181                             "Cannot detach, sessions still active.\n");
182                         return (EBUSY);
183                 }
184         }
185         sc->dying = true;
186         while ((ses = TAILQ_FIRST(&sc->sessions)) != NULL) {
187                 TAILQ_REMOVE(&sc->sessions, ses, next);
188                 free(ses, M_BLAKE2);
189         }
190         rw_wunlock(&sc->lock);
191         crypto_unregister_all(sc->cid);
192
193         rw_destroy(&sc->lock);
194
195         blake2_cleanctx();
196
197         return (0);
198 }
199
200 static int
201 blake2_newsession(device_t dev, uint32_t *sidp, struct cryptoini *cri)
202 {
203         struct blake2_softc *sc;
204         struct blake2_session *ses;
205         struct cryptoini *authini;
206         int error;
207
208         if (sidp == NULL || cri == NULL) {
209                 CRYPTDEB("no sidp or cri");
210                 return (EINVAL);
211         }
212
213         sc = device_get_softc(dev);
214
215         ses = NULL;
216         authini = NULL;
217         for (; cri != NULL; cri = cri->cri_next) {
218                 switch (cri->cri_alg) {
219                 case CRYPTO_BLAKE2B:
220                 case CRYPTO_BLAKE2S:
221                         if (authini != NULL) {
222                                 CRYPTDEB("authini already set");
223                                 return (EINVAL);
224                         }
225                         authini = cri;
226                         break;
227                 default:
228                         CRYPTDEB("unhandled algorithm");
229                         return (EINVAL);
230                 }
231         }
232         if (authini == NULL) {
233                 CRYPTDEB("no cipher");
234                 return (EINVAL);
235         }
236
237         rw_wlock(&sc->lock);
238         if (sc->dying) {
239                 rw_wunlock(&sc->lock);
240                 return (EINVAL);
241         }
242         /*
243          * Free sessions are inserted at the head of the list.  So if the first
244          * session is used, none are free and we must allocate a new one.
245          */
246         ses = TAILQ_FIRST(&sc->sessions);
247         if (ses == NULL || ses->used) {
248                 ses = malloc(sizeof(*ses), M_BLAKE2, M_NOWAIT | M_ZERO);
249                 if (ses == NULL) {
250                         rw_wunlock(&sc->lock);
251                         return (ENOMEM);
252                 }
253                 ses->id = sc->sid++;
254         } else {
255                 TAILQ_REMOVE(&sc->sessions, ses, next);
256         }
257         ses->used = true;
258         TAILQ_INSERT_TAIL(&sc->sessions, ses, next);
259         rw_wunlock(&sc->lock);
260
261         ses->algo = authini->cri_alg;
262         error = blake2_cipher_setup(ses, authini);
263         if (error != 0) {
264                 CRYPTDEB("setup failed");
265                 rw_wlock(&sc->lock);
266                 blake2_freesession_locked(sc, ses);
267                 rw_wunlock(&sc->lock);
268                 return (error);
269         }
270
271         *sidp = ses->id;
272         return (0);
273 }
274
275 static void
276 blake2_freesession_locked(struct blake2_softc *sc, struct blake2_session *ses)
277 {
278         uint32_t sid;
279
280         rw_assert(&sc->lock, RA_WLOCKED);
281
282         sid = ses->id;
283         TAILQ_REMOVE(&sc->sessions, ses, next);
284         explicit_bzero(ses, sizeof(*ses));
285         ses->id = sid;
286         TAILQ_INSERT_HEAD(&sc->sessions, ses, next);
287 }
288
289 static int
290 blake2_freesession(device_t dev, uint64_t tid)
291 {
292         struct blake2_softc *sc;
293         struct blake2_session *ses;
294         uint32_t sid;
295
296         sc = device_get_softc(dev);
297         sid = ((uint32_t)tid) & 0xffffffff;
298         rw_wlock(&sc->lock);
299         TAILQ_FOREACH_REVERSE(ses, &sc->sessions, blake2_sessions_head, next) {
300                 if (ses->id == sid)
301                         break;
302         }
303         if (ses == NULL) {
304                 rw_wunlock(&sc->lock);
305                 return (EINVAL);
306         }
307         blake2_freesession_locked(sc, ses);
308         rw_wunlock(&sc->lock);
309         return (0);
310 }
311
312 static int
313 blake2_process(device_t dev, struct cryptop *crp, int hint __unused)
314 {
315         struct blake2_softc *sc;
316         struct blake2_session *ses;
317         struct cryptodesc *crd, *authcrd;
318         int error;
319
320         sc = device_get_softc(dev);
321         ses = NULL;
322         error = 0;
323         authcrd = NULL;
324
325         /* Sanity check. */
326         if (crp == NULL)
327                 return (EINVAL);
328
329         if (crp->crp_callback == NULL || crp->crp_desc == NULL) {
330                 error = EINVAL;
331                 goto out;
332         }
333
334         for (crd = crp->crp_desc; crd != NULL; crd = crd->crd_next) {
335                 switch (crd->crd_alg) {
336                 case CRYPTO_BLAKE2B:
337                 case CRYPTO_BLAKE2S:
338                         if (authcrd != NULL) {
339                                 error = EINVAL;
340                                 goto out;
341                         }
342                         authcrd = crd;
343                         break;
344
345                 default:
346                         error = EINVAL;
347                         goto out;
348                 }
349         }
350
351         rw_rlock(&sc->lock);
352         TAILQ_FOREACH_REVERSE(ses, &sc->sessions, blake2_sessions_head, next) {
353                 if (ses->id == (crp->crp_sid & 0xffffffff))
354                         break;
355         }
356         rw_runlock(&sc->lock);
357         if (ses == NULL) {
358                 error = EINVAL;
359                 goto out;
360         }
361
362         error = blake2_cipher_process(ses, crp);
363         if (error != 0)
364                 goto out;
365
366 out:
367         crp->crp_etype = error;
368         crypto_done(crp);
369         return (error);
370 }
371
372 static device_method_t blake2_methods[] = {
373         DEVMETHOD(device_identify, blake2_identify),
374         DEVMETHOD(device_probe, blake2_probe),
375         DEVMETHOD(device_attach, blake2_attach),
376         DEVMETHOD(device_detach, blake2_detach),
377
378         DEVMETHOD(cryptodev_newsession, blake2_newsession),
379         DEVMETHOD(cryptodev_freesession, blake2_freesession),
380         DEVMETHOD(cryptodev_process, blake2_process),
381
382         DEVMETHOD_END
383 };
384
385 static driver_t blake2_driver = {
386         "blaketwo",
387         blake2_methods,
388         sizeof(struct blake2_softc),
389 };
390 static devclass_t blake2_devclass;
391
392 DRIVER_MODULE(blake2, nexus, blake2_driver, blake2_devclass, 0, 0);
393 MODULE_VERSION(blake2, 1);
394 MODULE_DEPEND(blake2, crypto, 1, 1, 1);
395
396 static int
397 blake2_cipher_setup(struct blake2_session *ses, struct cryptoini *authini)
398 {
399         int keylen;
400
401         CTASSERT((size_t)BLAKE2S_OUTBYTES <= (size_t)BLAKE2B_OUTBYTES);
402
403         if (authini->cri_mlen < 0)
404                 return (EINVAL);
405
406         switch (ses->algo) {
407         case CRYPTO_BLAKE2S:
408                 if (authini->cri_mlen != 0 &&
409                     authini->cri_mlen > BLAKE2S_OUTBYTES)
410                         return (EINVAL);
411                 /* FALLTHROUGH */
412         case CRYPTO_BLAKE2B:
413                 if (authini->cri_mlen != 0 &&
414                     authini->cri_mlen > BLAKE2B_OUTBYTES)
415                         return (EINVAL);
416
417                 if (authini->cri_klen % 8 != 0)
418                         return (EINVAL);
419                 keylen = authini->cri_klen / 8;
420                 if (keylen > sizeof(ses->key) ||
421                     (ses->algo == CRYPTO_BLAKE2S && keylen > BLAKE2S_KEYBYTES))
422                         return (EINVAL);
423                 ses->klen = keylen;
424                 memcpy(ses->key, authini->cri_key, keylen);
425                 ses->mlen = authini->cri_mlen;
426         }
427         return (0);
428 }
429
430 static int
431 blake2b_applicator(void *state, void *buf, u_int len)
432 {
433         int rc;
434
435         rc = blake2b_update(state, buf, len);
436         if (rc != 0)
437                 return (EINVAL);
438         return (0);
439 }
440
441 static int
442 blake2s_applicator(void *state, void *buf, u_int len)
443 {
444         int rc;
445
446         rc = blake2s_update(state, buf, len);
447         if (rc != 0)
448                 return (EINVAL);
449         return (0);
450 }
451
452 static int
453 blake2_cipher_process(struct blake2_session *ses, struct cryptop *crp)
454 {
455         union {
456                 blake2b_state sb;
457                 blake2s_state ss;
458         } bctx;
459         char res[BLAKE2B_OUTBYTES];
460         struct fpu_kern_ctx *ctx;
461         int ctxidx;
462         bool kt;
463         struct cryptodesc *crd;
464         int error, rc;
465         size_t hashlen;
466
467         crd = crp->crp_desc;
468         ctx = NULL;
469         ctxidx = 0;
470         error = EINVAL;
471
472         kt = is_fpu_kern_thread(0);
473         if (!kt) {
474                 ACQUIRE_CTX(ctxidx, ctx);
475                 fpu_kern_enter(curthread, ctx,
476                     FPU_KERN_NORMAL | FPU_KERN_KTHR);
477         }
478
479         if (crd->crd_flags != 0)
480                 goto out;
481
482         switch (ses->algo) {
483         case CRYPTO_BLAKE2B:
484                 if (ses->mlen != 0)
485                         hashlen = ses->mlen;
486                 else
487                         hashlen = BLAKE2B_OUTBYTES;
488                 if (ses->klen > 0)
489                         rc = blake2b_init_key(&bctx.sb, hashlen, ses->key, ses->klen);
490                 else
491                         rc = blake2b_init(&bctx.sb, hashlen);
492                 if (rc != 0)
493                         goto out;
494                 error = crypto_apply(crp->crp_flags, crp->crp_buf, crd->crd_skip,
495                     crd->crd_len, blake2b_applicator, &bctx.sb);
496                 if (error != 0)
497                         goto out;
498                 rc = blake2b_final(&bctx.sb, res, hashlen);
499                 if (rc != 0) {
500                         error = EINVAL;
501                         goto out;
502                 }
503                 break;
504         case CRYPTO_BLAKE2S:
505                 if (ses->mlen != 0)
506                         hashlen = ses->mlen;
507                 else
508                         hashlen = BLAKE2S_OUTBYTES;
509                 if (ses->klen > 0)
510                         rc = blake2s_init_key(&bctx.ss, hashlen, ses->key, ses->klen);
511                 else
512                         rc = blake2s_init(&bctx.ss, hashlen);
513                 if (rc != 0)
514                         goto out;
515                 error = crypto_apply(crp->crp_flags, crp->crp_buf, crd->crd_skip,
516                     crd->crd_len, blake2s_applicator, &bctx.ss);
517                 if (error != 0)
518                         goto out;
519                 rc = blake2s_final(&bctx.ss, res, hashlen);
520                 if (rc != 0) {
521                         error = EINVAL;
522                         goto out;
523                 }
524                 break;
525         default:
526                 panic("unreachable");
527         }
528
529         crypto_copyback(crp->crp_flags, crp->crp_buf, crd->crd_inject, hashlen,
530             (void *)res);
531
532 out:
533         if (!kt) {
534                 fpu_kern_leave(curthread, ctx);
535                 RELEASE_CTX(ctxidx, ctx);
536         }
537         return (error);
538 }