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/mips/cavium/cryptocteon/cryptocteon.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  * Octeon Crypto for OCF
    3  *
    4  * Written by David McCullough <david_mccullough@securecomputing.com>
    5  * Copyright (C) 2009 David McCullough
    6  *
    7  * LICENSE TERMS
    8  *
    9  * The free distribution and use of this software in both source and binary
   10  * form is allowed (with or without changes) provided that:
   11  *
   12  *   1. distributions of this source code include the above copyright
   13  *      notice, this list of conditions and the following disclaimer;
   14  *
   15  *   2. distributions in binary form include the above copyright
   16  *      notice, this list of conditions and the following disclaimer
   17  *      in the documentation and/or other associated materials;
   18  *
   19  *   3. the copyright holder's name is not used to endorse products
   20  *      built using this software without specific written permission.
   21  *
   22  * DISCLAIMER
   23  *
   24  * This software is provided 'as is' with no explicit or implied warranties
   25  * in respect of its properties, including, but not limited to, correctness
   26  * and/or fitness for purpose.
   27  * ---------------------------------------------------------------------------
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/bus.h>
   36 #include <sys/kernel.h>
   37 #include <sys/module.h>
   38 #include <sys/malloc.h>
   39 #include <sys/mbuf.h>
   40 #include <sys/uio.h>
   41 
   42 #include <opencrypto/cryptodev.h>
   43 
   44 #include <contrib/octeon-sdk/cvmx.h>
   45 
   46 #include <mips/cavium/cryptocteon/cryptocteonvar.h>
   47 
   48 #include "cryptodev_if.h"
   49 
   50 struct cryptocteon_softc {
   51         int32_t                 sc_cid;         /* opencrypto id */
   52 };
   53 
   54 int cryptocteon_debug = 0;
   55 TUNABLE_INT("hw.cryptocteon.debug", &cryptocteon_debug);
   56 
   57 static void cryptocteon_identify(driver_t *, device_t);
   58 static int cryptocteon_probe(device_t);
   59 static int cryptocteon_attach(device_t);
   60 
   61 static int cryptocteon_process(device_t, struct cryptop *, int);
   62 static int cryptocteon_probesession(device_t,
   63     const struct crypto_session_params *);
   64 static int cryptocteon_newsession(device_t, crypto_session_t,
   65     const struct crypto_session_params *);
   66 
   67 static void
   68 cryptocteon_identify(driver_t *drv, device_t parent)
   69 {
   70         if (octeon_has_feature(OCTEON_FEATURE_CRYPTO))
   71                 BUS_ADD_CHILD(parent, 0, "cryptocteon", 0);
   72 }
   73 
   74 static int
   75 cryptocteon_probe(device_t dev)
   76 {
   77         device_set_desc(dev, "Octeon Secure Coprocessor");
   78         return (0);
   79 }
   80 
   81 static int
   82 cryptocteon_attach(device_t dev)
   83 {
   84         struct cryptocteon_softc *sc;
   85 
   86         sc = device_get_softc(dev);
   87 
   88         sc->sc_cid = crypto_get_driverid(dev, sizeof(struct octo_sess),
   89             CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC |
   90             CRYPTOCAP_F_ACCEL_SOFTWARE);
   91         if (sc->sc_cid < 0) {
   92                 device_printf(dev, "crypto_get_driverid ret %d\n", sc->sc_cid);
   93                 return (ENXIO);
   94         }
   95 
   96         return (0);
   97 }
   98 
   99 static bool
  100 cryptocteon_auth_supported(const struct crypto_session_params *csp)
  101 {
  102         u_int hash_len;
  103 
  104         switch (csp->csp_auth_alg) {
  105         case CRYPTO_SHA1_HMAC:
  106                 hash_len = SHA1_HASH_LEN;
  107                 break;
  108         default:
  109                 return (false);
  110         }
  111 
  112         if (csp->csp_auth_klen > hash_len)
  113                 return (false);
  114         return (true);
  115 }
  116 
  117 static bool
  118 cryptocteon_cipher_supported(const struct crypto_session_params *csp)
  119 {
  120 
  121         switch (csp->csp_cipher_alg) {
  122         case CRYPTO_AES_CBC:
  123                 if (csp->csp_ivlen != 16)
  124                         return (false);
  125                 if (csp->csp_cipher_klen != 16 &&
  126                     csp->csp_cipher_klen != 24 &&
  127                     csp->csp_cipher_klen != 32)
  128                         return (false);
  129                 break;
  130         default:
  131                 return (false);
  132         }
  133 
  134         return (true);
  135 }
  136 
  137 static int
  138 cryptocteon_probesession(device_t dev, const struct crypto_session_params *csp)
  139 {
  140 
  141         if (csp->csp_flags != 0)
  142                 return (EINVAL);
  143         switch (csp->csp_mode) {
  144         case CSP_MODE_DIGEST:
  145                 if (!cryptocteon_auth_supported(csp))
  146                         return (EINVAL);
  147                 break;
  148         case CSP_MODE_CIPHER:
  149                 if (!cryptocteon_cipher_supported(csp))
  150                         return (EINVAL);
  151                 break;
  152         case CSP_MODE_ETA:
  153                 if (!cryptocteon_auth_supported(csp) ||
  154                     !cryptocteon_cipher_supported(csp))
  155                         return (EINVAL);
  156                 break;
  157         default:
  158                 return (EINVAL);
  159         }
  160         return (CRYPTODEV_PROBE_ACCEL_SOFTWARE);
  161 }
  162 
  163 static void
  164 cryptocteon_calc_hash(const struct crypto_session_params *csp, const char *key,
  165     struct octo_sess *ocd)
  166 {
  167         char hash_key[SHA1_HASH_LEN];
  168 
  169         memset(hash_key, 0, sizeof(hash_key));
  170         memcpy(hash_key, key, csp->csp_auth_klen);
  171         octo_calc_hash(csp->csp_auth_alg == CRYPTO_SHA1_HMAC, hash_key,
  172             ocd->octo_hminner, ocd->octo_hmouter);
  173 }
  174 
  175 /* Generate a new octo session. */
  176 static int
  177 cryptocteon_newsession(device_t dev, crypto_session_t cses,
  178     const struct crypto_session_params *csp)
  179 {
  180         struct cryptocteon_softc *sc;
  181         struct octo_sess *ocd;
  182 
  183         sc = device_get_softc(dev);
  184 
  185         ocd = crypto_get_driver_session(cses);
  186 
  187         ocd->octo_encklen = csp->csp_cipher_klen;
  188         if (csp->csp_cipher_key != NULL)
  189                 memcpy(ocd->octo_enckey, csp->csp_cipher_key,
  190                     ocd->octo_encklen);
  191 
  192         if (csp->csp_auth_key != NULL)
  193                 cryptocteon_calc_hash(csp, csp->csp_auth_key, ocd);
  194 
  195         ocd->octo_mlen = csp->csp_auth_mlen;
  196         if (csp->csp_auth_mlen == 0) {
  197                 switch (csp->csp_auth_alg) {
  198                 case CRYPTO_SHA1_HMAC:
  199                         ocd->octo_mlen = SHA1_HASH_LEN;
  200                         break;
  201                 }
  202         }
  203 
  204         switch (csp->csp_mode) {
  205         case CSP_MODE_DIGEST:
  206                 switch (csp->csp_auth_alg) {
  207                 case CRYPTO_SHA1_HMAC:
  208                         ocd->octo_encrypt = octo_null_sha1_encrypt;
  209                         ocd->octo_decrypt = octo_null_sha1_encrypt;
  210                         break;
  211                 }
  212                 break;
  213         case CSP_MODE_CIPHER:
  214                 switch (csp->csp_cipher_alg) {
  215                 case CRYPTO_AES_CBC:
  216                         ocd->octo_encrypt = octo_aes_cbc_encrypt;
  217                         ocd->octo_decrypt = octo_aes_cbc_decrypt;
  218                         break;
  219                 }
  220                 break;
  221         case CSP_MODE_ETA:
  222                 switch (csp->csp_cipher_alg) {
  223                 case CRYPTO_AES_CBC:
  224                         switch (csp->csp_auth_alg) {
  225                         case CRYPTO_SHA1_HMAC:
  226                                 ocd->octo_encrypt = octo_aes_cbc_sha1_encrypt;
  227                                 ocd->octo_decrypt = octo_aes_cbc_sha1_decrypt;
  228                                 break;
  229                         }
  230                         break;
  231                 }
  232                 break;
  233         }
  234 
  235         KASSERT(ocd->octo_encrypt != NULL && ocd->octo_decrypt != NULL,
  236             ("%s: missing function pointers", __func__));
  237 
  238         return (0);
  239 }
  240 
  241 /*
  242  * Process a request.
  243  */
  244 static int
  245 cryptocteon_process(device_t dev, struct cryptop *crp, int hint)
  246 {
  247         const struct crypto_session_params *csp;
  248         struct octo_sess *od;
  249         size_t iovcnt, iovlen;
  250         struct mbuf *m = NULL;
  251         struct uio *uiop = NULL;
  252         unsigned char *ivp = NULL;
  253         unsigned char iv_data[16];
  254         unsigned char icv[SHA1_HASH_LEN], icv2[SHA1_HASH_LEN];
  255         int auth_off, auth_len, crypt_off, crypt_len;
  256         struct cryptocteon_softc *sc;
  257 
  258         sc = device_get_softc(dev);
  259 
  260         crp->crp_etype = 0;
  261 
  262         od = crypto_get_driver_session(crp->crp_session);
  263         csp = crypto_get_params(crp->crp_session);
  264 
  265         /*
  266          * The crypto routines assume that the regions to auth and
  267          * cipher are exactly 8 byte multiples and aligned on 8
  268          * byte logical boundaries within the iovecs.
  269          */
  270         if (crp->crp_aad_length % 8 != 0 || crp->crp_payload_length % 8 != 0) {
  271                 crp->crp_etype = EFBIG;
  272                 goto done;
  273         }
  274 
  275         /*
  276          * As currently written, the crypto routines assume the AAD and
  277          * payload are adjacent.
  278          */
  279         if (crp->crp_aad_length != 0 && crp->crp_payload_start !=
  280             crp->crp_aad_start + crp->crp_aad_length) {
  281                 crp->crp_etype = EFBIG;
  282                 goto done;
  283         }
  284 
  285         crypt_off = crp->crp_payload_start;
  286         crypt_len = crp->crp_payload_length;
  287         if (crp->crp_aad_length != 0) {
  288                 auth_off = crp->crp_aad_start;
  289                 auth_len = crp->crp_aad_length + crp->crp_payload_length;
  290         } else {
  291                 auth_off = crypt_off;
  292                 auth_len = crypt_len;
  293         }
  294 
  295         /*
  296          * do some error checking outside of the loop for m and IOV processing
  297          * this leaves us with valid m or uiop pointers for later
  298          */
  299         switch (crp->crp_buf.cb_type) {
  300         case CRYPTO_BUF_MBUF:
  301         {
  302                 unsigned frags;
  303 
  304                 m = crp->crp_buf.cb_mbuf;
  305                 for (frags = 0; m != NULL; frags++)
  306                         m = m->m_next;
  307 
  308                 if (frags >= UIO_MAXIOV) {
  309                         printf("%s,%d: %d frags > UIO_MAXIOV", __FILE__, __LINE__, frags);
  310                         crp->crp_etype = EFBIG;
  311                         goto done;
  312                 }
  313 
  314                 m = crp->crp_buf.cb_mbuf;
  315                 break;
  316         }
  317         case CRYPTO_BUF_UIO:
  318                 uiop = crp->crp_buf.cb_uio;
  319                 if (uiop->uio_iovcnt > UIO_MAXIOV) {
  320                         printf("%s,%d: %d uio_iovcnt > UIO_MAXIOV", __FILE__, __LINE__,
  321                                uiop->uio_iovcnt);
  322                         crp->crp_etype = EFBIG;
  323                         goto done;
  324                 }
  325                 break;
  326         default:
  327                 break;
  328         }
  329 
  330         if (csp->csp_cipher_alg != 0) {
  331                 if (crp->crp_flags & CRYPTO_F_IV_SEPARATE)
  332                         ivp = crp->crp_iv;
  333                 else {
  334                         crypto_copydata(crp, crp->crp_iv_start, csp->csp_ivlen,
  335                             iv_data);
  336                         ivp = iv_data;
  337                 }
  338         }
  339 
  340         /*
  341          * setup the I/O vector to cover the buffer
  342          */
  343         switch (crp->crp_buf.cb_type) {
  344         case CRYPTO_BUF_MBUF:
  345                 iovcnt = 0;
  346                 iovlen = 0;
  347 
  348                 while (m != NULL) {
  349                         od->octo_iov[iovcnt].iov_base = mtod(m, void *);
  350                         od->octo_iov[iovcnt].iov_len = m->m_len;
  351 
  352                         m = m->m_next;
  353                         iovlen += od->octo_iov[iovcnt++].iov_len;
  354                 }
  355                 break;
  356         case CRYPTO_BUF_UIO:
  357                 iovlen = 0;
  358                 for (iovcnt = 0; iovcnt < uiop->uio_iovcnt; iovcnt++) {
  359                         od->octo_iov[iovcnt].iov_base = uiop->uio_iov[iovcnt].iov_base;
  360                         od->octo_iov[iovcnt].iov_len = uiop->uio_iov[iovcnt].iov_len;
  361 
  362                         iovlen += od->octo_iov[iovcnt].iov_len;
  363                 }
  364                 break;
  365         case CRYPTO_BUF_CONTIG:
  366                 iovlen = crp->crp_buf.cb_buf_len;
  367                 od->octo_iov[0].iov_base = crp->crp_buf.cb_buf;
  368                 od->octo_iov[0].iov_len = crp->crp_buf.cb_buf_len;
  369                 iovcnt = 1;
  370                 break;
  371         default:
  372                 panic("can't happen");
  373         }
  374 
  375         /*
  376          * setup a new explicit key
  377          */
  378         if (crp->crp_cipher_key != NULL)
  379                 memcpy(od->octo_enckey, crp->crp_cipher_key, od->octo_encklen);
  380         if (crp->crp_auth_key != NULL)
  381                 cryptocteon_calc_hash(csp, crp->crp_auth_key, od);
  382 
  383         if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
  384                 (*od->octo_encrypt)(od, od->octo_iov, iovcnt, iovlen,
  385                     auth_off, auth_len, crypt_off, crypt_len, icv, ivp);
  386         else
  387                 (*od->octo_decrypt)(od, od->octo_iov, iovcnt, iovlen,
  388                     auth_off, auth_len, crypt_off, crypt_len, icv, ivp);
  389 
  390         if (csp->csp_auth_alg != 0) {
  391                 if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
  392                         crypto_copydata(crp, crp->crp_digest_start,
  393                             od->octo_mlen, icv2);
  394                         if (timingsafe_bcmp(icv, icv2, od->octo_mlen) != 0)
  395                                 crp->crp_etype = EBADMSG;
  396                 } else
  397                         crypto_copyback(crp, crp->crp_digest_start,
  398                             od->octo_mlen, icv);
  399         }
  400 done:
  401         crypto_done(crp);
  402         return (0);
  403 }
  404 
  405 static device_method_t cryptocteon_methods[] = {
  406         /* device methods */
  407         DEVMETHOD(device_identify,      cryptocteon_identify),
  408         DEVMETHOD(device_probe,         cryptocteon_probe),
  409         DEVMETHOD(device_attach,        cryptocteon_attach),
  410 
  411         /* crypto device methods */
  412         DEVMETHOD(cryptodev_probesession, cryptocteon_probesession),
  413         DEVMETHOD(cryptodev_newsession, cryptocteon_newsession),
  414         DEVMETHOD(cryptodev_process,    cryptocteon_process),
  415         { 0, 0 }
  416 };
  417 
  418 static driver_t cryptocteon_driver = {
  419         "cryptocteon",
  420         cryptocteon_methods,
  421         sizeof (struct cryptocteon_softc),
  422 };
  423 static devclass_t cryptocteon_devclass;
  424 DRIVER_MODULE(cryptocteon, nexus, cryptocteon_driver, cryptocteon_devclass, 0, 0);

Cache object: e74acacd0d29fac1edb77dfe488f7dd4


[ 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.