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 #include <crypto/openssl/ossl_chacha.h> 52 #include <crypto/openssl/ossl_cipher.h> 53 54 #include "cryptodev_if.h" 55 56 static MALLOC_DEFINE(M_OSSL, "ossl", "OpenSSL crypto"); 57 58 static void 59 ossl_identify(driver_t *driver, device_t parent) 60 { 61 62 if (device_find_child(parent, "ossl", -1) == NULL) 63 BUS_ADD_CHILD(parent, 10, "ossl", -1); 64 } 65 66 static int 67 ossl_probe(device_t dev) 68 { 69 70 device_set_desc(dev, "OpenSSL crypto"); 71 return (BUS_PROBE_DEFAULT); 72 } 73 74 static int 75 ossl_attach(device_t dev) 76 { 77 struct ossl_softc *sc; 78 79 sc = device_get_softc(dev); 80 81 ossl_cpuid(sc); 82 sc->sc_cid = crypto_get_driverid(dev, sizeof(struct ossl_session), 83 CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC | 84 CRYPTOCAP_F_ACCEL_SOFTWARE); 85 if (sc->sc_cid < 0) { 86 device_printf(dev, "failed to allocate crypto driver id\n"); 87 return (ENXIO); 88 } 89 90 return (0); 91 } 92 93 static int 94 ossl_detach(device_t dev) 95 { 96 struct ossl_softc *sc; 97 98 sc = device_get_softc(dev); 99 100 crypto_unregister_all(sc->sc_cid); 101 102 return (0); 103 } 104 105 static struct auth_hash * 106 ossl_lookup_hash(const struct crypto_session_params *csp) 107 { 108 109 switch (csp->csp_auth_alg) { 110 case CRYPTO_SHA1: 111 case CRYPTO_SHA1_HMAC: 112 return (&ossl_hash_sha1); 113 case CRYPTO_SHA2_224: 114 case CRYPTO_SHA2_224_HMAC: 115 return (&ossl_hash_sha224); 116 case CRYPTO_SHA2_256: 117 case CRYPTO_SHA2_256_HMAC: 118 return (&ossl_hash_sha256); 119 case CRYPTO_SHA2_384: 120 case CRYPTO_SHA2_384_HMAC: 121 return (&ossl_hash_sha384); 122 case CRYPTO_SHA2_512: 123 case CRYPTO_SHA2_512_HMAC: 124 return (&ossl_hash_sha512); 125 case CRYPTO_POLY1305: 126 return (&ossl_hash_poly1305); 127 default: 128 return (NULL); 129 } 130 } 131 132 static struct ossl_cipher* 133 ossl_lookup_cipher(const struct crypto_session_params *csp) 134 { 135 136 switch (csp->csp_cipher_alg) { 137 case CRYPTO_AES_CBC: 138 switch (csp->csp_cipher_klen * 8) { 139 case 128: 140 case 192: 141 case 256: 142 break; 143 default: 144 return (NULL); 145 } 146 return (&ossl_cipher_aes_cbc); 147 case CRYPTO_CHACHA20: 148 if (csp->csp_cipher_klen != CHACHA_KEY_SIZE) 149 return (NULL); 150 return (&ossl_cipher_chacha20); 151 default: 152 return (NULL); 153 } 154 } 155 156 static int 157 ossl_probesession(device_t dev, const struct crypto_session_params *csp) 158 { 159 struct ossl_softc *sc = device_get_softc(dev); 160 161 if ((csp->csp_flags & ~(CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD)) != 162 0) 163 return (EINVAL); 164 switch (csp->csp_mode) { 165 case CSP_MODE_DIGEST: 166 if (ossl_lookup_hash(csp) == NULL) 167 return (EINVAL); 168 break; 169 case CSP_MODE_CIPHER: 170 if (csp->csp_cipher_alg != CRYPTO_CHACHA20 && !sc->has_aes) 171 return (EINVAL); 172 if (ossl_lookup_cipher(csp) == NULL) 173 return (EINVAL); 174 break; 175 case CSP_MODE_ETA: 176 if (!sc->has_aes || 177 csp->csp_cipher_alg == CRYPTO_CHACHA20 || 178 ossl_lookup_hash(csp) == NULL || 179 ossl_lookup_cipher(csp) == NULL) 180 return (EINVAL); 181 break; 182 case CSP_MODE_AEAD: 183 switch (csp->csp_cipher_alg) { 184 case CRYPTO_CHACHA20_POLY1305: 185 break; 186 default: 187 return (EINVAL); 188 } 189 break; 190 default: 191 return (EINVAL); 192 } 193 194 return (CRYPTODEV_PROBE_ACCEL_SOFTWARE); 195 } 196 197 static void 198 ossl_newsession_hash(struct ossl_session *s, 199 const struct crypto_session_params *csp) 200 { 201 struct auth_hash *axf; 202 203 axf = ossl_lookup_hash(csp); 204 s->hash.axf = axf; 205 if (csp->csp_auth_mlen == 0) 206 s->hash.mlen = axf->hashsize; 207 else 208 s->hash.mlen = csp->csp_auth_mlen; 209 210 if (csp->csp_auth_klen == 0) { 211 axf->Init(&s->hash.ictx); 212 } else { 213 if (csp->csp_auth_key != NULL) { 214 fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX); 215 if (axf->Setkey != NULL) { 216 axf->Init(&s->hash.ictx); 217 axf->Setkey(&s->hash.ictx, csp->csp_auth_key, 218 csp->csp_auth_klen); 219 } else { 220 hmac_init_ipad(axf, csp->csp_auth_key, 221 csp->csp_auth_klen, &s->hash.ictx); 222 hmac_init_opad(axf, csp->csp_auth_key, 223 csp->csp_auth_klen, &s->hash.octx); 224 } 225 fpu_kern_leave(curthread, NULL); 226 } 227 } 228 } 229 230 static int 231 ossl_newsession_cipher(struct ossl_session *s, 232 const struct crypto_session_params *csp) 233 { 234 struct ossl_cipher *cipher; 235 int error = 0; 236 237 cipher = ossl_lookup_cipher(csp); 238 if (cipher == NULL) 239 return (EINVAL); 240 241 s->cipher.cipher = cipher; 242 243 if (csp->csp_cipher_key == NULL) 244 return (0); 245 246 fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX); 247 if (cipher->set_encrypt_key != NULL) { 248 error = cipher->set_encrypt_key(csp->csp_cipher_key, 249 8 * csp->csp_cipher_klen, &s->cipher.enc_ctx); 250 if (error != 0) { 251 fpu_kern_leave(curthread, NULL); 252 return (error); 253 } 254 } 255 if (cipher->set_decrypt_key != NULL) 256 error = cipher->set_decrypt_key(csp->csp_cipher_key, 257 8 * csp->csp_cipher_klen, &s->cipher.dec_ctx); 258 fpu_kern_leave(curthread, NULL); 259 260 return (error); 261 } 262 263 static int 264 ossl_newsession(device_t dev, crypto_session_t cses, 265 const struct crypto_session_params *csp) 266 { 267 struct ossl_session *s; 268 int error = 0; 269 270 s = crypto_get_driver_session(cses); 271 switch (csp->csp_mode) { 272 case CSP_MODE_DIGEST: 273 ossl_newsession_hash(s, csp); 274 break; 275 case CSP_MODE_CIPHER: 276 error = ossl_newsession_cipher(s, csp); 277 break; 278 case CSP_MODE_ETA: 279 ossl_newsession_hash(s, csp); 280 error = ossl_newsession_cipher(s, csp); 281 break; 282 } 283 284 return (error); 285 } 286 287 static int 288 ossl_process_hash(struct ossl_session *s, struct cryptop *crp, 289 const struct crypto_session_params *csp) 290 { 291 struct ossl_hash_context ctx; 292 char digest[HASH_MAX_LEN]; 293 struct auth_hash *axf; 294 int error; 295 296 axf = s->hash.axf; 297 298 if (crp->crp_auth_key == NULL) { 299 ctx = s->hash.ictx; 300 } else { 301 if (axf->Setkey != NULL) { 302 axf->Init(&ctx); 303 axf->Setkey(&ctx, crp->crp_auth_key, 304 csp->csp_auth_klen); 305 } else { 306 hmac_init_ipad(axf, crp->crp_auth_key, 307 csp->csp_auth_klen, &ctx); 308 } 309 } 310 311 if (crp->crp_aad != NULL) 312 error = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length); 313 else 314 error = crypto_apply(crp, crp->crp_aad_start, 315 crp->crp_aad_length, axf->Update, &ctx); 316 if (error) 317 goto out; 318 319 error = crypto_apply(crp, crp->crp_payload_start, 320 crp->crp_payload_length, axf->Update, &ctx); 321 if (error) 322 goto out; 323 324 axf->Final(digest, &ctx); 325 326 if (csp->csp_auth_klen != 0 && axf->Setkey == NULL) { 327 if (crp->crp_auth_key == NULL) 328 ctx = s->hash.octx; 329 else 330 hmac_init_opad(axf, crp->crp_auth_key, 331 csp->csp_auth_klen, &ctx); 332 axf->Update(&ctx, digest, axf->hashsize); 333 axf->Final(digest, &ctx); 334 } 335 336 if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { 337 char digest2[HASH_MAX_LEN]; 338 339 crypto_copydata(crp, crp->crp_digest_start, s->hash.mlen, 340 digest2); 341 if (timingsafe_bcmp(digest, digest2, s->hash.mlen) != 0) 342 error = EBADMSG; 343 explicit_bzero(digest2, sizeof(digest2)); 344 } else { 345 crypto_copyback(crp, crp->crp_digest_start, s->hash.mlen, 346 digest); 347 } 348 explicit_bzero(digest, sizeof(digest)); 349 350 out: 351 explicit_bzero(&ctx, sizeof(ctx)); 352 return (error); 353 } 354 355 static int 356 ossl_process_eta(struct ossl_session *s, struct cryptop *crp, 357 const struct crypto_session_params *csp) 358 { 359 int error; 360 361 if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 362 error = s->cipher.cipher->process(&s->cipher, crp, csp); 363 if (error == 0) 364 error = ossl_process_hash(s, crp, csp); 365 } else { 366 error = ossl_process_hash(s, crp, csp); 367 if (error == 0) 368 error = s->cipher.cipher->process(&s->cipher, crp, csp); 369 } 370 371 return (error); 372 } 373 374 static int 375 ossl_process(device_t dev, struct cryptop *crp, int hint) 376 { 377 const struct crypto_session_params *csp; 378 struct ossl_session *s; 379 int error; 380 bool fpu_entered; 381 382 s = crypto_get_driver_session(crp->crp_session); 383 csp = crypto_get_params(crp->crp_session); 384 385 if (is_fpu_kern_thread(0)) { 386 fpu_entered = false; 387 } else { 388 fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX); 389 fpu_entered = true; 390 } 391 392 switch (csp->csp_mode) { 393 case CSP_MODE_DIGEST: 394 error = ossl_process_hash(s, crp, csp); 395 break; 396 case CSP_MODE_CIPHER: 397 error = s->cipher.cipher->process(&s->cipher, crp, csp); 398 break; 399 case CSP_MODE_ETA: 400 error = ossl_process_eta(s, crp, csp); 401 break; 402 case CSP_MODE_AEAD: 403 if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) 404 error = ossl_chacha20_poly1305_encrypt(crp, csp); 405 else 406 error = ossl_chacha20_poly1305_decrypt(crp, csp); 407 break; 408 default: 409 __assert_unreachable(); 410 } 411 412 if (fpu_entered) 413 fpu_kern_leave(curthread, NULL); 414 415 crp->crp_etype = error; 416 crypto_done(crp); 417 418 return (0); 419 } 420 421 static device_method_t ossl_methods[] = { 422 DEVMETHOD(device_identify, ossl_identify), 423 DEVMETHOD(device_probe, ossl_probe), 424 DEVMETHOD(device_attach, ossl_attach), 425 DEVMETHOD(device_detach, ossl_detach), 426 427 DEVMETHOD(cryptodev_probesession, ossl_probesession), 428 DEVMETHOD(cryptodev_newsession, ossl_newsession), 429 DEVMETHOD(cryptodev_process, ossl_process), 430 431 DEVMETHOD_END 432 }; 433 434 static driver_t ossl_driver = { 435 "ossl", 436 ossl_methods, 437 sizeof(struct ossl_softc) 438 }; 439 440 DRIVER_MODULE(ossl, nexus, ossl_driver, NULL, NULL); 441 MODULE_VERSION(ossl, 1); 442 MODULE_DEPEND(ossl, crypto, 1, 1, 1); 443