2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2020 Netflix, Inc
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer,
11 * without modification.
12 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
13 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
14 * redistribution must be conditioned upon including a substantially
15 * similar Disclaimer requirement for further binary redistribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
21 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
23 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGES.
32 * A driver for the OpenCrypto framework which uses assembly routines
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
39 #include <sys/types.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/module.h>
45 #include <machine/fpu.h>
47 #include <opencrypto/cryptodev.h>
48 #include <opencrypto/xform_auth.h>
50 #include <crypto/openssl/ossl.h>
51 #include <crypto/openssl/ossl_chacha.h>
52 #include <crypto/openssl/ossl_cipher.h>
54 #include "cryptodev_if.h"
56 static MALLOC_DEFINE(M_OSSL, "ossl", "OpenSSL crypto");
59 ossl_identify(driver_t *driver, device_t parent)
62 if (device_find_child(parent, "ossl", -1) == NULL)
63 BUS_ADD_CHILD(parent, 10, "ossl", -1);
67 ossl_probe(device_t dev)
70 device_set_desc(dev, "OpenSSL crypto");
71 return (BUS_PROBE_DEFAULT);
75 ossl_attach(device_t dev)
77 struct ossl_softc *sc;
79 sc = device_get_softc(dev);
81 sc->has_aes = sc->has_aes_gcm = false;
84 sc->sc_cid = crypto_get_driverid(dev, sizeof(struct ossl_session),
85 CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC |
86 CRYPTOCAP_F_ACCEL_SOFTWARE);
88 device_printf(dev, "failed to allocate crypto driver id\n");
96 ossl_detach(device_t dev)
98 struct ossl_softc *sc;
100 sc = device_get_softc(dev);
102 crypto_unregister_all(sc->sc_cid);
107 static struct auth_hash *
108 ossl_lookup_hash(const struct crypto_session_params *csp)
111 switch (csp->csp_auth_alg) {
113 case CRYPTO_SHA1_HMAC:
114 return (&ossl_hash_sha1);
115 case CRYPTO_SHA2_224:
116 case CRYPTO_SHA2_224_HMAC:
117 return (&ossl_hash_sha224);
118 case CRYPTO_SHA2_256:
119 case CRYPTO_SHA2_256_HMAC:
120 return (&ossl_hash_sha256);
121 case CRYPTO_SHA2_384:
122 case CRYPTO_SHA2_384_HMAC:
123 return (&ossl_hash_sha384);
124 case CRYPTO_SHA2_512:
125 case CRYPTO_SHA2_512_HMAC:
126 return (&ossl_hash_sha512);
127 case CRYPTO_POLY1305:
128 return (&ossl_hash_poly1305);
134 static struct ossl_cipher*
135 ossl_lookup_cipher(const struct crypto_session_params *csp)
138 switch (csp->csp_cipher_alg) {
140 switch (csp->csp_cipher_klen * 8) {
148 return (&ossl_cipher_aes_cbc);
149 case CRYPTO_AES_NIST_GCM_16:
150 switch (csp->csp_cipher_klen * 8) {
158 return (&ossl_cipher_aes_gcm);
159 case CRYPTO_CHACHA20:
160 if (csp->csp_cipher_klen != CHACHA_KEY_SIZE)
162 return (&ossl_cipher_chacha20);
169 ossl_probesession(device_t dev, const struct crypto_session_params *csp)
171 struct ossl_softc *sc = device_get_softc(dev);
173 if ((csp->csp_flags & ~(CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD)) !=
176 switch (csp->csp_mode) {
177 case CSP_MODE_DIGEST:
178 if (ossl_lookup_hash(csp) == NULL)
181 case CSP_MODE_CIPHER:
182 if (csp->csp_cipher_alg != CRYPTO_CHACHA20 && !sc->has_aes)
184 if (ossl_lookup_cipher(csp) == NULL)
189 csp->csp_cipher_alg == CRYPTO_CHACHA20 ||
190 ossl_lookup_hash(csp) == NULL ||
191 ossl_lookup_cipher(csp) == NULL)
195 switch (csp->csp_cipher_alg) {
196 case CRYPTO_CHACHA20_POLY1305:
198 case CRYPTO_AES_NIST_GCM_16:
199 if (!sc->has_aes_gcm || ossl_lookup_cipher(csp) == NULL)
201 if (csp->csp_ivlen != AES_GCM_IV_LEN)
203 if (csp->csp_auth_mlen != 0 &&
204 csp->csp_auth_mlen != GMAC_DIGEST_LEN)
215 return (CRYPTODEV_PROBE_ACCEL_SOFTWARE);
219 ossl_newsession_hash(struct ossl_session *s,
220 const struct crypto_session_params *csp)
222 struct auth_hash *axf;
224 axf = ossl_lookup_hash(csp);
226 if (csp->csp_auth_mlen == 0)
227 s->hash.mlen = axf->hashsize;
229 s->hash.mlen = csp->csp_auth_mlen;
231 if (csp->csp_auth_klen == 0) {
232 axf->Init(&s->hash.ictx);
234 if (csp->csp_auth_key != NULL) {
235 fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX);
236 if (axf->Setkey != NULL) {
237 axf->Init(&s->hash.ictx);
238 axf->Setkey(&s->hash.ictx, csp->csp_auth_key,
241 hmac_init_ipad(axf, csp->csp_auth_key,
242 csp->csp_auth_klen, &s->hash.ictx);
243 hmac_init_opad(axf, csp->csp_auth_key,
244 csp->csp_auth_klen, &s->hash.octx);
246 fpu_kern_leave(curthread, NULL);
252 ossl_newsession_cipher(struct ossl_session *s,
253 const struct crypto_session_params *csp)
255 struct ossl_cipher *cipher;
258 cipher = ossl_lookup_cipher(csp);
262 s->cipher.cipher = cipher;
264 if (csp->csp_cipher_key == NULL)
267 fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX);
268 if (cipher->set_encrypt_key != NULL) {
269 error = cipher->set_encrypt_key(csp->csp_cipher_key,
270 8 * csp->csp_cipher_klen, &s->cipher.enc_ctx);
272 fpu_kern_leave(curthread, NULL);
276 if (cipher->set_decrypt_key != NULL)
277 error = cipher->set_decrypt_key(csp->csp_cipher_key,
278 8 * csp->csp_cipher_klen, &s->cipher.dec_ctx);
279 fpu_kern_leave(curthread, NULL);
285 ossl_newsession(device_t dev, crypto_session_t cses,
286 const struct crypto_session_params *csp)
288 struct ossl_session *s;
291 s = crypto_get_driver_session(cses);
292 switch (csp->csp_mode) {
293 case CSP_MODE_DIGEST:
294 ossl_newsession_hash(s, csp);
296 case CSP_MODE_CIPHER:
297 error = ossl_newsession_cipher(s, csp);
300 ossl_newsession_hash(s, csp);
301 error = ossl_newsession_cipher(s, csp);
304 if (csp->csp_cipher_alg != CRYPTO_CHACHA20_POLY1305)
305 error = ossl_newsession_cipher(s, csp);
308 __assert_unreachable();
315 ossl_process_hash(struct ossl_session *s, struct cryptop *crp,
316 const struct crypto_session_params *csp)
318 struct ossl_hash_context ctx;
319 char digest[HASH_MAX_LEN];
320 struct auth_hash *axf;
325 if (crp->crp_auth_key == NULL) {
328 if (axf->Setkey != NULL) {
330 axf->Setkey(&ctx, crp->crp_auth_key,
333 hmac_init_ipad(axf, crp->crp_auth_key,
334 csp->csp_auth_klen, &ctx);
338 if (crp->crp_aad != NULL)
339 error = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length);
341 error = crypto_apply(crp, crp->crp_aad_start,
342 crp->crp_aad_length, axf->Update, &ctx);
346 error = crypto_apply(crp, crp->crp_payload_start,
347 crp->crp_payload_length, axf->Update, &ctx);
351 axf->Final(digest, &ctx);
353 if (csp->csp_auth_klen != 0 && axf->Setkey == NULL) {
354 if (crp->crp_auth_key == NULL)
357 hmac_init_opad(axf, crp->crp_auth_key,
358 csp->csp_auth_klen, &ctx);
359 axf->Update(&ctx, digest, axf->hashsize);
360 axf->Final(digest, &ctx);
363 if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
364 char digest2[HASH_MAX_LEN];
366 crypto_copydata(crp, crp->crp_digest_start, s->hash.mlen,
368 if (timingsafe_bcmp(digest, digest2, s->hash.mlen) != 0)
370 explicit_bzero(digest2, sizeof(digest2));
372 crypto_copyback(crp, crp->crp_digest_start, s->hash.mlen,
375 explicit_bzero(digest, sizeof(digest));
378 explicit_bzero(&ctx, sizeof(ctx));
383 ossl_process_cipher(struct ossl_session *s, struct cryptop *crp,
384 const struct crypto_session_params *csp)
386 return (s->cipher.cipher->process(&s->cipher, crp, csp));
390 ossl_process_eta(struct ossl_session *s, struct cryptop *crp,
391 const struct crypto_session_params *csp)
395 if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
396 error = s->cipher.cipher->process(&s->cipher, crp, csp);
398 error = ossl_process_hash(s, crp, csp);
400 error = ossl_process_hash(s, crp, csp);
402 error = s->cipher.cipher->process(&s->cipher, crp, csp);
409 ossl_process_aead(struct ossl_session *s, struct cryptop *crp,
410 const struct crypto_session_params *csp)
412 if (csp->csp_cipher_alg == CRYPTO_CHACHA20_POLY1305) {
413 if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
414 return (ossl_chacha20_poly1305_encrypt(crp, csp));
416 return (ossl_chacha20_poly1305_decrypt(crp, csp));
418 return (s->cipher.cipher->process(&s->cipher, crp, csp));
423 ossl_process(device_t dev, struct cryptop *crp, int hint)
425 const struct crypto_session_params *csp;
426 struct ossl_session *s;
430 s = crypto_get_driver_session(crp->crp_session);
431 csp = crypto_get_params(crp->crp_session);
433 if (is_fpu_kern_thread(0)) {
436 fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX);
440 switch (csp->csp_mode) {
441 case CSP_MODE_DIGEST:
442 error = ossl_process_hash(s, crp, csp);
444 case CSP_MODE_CIPHER:
445 error = ossl_process_cipher(s, crp, csp);
448 error = ossl_process_eta(s, crp, csp);
451 error = ossl_process_aead(s, crp, csp);
454 __assert_unreachable();
458 fpu_kern_leave(curthread, NULL);
460 crp->crp_etype = error;
466 static device_method_t ossl_methods[] = {
467 DEVMETHOD(device_identify, ossl_identify),
468 DEVMETHOD(device_probe, ossl_probe),
469 DEVMETHOD(device_attach, ossl_attach),
470 DEVMETHOD(device_detach, ossl_detach),
472 DEVMETHOD(cryptodev_probesession, ossl_probesession),
473 DEVMETHOD(cryptodev_newsession, ossl_newsession),
474 DEVMETHOD(cryptodev_process, ossl_process),
479 static driver_t ossl_driver = {
482 sizeof(struct ossl_softc)
485 DRIVER_MODULE(ossl, nexus, ossl_driver, NULL, NULL);
486 MODULE_VERSION(ossl, 1);
487 MODULE_DEPEND(ossl, crypto, 1, 1, 1);