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/contrib/openzfs/module/icp/io/skein_mod.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  * CDDL HEADER START
    3  *
    4  * The contents of this file are subject to the terms of the
    5  * Common Development and Distribution License (the "License").
    6  * You may not use this file except in compliance with the License.
    7  *
    8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    9  * or http://opensource.org/licenses/CDDL-1.0.
   10  * See the License for the specific language governing permissions
   11  * and limitations under the License.
   12  *
   13  * When distributing Covered Code, include this CDDL HEADER in each
   14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   15  * If applicable, add the following below this CDDL HEADER, with the
   16  * fields enclosed by brackets "[]" replaced with your own identifying
   17  * information: Portions Copyright [yyyy] [name of copyright owner]
   18  *
   19  * CDDL HEADER END
   20  */
   21 
   22 /*
   23  * Copyright 2013 Saso Kiselkov. All rights reserved.
   24  */
   25 
   26 #include <sys/crypto/common.h>
   27 #include <sys/crypto/icp.h>
   28 #include <sys/crypto/spi.h>
   29 #include <sys/sysmacros.h>
   30 #define SKEIN_MODULE_IMPL
   31 #include <sys/skein.h>
   32 
   33 static const crypto_mech_info_t skein_mech_info_tab[] = {
   34         {CKM_SKEIN_256, SKEIN_256_MECH_INFO_TYPE,
   35             CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC},
   36         {CKM_SKEIN_256_MAC, SKEIN_256_MAC_MECH_INFO_TYPE,
   37             CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC},
   38         {CKM_SKEIN_512, SKEIN_512_MECH_INFO_TYPE,
   39             CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC},
   40         {CKM_SKEIN_512_MAC, SKEIN_512_MAC_MECH_INFO_TYPE,
   41             CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC},
   42         {CKM_SKEIN1024, SKEIN1024_MECH_INFO_TYPE,
   43             CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC},
   44         {CKM_SKEIN1024_MAC, SKEIN1024_MAC_MECH_INFO_TYPE,
   45             CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC},
   46 };
   47 
   48 static int skein_digest_init(crypto_ctx_t *, crypto_mechanism_t *);
   49 static int skein_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *);
   50 static int skein_update(crypto_ctx_t *, crypto_data_t *);
   51 static int skein_final(crypto_ctx_t *, crypto_data_t *);
   52 static int skein_digest_atomic(crypto_mechanism_t *, crypto_data_t *,
   53     crypto_data_t *);
   54 
   55 static const crypto_digest_ops_t skein_digest_ops = {
   56         .digest_init = skein_digest_init,
   57         .digest = skein_digest,
   58         .digest_update = skein_update,
   59         .digest_final = skein_final,
   60         .digest_atomic = skein_digest_atomic
   61 };
   62 
   63 static int skein_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *,
   64     crypto_spi_ctx_template_t);
   65 static int skein_mac_atomic(crypto_mechanism_t *, crypto_key_t *,
   66     crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t);
   67 
   68 static const crypto_mac_ops_t skein_mac_ops = {
   69         .mac_init = skein_mac_init,
   70         .mac = NULL,
   71         .mac_update = skein_update, /* using regular digest update is OK here */
   72         .mac_final = skein_final,   /* using regular digest final is OK here */
   73         .mac_atomic = skein_mac_atomic,
   74         .mac_verify_atomic = NULL
   75 };
   76 
   77 static int skein_create_ctx_template(crypto_mechanism_t *, crypto_key_t *,
   78     crypto_spi_ctx_template_t *, size_t *);
   79 static int skein_free_context(crypto_ctx_t *);
   80 
   81 static const crypto_ctx_ops_t skein_ctx_ops = {
   82         .create_ctx_template = skein_create_ctx_template,
   83         .free_context = skein_free_context
   84 };
   85 
   86 static const crypto_ops_t skein_crypto_ops = {
   87         &skein_digest_ops,
   88         NULL,
   89         &skein_mac_ops,
   90         &skein_ctx_ops,
   91 };
   92 
   93 static const crypto_provider_info_t skein_prov_info = {
   94         "Skein Software Provider",
   95         &skein_crypto_ops,
   96         sizeof (skein_mech_info_tab) / sizeof (crypto_mech_info_t),
   97         skein_mech_info_tab
   98 };
   99 
  100 static crypto_kcf_provider_handle_t skein_prov_handle = 0;
  101 
  102 typedef struct skein_ctx {
  103         skein_mech_type_t               sc_mech_type;
  104         size_t                          sc_digest_bitlen;
  105         /*LINTED(E_ANONYMOUS_UNION_DECL)*/
  106         union {
  107                 Skein_256_Ctxt_t        sc_256;
  108                 Skein_512_Ctxt_t        sc_512;
  109                 Skein1024_Ctxt_t        sc_1024;
  110         };
  111 } skein_ctx_t;
  112 #define SKEIN_CTX(_ctx_)        ((skein_ctx_t *)((_ctx_)->cc_provider_private))
  113 #define SKEIN_CTX_LVALUE(_ctx_) (_ctx_)->cc_provider_private
  114 #define SKEIN_OP(_skein_ctx, _op, ...)                                  \
  115         do {                                                            \
  116                 skein_ctx_t     *sc = (_skein_ctx);                     \
  117                 switch (sc->sc_mech_type) {                             \
  118                 case SKEIN_256_MECH_INFO_TYPE:                          \
  119                 case SKEIN_256_MAC_MECH_INFO_TYPE:                      \
  120                         (void) Skein_256_ ## _op(&sc->sc_256, __VA_ARGS__);\
  121                         break;                                          \
  122                 case SKEIN_512_MECH_INFO_TYPE:                          \
  123                 case SKEIN_512_MAC_MECH_INFO_TYPE:                      \
  124                         (void) Skein_512_ ## _op(&sc->sc_512, __VA_ARGS__);\
  125                         break;                                          \
  126                 case SKEIN1024_MECH_INFO_TYPE:                          \
  127                 case SKEIN1024_MAC_MECH_INFO_TYPE:                      \
  128                         (void) Skein1024_ ## _op(&sc->sc_1024, __VA_ARGS__);\
  129                         break;                                          \
  130                 }                                                       \
  131         } while (0)
  132 
  133 static int
  134 skein_get_digest_bitlen(const crypto_mechanism_t *mechanism, size_t *result)
  135 {
  136         if (mechanism->cm_param != NULL) {
  137                 /*LINTED(E_BAD_PTR_CAST_ALIGN)*/
  138                 skein_param_t   *param = (skein_param_t *)mechanism->cm_param;
  139 
  140                 if (mechanism->cm_param_len != sizeof (*param) ||
  141                     param->sp_digest_bitlen == 0) {
  142                         return (CRYPTO_MECHANISM_PARAM_INVALID);
  143                 }
  144                 *result = param->sp_digest_bitlen;
  145         } else {
  146                 switch (mechanism->cm_type) {
  147                 case SKEIN_256_MECH_INFO_TYPE:
  148                         *result = 256;
  149                         break;
  150                 case SKEIN_512_MECH_INFO_TYPE:
  151                         *result = 512;
  152                         break;
  153                 case SKEIN1024_MECH_INFO_TYPE:
  154                         *result = 1024;
  155                         break;
  156                 default:
  157                         return (CRYPTO_MECHANISM_INVALID);
  158                 }
  159         }
  160         return (CRYPTO_SUCCESS);
  161 }
  162 
  163 int
  164 skein_mod_init(void)
  165 {
  166         /*
  167          * Try to register with KCF - failure shouldn't unload us, since we
  168          * still may want to continue providing misc/skein functionality.
  169          */
  170         (void) crypto_register_provider(&skein_prov_info, &skein_prov_handle);
  171 
  172         return (0);
  173 }
  174 
  175 int
  176 skein_mod_fini(void)
  177 {
  178         int ret = 0;
  179 
  180         if (skein_prov_handle != 0) {
  181                 if ((ret = crypto_unregister_provider(skein_prov_handle)) !=
  182                     CRYPTO_SUCCESS) {
  183                         cmn_err(CE_WARN,
  184                             "skein _fini: crypto_unregister_provider() "
  185                             "failed (0x%x)", ret);
  186                         return (EBUSY);
  187                 }
  188                 skein_prov_handle = 0;
  189         }
  190 
  191         return (0);
  192 }
  193 
  194 /*
  195  * General Skein hashing helper functions.
  196  */
  197 
  198 /*
  199  * Performs an Update on a context with uio input data.
  200  */
  201 static int
  202 skein_digest_update_uio(skein_ctx_t *ctx, const crypto_data_t *data)
  203 {
  204         off_t           offset = data->cd_offset;
  205         size_t          length = data->cd_length;
  206         uint_t          vec_idx = 0;
  207         size_t          cur_len;
  208         zfs_uio_t       *uio = data->cd_uio;
  209 
  210         /* we support only kernel buffer */
  211         if (zfs_uio_segflg(uio) != UIO_SYSSPACE)
  212                 return (CRYPTO_ARGUMENTS_BAD);
  213 
  214         /*
  215          * Jump to the first iovec containing data to be
  216          * digested.
  217          */
  218         offset = zfs_uio_index_at_offset(uio, offset, &vec_idx);
  219         if (vec_idx == zfs_uio_iovcnt(uio)) {
  220                 /*
  221                  * The caller specified an offset that is larger than the
  222                  * total size of the buffers it provided.
  223                  */
  224                 return (CRYPTO_DATA_LEN_RANGE);
  225         }
  226 
  227         /*
  228          * Now do the digesting on the iovecs.
  229          */
  230         while (vec_idx < zfs_uio_iovcnt(uio) && length > 0) {
  231                 cur_len = MIN(zfs_uio_iovlen(uio, vec_idx) - offset, length);
  232                 SKEIN_OP(ctx, Update, (uint8_t *)zfs_uio_iovbase(uio, vec_idx)
  233                     + offset, cur_len);
  234                 length -= cur_len;
  235                 vec_idx++;
  236                 offset = 0;
  237         }
  238 
  239         if (vec_idx == zfs_uio_iovcnt(uio) && length > 0) {
  240                 /*
  241                  * The end of the specified iovec's was reached but
  242                  * the length requested could not be processed, i.e.
  243                  * The caller requested to digest more data than it provided.
  244                  */
  245                 return (CRYPTO_DATA_LEN_RANGE);
  246         }
  247 
  248         return (CRYPTO_SUCCESS);
  249 }
  250 
  251 /*
  252  * Performs a Final on a context and writes to a uio digest output.
  253  */
  254 static int
  255 skein_digest_final_uio(skein_ctx_t *ctx, crypto_data_t *digest)
  256 {
  257         off_t offset = digest->cd_offset;
  258         uint_t vec_idx = 0;
  259         zfs_uio_t *uio = digest->cd_uio;
  260 
  261         /* we support only kernel buffer */
  262         if (zfs_uio_segflg(uio) != UIO_SYSSPACE)
  263                 return (CRYPTO_ARGUMENTS_BAD);
  264 
  265         /*
  266          * Jump to the first iovec containing ptr to the digest to be returned.
  267          */
  268         offset = zfs_uio_index_at_offset(uio, offset, &vec_idx);
  269         if (vec_idx == zfs_uio_iovcnt(uio)) {
  270                 /*
  271                  * The caller specified an offset that is larger than the
  272                  * total size of the buffers it provided.
  273                  */
  274                 return (CRYPTO_DATA_LEN_RANGE);
  275         }
  276         if (offset + CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen) <=
  277             zfs_uio_iovlen(uio, vec_idx)) {
  278                 /* The computed digest will fit in the current iovec. */
  279                 SKEIN_OP(ctx, Final,
  280                     (uchar_t *)zfs_uio_iovbase(uio, vec_idx) + offset);
  281         } else {
  282                 uint8_t *digest_tmp;
  283                 off_t scratch_offset = 0;
  284                 size_t length = CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen);
  285                 size_t cur_len;
  286 
  287                 digest_tmp = kmem_alloc(CRYPTO_BITS2BYTES(
  288                     ctx->sc_digest_bitlen), KM_SLEEP);
  289                 if (digest_tmp == NULL)
  290                         return (CRYPTO_HOST_MEMORY);
  291                 SKEIN_OP(ctx, Final, digest_tmp);
  292                 while (vec_idx < zfs_uio_iovcnt(uio) && length > 0) {
  293                         cur_len = MIN(zfs_uio_iovlen(uio, vec_idx) - offset,
  294                             length);
  295                         memcpy(zfs_uio_iovbase(uio, vec_idx) + offset,
  296                             digest_tmp + scratch_offset, cur_len);
  297 
  298                         length -= cur_len;
  299                         vec_idx++;
  300                         scratch_offset += cur_len;
  301                         offset = 0;
  302                 }
  303                 kmem_free(digest_tmp, CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen));
  304 
  305                 if (vec_idx == zfs_uio_iovcnt(uio) && length > 0) {
  306                         /*
  307                          * The end of the specified iovec's was reached but
  308                          * the length requested could not be processed, i.e.
  309                          * The caller requested to digest more data than it
  310                          * provided.
  311                          */
  312                         return (CRYPTO_DATA_LEN_RANGE);
  313                 }
  314         }
  315 
  316         return (CRYPTO_SUCCESS);
  317 }
  318 
  319 /*
  320  * KCF software provider digest entry points.
  321  */
  322 
  323 /*
  324  * Initializes a skein digest context to the configuration in `mechanism'.
  325  * The mechanism cm_type must be one of SKEIN_*_MECH_INFO_TYPE. The cm_param
  326  * field may contain a skein_param_t structure indicating the length of the
  327  * digest the algorithm should produce. Otherwise the default output lengths
  328  * are applied (32 bytes for Skein-256, 64 bytes for Skein-512 and 128 bytes
  329  * for Skein-1024).
  330  */
  331 static int
  332 skein_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism)
  333 {
  334         int     error = CRYPTO_SUCCESS;
  335 
  336         if (!VALID_SKEIN_DIGEST_MECH(mechanism->cm_type))
  337                 return (CRYPTO_MECHANISM_INVALID);
  338 
  339         SKEIN_CTX_LVALUE(ctx) = kmem_alloc(sizeof (*SKEIN_CTX(ctx)), KM_SLEEP);
  340         if (SKEIN_CTX(ctx) == NULL)
  341                 return (CRYPTO_HOST_MEMORY);
  342 
  343         SKEIN_CTX(ctx)->sc_mech_type = mechanism->cm_type;
  344         error = skein_get_digest_bitlen(mechanism,
  345             &SKEIN_CTX(ctx)->sc_digest_bitlen);
  346         if (error != CRYPTO_SUCCESS)
  347                 goto errout;
  348         SKEIN_OP(SKEIN_CTX(ctx), Init, SKEIN_CTX(ctx)->sc_digest_bitlen);
  349 
  350         return (CRYPTO_SUCCESS);
  351 errout:
  352         memset(SKEIN_CTX(ctx), 0, sizeof (*SKEIN_CTX(ctx)));
  353         kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx)));
  354         SKEIN_CTX_LVALUE(ctx) = NULL;
  355         return (error);
  356 }
  357 
  358 /*
  359  * Executes a skein_update and skein_digest on a pre-initialized crypto
  360  * context in a single step. See the documentation to these functions to
  361  * see what to pass here.
  362  */
  363 static int
  364 skein_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest)
  365 {
  366         int error = CRYPTO_SUCCESS;
  367 
  368         ASSERT(SKEIN_CTX(ctx) != NULL);
  369 
  370         if (digest->cd_length <
  371             CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen)) {
  372                 digest->cd_length =
  373                     CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen);
  374                 return (CRYPTO_BUFFER_TOO_SMALL);
  375         }
  376 
  377         error = skein_update(ctx, data);
  378         if (error != CRYPTO_SUCCESS) {
  379                 memset(SKEIN_CTX(ctx), 0, sizeof (*SKEIN_CTX(ctx)));
  380                 kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx)));
  381                 SKEIN_CTX_LVALUE(ctx) = NULL;
  382                 digest->cd_length = 0;
  383                 return (error);
  384         }
  385         error = skein_final(ctx, digest);
  386 
  387         return (error);
  388 }
  389 
  390 /*
  391  * Performs a skein Update with the input message in `data' (successive calls
  392  * can push more data). This is used both for digest and MAC operation.
  393  * Supported input data formats are raw, uio and mblk.
  394  */
  395 static int
  396 skein_update(crypto_ctx_t *ctx, crypto_data_t *data)
  397 {
  398         int error = CRYPTO_SUCCESS;
  399 
  400         ASSERT(SKEIN_CTX(ctx) != NULL);
  401 
  402         switch (data->cd_format) {
  403         case CRYPTO_DATA_RAW:
  404                 SKEIN_OP(SKEIN_CTX(ctx), Update,
  405                     (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
  406                     data->cd_length);
  407                 break;
  408         case CRYPTO_DATA_UIO:
  409                 error = skein_digest_update_uio(SKEIN_CTX(ctx), data);
  410                 break;
  411         default:
  412                 error = CRYPTO_ARGUMENTS_BAD;
  413         }
  414 
  415         return (error);
  416 }
  417 
  418 /*
  419  * Performs a skein Final, writing the output to `digest'. This is used both
  420  * for digest and MAC operation.
  421  * Supported output digest formats are raw, uio and mblk.
  422  */
  423 static int
  424 skein_final_nofree(crypto_ctx_t *ctx, crypto_data_t *digest)
  425 {
  426         int error = CRYPTO_SUCCESS;
  427 
  428         ASSERT(SKEIN_CTX(ctx) != NULL);
  429 
  430         if (digest->cd_length <
  431             CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen)) {
  432                 digest->cd_length =
  433                     CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen);
  434                 return (CRYPTO_BUFFER_TOO_SMALL);
  435         }
  436 
  437         switch (digest->cd_format) {
  438         case CRYPTO_DATA_RAW:
  439                 SKEIN_OP(SKEIN_CTX(ctx), Final,
  440                     (uint8_t *)digest->cd_raw.iov_base + digest->cd_offset);
  441                 break;
  442         case CRYPTO_DATA_UIO:
  443                 error = skein_digest_final_uio(SKEIN_CTX(ctx), digest);
  444                 break;
  445         default:
  446                 error = CRYPTO_ARGUMENTS_BAD;
  447         }
  448 
  449         if (error == CRYPTO_SUCCESS)
  450                 digest->cd_length =
  451                     CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen);
  452         else
  453                 digest->cd_length = 0;
  454 
  455         return (error);
  456 }
  457 
  458 static int
  459 skein_final(crypto_ctx_t *ctx, crypto_data_t *digest)
  460 {
  461         int error = skein_final_nofree(ctx, digest);
  462 
  463         if (error == CRYPTO_BUFFER_TOO_SMALL)
  464                 return (error);
  465 
  466         memset(SKEIN_CTX(ctx), 0, sizeof (*SKEIN_CTX(ctx)));
  467         kmem_free(SKEIN_CTX(ctx), sizeof (*(SKEIN_CTX(ctx))));
  468         SKEIN_CTX_LVALUE(ctx) = NULL;
  469 
  470         return (error);
  471 }
  472 
  473 /*
  474  * Performs a full skein digest computation in a single call, configuring the
  475  * algorithm according to `mechanism', reading the input to be digested from
  476  * `data' and writing the output to `digest'.
  477  * Supported input/output formats are raw, uio and mblk.
  478  */
  479 static int
  480 skein_digest_atomic(crypto_mechanism_t *mechanism, crypto_data_t *data,
  481     crypto_data_t *digest)
  482 {
  483         int      error;
  484         skein_ctx_t skein_ctx;
  485         crypto_ctx_t ctx;
  486         SKEIN_CTX_LVALUE(&ctx) = &skein_ctx;
  487 
  488         /* Init */
  489         if (!VALID_SKEIN_DIGEST_MECH(mechanism->cm_type))
  490                 return (CRYPTO_MECHANISM_INVALID);
  491         skein_ctx.sc_mech_type = mechanism->cm_type;
  492         error = skein_get_digest_bitlen(mechanism, &skein_ctx.sc_digest_bitlen);
  493         if (error != CRYPTO_SUCCESS)
  494                 goto out;
  495         SKEIN_OP(&skein_ctx, Init, skein_ctx.sc_digest_bitlen);
  496 
  497         if ((error = skein_update(&ctx, data)) != CRYPTO_SUCCESS)
  498                 goto out;
  499         if ((error = skein_final_nofree(&ctx, data)) != CRYPTO_SUCCESS)
  500                 goto out;
  501 
  502 out:
  503         if (error == CRYPTO_SUCCESS)
  504                 digest->cd_length =
  505                     CRYPTO_BITS2BYTES(skein_ctx.sc_digest_bitlen);
  506         else
  507                 digest->cd_length = 0;
  508         memset(&skein_ctx, 0, sizeof (skein_ctx));
  509 
  510         return (error);
  511 }
  512 
  513 /*
  514  * Helper function that builds a Skein MAC context from the provided
  515  * mechanism and key.
  516  */
  517 static int
  518 skein_mac_ctx_build(skein_ctx_t *ctx, crypto_mechanism_t *mechanism,
  519     crypto_key_t *key)
  520 {
  521         int error;
  522 
  523         if (!VALID_SKEIN_MAC_MECH(mechanism->cm_type))
  524                 return (CRYPTO_MECHANISM_INVALID);
  525         ctx->sc_mech_type = mechanism->cm_type;
  526         error = skein_get_digest_bitlen(mechanism, &ctx->sc_digest_bitlen);
  527         if (error != CRYPTO_SUCCESS)
  528                 return (error);
  529         SKEIN_OP(ctx, InitExt, ctx->sc_digest_bitlen, 0, key->ck_data,
  530             CRYPTO_BITS2BYTES(key->ck_length));
  531 
  532         return (CRYPTO_SUCCESS);
  533 }
  534 
  535 /*
  536  * KCF software provide mac entry points.
  537  */
  538 /*
  539  * Initializes a skein MAC context. You may pass a ctx_template, in which
  540  * case the template will be reused to make initialization more efficient.
  541  * Otherwise a new context will be constructed. The mechanism cm_type must
  542  * be one of SKEIN_*_MAC_MECH_INFO_TYPE. Same as in skein_digest_init, you
  543  * may pass a skein_param_t in cm_param to configure the length of the
  544  * digest. The key must be in raw format.
  545  */
  546 static int
  547 skein_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
  548     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template)
  549 {
  550         int     error;
  551 
  552         SKEIN_CTX_LVALUE(ctx) = kmem_alloc(sizeof (*SKEIN_CTX(ctx)), KM_SLEEP);
  553         if (SKEIN_CTX(ctx) == NULL)
  554                 return (CRYPTO_HOST_MEMORY);
  555 
  556         if (ctx_template != NULL) {
  557                 memcpy(SKEIN_CTX(ctx), ctx_template,
  558                     sizeof (*SKEIN_CTX(ctx)));
  559         } else {
  560                 error = skein_mac_ctx_build(SKEIN_CTX(ctx), mechanism, key);
  561                 if (error != CRYPTO_SUCCESS)
  562                         goto errout;
  563         }
  564 
  565         return (CRYPTO_SUCCESS);
  566 errout:
  567         memset(SKEIN_CTX(ctx), 0, sizeof (*SKEIN_CTX(ctx)));
  568         kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx)));
  569         return (error);
  570 }
  571 
  572 /*
  573  * The MAC update and final calls are reused from the regular digest code.
  574  */
  575 
  576 /*
  577  * Same as skein_digest_atomic, performs an atomic Skein MAC operation in
  578  * one step. All the same properties apply to the arguments of this
  579  * function as to those of the partial operations above.
  580  */
  581 static int
  582 skein_mac_atomic(crypto_mechanism_t *mechanism,
  583     crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
  584     crypto_spi_ctx_template_t ctx_template)
  585 {
  586         /* faux crypto context just for skein_digest_{update,final} */
  587         int     error;
  588         crypto_ctx_t ctx;
  589         skein_ctx_t skein_ctx;
  590         SKEIN_CTX_LVALUE(&ctx) = &skein_ctx;
  591 
  592         if (ctx_template != NULL) {
  593                 memcpy(&skein_ctx, ctx_template, sizeof (skein_ctx));
  594         } else {
  595                 error = skein_mac_ctx_build(&skein_ctx, mechanism, key);
  596                 if (error != CRYPTO_SUCCESS)
  597                         goto errout;
  598         }
  599 
  600         if ((error = skein_update(&ctx, data)) != CRYPTO_SUCCESS)
  601                 goto errout;
  602         if ((error = skein_final_nofree(&ctx, mac)) != CRYPTO_SUCCESS)
  603                 goto errout;
  604 
  605         return (CRYPTO_SUCCESS);
  606 errout:
  607         memset(&skein_ctx, 0, sizeof (skein_ctx));
  608         return (error);
  609 }
  610 
  611 /*
  612  * KCF software provider context management entry points.
  613  */
  614 
  615 /*
  616  * Constructs a context template for the Skein MAC algorithm. The same
  617  * properties apply to the arguments of this function as to those of
  618  * skein_mac_init.
  619  */
  620 static int
  621 skein_create_ctx_template(crypto_mechanism_t *mechanism, crypto_key_t *key,
  622     crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size)
  623 {
  624         int      error;
  625         skein_ctx_t *ctx_tmpl;
  626 
  627         ctx_tmpl = kmem_alloc(sizeof (*ctx_tmpl), KM_SLEEP);
  628         if (ctx_tmpl == NULL)
  629                 return (CRYPTO_HOST_MEMORY);
  630         error = skein_mac_ctx_build(ctx_tmpl, mechanism, key);
  631         if (error != CRYPTO_SUCCESS)
  632                 goto errout;
  633         *ctx_template = ctx_tmpl;
  634         *ctx_template_size = sizeof (*ctx_tmpl);
  635 
  636         return (CRYPTO_SUCCESS);
  637 errout:
  638         memset(ctx_tmpl, 0, sizeof (*ctx_tmpl));
  639         kmem_free(ctx_tmpl, sizeof (*ctx_tmpl));
  640         return (error);
  641 }
  642 
  643 /*
  644  * Frees a skein context in a parent crypto context.
  645  */
  646 static int
  647 skein_free_context(crypto_ctx_t *ctx)
  648 {
  649         if (SKEIN_CTX(ctx) != NULL) {
  650                 memset(SKEIN_CTX(ctx), 0, sizeof (*SKEIN_CTX(ctx)));
  651                 kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx)));
  652                 SKEIN_CTX_LVALUE(ctx) = NULL;
  653         }
  654 
  655         return (CRYPTO_SUCCESS);
  656 }

Cache object: 642662d17269090a8778246428e5aebb


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