xref: /freebsd/sys/crypto/openssl/ossl.c (revision a05a680469a7ac77b195021fed74e3aa58152dd7)
1fd86ae68SMitchell Horne /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3fd86ae68SMitchell Horne  *
4ba610be9SJohn Baldwin  * Copyright (c) 2020 Netflix, Inc
5ba610be9SJohn Baldwin  *
6ba610be9SJohn Baldwin  * Redistribution and use in source and binary forms, with or without
7ba610be9SJohn Baldwin  * modification, are permitted provided that the following conditions
8ba610be9SJohn Baldwin  * are met:
9ba610be9SJohn Baldwin  * 1. Redistributions of source code must retain the above copyright
10ba610be9SJohn Baldwin  *    notice, this list of conditions and the following disclaimer,
11ba610be9SJohn Baldwin  *    without modification.
12ba610be9SJohn Baldwin  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
13ba610be9SJohn Baldwin  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
14ba610be9SJohn Baldwin  *    redistribution must be conditioned upon including a substantially
15ba610be9SJohn Baldwin  *    similar Disclaimer requirement for further binary redistribution.
16ba610be9SJohn Baldwin  *
17ba610be9SJohn Baldwin  * NO WARRANTY
18ba610be9SJohn Baldwin  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19ba610be9SJohn Baldwin  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20ba610be9SJohn Baldwin  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
21ba610be9SJohn Baldwin  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22ba610be9SJohn Baldwin  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
23ba610be9SJohn Baldwin  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24ba610be9SJohn Baldwin  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25ba610be9SJohn Baldwin  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26ba610be9SJohn Baldwin  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27ba610be9SJohn Baldwin  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28ba610be9SJohn Baldwin  * THE POSSIBILITY OF SUCH DAMAGES.
29ba610be9SJohn Baldwin  */
30ba610be9SJohn Baldwin 
31ba610be9SJohn Baldwin /*
32ba610be9SJohn Baldwin  * A driver for the OpenCrypto framework which uses assembly routines
33ba610be9SJohn Baldwin  * from OpenSSL.
34ba610be9SJohn Baldwin  */
35ba610be9SJohn Baldwin 
36ba610be9SJohn Baldwin #include <sys/types.h>
37ba610be9SJohn Baldwin #include <sys/bus.h>
38ba610be9SJohn Baldwin #include <sys/kernel.h>
39ba610be9SJohn Baldwin #include <sys/malloc.h>
40ba610be9SJohn Baldwin #include <sys/module.h>
41fd86ae68SMitchell Horne 
42ba610be9SJohn Baldwin #include <machine/fpu.h>
43ba610be9SJohn Baldwin 
44ba610be9SJohn Baldwin #include <opencrypto/cryptodev.h>
45ba610be9SJohn Baldwin #include <opencrypto/xform_auth.h>
46ba610be9SJohn Baldwin 
47ba610be9SJohn Baldwin #include <crypto/openssl/ossl.h>
4892aecd1eSJohn Baldwin #include <crypto/openssl/ossl_chacha.h>
49197ff4c3SKornel Duleba #include <crypto/openssl/ossl_cipher.h>
50ba610be9SJohn Baldwin 
51ba610be9SJohn Baldwin #include "cryptodev_if.h"
52ba610be9SJohn Baldwin 
53ba610be9SJohn Baldwin static MALLOC_DEFINE(M_OSSL, "ossl", "OpenSSL crypto");
54ba610be9SJohn Baldwin 
55ba610be9SJohn Baldwin static void
56ba610be9SJohn Baldwin ossl_identify(driver_t *driver, device_t parent)
57ba610be9SJohn Baldwin {
58ba610be9SJohn Baldwin 
59ba610be9SJohn Baldwin 	if (device_find_child(parent, "ossl", -1) == NULL)
60*a05a6804SWarner Losh 		BUS_ADD_CHILD(parent, 10, "ossl", DEVICE_UNIT_ANY);
61ba610be9SJohn Baldwin }
62ba610be9SJohn Baldwin 
63ba610be9SJohn Baldwin static int
64ba610be9SJohn Baldwin ossl_probe(device_t dev)
65ba610be9SJohn Baldwin {
66ba610be9SJohn Baldwin 
67ba610be9SJohn Baldwin 	device_set_desc(dev, "OpenSSL crypto");
68ba610be9SJohn Baldwin 	return (BUS_PROBE_DEFAULT);
69ba610be9SJohn Baldwin }
70ba610be9SJohn Baldwin 
71ba610be9SJohn Baldwin static int
72ba610be9SJohn Baldwin ossl_attach(device_t dev)
73ba610be9SJohn Baldwin {
74ba610be9SJohn Baldwin 	struct ossl_softc *sc;
75ba610be9SJohn Baldwin 
76ba610be9SJohn Baldwin 	sc = device_get_softc(dev);
77ba610be9SJohn Baldwin 
789a3444d9SMark Johnston 	sc->has_aes = sc->has_aes_gcm = false;
799a3444d9SMark Johnston 
80197ff4c3SKornel Duleba 	ossl_cpuid(sc);
81ba610be9SJohn Baldwin 	sc->sc_cid = crypto_get_driverid(dev, sizeof(struct ossl_session),
82ba610be9SJohn Baldwin 	    CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC |
83ba610be9SJohn Baldwin 	    CRYPTOCAP_F_ACCEL_SOFTWARE);
84ba610be9SJohn Baldwin 	if (sc->sc_cid < 0) {
85ba610be9SJohn Baldwin 		device_printf(dev, "failed to allocate crypto driver id\n");
86ba610be9SJohn Baldwin 		return (ENXIO);
87ba610be9SJohn Baldwin 	}
88ba610be9SJohn Baldwin 
89ba610be9SJohn Baldwin 	return (0);
90ba610be9SJohn Baldwin }
91ba610be9SJohn Baldwin 
92ba610be9SJohn Baldwin static int
93ba610be9SJohn Baldwin ossl_detach(device_t dev)
94ba610be9SJohn Baldwin {
95ba610be9SJohn Baldwin 	struct ossl_softc *sc;
96ba610be9SJohn Baldwin 
97ba610be9SJohn Baldwin 	sc = device_get_softc(dev);
98ba610be9SJohn Baldwin 
99ba610be9SJohn Baldwin 	crypto_unregister_all(sc->sc_cid);
100ba610be9SJohn Baldwin 
101ba610be9SJohn Baldwin 	return (0);
102ba610be9SJohn Baldwin }
103ba610be9SJohn Baldwin 
104ba610be9SJohn Baldwin static struct auth_hash *
105ba610be9SJohn Baldwin ossl_lookup_hash(const struct crypto_session_params *csp)
106ba610be9SJohn Baldwin {
107ba610be9SJohn Baldwin 
108ba610be9SJohn Baldwin 	switch (csp->csp_auth_alg) {
109ba610be9SJohn Baldwin 	case CRYPTO_SHA1:
110ba610be9SJohn Baldwin 	case CRYPTO_SHA1_HMAC:
111ba610be9SJohn Baldwin 		return (&ossl_hash_sha1);
112ba610be9SJohn Baldwin 	case CRYPTO_SHA2_224:
113ba610be9SJohn Baldwin 	case CRYPTO_SHA2_224_HMAC:
114ba610be9SJohn Baldwin 		return (&ossl_hash_sha224);
115ba610be9SJohn Baldwin 	case CRYPTO_SHA2_256:
116ba610be9SJohn Baldwin 	case CRYPTO_SHA2_256_HMAC:
117ba610be9SJohn Baldwin 		return (&ossl_hash_sha256);
118ba610be9SJohn Baldwin 	case CRYPTO_SHA2_384:
119ba610be9SJohn Baldwin 	case CRYPTO_SHA2_384_HMAC:
120ba610be9SJohn Baldwin 		return (&ossl_hash_sha384);
121ba610be9SJohn Baldwin 	case CRYPTO_SHA2_512:
122ba610be9SJohn Baldwin 	case CRYPTO_SHA2_512_HMAC:
123ba610be9SJohn Baldwin 		return (&ossl_hash_sha512);
124a079e38bSJohn Baldwin 	case CRYPTO_POLY1305:
125a079e38bSJohn Baldwin 		return (&ossl_hash_poly1305);
126ba610be9SJohn Baldwin 	default:
127ba610be9SJohn Baldwin 		return (NULL);
128ba610be9SJohn Baldwin 	}
129ba610be9SJohn Baldwin }
130ba610be9SJohn Baldwin 
131197ff4c3SKornel Duleba static struct ossl_cipher*
132197ff4c3SKornel Duleba ossl_lookup_cipher(const struct crypto_session_params *csp)
133197ff4c3SKornel Duleba {
134197ff4c3SKornel Duleba 
135197ff4c3SKornel Duleba 	switch (csp->csp_cipher_alg) {
136197ff4c3SKornel Duleba 	case CRYPTO_AES_CBC:
137197ff4c3SKornel Duleba 		switch (csp->csp_cipher_klen * 8) {
138197ff4c3SKornel Duleba 		case 128:
139197ff4c3SKornel Duleba 		case 192:
140197ff4c3SKornel Duleba 		case 256:
141197ff4c3SKornel Duleba 			break;
142197ff4c3SKornel Duleba 		default:
143197ff4c3SKornel Duleba 			return (NULL);
144197ff4c3SKornel Duleba 		}
145197ff4c3SKornel Duleba 		return (&ossl_cipher_aes_cbc);
1469a3444d9SMark Johnston 	case CRYPTO_AES_NIST_GCM_16:
1479a3444d9SMark Johnston 		switch (csp->csp_cipher_klen * 8) {
1489a3444d9SMark Johnston 		case 128:
1499a3444d9SMark Johnston 		case 192:
1509a3444d9SMark Johnston 		case 256:
1519a3444d9SMark Johnston 			break;
1529a3444d9SMark Johnston 		default:
1539a3444d9SMark Johnston 			return (NULL);
1549a3444d9SMark Johnston 		}
1559a3444d9SMark Johnston 		return (&ossl_cipher_aes_gcm);
156197ff4c3SKornel Duleba 	case CRYPTO_CHACHA20:
157197ff4c3SKornel Duleba 		if (csp->csp_cipher_klen != CHACHA_KEY_SIZE)
158197ff4c3SKornel Duleba 			return (NULL);
159197ff4c3SKornel Duleba 		return (&ossl_cipher_chacha20);
160197ff4c3SKornel Duleba 	default:
161197ff4c3SKornel Duleba 		return (NULL);
162197ff4c3SKornel Duleba 	}
163197ff4c3SKornel Duleba }
164197ff4c3SKornel Duleba 
165ba610be9SJohn Baldwin static int
166ba610be9SJohn Baldwin ossl_probesession(device_t dev, const struct crypto_session_params *csp)
167ba610be9SJohn Baldwin {
168197ff4c3SKornel Duleba 	struct ossl_softc *sc = device_get_softc(dev);
169ba610be9SJohn Baldwin 
170ba610be9SJohn Baldwin 	if ((csp->csp_flags & ~(CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD)) !=
171ba610be9SJohn Baldwin 	    0)
172ba610be9SJohn Baldwin 		return (EINVAL);
173ba610be9SJohn Baldwin 	switch (csp->csp_mode) {
174ba610be9SJohn Baldwin 	case CSP_MODE_DIGEST:
175ba610be9SJohn Baldwin 		if (ossl_lookup_hash(csp) == NULL)
176ba610be9SJohn Baldwin 			return (EINVAL);
177ba610be9SJohn Baldwin 		break;
17892aecd1eSJohn Baldwin 	case CSP_MODE_CIPHER:
179197ff4c3SKornel Duleba 		if (csp->csp_cipher_alg != CRYPTO_CHACHA20 && !sc->has_aes)
18092aecd1eSJohn Baldwin 			return (EINVAL);
181197ff4c3SKornel Duleba 		if (ossl_lookup_cipher(csp) == NULL)
18292aecd1eSJohn Baldwin 			return (EINVAL);
18392aecd1eSJohn Baldwin 		break;
184c4026909SKornel Duleba 	case CSP_MODE_ETA:
185c4026909SKornel Duleba 		if (!sc->has_aes ||
186c4026909SKornel Duleba 		    csp->csp_cipher_alg == CRYPTO_CHACHA20 ||
187c4026909SKornel Duleba 		    ossl_lookup_hash(csp) == NULL ||
188c4026909SKornel Duleba 		    ossl_lookup_cipher(csp) == NULL)
189c4026909SKornel Duleba 			return (EINVAL);
190c4026909SKornel Duleba 		break;
19178991a93SJohn Baldwin 	case CSP_MODE_AEAD:
19278991a93SJohn Baldwin 		switch (csp->csp_cipher_alg) {
19378991a93SJohn Baldwin 		case CRYPTO_CHACHA20_POLY1305:
19478991a93SJohn Baldwin 			break;
1959a3444d9SMark Johnston 		case CRYPTO_AES_NIST_GCM_16:
1969a3444d9SMark Johnston 			if (!sc->has_aes_gcm || ossl_lookup_cipher(csp) == NULL)
1979a3444d9SMark Johnston 				return (EINVAL);
1989a3444d9SMark Johnston 			if (csp->csp_ivlen != AES_GCM_IV_LEN)
1999a3444d9SMark Johnston 				return (EINVAL);
2009a3444d9SMark Johnston 			if (csp->csp_auth_mlen != 0 &&
2019a3444d9SMark Johnston 			    csp->csp_auth_mlen != GMAC_DIGEST_LEN)
2029a3444d9SMark Johnston 				return (EINVAL);
2039a3444d9SMark Johnston 			break;
20478991a93SJohn Baldwin 		default:
20578991a93SJohn Baldwin 			return (EINVAL);
20678991a93SJohn Baldwin 		}
20778991a93SJohn Baldwin 		break;
208ba610be9SJohn Baldwin 	default:
209ba610be9SJohn Baldwin 		return (EINVAL);
210ba610be9SJohn Baldwin 	}
211ba610be9SJohn Baldwin 
212ba610be9SJohn Baldwin 	return (CRYPTODEV_PROBE_ACCEL_SOFTWARE);
213ba610be9SJohn Baldwin }
214ba610be9SJohn Baldwin 
21592aecd1eSJohn Baldwin static void
21692aecd1eSJohn Baldwin ossl_newsession_hash(struct ossl_session *s,
217ba610be9SJohn Baldwin     const struct crypto_session_params *csp)
218ba610be9SJohn Baldwin {
219ba610be9SJohn Baldwin 	struct auth_hash *axf;
220ba610be9SJohn Baldwin 
221ba610be9SJohn Baldwin 	axf = ossl_lookup_hash(csp);
222ba610be9SJohn Baldwin 	s->hash.axf = axf;
223ba610be9SJohn Baldwin 	if (csp->csp_auth_mlen == 0)
224ba610be9SJohn Baldwin 		s->hash.mlen = axf->hashsize;
225ba610be9SJohn Baldwin 	else
226ba610be9SJohn Baldwin 		s->hash.mlen = csp->csp_auth_mlen;
227ba610be9SJohn Baldwin 
228ba610be9SJohn Baldwin 	if (csp->csp_auth_klen == 0) {
229ba610be9SJohn Baldwin 		axf->Init(&s->hash.ictx);
230ba610be9SJohn Baldwin 	} else {
231ba610be9SJohn Baldwin 		if (csp->csp_auth_key != NULL) {
232ba610be9SJohn Baldwin 			fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX);
233a079e38bSJohn Baldwin 			if (axf->Setkey != NULL) {
234a079e38bSJohn Baldwin 				axf->Init(&s->hash.ictx);
235a079e38bSJohn Baldwin 				axf->Setkey(&s->hash.ictx, csp->csp_auth_key,
236ba610be9SJohn Baldwin 				    csp->csp_auth_klen);
237a079e38bSJohn Baldwin 			} else {
238a079e38bSJohn Baldwin 				hmac_init_ipad(axf, csp->csp_auth_key,
239a079e38bSJohn Baldwin 				    csp->csp_auth_klen, &s->hash.ictx);
240a079e38bSJohn Baldwin 				hmac_init_opad(axf, csp->csp_auth_key,
241a079e38bSJohn Baldwin 				    csp->csp_auth_klen, &s->hash.octx);
242a079e38bSJohn Baldwin 			}
243ba610be9SJohn Baldwin 			fpu_kern_leave(curthread, NULL);
244ba610be9SJohn Baldwin 		}
245ba610be9SJohn Baldwin 	}
24692aecd1eSJohn Baldwin }
24792aecd1eSJohn Baldwin 
24892aecd1eSJohn Baldwin static int
249197ff4c3SKornel Duleba ossl_newsession_cipher(struct ossl_session *s,
250197ff4c3SKornel Duleba     const struct crypto_session_params *csp)
251197ff4c3SKornel Duleba {
252197ff4c3SKornel Duleba 	struct ossl_cipher *cipher;
253197ff4c3SKornel Duleba 	int error = 0;
254197ff4c3SKornel Duleba 
255197ff4c3SKornel Duleba 	cipher = ossl_lookup_cipher(csp);
256197ff4c3SKornel Duleba 	if (cipher == NULL)
257197ff4c3SKornel Duleba 		return (EINVAL);
258197ff4c3SKornel Duleba 
259197ff4c3SKornel Duleba 	s->cipher.cipher = cipher;
260197ff4c3SKornel Duleba 
261197ff4c3SKornel Duleba 	if (csp->csp_cipher_key == NULL)
262197ff4c3SKornel Duleba 		return (0);
263197ff4c3SKornel Duleba 
264197ff4c3SKornel Duleba 	fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX);
265197ff4c3SKornel Duleba 	if (cipher->set_encrypt_key != NULL) {
266197ff4c3SKornel Duleba 		error = cipher->set_encrypt_key(csp->csp_cipher_key,
267197ff4c3SKornel Duleba 		    8 * csp->csp_cipher_klen, &s->cipher.enc_ctx);
268197ff4c3SKornel Duleba 		if (error != 0) {
269197ff4c3SKornel Duleba 			fpu_kern_leave(curthread, NULL);
270197ff4c3SKornel Duleba 			return (error);
271197ff4c3SKornel Duleba 		}
272197ff4c3SKornel Duleba 	}
273197ff4c3SKornel Duleba 	if (cipher->set_decrypt_key != NULL)
274197ff4c3SKornel Duleba 		error = cipher->set_decrypt_key(csp->csp_cipher_key,
275197ff4c3SKornel Duleba 		    8 * csp->csp_cipher_klen, &s->cipher.dec_ctx);
276197ff4c3SKornel Duleba 	fpu_kern_leave(curthread, NULL);
277197ff4c3SKornel Duleba 
278197ff4c3SKornel Duleba 	return (error);
279197ff4c3SKornel Duleba }
280197ff4c3SKornel Duleba 
281197ff4c3SKornel Duleba static int
28292aecd1eSJohn Baldwin ossl_newsession(device_t dev, crypto_session_t cses,
28392aecd1eSJohn Baldwin     const struct crypto_session_params *csp)
28492aecd1eSJohn Baldwin {
28592aecd1eSJohn Baldwin 	struct ossl_session *s;
286197ff4c3SKornel Duleba 	int error = 0;
28792aecd1eSJohn Baldwin 
28892aecd1eSJohn Baldwin 	s = crypto_get_driver_session(cses);
28992aecd1eSJohn Baldwin 	switch (csp->csp_mode) {
29092aecd1eSJohn Baldwin 	case CSP_MODE_DIGEST:
29192aecd1eSJohn Baldwin 		ossl_newsession_hash(s, csp);
29292aecd1eSJohn Baldwin 		break;
293197ff4c3SKornel Duleba 	case CSP_MODE_CIPHER:
294197ff4c3SKornel Duleba 		error = ossl_newsession_cipher(s, csp);
295197ff4c3SKornel Duleba 		break;
296c4026909SKornel Duleba 	case CSP_MODE_ETA:
297c4026909SKornel Duleba 		ossl_newsession_hash(s, csp);
298c4026909SKornel Duleba 		error = ossl_newsession_cipher(s, csp);
299c4026909SKornel Duleba 		break;
3009a3444d9SMark Johnston 	case CSP_MODE_AEAD:
301474d9290SJohn Baldwin 		if (csp->csp_cipher_alg != CRYPTO_CHACHA20_POLY1305)
3029a3444d9SMark Johnston 			error = ossl_newsession_cipher(s, csp);
3039a3444d9SMark Johnston 		break;
3049a3444d9SMark Johnston 	default:
3059a3444d9SMark Johnston 		__assert_unreachable();
30692aecd1eSJohn Baldwin 	}
30792aecd1eSJohn Baldwin 
308197ff4c3SKornel Duleba 	return (error);
309ba610be9SJohn Baldwin }
310ba610be9SJohn Baldwin 
311ba610be9SJohn Baldwin static int
31292aecd1eSJohn Baldwin ossl_process_hash(struct ossl_session *s, struct cryptop *crp,
31392aecd1eSJohn Baldwin     const struct crypto_session_params *csp)
314ba610be9SJohn Baldwin {
315ba610be9SJohn Baldwin 	struct ossl_hash_context ctx;
316ba610be9SJohn Baldwin 	char digest[HASH_MAX_LEN];
317ba610be9SJohn Baldwin 	struct auth_hash *axf;
318ba610be9SJohn Baldwin 	int error;
319ba610be9SJohn Baldwin 
320ba610be9SJohn Baldwin 	axf = s->hash.axf;
321ba610be9SJohn Baldwin 
322a079e38bSJohn Baldwin 	if (crp->crp_auth_key == NULL) {
323ba610be9SJohn Baldwin 		ctx = s->hash.ictx;
324a079e38bSJohn Baldwin 	} else {
325a079e38bSJohn Baldwin 		if (axf->Setkey != NULL) {
326a079e38bSJohn Baldwin 			axf->Init(&ctx);
327a079e38bSJohn Baldwin 			axf->Setkey(&ctx, crp->crp_auth_key,
328a079e38bSJohn Baldwin 			    csp->csp_auth_klen);
329a079e38bSJohn Baldwin 		} else {
330a079e38bSJohn Baldwin 			hmac_init_ipad(axf, crp->crp_auth_key,
331a079e38bSJohn Baldwin 			    csp->csp_auth_klen, &ctx);
332a079e38bSJohn Baldwin 		}
333a079e38bSJohn Baldwin 	}
334ba610be9SJohn Baldwin 
335ba610be9SJohn Baldwin 	if (crp->crp_aad != NULL)
336ba610be9SJohn Baldwin 		error = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length);
337ba610be9SJohn Baldwin 	else
338ba610be9SJohn Baldwin 		error = crypto_apply(crp, crp->crp_aad_start,
339ba610be9SJohn Baldwin 		    crp->crp_aad_length, axf->Update, &ctx);
340ba610be9SJohn Baldwin 	if (error)
341ba610be9SJohn Baldwin 		goto out;
342ba610be9SJohn Baldwin 
343ba610be9SJohn Baldwin 	error = crypto_apply(crp, crp->crp_payload_start,
344ba610be9SJohn Baldwin 	    crp->crp_payload_length, axf->Update, &ctx);
345ba610be9SJohn Baldwin 	if (error)
346ba610be9SJohn Baldwin 		goto out;
347ba610be9SJohn Baldwin 
348ba610be9SJohn Baldwin 	axf->Final(digest, &ctx);
349ba610be9SJohn Baldwin 
350a079e38bSJohn Baldwin 	if (csp->csp_auth_klen != 0 && axf->Setkey == NULL) {
351a079e38bSJohn Baldwin 		if (crp->crp_auth_key == NULL)
352ba610be9SJohn Baldwin 			ctx = s->hash.octx;
353a079e38bSJohn Baldwin 		else
354a079e38bSJohn Baldwin 			hmac_init_opad(axf, crp->crp_auth_key,
355a079e38bSJohn Baldwin 			    csp->csp_auth_klen, &ctx);
356ba610be9SJohn Baldwin 		axf->Update(&ctx, digest, axf->hashsize);
357ba610be9SJohn Baldwin 		axf->Final(digest, &ctx);
358ba610be9SJohn Baldwin 	}
359ba610be9SJohn Baldwin 
360ba610be9SJohn Baldwin 	if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
361ba610be9SJohn Baldwin 		char digest2[HASH_MAX_LEN];
362ba610be9SJohn Baldwin 
363ba610be9SJohn Baldwin 		crypto_copydata(crp, crp->crp_digest_start, s->hash.mlen,
364ba610be9SJohn Baldwin 		    digest2);
365ba610be9SJohn Baldwin 		if (timingsafe_bcmp(digest, digest2, s->hash.mlen) != 0)
366ba610be9SJohn Baldwin 			error = EBADMSG;
367ba610be9SJohn Baldwin 		explicit_bzero(digest2, sizeof(digest2));
368ba610be9SJohn Baldwin 	} else {
369ba610be9SJohn Baldwin 		crypto_copyback(crp, crp->crp_digest_start, s->hash.mlen,
370ba610be9SJohn Baldwin 		    digest);
371ba610be9SJohn Baldwin 	}
372ba610be9SJohn Baldwin 	explicit_bzero(digest, sizeof(digest));
373ba610be9SJohn Baldwin 
374ba610be9SJohn Baldwin out:
37592aecd1eSJohn Baldwin 	explicit_bzero(&ctx, sizeof(ctx));
37692aecd1eSJohn Baldwin 	return (error);
37792aecd1eSJohn Baldwin }
37892aecd1eSJohn Baldwin 
37992aecd1eSJohn Baldwin static int
3809a3444d9SMark Johnston ossl_process_cipher(struct ossl_session *s, struct cryptop *crp,
3819a3444d9SMark Johnston     const struct crypto_session_params *csp)
3829a3444d9SMark Johnston {
3839a3444d9SMark Johnston 	return (s->cipher.cipher->process(&s->cipher, crp, csp));
3849a3444d9SMark Johnston }
3859a3444d9SMark Johnston 
3869a3444d9SMark Johnston static int
387c4026909SKornel Duleba ossl_process_eta(struct ossl_session *s, struct cryptop *crp,
388c4026909SKornel Duleba     const struct crypto_session_params *csp)
389c4026909SKornel Duleba {
390c4026909SKornel Duleba 	int error;
391c4026909SKornel Duleba 
392c4026909SKornel Duleba 	if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
393c4026909SKornel Duleba 		error = s->cipher.cipher->process(&s->cipher, crp, csp);
394c4026909SKornel Duleba 		if (error == 0)
395c4026909SKornel Duleba 			error = ossl_process_hash(s, crp, csp);
396c4026909SKornel Duleba 	} else {
397c4026909SKornel Duleba 		error = ossl_process_hash(s, crp, csp);
398c4026909SKornel Duleba 		if (error == 0)
399c4026909SKornel Duleba 			error = s->cipher.cipher->process(&s->cipher, crp, csp);
400c4026909SKornel Duleba 	}
401c4026909SKornel Duleba 
402c4026909SKornel Duleba 	return (error);
403c4026909SKornel Duleba }
404c4026909SKornel Duleba 
405c4026909SKornel Duleba static int
4069a3444d9SMark Johnston ossl_process_aead(struct ossl_session *s, struct cryptop *crp,
4079a3444d9SMark Johnston     const struct crypto_session_params *csp)
4089a3444d9SMark Johnston {
4099a3444d9SMark Johnston 	if (csp->csp_cipher_alg == CRYPTO_CHACHA20_POLY1305) {
4109a3444d9SMark Johnston 		if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
4119a3444d9SMark Johnston 			return (ossl_chacha20_poly1305_encrypt(crp, csp));
4129a3444d9SMark Johnston 		else
4139a3444d9SMark Johnston 			return (ossl_chacha20_poly1305_decrypt(crp, csp));
4149a3444d9SMark Johnston 	} else {
4159a3444d9SMark Johnston 		return (s->cipher.cipher->process(&s->cipher, crp, csp));
4169a3444d9SMark Johnston 	}
4179a3444d9SMark Johnston }
4189a3444d9SMark Johnston 
4199a3444d9SMark Johnston static int
42092aecd1eSJohn Baldwin ossl_process(device_t dev, struct cryptop *crp, int hint)
42192aecd1eSJohn Baldwin {
42292aecd1eSJohn Baldwin 	const struct crypto_session_params *csp;
42392aecd1eSJohn Baldwin 	struct ossl_session *s;
42492aecd1eSJohn Baldwin 	int error;
42592aecd1eSJohn Baldwin 	bool fpu_entered;
42692aecd1eSJohn Baldwin 
42792aecd1eSJohn Baldwin 	s = crypto_get_driver_session(crp->crp_session);
42892aecd1eSJohn Baldwin 	csp = crypto_get_params(crp->crp_session);
42992aecd1eSJohn Baldwin 
43092aecd1eSJohn Baldwin 	if (is_fpu_kern_thread(0)) {
43192aecd1eSJohn Baldwin 		fpu_entered = false;
43292aecd1eSJohn Baldwin 	} else {
43392aecd1eSJohn Baldwin 		fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX);
43492aecd1eSJohn Baldwin 		fpu_entered = true;
43592aecd1eSJohn Baldwin 	}
43692aecd1eSJohn Baldwin 
43792aecd1eSJohn Baldwin 	switch (csp->csp_mode) {
43892aecd1eSJohn Baldwin 	case CSP_MODE_DIGEST:
43992aecd1eSJohn Baldwin 		error = ossl_process_hash(s, crp, csp);
44092aecd1eSJohn Baldwin 		break;
44192aecd1eSJohn Baldwin 	case CSP_MODE_CIPHER:
4429a3444d9SMark Johnston 		error = ossl_process_cipher(s, crp, csp);
44392aecd1eSJohn Baldwin 		break;
444c4026909SKornel Duleba 	case CSP_MODE_ETA:
445c4026909SKornel Duleba 		error = ossl_process_eta(s, crp, csp);
446c4026909SKornel Duleba 		break;
44778991a93SJohn Baldwin 	case CSP_MODE_AEAD:
4489a3444d9SMark Johnston 		error = ossl_process_aead(s, crp, csp);
44978991a93SJohn Baldwin 		break;
45092aecd1eSJohn Baldwin 	default:
45192aecd1eSJohn Baldwin 		__assert_unreachable();
45292aecd1eSJohn Baldwin 	}
45392aecd1eSJohn Baldwin 
454ba610be9SJohn Baldwin 	if (fpu_entered)
455ba610be9SJohn Baldwin 		fpu_kern_leave(curthread, NULL);
456ba610be9SJohn Baldwin 
457ba610be9SJohn Baldwin 	crp->crp_etype = error;
458ba610be9SJohn Baldwin 	crypto_done(crp);
459ba610be9SJohn Baldwin 
460ba610be9SJohn Baldwin 	return (0);
461ba610be9SJohn Baldwin }
462ba610be9SJohn Baldwin 
463ba610be9SJohn Baldwin static device_method_t ossl_methods[] = {
464ba610be9SJohn Baldwin 	DEVMETHOD(device_identify,	ossl_identify),
465ba610be9SJohn Baldwin 	DEVMETHOD(device_probe,		ossl_probe),
466ba610be9SJohn Baldwin 	DEVMETHOD(device_attach,	ossl_attach),
467ba610be9SJohn Baldwin 	DEVMETHOD(device_detach,	ossl_detach),
468ba610be9SJohn Baldwin 
469ba610be9SJohn Baldwin 	DEVMETHOD(cryptodev_probesession, ossl_probesession),
470ba610be9SJohn Baldwin 	DEVMETHOD(cryptodev_newsession,	ossl_newsession),
471ba610be9SJohn Baldwin 	DEVMETHOD(cryptodev_process,	ossl_process),
472ba610be9SJohn Baldwin 
473ba610be9SJohn Baldwin 	DEVMETHOD_END
474ba610be9SJohn Baldwin };
475ba610be9SJohn Baldwin 
476ba610be9SJohn Baldwin static driver_t ossl_driver = {
477ba610be9SJohn Baldwin 	"ossl",
478ba610be9SJohn Baldwin 	ossl_methods,
479ba610be9SJohn Baldwin 	sizeof(struct ossl_softc)
480ba610be9SJohn Baldwin };
481ba610be9SJohn Baldwin 
482ab050b2bSJohn Baldwin DRIVER_MODULE(ossl, nexus, ossl_driver, NULL, NULL);
483ba610be9SJohn Baldwin MODULE_VERSION(ossl, 1);
484ba610be9SJohn Baldwin MODULE_DEPEND(ossl, crypto, 1, 1, 1);
485