1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2020 Netflix, Inc 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 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. 16 * 17 * NO WARRANTY 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. 29 */ 30 31 /* 32 * A driver for the OpenCrypto framework which uses assembly routines 33 * from OpenSSL. 34 */ 35 36 #include <sys/cdefs.h> 37 __FBSDID("$FreeBSD$"); 38 39 #include <sys/types.h> 40 #include <sys/bus.h> 41 #include <sys/kernel.h> 42 #include <sys/malloc.h> 43 #include <sys/module.h> 44 45 #include <machine/fpu.h> 46 47 #include <opencrypto/cryptodev.h> 48 #include <opencrypto/xform_auth.h> 49 50 #include <crypto/openssl/ossl.h> 51 52 #include "cryptodev_if.h" 53 54 struct ossl_softc { 55 int32_t sc_cid; 56 }; 57 58 struct ossl_session_hash { 59 struct ossl_hash_context ictx; 60 struct ossl_hash_context octx; 61 struct auth_hash *axf; 62 u_int mlen; 63 }; 64 65 struct ossl_session { 66 struct ossl_session_hash hash; 67 }; 68 69 static MALLOC_DEFINE(M_OSSL, "ossl", "OpenSSL crypto"); 70 71 static void 72 ossl_identify(driver_t *driver, device_t parent) 73 { 74 75 if (device_find_child(parent, "ossl", -1) == NULL) 76 BUS_ADD_CHILD(parent, 10, "ossl", -1); 77 } 78 79 static int 80 ossl_probe(device_t dev) 81 { 82 83 device_set_desc(dev, "OpenSSL crypto"); 84 return (BUS_PROBE_DEFAULT); 85 } 86 87 static int 88 ossl_attach(device_t dev) 89 { 90 struct ossl_softc *sc; 91 92 sc = device_get_softc(dev); 93 94 ossl_cpuid(); 95 sc->sc_cid = crypto_get_driverid(dev, sizeof(struct ossl_session), 96 CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC | 97 CRYPTOCAP_F_ACCEL_SOFTWARE); 98 if (sc->sc_cid < 0) { 99 device_printf(dev, "failed to allocate crypto driver id\n"); 100 return (ENXIO); 101 } 102 103 return (0); 104 } 105 106 static int 107 ossl_detach(device_t dev) 108 { 109 struct ossl_softc *sc; 110 111 sc = device_get_softc(dev); 112 113 crypto_unregister_all(sc->sc_cid); 114 115 return (0); 116 } 117 118 static struct auth_hash * 119 ossl_lookup_hash(const struct crypto_session_params *csp) 120 { 121 122 switch (csp->csp_auth_alg) { 123 case CRYPTO_SHA1: 124 case CRYPTO_SHA1_HMAC: 125 return (&ossl_hash_sha1); 126 case CRYPTO_SHA2_224: 127 case CRYPTO_SHA2_224_HMAC: 128 return (&ossl_hash_sha224); 129 case CRYPTO_SHA2_256: 130 case CRYPTO_SHA2_256_HMAC: 131 return (&ossl_hash_sha256); 132 case CRYPTO_SHA2_384: 133 case CRYPTO_SHA2_384_HMAC: 134 return (&ossl_hash_sha384); 135 case CRYPTO_SHA2_512: 136 case CRYPTO_SHA2_512_HMAC: 137 return (&ossl_hash_sha512); 138 default: 139 return (NULL); 140 } 141 } 142 143 static int 144 ossl_probesession(device_t dev, const struct crypto_session_params *csp) 145 { 146 147 if ((csp->csp_flags & ~(CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD)) != 148 0) 149 return (EINVAL); 150 switch (csp->csp_mode) { 151 case CSP_MODE_DIGEST: 152 if (ossl_lookup_hash(csp) == NULL) 153 return (EINVAL); 154 break; 155 default: 156 return (EINVAL); 157 } 158 159 return (CRYPTODEV_PROBE_ACCEL_SOFTWARE); 160 } 161 162 static void 163 ossl_setkey_hmac(struct ossl_session *s, const void *key, int klen) 164 { 165 166 hmac_init_ipad(s->hash.axf, key, klen, &s->hash.ictx); 167 hmac_init_opad(s->hash.axf, key, klen, &s->hash.octx); 168 } 169 170 static int 171 ossl_newsession(device_t dev, crypto_session_t cses, 172 const struct crypto_session_params *csp) 173 { 174 struct ossl_session *s; 175 struct auth_hash *axf; 176 177 s = crypto_get_driver_session(cses); 178 179 axf = ossl_lookup_hash(csp); 180 s->hash.axf = axf; 181 if (csp->csp_auth_mlen == 0) 182 s->hash.mlen = axf->hashsize; 183 else 184 s->hash.mlen = csp->csp_auth_mlen; 185 186 if (csp->csp_auth_klen == 0) { 187 axf->Init(&s->hash.ictx); 188 } else { 189 if (csp->csp_auth_key != NULL) { 190 fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX); 191 ossl_setkey_hmac(s, csp->csp_auth_key, 192 csp->csp_auth_klen); 193 fpu_kern_leave(curthread, NULL); 194 } 195 } 196 return (0); 197 } 198 199 static int 200 ossl_process(device_t dev, struct cryptop *crp, int hint) 201 { 202 struct ossl_hash_context ctx; 203 char digest[HASH_MAX_LEN]; 204 const struct crypto_session_params *csp; 205 struct ossl_session *s; 206 struct auth_hash *axf; 207 int error; 208 bool fpu_entered; 209 210 s = crypto_get_driver_session(crp->crp_session); 211 csp = crypto_get_params(crp->crp_session); 212 axf = s->hash.axf; 213 214 if (is_fpu_kern_thread(0)) { 215 fpu_entered = false; 216 } else { 217 fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX); 218 fpu_entered = true; 219 } 220 221 if (crp->crp_auth_key != NULL) 222 ossl_setkey_hmac(s, crp->crp_auth_key, csp->csp_auth_klen); 223 224 ctx = s->hash.ictx; 225 226 if (crp->crp_aad != NULL) 227 error = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length); 228 else 229 error = crypto_apply(crp, crp->crp_aad_start, 230 crp->crp_aad_length, axf->Update, &ctx); 231 if (error) 232 goto out; 233 234 error = crypto_apply(crp, crp->crp_payload_start, 235 crp->crp_payload_length, axf->Update, &ctx); 236 if (error) 237 goto out; 238 239 axf->Final(digest, &ctx); 240 241 if (csp->csp_auth_klen != 0) { 242 ctx = s->hash.octx; 243 axf->Update(&ctx, digest, axf->hashsize); 244 axf->Final(digest, &ctx); 245 } 246 247 if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { 248 char digest2[HASH_MAX_LEN]; 249 250 crypto_copydata(crp, crp->crp_digest_start, s->hash.mlen, 251 digest2); 252 if (timingsafe_bcmp(digest, digest2, s->hash.mlen) != 0) 253 error = EBADMSG; 254 explicit_bzero(digest2, sizeof(digest2)); 255 } else { 256 crypto_copyback(crp, crp->crp_digest_start, s->hash.mlen, 257 digest); 258 } 259 explicit_bzero(digest, sizeof(digest)); 260 261 out: 262 if (fpu_entered) 263 fpu_kern_leave(curthread, NULL); 264 265 crp->crp_etype = error; 266 crypto_done(crp); 267 268 explicit_bzero(&ctx, sizeof(ctx)); 269 return (0); 270 } 271 272 static device_method_t ossl_methods[] = { 273 DEVMETHOD(device_identify, ossl_identify), 274 DEVMETHOD(device_probe, ossl_probe), 275 DEVMETHOD(device_attach, ossl_attach), 276 DEVMETHOD(device_detach, ossl_detach), 277 278 DEVMETHOD(cryptodev_probesession, ossl_probesession), 279 DEVMETHOD(cryptodev_newsession, ossl_newsession), 280 DEVMETHOD(cryptodev_process, ossl_process), 281 282 DEVMETHOD_END 283 }; 284 285 static driver_t ossl_driver = { 286 "ossl", 287 ossl_methods, 288 sizeof(struct ossl_softc) 289 }; 290 291 static devclass_t ossl_devclass; 292 293 DRIVER_MODULE(ossl, nexus, ossl_driver, ossl_devclass, NULL, NULL); 294 MODULE_VERSION(ossl, 1); 295 MODULE_DEPEND(ossl, crypto, 1, 1, 1); 296