1fd86ae68SMitchell Horne /*- 2fd86ae68SMitchell Horne * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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/cdefs.h> 37ba610be9SJohn Baldwin __FBSDID("$FreeBSD$"); 38ba610be9SJohn Baldwin 39ba610be9SJohn Baldwin #include <sys/types.h> 40ba610be9SJohn Baldwin #include <sys/bus.h> 41ba610be9SJohn Baldwin #include <sys/kernel.h> 42ba610be9SJohn Baldwin #include <sys/malloc.h> 43ba610be9SJohn Baldwin #include <sys/module.h> 44fd86ae68SMitchell Horne 45ba610be9SJohn Baldwin #include <machine/fpu.h> 46ba610be9SJohn Baldwin 47ba610be9SJohn Baldwin #include <opencrypto/cryptodev.h> 48ba610be9SJohn Baldwin #include <opencrypto/xform_auth.h> 49ba610be9SJohn Baldwin 50ba610be9SJohn Baldwin #include <crypto/openssl/ossl.h> 51*92aecd1eSJohn Baldwin #include <crypto/openssl/ossl_chacha.h> 52ba610be9SJohn Baldwin 53ba610be9SJohn Baldwin #include "cryptodev_if.h" 54ba610be9SJohn Baldwin 55ba610be9SJohn Baldwin struct ossl_softc { 56ba610be9SJohn Baldwin int32_t sc_cid; 57ba610be9SJohn Baldwin }; 58ba610be9SJohn Baldwin 59ba610be9SJohn Baldwin struct ossl_session_hash { 60ba610be9SJohn Baldwin struct ossl_hash_context ictx; 61ba610be9SJohn Baldwin struct ossl_hash_context octx; 62ba610be9SJohn Baldwin struct auth_hash *axf; 63ba610be9SJohn Baldwin u_int mlen; 64ba610be9SJohn Baldwin }; 65ba610be9SJohn Baldwin 66ba610be9SJohn Baldwin struct ossl_session { 67ba610be9SJohn Baldwin struct ossl_session_hash hash; 68ba610be9SJohn Baldwin }; 69ba610be9SJohn Baldwin 70ba610be9SJohn Baldwin static MALLOC_DEFINE(M_OSSL, "ossl", "OpenSSL crypto"); 71ba610be9SJohn Baldwin 72ba610be9SJohn Baldwin static void 73ba610be9SJohn Baldwin ossl_identify(driver_t *driver, device_t parent) 74ba610be9SJohn Baldwin { 75ba610be9SJohn Baldwin 76ba610be9SJohn Baldwin if (device_find_child(parent, "ossl", -1) == NULL) 77ba610be9SJohn Baldwin BUS_ADD_CHILD(parent, 10, "ossl", -1); 78ba610be9SJohn Baldwin } 79ba610be9SJohn Baldwin 80ba610be9SJohn Baldwin static int 81ba610be9SJohn Baldwin ossl_probe(device_t dev) 82ba610be9SJohn Baldwin { 83ba610be9SJohn Baldwin 84ba610be9SJohn Baldwin device_set_desc(dev, "OpenSSL crypto"); 85ba610be9SJohn Baldwin return (BUS_PROBE_DEFAULT); 86ba610be9SJohn Baldwin } 87ba610be9SJohn Baldwin 88ba610be9SJohn Baldwin static int 89ba610be9SJohn Baldwin ossl_attach(device_t dev) 90ba610be9SJohn Baldwin { 91ba610be9SJohn Baldwin struct ossl_softc *sc; 92ba610be9SJohn Baldwin 93ba610be9SJohn Baldwin sc = device_get_softc(dev); 94ba610be9SJohn Baldwin 95ba610be9SJohn Baldwin ossl_cpuid(); 96ba610be9SJohn Baldwin sc->sc_cid = crypto_get_driverid(dev, sizeof(struct ossl_session), 97ba610be9SJohn Baldwin CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC | 98ba610be9SJohn Baldwin CRYPTOCAP_F_ACCEL_SOFTWARE); 99ba610be9SJohn Baldwin if (sc->sc_cid < 0) { 100ba610be9SJohn Baldwin device_printf(dev, "failed to allocate crypto driver id\n"); 101ba610be9SJohn Baldwin return (ENXIO); 102ba610be9SJohn Baldwin } 103ba610be9SJohn Baldwin 104ba610be9SJohn Baldwin return (0); 105ba610be9SJohn Baldwin } 106ba610be9SJohn Baldwin 107ba610be9SJohn Baldwin static int 108ba610be9SJohn Baldwin ossl_detach(device_t dev) 109ba610be9SJohn Baldwin { 110ba610be9SJohn Baldwin struct ossl_softc *sc; 111ba610be9SJohn Baldwin 112ba610be9SJohn Baldwin sc = device_get_softc(dev); 113ba610be9SJohn Baldwin 114ba610be9SJohn Baldwin crypto_unregister_all(sc->sc_cid); 115ba610be9SJohn Baldwin 116ba610be9SJohn Baldwin return (0); 117ba610be9SJohn Baldwin } 118ba610be9SJohn Baldwin 119ba610be9SJohn Baldwin static struct auth_hash * 120ba610be9SJohn Baldwin ossl_lookup_hash(const struct crypto_session_params *csp) 121ba610be9SJohn Baldwin { 122ba610be9SJohn Baldwin 123ba610be9SJohn Baldwin switch (csp->csp_auth_alg) { 124ba610be9SJohn Baldwin case CRYPTO_SHA1: 125ba610be9SJohn Baldwin case CRYPTO_SHA1_HMAC: 126ba610be9SJohn Baldwin return (&ossl_hash_sha1); 127ba610be9SJohn Baldwin case CRYPTO_SHA2_224: 128ba610be9SJohn Baldwin case CRYPTO_SHA2_224_HMAC: 129ba610be9SJohn Baldwin return (&ossl_hash_sha224); 130ba610be9SJohn Baldwin case CRYPTO_SHA2_256: 131ba610be9SJohn Baldwin case CRYPTO_SHA2_256_HMAC: 132ba610be9SJohn Baldwin return (&ossl_hash_sha256); 133ba610be9SJohn Baldwin case CRYPTO_SHA2_384: 134ba610be9SJohn Baldwin case CRYPTO_SHA2_384_HMAC: 135ba610be9SJohn Baldwin return (&ossl_hash_sha384); 136ba610be9SJohn Baldwin case CRYPTO_SHA2_512: 137ba610be9SJohn Baldwin case CRYPTO_SHA2_512_HMAC: 138ba610be9SJohn Baldwin return (&ossl_hash_sha512); 139a079e38bSJohn Baldwin case CRYPTO_POLY1305: 140a079e38bSJohn Baldwin return (&ossl_hash_poly1305); 141ba610be9SJohn Baldwin default: 142ba610be9SJohn Baldwin return (NULL); 143ba610be9SJohn Baldwin } 144ba610be9SJohn Baldwin } 145ba610be9SJohn Baldwin 146ba610be9SJohn Baldwin static int 147ba610be9SJohn Baldwin ossl_probesession(device_t dev, const struct crypto_session_params *csp) 148ba610be9SJohn Baldwin { 149ba610be9SJohn Baldwin 150ba610be9SJohn Baldwin if ((csp->csp_flags & ~(CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD)) != 151ba610be9SJohn Baldwin 0) 152ba610be9SJohn Baldwin return (EINVAL); 153ba610be9SJohn Baldwin switch (csp->csp_mode) { 154ba610be9SJohn Baldwin case CSP_MODE_DIGEST: 155ba610be9SJohn Baldwin if (ossl_lookup_hash(csp) == NULL) 156ba610be9SJohn Baldwin return (EINVAL); 157ba610be9SJohn Baldwin break; 158*92aecd1eSJohn Baldwin case CSP_MODE_CIPHER: 159*92aecd1eSJohn Baldwin switch (csp->csp_cipher_alg) { 160*92aecd1eSJohn Baldwin case CRYPTO_CHACHA20: 161*92aecd1eSJohn Baldwin if (csp->csp_cipher_klen != CHACHA_KEY_SIZE) 162*92aecd1eSJohn Baldwin return (EINVAL); 163*92aecd1eSJohn Baldwin break; 164*92aecd1eSJohn Baldwin default: 165*92aecd1eSJohn Baldwin return (EINVAL); 166*92aecd1eSJohn Baldwin } 167*92aecd1eSJohn Baldwin break; 168ba610be9SJohn Baldwin default: 169ba610be9SJohn Baldwin return (EINVAL); 170ba610be9SJohn Baldwin } 171ba610be9SJohn Baldwin 172ba610be9SJohn Baldwin return (CRYPTODEV_PROBE_ACCEL_SOFTWARE); 173ba610be9SJohn Baldwin } 174ba610be9SJohn Baldwin 175*92aecd1eSJohn Baldwin static void 176*92aecd1eSJohn Baldwin ossl_newsession_hash(struct ossl_session *s, 177ba610be9SJohn Baldwin const struct crypto_session_params *csp) 178ba610be9SJohn Baldwin { 179ba610be9SJohn Baldwin struct auth_hash *axf; 180ba610be9SJohn Baldwin 181ba610be9SJohn Baldwin axf = ossl_lookup_hash(csp); 182ba610be9SJohn Baldwin s->hash.axf = axf; 183ba610be9SJohn Baldwin if (csp->csp_auth_mlen == 0) 184ba610be9SJohn Baldwin s->hash.mlen = axf->hashsize; 185ba610be9SJohn Baldwin else 186ba610be9SJohn Baldwin s->hash.mlen = csp->csp_auth_mlen; 187ba610be9SJohn Baldwin 188ba610be9SJohn Baldwin if (csp->csp_auth_klen == 0) { 189ba610be9SJohn Baldwin axf->Init(&s->hash.ictx); 190ba610be9SJohn Baldwin } else { 191ba610be9SJohn Baldwin if (csp->csp_auth_key != NULL) { 192ba610be9SJohn Baldwin fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX); 193a079e38bSJohn Baldwin if (axf->Setkey != NULL) { 194a079e38bSJohn Baldwin axf->Init(&s->hash.ictx); 195a079e38bSJohn Baldwin axf->Setkey(&s->hash.ictx, csp->csp_auth_key, 196ba610be9SJohn Baldwin csp->csp_auth_klen); 197a079e38bSJohn Baldwin } else { 198a079e38bSJohn Baldwin hmac_init_ipad(axf, csp->csp_auth_key, 199a079e38bSJohn Baldwin csp->csp_auth_klen, &s->hash.ictx); 200a079e38bSJohn Baldwin hmac_init_opad(axf, csp->csp_auth_key, 201a079e38bSJohn Baldwin csp->csp_auth_klen, &s->hash.octx); 202a079e38bSJohn Baldwin } 203ba610be9SJohn Baldwin fpu_kern_leave(curthread, NULL); 204ba610be9SJohn Baldwin } 205ba610be9SJohn Baldwin } 206*92aecd1eSJohn Baldwin } 207*92aecd1eSJohn Baldwin 208*92aecd1eSJohn Baldwin static int 209*92aecd1eSJohn Baldwin ossl_newsession(device_t dev, crypto_session_t cses, 210*92aecd1eSJohn Baldwin const struct crypto_session_params *csp) 211*92aecd1eSJohn Baldwin { 212*92aecd1eSJohn Baldwin struct ossl_session *s; 213*92aecd1eSJohn Baldwin 214*92aecd1eSJohn Baldwin s = crypto_get_driver_session(cses); 215*92aecd1eSJohn Baldwin switch (csp->csp_mode) { 216*92aecd1eSJohn Baldwin case CSP_MODE_DIGEST: 217*92aecd1eSJohn Baldwin ossl_newsession_hash(s, csp); 218*92aecd1eSJohn Baldwin break; 219*92aecd1eSJohn Baldwin } 220*92aecd1eSJohn Baldwin 221ba610be9SJohn Baldwin return (0); 222ba610be9SJohn Baldwin } 223ba610be9SJohn Baldwin 224ba610be9SJohn Baldwin static int 225*92aecd1eSJohn Baldwin ossl_process_hash(struct ossl_session *s, struct cryptop *crp, 226*92aecd1eSJohn Baldwin const struct crypto_session_params *csp) 227ba610be9SJohn Baldwin { 228ba610be9SJohn Baldwin struct ossl_hash_context ctx; 229ba610be9SJohn Baldwin char digest[HASH_MAX_LEN]; 230ba610be9SJohn Baldwin struct auth_hash *axf; 231ba610be9SJohn Baldwin int error; 232ba610be9SJohn Baldwin 233ba610be9SJohn Baldwin axf = s->hash.axf; 234ba610be9SJohn Baldwin 235a079e38bSJohn Baldwin if (crp->crp_auth_key == NULL) { 236ba610be9SJohn Baldwin ctx = s->hash.ictx; 237a079e38bSJohn Baldwin } else { 238a079e38bSJohn Baldwin if (axf->Setkey != NULL) { 239a079e38bSJohn Baldwin axf->Init(&ctx); 240a079e38bSJohn Baldwin axf->Setkey(&ctx, crp->crp_auth_key, 241a079e38bSJohn Baldwin csp->csp_auth_klen); 242a079e38bSJohn Baldwin } else { 243a079e38bSJohn Baldwin hmac_init_ipad(axf, crp->crp_auth_key, 244a079e38bSJohn Baldwin csp->csp_auth_klen, &ctx); 245a079e38bSJohn Baldwin } 246a079e38bSJohn Baldwin } 247ba610be9SJohn Baldwin 248ba610be9SJohn Baldwin if (crp->crp_aad != NULL) 249ba610be9SJohn Baldwin error = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length); 250ba610be9SJohn Baldwin else 251ba610be9SJohn Baldwin error = crypto_apply(crp, crp->crp_aad_start, 252ba610be9SJohn Baldwin crp->crp_aad_length, axf->Update, &ctx); 253ba610be9SJohn Baldwin if (error) 254ba610be9SJohn Baldwin goto out; 255ba610be9SJohn Baldwin 256ba610be9SJohn Baldwin error = crypto_apply(crp, crp->crp_payload_start, 257ba610be9SJohn Baldwin crp->crp_payload_length, axf->Update, &ctx); 258ba610be9SJohn Baldwin if (error) 259ba610be9SJohn Baldwin goto out; 260ba610be9SJohn Baldwin 261ba610be9SJohn Baldwin axf->Final(digest, &ctx); 262ba610be9SJohn Baldwin 263a079e38bSJohn Baldwin if (csp->csp_auth_klen != 0 && axf->Setkey == NULL) { 264a079e38bSJohn Baldwin if (crp->crp_auth_key == NULL) 265ba610be9SJohn Baldwin ctx = s->hash.octx; 266a079e38bSJohn Baldwin else 267a079e38bSJohn Baldwin hmac_init_opad(axf, crp->crp_auth_key, 268a079e38bSJohn Baldwin csp->csp_auth_klen, &ctx); 269ba610be9SJohn Baldwin axf->Update(&ctx, digest, axf->hashsize); 270ba610be9SJohn Baldwin axf->Final(digest, &ctx); 271ba610be9SJohn Baldwin } 272ba610be9SJohn Baldwin 273ba610be9SJohn Baldwin if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { 274ba610be9SJohn Baldwin char digest2[HASH_MAX_LEN]; 275ba610be9SJohn Baldwin 276ba610be9SJohn Baldwin crypto_copydata(crp, crp->crp_digest_start, s->hash.mlen, 277ba610be9SJohn Baldwin digest2); 278ba610be9SJohn Baldwin if (timingsafe_bcmp(digest, digest2, s->hash.mlen) != 0) 279ba610be9SJohn Baldwin error = EBADMSG; 280ba610be9SJohn Baldwin explicit_bzero(digest2, sizeof(digest2)); 281ba610be9SJohn Baldwin } else { 282ba610be9SJohn Baldwin crypto_copyback(crp, crp->crp_digest_start, s->hash.mlen, 283ba610be9SJohn Baldwin digest); 284ba610be9SJohn Baldwin } 285ba610be9SJohn Baldwin explicit_bzero(digest, sizeof(digest)); 286ba610be9SJohn Baldwin 287ba610be9SJohn Baldwin out: 288*92aecd1eSJohn Baldwin explicit_bzero(&ctx, sizeof(ctx)); 289*92aecd1eSJohn Baldwin return (error); 290*92aecd1eSJohn Baldwin } 291*92aecd1eSJohn Baldwin 292*92aecd1eSJohn Baldwin static int 293*92aecd1eSJohn Baldwin ossl_process(device_t dev, struct cryptop *crp, int hint) 294*92aecd1eSJohn Baldwin { 295*92aecd1eSJohn Baldwin const struct crypto_session_params *csp; 296*92aecd1eSJohn Baldwin struct ossl_session *s; 297*92aecd1eSJohn Baldwin int error; 298*92aecd1eSJohn Baldwin bool fpu_entered; 299*92aecd1eSJohn Baldwin 300*92aecd1eSJohn Baldwin s = crypto_get_driver_session(crp->crp_session); 301*92aecd1eSJohn Baldwin csp = crypto_get_params(crp->crp_session); 302*92aecd1eSJohn Baldwin 303*92aecd1eSJohn Baldwin if (is_fpu_kern_thread(0)) { 304*92aecd1eSJohn Baldwin fpu_entered = false; 305*92aecd1eSJohn Baldwin } else { 306*92aecd1eSJohn Baldwin fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX); 307*92aecd1eSJohn Baldwin fpu_entered = true; 308*92aecd1eSJohn Baldwin } 309*92aecd1eSJohn Baldwin 310*92aecd1eSJohn Baldwin switch (csp->csp_mode) { 311*92aecd1eSJohn Baldwin case CSP_MODE_DIGEST: 312*92aecd1eSJohn Baldwin error = ossl_process_hash(s, crp, csp); 313*92aecd1eSJohn Baldwin break; 314*92aecd1eSJohn Baldwin case CSP_MODE_CIPHER: 315*92aecd1eSJohn Baldwin error = ossl_chacha20(crp, csp); 316*92aecd1eSJohn Baldwin break; 317*92aecd1eSJohn Baldwin default: 318*92aecd1eSJohn Baldwin __assert_unreachable(); 319*92aecd1eSJohn Baldwin } 320*92aecd1eSJohn Baldwin 321ba610be9SJohn Baldwin if (fpu_entered) 322ba610be9SJohn Baldwin fpu_kern_leave(curthread, NULL); 323ba610be9SJohn Baldwin 324ba610be9SJohn Baldwin crp->crp_etype = error; 325ba610be9SJohn Baldwin crypto_done(crp); 326ba610be9SJohn Baldwin 327ba610be9SJohn Baldwin return (0); 328ba610be9SJohn Baldwin } 329ba610be9SJohn Baldwin 330ba610be9SJohn Baldwin static device_method_t ossl_methods[] = { 331ba610be9SJohn Baldwin DEVMETHOD(device_identify, ossl_identify), 332ba610be9SJohn Baldwin DEVMETHOD(device_probe, ossl_probe), 333ba610be9SJohn Baldwin DEVMETHOD(device_attach, ossl_attach), 334ba610be9SJohn Baldwin DEVMETHOD(device_detach, ossl_detach), 335ba610be9SJohn Baldwin 336ba610be9SJohn Baldwin DEVMETHOD(cryptodev_probesession, ossl_probesession), 337ba610be9SJohn Baldwin DEVMETHOD(cryptodev_newsession, ossl_newsession), 338ba610be9SJohn Baldwin DEVMETHOD(cryptodev_process, ossl_process), 339ba610be9SJohn Baldwin 340ba610be9SJohn Baldwin DEVMETHOD_END 341ba610be9SJohn Baldwin }; 342ba610be9SJohn Baldwin 343ba610be9SJohn Baldwin static driver_t ossl_driver = { 344ba610be9SJohn Baldwin "ossl", 345ba610be9SJohn Baldwin ossl_methods, 346ba610be9SJohn Baldwin sizeof(struct ossl_softc) 347ba610be9SJohn Baldwin }; 348ba610be9SJohn Baldwin 349ba610be9SJohn Baldwin static devclass_t ossl_devclass; 350ba610be9SJohn Baldwin 351ba610be9SJohn Baldwin DRIVER_MODULE(ossl, nexus, ossl_driver, ossl_devclass, NULL, NULL); 352ba610be9SJohn Baldwin MODULE_VERSION(ossl, 1); 353ba610be9SJohn Baldwin MODULE_DEPEND(ossl, crypto, 1, 1, 1); 354