The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/crypto/openssl/ossl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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);

Cache object: 423eac85269317cf872469ab08a156bb


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.