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/algs/skein/skein.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  * Implementation of the Skein hash function.
    3  * Source code author: Doug Whiting, 2008.
    4  * This algorithm and source code is released to the public domain.
    5  */
    6 /* Copyright 2013 Doug Whiting. This code is released to the public domain. */
    7 
    8 #include <sys/sysmacros.h>
    9 #include <sys/types.h>
   10 #include <sys/skein.h>          /* get the Skein API definitions   */
   11 #include "skein_impl.h"         /* get internal definitions */
   12 
   13 /* 256-bit Skein */
   14 /* init the context for a straight hashing operation  */
   15 int
   16 Skein_256_Init(Skein_256_Ctxt_t *ctx, size_t hashBitLen)
   17 {
   18         union {
   19                 uint8_t b[SKEIN_256_STATE_BYTES];
   20                 uint64_t w[SKEIN_256_STATE_WORDS];
   21         } cfg;                  /* config block */
   22 
   23         Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
   24         ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
   25 
   26         switch (hashBitLen) {   /* use pre-computed values, where available */
   27 #ifndef SKEIN_NO_PRECOMP
   28         case 256:
   29                 memcpy(ctx->X, SKEIN_256_IV_256, sizeof (ctx->X));
   30                 break;
   31         case 224:
   32                 memcpy(ctx->X, SKEIN_256_IV_224, sizeof (ctx->X));
   33                 break;
   34         case 160:
   35                 memcpy(ctx->X, SKEIN_256_IV_160, sizeof (ctx->X));
   36                 break;
   37         case 128:
   38                 memcpy(ctx->X, SKEIN_256_IV_128, sizeof (ctx->X));
   39                 break;
   40 #endif
   41         default:
   42                 /* here if there is no precomputed IV value available */
   43                 /*
   44                  * build/process the config block, type == CONFIG (could be
   45                  * precomputed)
   46                  */
   47                 /* set tweaks: T0=0; T1=CFG | FINAL */
   48                 Skein_Start_New_Type(ctx, CFG_FINAL);
   49 
   50                 /* set the schema, version */
   51                 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
   52                 /* hash result length in bits */
   53                 cfg.w[1] = Skein_Swap64(hashBitLen);
   54                 cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
   55                 /* zero pad config block */
   56                 memset(&cfg.w[3], 0, sizeof (cfg) - 3 * sizeof (cfg.w[0]));
   57 
   58                 /* compute the initial chaining values from config block */
   59                 /* zero the chaining variables */
   60                 memset(ctx->X, 0, sizeof (ctx->X));
   61                 Skein_256_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
   62                 break;
   63         }
   64         /*
   65          * The chaining vars ctx->X are now initialized for the given
   66          * hashBitLen.
   67          * Set up to process the data message portion of the hash (default)
   68          */
   69         Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
   70 
   71         return (SKEIN_SUCCESS);
   72 }
   73 
   74 /* init the context for a MAC and/or tree hash operation */
   75 /*
   76  * [identical to Skein_256_Init() when keyBytes == 0 &&
   77  * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
   78  */
   79 int
   80 Skein_256_InitExt(Skein_256_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
   81     const uint8_t *key, size_t keyBytes)
   82 {
   83         union {
   84                 uint8_t b[SKEIN_256_STATE_BYTES];
   85                 uint64_t w[SKEIN_256_STATE_WORDS];
   86         } cfg;                  /* config block */
   87 
   88         Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
   89         Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL);
   90 
   91         /* compute the initial chaining values ctx->X[], based on key */
   92         if (keyBytes == 0) {    /* is there a key? */
   93                 /* no key: use all zeroes as key for config block */
   94                 memset(ctx->X, 0, sizeof (ctx->X));
   95         } else {                /* here to pre-process a key */
   96 
   97                 Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X));
   98                 /* do a mini-Init right here */
   99                 /* set output hash bit count = state size */
  100                 ctx->h.hashBitLen = 8 * sizeof (ctx->X);
  101                 /* set tweaks: T0 = 0; T1 = KEY type */
  102                 Skein_Start_New_Type(ctx, KEY);
  103                 /* zero the initial chaining variables */
  104                 memset(ctx->X, 0, sizeof (ctx->X));
  105                 /* hash the key */
  106                 (void) Skein_256_Update(ctx, key, keyBytes);
  107                 /* put result into cfg.b[] */
  108                 (void) Skein_256_Final_Pad(ctx, cfg.b);
  109                 /* copy over into ctx->X[] */
  110                 memcpy(ctx->X, cfg.b, sizeof (cfg.b));
  111 #if     SKEIN_NEED_SWAP
  112                 {
  113                         uint_t i;
  114                         /* convert key bytes to context words */
  115                         for (i = 0; i < SKEIN_256_STATE_WORDS; i++)
  116                                 ctx->X[i] = Skein_Swap64(ctx->X[i]);
  117                 }
  118 #endif
  119         }
  120         /*
  121          * build/process the config block, type == CONFIG (could be
  122          * precomputed for each key)
  123          */
  124         ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
  125         Skein_Start_New_Type(ctx, CFG_FINAL);
  126 
  127         memset(&cfg.w, 0, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */
  128         cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
  129         cfg.w[1] = Skein_Swap64(hashBitLen);    /* hash result length in bits */
  130         /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
  131         cfg.w[2] = Skein_Swap64(treeInfo);
  132 
  133         Skein_Show_Key(256, &ctx->h, key, keyBytes);
  134 
  135         /* compute the initial chaining values from config block */
  136         Skein_256_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
  137 
  138         /* The chaining vars ctx->X are now initialized */
  139         /* Set up to process the data message portion of the hash (default) */
  140         ctx->h.bCnt = 0;        /* buffer b[] starts out empty */
  141         Skein_Start_New_Type(ctx, MSG);
  142 
  143         return (SKEIN_SUCCESS);
  144 }
  145 
  146 /* process the input bytes */
  147 int
  148 Skein_256_Update(Skein_256_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
  149 {
  150         size_t n;
  151 
  152         /* catch uninitialized context */
  153         Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
  154 
  155         /* process full blocks, if any */
  156         if (msgByteCnt + ctx->h.bCnt > SKEIN_256_BLOCK_BYTES) {
  157                 /* finish up any buffered message data */
  158                 if (ctx->h.bCnt) {
  159                         /* # bytes free in buffer b[] */
  160                         n = SKEIN_256_BLOCK_BYTES - ctx->h.bCnt;
  161                         if (n) {
  162                                 /* check on our logic here */
  163                                 Skein_assert(n < msgByteCnt);
  164                                 memcpy(&ctx->b[ctx->h.bCnt], msg, n);
  165                                 msgByteCnt -= n;
  166                                 msg += n;
  167                                 ctx->h.bCnt += n;
  168                         }
  169                         Skein_assert(ctx->h.bCnt == SKEIN_256_BLOCK_BYTES);
  170                         Skein_256_Process_Block(ctx, ctx->b, 1,
  171                             SKEIN_256_BLOCK_BYTES);
  172                         ctx->h.bCnt = 0;
  173                 }
  174                 /*
  175                  * now process any remaining full blocks, directly from input
  176                  * message data
  177                  */
  178                 if (msgByteCnt > SKEIN_256_BLOCK_BYTES) {
  179                         /* number of full blocks to process */
  180                         n = (msgByteCnt - 1) / SKEIN_256_BLOCK_BYTES;
  181                         Skein_256_Process_Block(ctx, msg, n,
  182                             SKEIN_256_BLOCK_BYTES);
  183                         msgByteCnt -= n * SKEIN_256_BLOCK_BYTES;
  184                         msg += n * SKEIN_256_BLOCK_BYTES;
  185                 }
  186                 Skein_assert(ctx->h.bCnt == 0);
  187         }
  188 
  189         /* copy any remaining source message data bytes into b[] */
  190         if (msgByteCnt) {
  191                 Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES);
  192                 memcpy(&ctx->b[ctx->h.bCnt], msg, msgByteCnt);
  193                 ctx->h.bCnt += msgByteCnt;
  194         }
  195 
  196         return (SKEIN_SUCCESS);
  197 }
  198 
  199 /* finalize the hash computation and output the result */
  200 int
  201 Skein_256_Final(Skein_256_Ctxt_t *ctx, uint8_t *hashVal)
  202 {
  203         size_t i, n, byteCnt;
  204         uint64_t X[SKEIN_256_STATE_WORDS];
  205 
  206         /* catch uninitialized context */
  207         Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
  208 
  209         ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;     /* tag as the final block */
  210         /* zero pad b[] if necessary */
  211         if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES)
  212                 memset(&ctx->b[ctx->h.bCnt], 0,
  213                     SKEIN_256_BLOCK_BYTES - ctx->h.bCnt);
  214 
  215         /* process the final block */
  216         Skein_256_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
  217 
  218         /* now output the result */
  219         /* total number of output bytes */
  220         byteCnt = (ctx->h.hashBitLen + 7) >> 3;
  221 
  222         /* run Threefish in "counter mode" to generate output */
  223         /* zero out b[], so it can hold the counter */
  224         memset(ctx->b, 0, sizeof (ctx->b));
  225         /* keep a local copy of counter mode "key" */
  226         memcpy(X, ctx->X, sizeof (X));
  227         for (i = 0; i * SKEIN_256_BLOCK_BYTES < byteCnt; i++) {
  228                 /* build the counter block */
  229                 *(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
  230                 Skein_Start_New_Type(ctx, OUT_FINAL);
  231                 /* run "counter mode" */
  232                 Skein_256_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
  233                 /* number of output bytes left to go */
  234                 n = byteCnt - i * SKEIN_256_BLOCK_BYTES;
  235                 if (n >= SKEIN_256_BLOCK_BYTES)
  236                         n = SKEIN_256_BLOCK_BYTES;
  237                 Skein_Put64_LSB_First(hashVal + i * SKEIN_256_BLOCK_BYTES,
  238                     ctx->X, n); /* "output" the ctr mode bytes */
  239                 Skein_Show_Final(256, &ctx->h, n,
  240                     hashVal + i * SKEIN_256_BLOCK_BYTES);
  241                 /* restore the counter mode key for next time */
  242                 memcpy(ctx->X, X, sizeof (X));
  243         }
  244         return (SKEIN_SUCCESS);
  245 }
  246 
  247 /* 512-bit Skein */
  248 
  249 /* init the context for a straight hashing operation  */
  250 int
  251 Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen)
  252 {
  253         union {
  254                 uint8_t b[SKEIN_512_STATE_BYTES];
  255                 uint64_t w[SKEIN_512_STATE_WORDS];
  256         } cfg;                  /* config block */
  257 
  258         Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
  259         ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
  260 
  261         switch (hashBitLen) {   /* use pre-computed values, where available */
  262 #ifndef SKEIN_NO_PRECOMP
  263         case 512:
  264                 memcpy(ctx->X, SKEIN_512_IV_512, sizeof (ctx->X));
  265                 break;
  266         case 384:
  267                 memcpy(ctx->X, SKEIN_512_IV_384, sizeof (ctx->X));
  268                 break;
  269         case 256:
  270                 memcpy(ctx->X, SKEIN_512_IV_256, sizeof (ctx->X));
  271                 break;
  272         case 224:
  273                 memcpy(ctx->X, SKEIN_512_IV_224, sizeof (ctx->X));
  274                 break;
  275 #endif
  276         default:
  277                 /*
  278                  * here if there is no precomputed IV value available
  279                  * build/process the config block, type == CONFIG (could be
  280                  * precomputed)
  281                  */
  282                 /* set tweaks: T0=0; T1=CFG | FINAL */
  283                 Skein_Start_New_Type(ctx, CFG_FINAL);
  284 
  285                 /* set the schema, version */
  286                 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
  287                 /* hash result length in bits */
  288                 cfg.w[1] = Skein_Swap64(hashBitLen);
  289                 cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
  290                 /* zero pad config block */
  291                 memset(&cfg.w[3], 0, sizeof (cfg) - 3 * sizeof (cfg.w[0]));
  292 
  293                 /* compute the initial chaining values from config block */
  294                 /* zero the chaining variables */
  295                 memset(ctx->X, 0, sizeof (ctx->X));
  296                 Skein_512_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
  297                 break;
  298         }
  299 
  300         /*
  301          * The chaining vars ctx->X are now initialized for the given
  302          * hashBitLen. Set up to process the data message portion of the
  303          * hash (default)
  304          */
  305         Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
  306 
  307         return (SKEIN_SUCCESS);
  308 }
  309 
  310 /* init the context for a MAC and/or tree hash operation */
  311 /*
  312  * [identical to Skein_512_Init() when keyBytes == 0 &&
  313  * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
  314  */
  315 int
  316 Skein_512_InitExt(Skein_512_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
  317     const uint8_t *key, size_t keyBytes)
  318 {
  319         union {
  320                 uint8_t b[SKEIN_512_STATE_BYTES];
  321                 uint64_t w[SKEIN_512_STATE_WORDS];
  322         } cfg;                  /* config block */
  323 
  324         Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
  325         Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL);
  326 
  327         /* compute the initial chaining values ctx->X[], based on key */
  328         if (keyBytes == 0) {    /* is there a key? */
  329                 /* no key: use all zeroes as key for config block */
  330                 memset(ctx->X, 0, sizeof (ctx->X));
  331         } else {                /* here to pre-process a key */
  332 
  333                 Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X));
  334                 /* do a mini-Init right here */
  335                 /* set output hash bit count = state size */
  336                 ctx->h.hashBitLen = 8 * sizeof (ctx->X);
  337                 /* set tweaks: T0 = 0; T1 = KEY type */
  338                 Skein_Start_New_Type(ctx, KEY);
  339                 /* zero the initial chaining variables */
  340                 memset(ctx->X, 0, sizeof (ctx->X));
  341                 (void) Skein_512_Update(ctx, key, keyBytes); /* hash the key */
  342                 /* put result into cfg.b[] */
  343                 (void) Skein_512_Final_Pad(ctx, cfg.b);
  344                 /* copy over into ctx->X[] */
  345                 memcpy(ctx->X, cfg.b, sizeof (cfg.b));
  346 #if     SKEIN_NEED_SWAP
  347                 {
  348                         uint_t i;
  349                         /* convert key bytes to context words */
  350                         for (i = 0; i < SKEIN_512_STATE_WORDS; i++)
  351                                 ctx->X[i] = Skein_Swap64(ctx->X[i]);
  352                 }
  353 #endif
  354         }
  355         /*
  356          * build/process the config block, type == CONFIG (could be
  357          * precomputed for each key)
  358          */
  359         ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
  360         Skein_Start_New_Type(ctx, CFG_FINAL);
  361 
  362         memset(&cfg.w, 0, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */
  363         cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
  364         cfg.w[1] = Skein_Swap64(hashBitLen);    /* hash result length in bits */
  365         /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
  366         cfg.w[2] = Skein_Swap64(treeInfo);
  367 
  368         Skein_Show_Key(512, &ctx->h, key, keyBytes);
  369 
  370         /* compute the initial chaining values from config block */
  371         Skein_512_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
  372 
  373         /* The chaining vars ctx->X are now initialized */
  374         /* Set up to process the data message portion of the hash (default) */
  375         ctx->h.bCnt = 0;        /* buffer b[] starts out empty */
  376         Skein_Start_New_Type(ctx, MSG);
  377 
  378         return (SKEIN_SUCCESS);
  379 }
  380 
  381 /* process the input bytes */
  382 int
  383 Skein_512_Update(Skein_512_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
  384 {
  385         size_t n;
  386 
  387         /* catch uninitialized context */
  388         Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
  389 
  390         /* process full blocks, if any */
  391         if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES) {
  392                 /* finish up any buffered message data */
  393                 if (ctx->h.bCnt) {
  394                         /* # bytes free in buffer b[] */
  395                         n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt;
  396                         if (n) {
  397                                 /* check on our logic here */
  398                                 Skein_assert(n < msgByteCnt);
  399                                 memcpy(&ctx->b[ctx->h.bCnt], msg, n);
  400                                 msgByteCnt -= n;
  401                                 msg += n;
  402                                 ctx->h.bCnt += n;
  403                         }
  404                         Skein_assert(ctx->h.bCnt == SKEIN_512_BLOCK_BYTES);
  405                         Skein_512_Process_Block(ctx, ctx->b, 1,
  406                             SKEIN_512_BLOCK_BYTES);
  407                         ctx->h.bCnt = 0;
  408                 }
  409                 /*
  410                  * now process any remaining full blocks, directly from input
  411                  * message data
  412                  */
  413                 if (msgByteCnt > SKEIN_512_BLOCK_BYTES) {
  414                         /* number of full blocks to process */
  415                         n = (msgByteCnt - 1) / SKEIN_512_BLOCK_BYTES;
  416                         Skein_512_Process_Block(ctx, msg, n,
  417                             SKEIN_512_BLOCK_BYTES);
  418                         msgByteCnt -= n * SKEIN_512_BLOCK_BYTES;
  419                         msg += n * SKEIN_512_BLOCK_BYTES;
  420                 }
  421                 Skein_assert(ctx->h.bCnt == 0);
  422         }
  423 
  424         /* copy any remaining source message data bytes into b[] */
  425         if (msgByteCnt) {
  426                 Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES);
  427                 memcpy(&ctx->b[ctx->h.bCnt], msg, msgByteCnt);
  428                 ctx->h.bCnt += msgByteCnt;
  429         }
  430 
  431         return (SKEIN_SUCCESS);
  432 }
  433 
  434 /* finalize the hash computation and output the result */
  435 int
  436 Skein_512_Final(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
  437 {
  438         size_t i, n, byteCnt;
  439         uint64_t X[SKEIN_512_STATE_WORDS];
  440 
  441         /* catch uninitialized context */
  442         Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
  443 
  444         ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;     /* tag as the final block */
  445         /* zero pad b[] if necessary */
  446         if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES)
  447                 memset(&ctx->b[ctx->h.bCnt], 0,
  448                     SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);
  449 
  450         /* process the final block */
  451         Skein_512_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
  452 
  453         /* now output the result */
  454         /* total number of output bytes */
  455         byteCnt = (ctx->h.hashBitLen + 7) >> 3;
  456 
  457         /* run Threefish in "counter mode" to generate output */
  458         /* zero out b[], so it can hold the counter */
  459         memset(ctx->b, 0, sizeof (ctx->b));
  460         /* keep a local copy of counter mode "key" */
  461         memcpy(X, ctx->X, sizeof (X));
  462         for (i = 0; i * SKEIN_512_BLOCK_BYTES < byteCnt; i++) {
  463                 /* build the counter block */
  464                 *(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
  465                 Skein_Start_New_Type(ctx, OUT_FINAL);
  466                 /* run "counter mode" */
  467                 Skein_512_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
  468                 /* number of output bytes left to go */
  469                 n = byteCnt - i * SKEIN_512_BLOCK_BYTES;
  470                 if (n >= SKEIN_512_BLOCK_BYTES)
  471                         n = SKEIN_512_BLOCK_BYTES;
  472                 Skein_Put64_LSB_First(hashVal + i * SKEIN_512_BLOCK_BYTES,
  473                     ctx->X, n); /* "output" the ctr mode bytes */
  474                 Skein_Show_Final(512, &ctx->h, n,
  475                     hashVal + i * SKEIN_512_BLOCK_BYTES);
  476                 /* restore the counter mode key for next time */
  477                 memcpy(ctx->X, X, sizeof (X));
  478         }
  479         return (SKEIN_SUCCESS);
  480 }
  481 
  482 /* 1024-bit Skein */
  483 
  484 /* init the context for a straight hashing operation  */
  485 int
  486 Skein1024_Init(Skein1024_Ctxt_t *ctx, size_t hashBitLen)
  487 {
  488         union {
  489                 uint8_t b[SKEIN1024_STATE_BYTES];
  490                 uint64_t w[SKEIN1024_STATE_WORDS];
  491         } cfg;                  /* config block */
  492 
  493         Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
  494         ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
  495 
  496         switch (hashBitLen) {   /* use pre-computed values, where available */
  497 #ifndef SKEIN_NO_PRECOMP
  498         case 512:
  499                 memcpy(ctx->X, SKEIN1024_IV_512, sizeof (ctx->X));
  500                 break;
  501         case 384:
  502                 memcpy(ctx->X, SKEIN1024_IV_384, sizeof (ctx->X));
  503                 break;
  504         case 1024:
  505                 memcpy(ctx->X, SKEIN1024_IV_1024, sizeof (ctx->X));
  506                 break;
  507 #endif
  508         default:
  509                 /* here if there is no precomputed IV value available */
  510                 /*
  511                  * build/process the config block, type == CONFIG (could be
  512                  * precomputed)
  513                  */
  514                 /* set tweaks: T0=0; T1=CFG | FINAL */
  515                 Skein_Start_New_Type(ctx, CFG_FINAL);
  516 
  517                 /* set the schema, version */
  518                 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
  519                 /* hash result length in bits */
  520                 cfg.w[1] = Skein_Swap64(hashBitLen);
  521                 cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
  522                 /* zero pad config block */
  523                 memset(&cfg.w[3], 0, sizeof (cfg) - 3 * sizeof (cfg.w[0]));
  524 
  525                 /* compute the initial chaining values from config block */
  526                 /* zero the chaining variables */
  527                 memset(ctx->X, 0, sizeof (ctx->X));
  528                 Skein1024_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
  529                 break;
  530         }
  531 
  532         /*
  533          * The chaining vars ctx->X are now initialized for the given
  534          * hashBitLen. Set up to process the data message portion of the hash
  535          * (default)
  536          */
  537         Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
  538 
  539         return (SKEIN_SUCCESS);
  540 }
  541 
  542 /* init the context for a MAC and/or tree hash operation */
  543 /*
  544  * [identical to Skein1024_Init() when keyBytes == 0 &&
  545  * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
  546  */
  547 int
  548 Skein1024_InitExt(Skein1024_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
  549     const uint8_t *key, size_t keyBytes)
  550 {
  551         union {
  552                 uint8_t b[SKEIN1024_STATE_BYTES];
  553                 uint64_t w[SKEIN1024_STATE_WORDS];
  554         } cfg;                  /* config block */
  555 
  556         Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
  557         Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL);
  558 
  559         /* compute the initial chaining values ctx->X[], based on key */
  560         if (keyBytes == 0) {    /* is there a key? */
  561                 /* no key: use all zeroes as key for config block */
  562                 memset(ctx->X, 0, sizeof (ctx->X));
  563         } else {                /* here to pre-process a key */
  564                 Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X));
  565                 /* do a mini-Init right here */
  566                 /* set output hash bit count = state size */
  567                 ctx->h.hashBitLen = 8 * sizeof (ctx->X);
  568                 /* set tweaks: T0 = 0; T1 = KEY type */
  569                 Skein_Start_New_Type(ctx, KEY);
  570                 /* zero the initial chaining variables */
  571                 memset(ctx->X, 0, sizeof (ctx->X));
  572                 (void) Skein1024_Update(ctx, key, keyBytes); /* hash the key */
  573                 /* put result into cfg.b[] */
  574                 (void) Skein1024_Final_Pad(ctx, cfg.b);
  575                 /* copy over into ctx->X[] */
  576                 memcpy(ctx->X, cfg.b, sizeof (cfg.b));
  577 #if     SKEIN_NEED_SWAP
  578                 {
  579                         uint_t i;
  580                         /* convert key bytes to context words */
  581                         for (i = 0; i < SKEIN1024_STATE_WORDS; i++)
  582                                 ctx->X[i] = Skein_Swap64(ctx->X[i]);
  583                 }
  584 #endif
  585         }
  586         /*
  587          * build/process the config block, type == CONFIG (could be
  588          * precomputed for each key)
  589          */
  590         ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
  591         Skein_Start_New_Type(ctx, CFG_FINAL);
  592 
  593         memset(&cfg.w, 0, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */
  594         cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
  595         /* hash result length in bits */
  596         cfg.w[1] = Skein_Swap64(hashBitLen);
  597         /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
  598         cfg.w[2] = Skein_Swap64(treeInfo);
  599 
  600         Skein_Show_Key(1024, &ctx->h, key, keyBytes);
  601 
  602         /* compute the initial chaining values from config block */
  603         Skein1024_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
  604 
  605         /* The chaining vars ctx->X are now initialized */
  606         /* Set up to process the data message portion of the hash (default) */
  607         ctx->h.bCnt = 0;        /* buffer b[] starts out empty */
  608         Skein_Start_New_Type(ctx, MSG);
  609 
  610         return (SKEIN_SUCCESS);
  611 }
  612 
  613 /* process the input bytes */
  614 int
  615 Skein1024_Update(Skein1024_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
  616 {
  617         size_t n;
  618 
  619         /* catch uninitialized context */
  620         Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
  621 
  622         /* process full blocks, if any */
  623         if (msgByteCnt + ctx->h.bCnt > SKEIN1024_BLOCK_BYTES) {
  624                 /* finish up any buffered message data */
  625                 if (ctx->h.bCnt) {
  626                         /* # bytes free in buffer b[] */
  627                         n = SKEIN1024_BLOCK_BYTES - ctx->h.bCnt;
  628                         if (n) {
  629                                 /* check on our logic here */
  630                                 Skein_assert(n < msgByteCnt);
  631                                 memcpy(&ctx->b[ctx->h.bCnt], msg, n);
  632                                 msgByteCnt -= n;
  633                                 msg += n;
  634                                 ctx->h.bCnt += n;
  635                         }
  636                         Skein_assert(ctx->h.bCnt == SKEIN1024_BLOCK_BYTES);
  637                         Skein1024_Process_Block(ctx, ctx->b, 1,
  638                             SKEIN1024_BLOCK_BYTES);
  639                         ctx->h.bCnt = 0;
  640                 }
  641                 /*
  642                  * now process any remaining full blocks, directly from
  643                  * input message data
  644                  */
  645                 if (msgByteCnt > SKEIN1024_BLOCK_BYTES) {
  646                         /* number of full blocks to process */
  647                         n = (msgByteCnt - 1) / SKEIN1024_BLOCK_BYTES;
  648                         Skein1024_Process_Block(ctx, msg, n,
  649                             SKEIN1024_BLOCK_BYTES);
  650                         msgByteCnt -= n * SKEIN1024_BLOCK_BYTES;
  651                         msg += n * SKEIN1024_BLOCK_BYTES;
  652                 }
  653                 Skein_assert(ctx->h.bCnt == 0);
  654         }
  655 
  656         /* copy any remaining source message data bytes into b[] */
  657         if (msgByteCnt) {
  658                 Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES);
  659                 memcpy(&ctx->b[ctx->h.bCnt], msg, msgByteCnt);
  660                 ctx->h.bCnt += msgByteCnt;
  661         }
  662 
  663         return (SKEIN_SUCCESS);
  664 }
  665 
  666 /* finalize the hash computation and output the result */
  667 int
  668 Skein1024_Final(Skein1024_Ctxt_t *ctx, uint8_t *hashVal)
  669 {
  670         size_t i, n, byteCnt;
  671         uint64_t X[SKEIN1024_STATE_WORDS];
  672 
  673         /* catch uninitialized context */
  674         Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
  675 
  676         ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;     /* tag as the final block */
  677         /* zero pad b[] if necessary */
  678         if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES)
  679                 memset(&ctx->b[ctx->h.bCnt], 0,
  680                     SKEIN1024_BLOCK_BYTES - ctx->h.bCnt);
  681 
  682         /* process the final block */
  683         Skein1024_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
  684 
  685         /* now output the result */
  686         /* total number of output bytes */
  687         byteCnt = (ctx->h.hashBitLen + 7) >> 3;
  688 
  689         /* run Threefish in "counter mode" to generate output */
  690         /* zero out b[], so it can hold the counter */
  691         memset(ctx->b, 0, sizeof (ctx->b));
  692         /* keep a local copy of counter mode "key" */
  693         memcpy(X, ctx->X, sizeof (X));
  694         for (i = 0; i * SKEIN1024_BLOCK_BYTES < byteCnt; i++) {
  695                 /* build the counter block */
  696                 *(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
  697                 Skein_Start_New_Type(ctx, OUT_FINAL);
  698                 /* run "counter mode" */
  699                 Skein1024_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
  700                 /* number of output bytes left to go */
  701                 n = byteCnt - i * SKEIN1024_BLOCK_BYTES;
  702                 if (n >= SKEIN1024_BLOCK_BYTES)
  703                         n = SKEIN1024_BLOCK_BYTES;
  704                 Skein_Put64_LSB_First(hashVal + i * SKEIN1024_BLOCK_BYTES,
  705                     ctx->X, n); /* "output" the ctr mode bytes */
  706                 Skein_Show_Final(1024, &ctx->h, n,
  707                     hashVal + i * SKEIN1024_BLOCK_BYTES);
  708                 /* restore the counter mode key for next time */
  709                 memcpy(ctx->X, X, sizeof (X));
  710         }
  711         return (SKEIN_SUCCESS);
  712 }
  713 
  714 /* Functions to support MAC/tree hashing */
  715 /* (this code is identical for Optimized and Reference versions) */
  716 
  717 /* finalize the hash computation and output the block, no OUTPUT stage */
  718 int
  719 Skein_256_Final_Pad(Skein_256_Ctxt_t *ctx, uint8_t *hashVal)
  720 {
  721         /* catch uninitialized context */
  722         Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
  723 
  724         ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;     /* tag as the final block */
  725         /* zero pad b[] if necessary */
  726         if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES)
  727                 memset(&ctx->b[ctx->h.bCnt], 0,
  728                     SKEIN_256_BLOCK_BYTES - ctx->h.bCnt);
  729         /* process the final block */
  730         Skein_256_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
  731 
  732         /* "output" the state bytes */
  733         Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN_256_BLOCK_BYTES);
  734 
  735         return (SKEIN_SUCCESS);
  736 }
  737 
  738 /* finalize the hash computation and output the block, no OUTPUT stage */
  739 int
  740 Skein_512_Final_Pad(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
  741 {
  742         /* catch uninitialized context */
  743         Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
  744 
  745         ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;     /* tag as the final block */
  746         /* zero pad b[] if necessary */
  747         if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES)
  748                 memset(&ctx->b[ctx->h.bCnt], 0,
  749                     SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);
  750         /* process the final block */
  751         Skein_512_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
  752 
  753         /* "output" the state bytes */
  754         Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN_512_BLOCK_BYTES);
  755 
  756         return (SKEIN_SUCCESS);
  757 }
  758 
  759 /* finalize the hash computation and output the block, no OUTPUT stage */
  760 int
  761 Skein1024_Final_Pad(Skein1024_Ctxt_t *ctx, uint8_t *hashVal)
  762 {
  763         /* catch uninitialized context */
  764         Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
  765 
  766         /* tag as the final block */
  767         ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;
  768         /* zero pad b[] if necessary */
  769         if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES)
  770                 memset(&ctx->b[ctx->h.bCnt], 0,
  771                     SKEIN1024_BLOCK_BYTES - ctx->h.bCnt);
  772         /* process the final block */
  773         Skein1024_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
  774 
  775         /* "output" the state bytes */
  776         Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN1024_BLOCK_BYTES);
  777 
  778         return (SKEIN_SUCCESS);
  779 }
  780 
  781 #if     SKEIN_TREE_HASH
  782 /* just do the OUTPUT stage */
  783 int
  784 Skein_256_Output(Skein_256_Ctxt_t *ctx, uint8_t *hashVal)
  785 {
  786         size_t i, n, byteCnt;
  787         uint64_t X[SKEIN_256_STATE_WORDS];
  788 
  789         /* catch uninitialized context */
  790         Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
  791 
  792         /* now output the result */
  793         /* total number of output bytes */
  794         byteCnt = (ctx->h.hashBitLen + 7) >> 3;
  795 
  796         /* run Threefish in "counter mode" to generate output */
  797         /* zero out b[], so it can hold the counter */
  798         memset(ctx->b, 0, sizeof (ctx->b));
  799         /* keep a local copy of counter mode "key" */
  800         memcpy(X, ctx->X, sizeof (X));
  801         for (i = 0; i * SKEIN_256_BLOCK_BYTES < byteCnt; i++) {
  802                 /* build the counter block */
  803                 *(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
  804                 Skein_Start_New_Type(ctx, OUT_FINAL);
  805                 /* run "counter mode" */
  806                 Skein_256_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
  807                 /* number of output bytes left to go */
  808                 n = byteCnt - i * SKEIN_256_BLOCK_BYTES;
  809                 if (n >= SKEIN_256_BLOCK_BYTES)
  810                         n = SKEIN_256_BLOCK_BYTES;
  811                 Skein_Put64_LSB_First(hashVal + i * SKEIN_256_BLOCK_BYTES,
  812                     ctx->X, n); /* "output" the ctr mode bytes */
  813                 Skein_Show_Final(256, &ctx->h, n,
  814                     hashVal + i * SKEIN_256_BLOCK_BYTES);
  815                 /* restore the counter mode key for next time */
  816                 memcpy(ctx->X, X, sizeof (X));
  817         }
  818         return (SKEIN_SUCCESS);
  819 }
  820 
  821 /* just do the OUTPUT stage */
  822 int
  823 Skein_512_Output(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
  824 {
  825         size_t i, n, byteCnt;
  826         uint64_t X[SKEIN_512_STATE_WORDS];
  827 
  828         /* catch uninitialized context */
  829         Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
  830 
  831         /* now output the result */
  832         /* total number of output bytes */
  833         byteCnt = (ctx->h.hashBitLen + 7) >> 3;
  834 
  835         /* run Threefish in "counter mode" to generate output */
  836         /* zero out b[], so it can hold the counter */
  837         memset(ctx->b, 0, sizeof (ctx->b));
  838         /* keep a local copy of counter mode "key" */
  839         memcpy(X, ctx->X, sizeof (X));
  840         for (i = 0; i * SKEIN_512_BLOCK_BYTES < byteCnt; i++) {
  841                 /* build the counter block */
  842                 *(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
  843                 Skein_Start_New_Type(ctx, OUT_FINAL);
  844                 /* run "counter mode" */
  845                 Skein_512_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
  846                 /* number of output bytes left to go */
  847                 n = byteCnt - i * SKEIN_512_BLOCK_BYTES;
  848                 if (n >= SKEIN_512_BLOCK_BYTES)
  849                         n = SKEIN_512_BLOCK_BYTES;
  850                 Skein_Put64_LSB_First(hashVal + i * SKEIN_512_BLOCK_BYTES,
  851                     ctx->X, n); /* "output" the ctr mode bytes */
  852                 Skein_Show_Final(256, &ctx->h, n,
  853                     hashVal + i * SKEIN_512_BLOCK_BYTES);
  854                 /* restore the counter mode key for next time */
  855                 memcpy(ctx->X, X, sizeof (X));
  856         }
  857         return (SKEIN_SUCCESS);
  858 }
  859 
  860 /* just do the OUTPUT stage */
  861 int
  862 Skein1024_Output(Skein1024_Ctxt_t *ctx, uint8_t *hashVal)
  863 {
  864         size_t i, n, byteCnt;
  865         uint64_t X[SKEIN1024_STATE_WORDS];
  866 
  867         /* catch uninitialized context */
  868         Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
  869 
  870         /* now output the result */
  871         /* total number of output bytes */
  872         byteCnt = (ctx->h.hashBitLen + 7) >> 3;
  873 
  874         /* run Threefish in "counter mode" to generate output */
  875         /* zero out b[], so it can hold the counter */
  876         memset(ctx->b, 0, sizeof (ctx->b));
  877         /* keep a local copy of counter mode "key" */
  878         memcpy(X, ctx->X, sizeof (X));
  879         for (i = 0; i * SKEIN1024_BLOCK_BYTES < byteCnt; i++) {
  880                 /* build the counter block */
  881                 *(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
  882                 Skein_Start_New_Type(ctx, OUT_FINAL);
  883                 /* run "counter mode" */
  884                 Skein1024_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
  885                 /* number of output bytes left to go */
  886                 n = byteCnt - i * SKEIN1024_BLOCK_BYTES;
  887                 if (n >= SKEIN1024_BLOCK_BYTES)
  888                         n = SKEIN1024_BLOCK_BYTES;
  889                 Skein_Put64_LSB_First(hashVal + i * SKEIN1024_BLOCK_BYTES,
  890                     ctx->X, n); /* "output" the ctr mode bytes */
  891                 Skein_Show_Final(256, &ctx->h, n,
  892                     hashVal + i * SKEIN1024_BLOCK_BYTES);
  893                 /* restore the counter mode key for next time */
  894                 memcpy(ctx->X, X, sizeof (X));
  895         }
  896         return (SKEIN_SUCCESS);
  897 }
  898 #endif
  899 
  900 #ifdef _KERNEL
  901 EXPORT_SYMBOL(Skein_512_Init);
  902 EXPORT_SYMBOL(Skein_512_InitExt);
  903 EXPORT_SYMBOL(Skein_512_Update);
  904 EXPORT_SYMBOL(Skein_512_Final);
  905 #endif

Cache object: 777d353f8545dca1da202b48a707732b


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